@0xsequence/marketplace-sdk 0.8.6 → 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 (138) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/chunk-2PSNAIAT.js +1 -0
  3. package/dist/chunk-2PSNAIAT.js.map +1 -0
  4. package/dist/{chunk-WXKV5N4T.js → chunk-35WWD5V6.js} +3 -3
  5. package/dist/{chunk-ZSCZLHKX.js → chunk-4XLXOEXQ.js} +2 -2
  6. package/dist/{chunk-TGFX3TMV.js → chunk-7IYKUVC3.js} +314 -147
  7. package/dist/chunk-7IYKUVC3.js.map +1 -0
  8. package/dist/{chunk-BB2PTJHI.js → chunk-D7RVSZAQ.js} +131 -83
  9. package/dist/chunk-D7RVSZAQ.js.map +1 -0
  10. package/dist/chunk-DWTLVJAW.js +42 -0
  11. package/dist/chunk-DWTLVJAW.js.map +1 -0
  12. package/dist/{chunk-SJU6QZHM.js → chunk-EODKQL6Y.js} +2 -2
  13. package/dist/{chunk-6SEJI7YS.js → chunk-G3447GIP.js} +39 -20
  14. package/dist/chunk-G3447GIP.js.map +1 -0
  15. package/dist/{chunk-QMWMJVTX.js → chunk-HHYNOPPI.js} +2 -2
  16. package/dist/{chunk-ALICO7NG.js → chunk-KGM2WLSP.js} +15 -158
  17. package/dist/chunk-KGM2WLSP.js.map +1 -0
  18. package/dist/chunk-MAD64DLJ.js +81 -0
  19. package/dist/chunk-MAD64DLJ.js.map +1 -0
  20. package/dist/chunk-N7BPFK46.js +1 -0
  21. package/dist/chunk-N7BPFK46.js.map +1 -0
  22. package/dist/chunk-NX52D7NX.js +135 -0
  23. package/dist/chunk-NX52D7NX.js.map +1 -0
  24. package/dist/chunk-O34GCB47.js +32 -0
  25. package/dist/chunk-O34GCB47.js.map +1 -0
  26. package/dist/{chunk-LDZZUYG7.js → chunk-YALXP2PW.js} +3 -3
  27. package/dist/{chunk-V3NVAVHV.js → chunk-YBOFRP65.js} +2 -2
  28. package/dist/{chunk-BGY4WXER.js → chunk-YEGD7PWE.js} +3 -2
  29. package/dist/{chunk-BGY4WXER.js.map → chunk-YEGD7PWE.js.map} +1 -1
  30. package/dist/{create-config-qDML4ZNn.d.ts → create-config-DwrnzwpM.d.ts} +2 -2
  31. package/dist/{index-DtWR0b_l.d.ts → index-DGsVBflk.d.ts} +3 -12
  32. package/dist/index.css +7 -5
  33. package/dist/index.css.map +1 -1
  34. package/dist/index.d.ts +13 -4
  35. package/dist/index.js +14 -6
  36. package/dist/{lowestListing-W7P4EkC3.d.ts → lowestListing-BQHIuvNF.d.ts} +2 -2
  37. package/dist/{marketplace.gen-DS-MmGEB.d.ts → marketplace.gen-DQzWciwC.d.ts} +5 -4
  38. package/dist/marketplaceConfig-B4Fdsmxu.d.ts +17 -0
  39. package/dist/react/_internal/api/index.d.ts +3 -3
  40. package/dist/react/_internal/api/index.js +4 -3
  41. package/dist/react/_internal/databeat/index.d.ts +2 -1
  42. package/dist/react/_internal/databeat/index.js +13 -9
  43. package/dist/react/_internal/index.d.ts +6 -6
  44. package/dist/react/_internal/index.js +13 -10
  45. package/dist/react/_internal/wagmi/index.d.ts +6 -5
  46. package/dist/react/_internal/wagmi/index.js +2 -2
  47. package/dist/react/hooks/index.d.ts +9 -8
  48. package/dist/react/hooks/index.js +12 -8
  49. package/dist/react/hooks/options/index.d.ts +4 -4
  50. package/dist/react/hooks/options/index.js +7 -4
  51. package/dist/react/index.css +2650 -0
  52. package/dist/react/index.css.map +1 -1
  53. package/dist/react/index.d.ts +8 -8
  54. package/dist/react/index.js +19 -14
  55. package/dist/react/queries/index.d.ts +3 -3
  56. package/dist/react/queries/index.js +6 -3
  57. package/dist/react/ssr/index.d.ts +3 -3
  58. package/dist/react/ssr/index.js +6 -3
  59. package/dist/react/ssr/index.js.map +1 -1
  60. package/dist/react/ui/components/collectible-card/index.css +2650 -0
  61. package/dist/react/ui/components/collectible-card/index.css.map +1 -1
  62. package/dist/react/ui/components/collectible-card/index.d.ts +1 -1
  63. package/dist/react/ui/components/collectible-card/index.js +17 -12
  64. package/dist/react/ui/icons/index.js +8 -5
  65. package/dist/react/ui/index.css +2650 -0
  66. package/dist/react/ui/index.css.map +1 -1
  67. package/dist/react/ui/index.d.ts +2 -1
  68. package/dist/react/ui/index.js +17 -12
  69. package/dist/react/ui/modals/_internal/components/actionModal/index.js +13 -9
  70. package/dist/sdk-config-txlivEKe.d.ts +133 -0
  71. package/dist/{services-BOX67E7W.d.ts → services-BI_w8Eq4.d.ts} +4 -4
  72. package/dist/types/index.d.ts +5 -4
  73. package/dist/types/index.js +9 -6
  74. package/dist/{types-CJLhc2VZ.d.ts → types-isjvwapz.d.ts} +3 -3
  75. package/dist/utils/index.d.ts +1 -1
  76. package/dist/utils/index.js +6 -3
  77. package/package.json +3 -3
  78. package/src/index.ts +1 -0
  79. package/src/react/{hooks/options/__mocks__/marketplaceConfig.msw.ts → _internal/api/__mocks__/builder.msw.ts} +70 -63
  80. package/src/react/_internal/api/__mocks__/metadata.msw.ts +30 -10
  81. package/src/react/_internal/api/builder-api.ts +32 -0
  82. package/src/react/_internal/api/builder.gen.ts +215 -0
  83. package/src/react/_internal/api/marketplace.gen.ts +6 -6
  84. package/src/react/_internal/api/services.ts +9 -2
  85. package/src/react/_internal/databeat/types.ts +1 -0
  86. package/src/react/_internal/wagmi/__tests__/create-config.test.ts +16 -41
  87. package/src/react/_internal/wagmi/create-config.ts +3 -16
  88. package/src/react/_internal/wagmi/get-connectors.ts +31 -21
  89. package/src/react/_internal/wallet/__tests__/wallet.test.ts +30 -0
  90. package/src/react/_internal/wallet/wallet.ts +25 -2
  91. package/src/react/hooks/__tests__/__snapshots__/useMarketplaceConfig.test.tsx.snap +96 -0
  92. package/src/react/hooks/__tests__/useCollection.test.tsx +4 -5
  93. package/src/react/hooks/__tests__/useCurrencies.test.tsx +1 -1
  94. package/src/react/hooks/__tests__/useInventory.test.tsx +15 -16
  95. package/src/react/hooks/__tests__/useListCollections.test.tsx +18 -163
  96. package/src/react/hooks/__tests__/useMarketplaceConfig.test.tsx +10 -11
  97. package/src/react/hooks/options/index.ts +1 -1
  98. package/src/react/hooks/useAutoSelectFeeOption.tsx +1 -0
  99. package/src/react/hooks/useMarketplaceConfig.tsx +2 -2
  100. package/src/react/queries/marketplaceConfig.ts +101 -0
  101. package/src/react/ssr/__tests__/__snapshots__/create-ssr-client.test.ts.snap +1 -0
  102. package/src/react/ssr/create-ssr-client.ts +1 -1
  103. package/src/react/ui/components/collectible-card/CollectibleCard.tsx +2 -2
  104. package/src/react/ui/components/collectible-card/__tests__/CollectibleAsset.test.tsx +72 -42
  105. package/src/react/ui/components/collectible-card/{CollectibleAsset.tsx → collectible-asset/CollectibleAsset.tsx} +44 -44
  106. package/src/react/ui/components/collectible-card/collectible-asset/CollectibleAssetSkeleton.tsx +14 -0
  107. package/src/react/ui/components/collectible-card/collectible-asset/utils.ts +36 -0
  108. package/src/react/ui/modals/BuyModal/hooks/usePaymentModalParams.ts +6 -1
  109. package/src/react/ui/modals/BuyModal/store.ts +1 -0
  110. package/src/react/ui/modals/CreateListingModal/hooks/useTransactionSteps.tsx +20 -2
  111. package/src/react/ui/modals/MakeOfferModal/hooks/useTransactionSteps.tsx +17 -1
  112. package/src/react/ui/modals/SellModal/hooks/useTransactionSteps.tsx +4 -0
  113. package/src/react/ui/modals/_internal/components/actionModal/ActionModal.test.tsx +7 -1
  114. package/src/types/index.ts +7 -1
  115. package/src/types/sdk-config.ts +4 -9
  116. package/src/utils/fetchContentType.ts +101 -0
  117. package/src/utils/getMarketplaceDetails.ts +2 -1
  118. package/src/utils/getSequenceMarketRequestId.ts +32 -0
  119. package/test/mocks/wallet.ts +3 -1
  120. package/test/test-utils.tsx +1 -1
  121. package/tsconfig.tsbuildinfo +1 -1
  122. package/dist/builder-types-BY6eD6vD.d.ts +0 -82
  123. package/dist/chunk-6SEJI7YS.js.map +0 -1
  124. package/dist/chunk-ALICO7NG.js.map +0 -1
  125. package/dist/chunk-BB2PTJHI.js.map +0 -1
  126. package/dist/chunk-HGKWWZWY.js +0 -58
  127. package/dist/chunk-HGKWWZWY.js.map +0 -1
  128. package/dist/chunk-TGFX3TMV.js.map +0 -1
  129. package/dist/sdk-config-DIzJk_tI.d.ts +0 -26
  130. package/src/react/hooks/options/__tests__/marketplaceConfigOptions.test.tsx +0 -134
  131. package/src/react/hooks/options/marketplaceConfigOptions.ts +0 -71
  132. package/src/types/builder-types.ts +0 -88
  133. /package/dist/{chunk-WXKV5N4T.js.map → chunk-35WWD5V6.js.map} +0 -0
  134. /package/dist/{chunk-ZSCZLHKX.js.map → chunk-4XLXOEXQ.js.map} +0 -0
  135. /package/dist/{chunk-SJU6QZHM.js.map → chunk-EODKQL6Y.js.map} +0 -0
  136. /package/dist/{chunk-QMWMJVTX.js.map → chunk-HHYNOPPI.js.map} +0 -0
  137. /package/dist/{chunk-LDZZUYG7.js.map → chunk-YALXP2PW.js.map} +0 -0
  138. /package/dist/{chunk-V3NVAVHV.js.map → chunk-YBOFRP65.js.map} +0 -0
@@ -1,38 +1,12 @@
1
1
  'use client';
2
2
 
3
- import { Skeleton } from '@0xsequence/design-system';
4
3
  import { useEffect, useRef, useState } from 'react';
5
- import { cn } from '../../../../utils';
6
- import type { TokenMetadata } from '../../../_internal';
7
- import ChessTileImage from '../../images/chess-tile.png';
8
-
9
- export function CollectibleAssetSkeleton() {
10
- return (
11
- <Skeleton
12
- data-testid="collectible-asset-skeleton"
13
- size="lg"
14
- className="absolute inset-0 h-full w-full animate-shimmer"
15
- style={{
16
- borderRadius: 0,
17
- }}
18
- />
19
- );
20
- }
21
-
22
- export const isHtml = (fileName: string | undefined) => {
23
- const isHtml = /.*\.(html\?.+|html)$/.test(fileName?.toLowerCase() || '');
24
- return isHtml;
25
- };
26
-
27
- export const isVideo = (fileName: string | undefined) => {
28
- const isVideo = /.*\.(mp4|ogg|webm)$/.test(fileName?.toLowerCase() || '');
29
- return isVideo;
30
- };
31
-
32
- export const is3dModel = (fileName: string | undefined) => {
33
- const isGltf = /.*\.gltf$/.test(fileName?.toLowerCase() || '');
34
- return isGltf;
35
- };
4
+ import { cn } from '../../../../../utils';
5
+ import { fetchContentType } from '../../../../../utils/fetchContentType';
6
+ import type { TokenMetadata } from '../../../../_internal';
7
+ import ChessTileImage from '../../../images/chess-tile.png';
8
+ import CollectibleAssetSkeleton from './CollectibleAssetSkeleton';
9
+ import { getContentType } from './utils';
36
10
 
37
11
  type CollectibleImageProps = {
38
12
  name?: string;
@@ -47,6 +21,11 @@ export function CollectibleAsset({
47
21
  }: CollectibleImageProps) {
48
22
  const [assetLoadFailed, setAssetLoadFailed] = useState(false);
49
23
  const [assetLoading, setAssetLoading] = useState(true);
24
+ const [contentType, setContentType] = useState<{
25
+ type: 'image' | 'video' | 'html' | null;
26
+ loading: boolean;
27
+ failed: boolean;
28
+ }>({ type: null, loading: true, failed: false });
50
29
  const videoRef = useRef<HTMLVideoElement>(null);
51
30
  const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
52
31
 
@@ -62,17 +41,29 @@ export function CollectibleAsset({
62
41
  : assetUrl;
63
42
 
64
43
  useEffect(() => {
65
- if (videoRef.current) {
66
- videoRef.current.addEventListener('loadedmetadata', () => {
67
- setAssetLoading(false);
44
+ getContentType(proxiedAssetUrl)
45
+ .then((contentType) => {
46
+ setContentType({ type: contentType, loading: false, failed: false });
47
+ })
48
+ .catch(() => {
49
+ fetchContentType(proxiedAssetUrl)
50
+ .then((contentType) => {
51
+ setContentType({
52
+ type: contentType,
53
+ loading: false,
54
+ failed: false,
55
+ });
56
+ })
57
+ .catch(() => {
58
+ setContentType({ type: null, loading: false, failed: true });
59
+ });
68
60
  });
69
- }
70
- }, []);
61
+ }, [proxiedAssetUrl]);
71
62
 
72
- if (isHtml(assetUrl)) {
63
+ if (contentType.type === 'html' && !assetLoadFailed) {
73
64
  return (
74
65
  <div className="flex aspect-square w-full items-center justify-center overflow-hidden rounded-lg bg-background-secondary">
75
- {assetLoading && <CollectibleAssetSkeleton />}
66
+ {(assetLoading || contentType.loading) && <CollectibleAssetSkeleton />}
76
67
 
77
68
  <iframe
78
69
  title={name || 'Collectible'}
@@ -92,10 +83,11 @@ export function CollectibleAsset({
92
83
 
93
84
  // TODO: Add 3d model support
94
85
 
95
- if (isVideo(assetUrl)) {
86
+ if (contentType.type === 'video' && !assetLoadFailed) {
96
87
  return (
97
88
  <div className="relative flex aspect-square w-full items-center justify-center overflow-hidden rounded-lg bg-background-secondary">
98
- {assetLoading && <CollectibleAssetSkeleton />}
89
+ {(assetLoading || contentType.loading) && <CollectibleAssetSkeleton />}
90
+
99
91
  <video
100
92
  ref={videoRef}
101
93
  className={cn(
@@ -114,6 +106,10 @@ export function CollectibleAsset({
114
106
  onError={() => {
115
107
  setAssetLoadFailed(true);
116
108
  }}
109
+ onLoadedMetadata={() => {
110
+ setAssetLoading(false);
111
+ }}
112
+ data-testid="collectible-asset-video"
117
113
  >
118
114
  <source src={proxiedAssetUrl} />
119
115
  </video>
@@ -123,13 +119,17 @@ export function CollectibleAsset({
123
119
 
124
120
  return (
125
121
  <div className="relative aspect-square overflow-hidden bg-background-secondary">
126
- {assetLoading && <CollectibleAssetSkeleton />}
122
+ {(assetLoading || contentType.loading) && <CollectibleAssetSkeleton />}
127
123
 
128
124
  <img
129
- src={assetLoadFailed ? placeholderImage : proxiedAssetUrl}
125
+ src={
126
+ assetLoadFailed || contentType.failed
127
+ ? placeholderImage
128
+ : proxiedAssetUrl
129
+ }
130
130
  alt={name || 'Collectible'}
131
131
  className={`absolute inset-0 h-full w-full object-cover transition-transform duration-200 ease-in-out group-hover:scale-hover ${
132
- assetLoading ? 'invisible' : 'visible'
132
+ assetLoading || contentType.loading ? 'invisible' : 'visible'
133
133
  }`}
134
134
  onError={() => setAssetLoadFailed(true)}
135
135
  onLoad={() => setAssetLoading(false)}
@@ -0,0 +1,14 @@
1
+ import { Skeleton } from '@0xsequence/design-system';
2
+
3
+ export default function CollectibleAssetSkeleton() {
4
+ return (
5
+ <Skeleton
6
+ data-testid="collectible-asset-skeleton"
7
+ size="lg"
8
+ className="absolute inset-0 h-full w-full animate-shimmer"
9
+ style={{
10
+ borderRadius: 0,
11
+ }}
12
+ />
13
+ );
14
+ }
@@ -0,0 +1,36 @@
1
+ export const isImage = (fileName: string | undefined) => {
2
+ const isImage = /.*\.(png|jpg|jpeg|gif|svg|webp)$/.test(
3
+ fileName?.toLowerCase() || '',
4
+ );
5
+ return isImage;
6
+ };
7
+
8
+ export const isHtml = (fileName: string | undefined) => {
9
+ const isHtml = /.*\.(html\?.+|html)$/.test(fileName?.toLowerCase() || '');
10
+ return isHtml;
11
+ };
12
+
13
+ export const isVideo = (fileName: string | undefined) => {
14
+ const isVideo = /.*\.(mp4|ogg|webm)$/.test(fileName?.toLowerCase() || '');
15
+ return isVideo;
16
+ };
17
+
18
+ export const is3dModel = (fileName: string | undefined) => {
19
+ const isGltf = /.*\.gltf$/.test(fileName?.toLowerCase() || '');
20
+ return isGltf;
21
+ };
22
+
23
+ export const getContentType = (
24
+ url: string,
25
+ ): Promise<'image' | 'video' | 'html' | null> => {
26
+ return new Promise((resolve) => {
27
+ const type = isHtml(url)
28
+ ? 'html'
29
+ : isVideo(url)
30
+ ? 'video'
31
+ : isImage(url)
32
+ ? 'image'
33
+ : null;
34
+ resolve(type);
35
+ });
36
+ };
@@ -40,6 +40,7 @@ interface GetBuyCollectableParams {
40
40
  priceCurrencyAddress: string;
41
41
  customCreditCardProviderCallback: ((buyStep: Step) => void) | undefined;
42
42
  skipNativeBalanceCheck: boolean | undefined;
43
+ nativeTokenAddress: string | undefined;
43
44
  }
44
45
 
45
46
  export const getBuyCollectableParams = async ({
@@ -58,6 +59,7 @@ export const getBuyCollectableParams = async ({
58
59
  checkoutOptions,
59
60
  fee,
60
61
  skipNativeBalanceCheck,
62
+ nativeTokenAddress,
61
63
  }: GetBuyCollectableParams) => {
62
64
  const marketplaceClient = getMarketplaceClient(chainId, config);
63
65
  const { steps } = await marketplaceClient.generateBuyTransaction({
@@ -111,7 +113,7 @@ export const getBuyCollectableParams = async ({
111
113
  callbacks?.onSuccess?.({ hash: hash as Hash });
112
114
  },
113
115
  supplementaryAnalyticsInfo: {
114
- orderId: orderId,
116
+ requestId: orderId,
115
117
  marketplaceKind: marketplace,
116
118
  },
117
119
  onError: callbacks?.onError,
@@ -121,6 +123,7 @@ export const getBuyCollectableParams = async ({
121
123
  buyModalStore.send({ type: 'close' });
122
124
  },
123
125
  skipNativeBalanceCheck,
126
+ nativeTokenAddress,
124
127
  ...(customCreditCardProviderCallback && {
125
128
  customProviderCallback: () => {
126
129
  customCreditCardProviderCallback(buyStep);
@@ -157,6 +160,7 @@ export const usePaymentModalParams = (args: usePaymentModalParams) => {
157
160
  orderId,
158
161
  customCreditCardProviderCallback,
159
162
  skipNativeBalanceCheck,
163
+ nativeTokenAddress,
160
164
  } = buyModalProps;
161
165
 
162
166
  const config = useConfig();
@@ -198,6 +202,7 @@ export const usePaymentModalParams = (args: usePaymentModalParams) => {
198
202
  },
199
203
  customCreditCardProviderCallback,
200
204
  skipNativeBalanceCheck,
205
+ nativeTokenAddress,
201
206
  })
202
207
  : skipToken,
203
208
  });
@@ -11,6 +11,7 @@ export type BuyModalProps = {
11
11
  marketplace: MarketplaceKind;
12
12
  customCreditCardProviderCallback?: (buyStep: Step) => void;
13
13
  skipNativeBalanceCheck?: boolean;
14
+ nativeTokenAddress?: Address;
14
15
  };
15
16
 
16
17
  export type onSuccessCallback = ({
@@ -1,6 +1,7 @@
1
1
  import type { Observable } from '@legendapp/state';
2
2
  import { type Address, type Hex, formatUnits } from 'viem';
3
- import type { OrderbookKind, Price } from '../../../../../types';
3
+ import { OrderbookKind, type Price } from '../../../../../types';
4
+ import { getSequenceMarketplaceRequestId } from '../../../../../utils/getSequenceMarketRequestId';
4
5
  import {
5
6
  type Step,
6
7
  StepType,
@@ -196,12 +197,28 @@ export const useTransactionSteps = ({
196
197
  formatUnits(BigInt(currencyValueRaw), currencyDecimal),
197
198
  );
198
199
 
200
+ let requestId = orderId;
201
+
202
+ if (
203
+ hash &&
204
+ (orderbookKind === OrderbookKind.sequence_marketplace_v1 ||
205
+ orderbookKind === OrderbookKind.sequence_marketplace_v2)
206
+ ) {
207
+ requestId = await getSequenceMarketplaceRequestId(
208
+ hash,
209
+ wallet.publicClient,
210
+ await wallet.address(),
211
+ );
212
+ }
213
+
199
214
  analytics.trackCreateListing({
200
215
  props: {
201
216
  orderbookKind,
202
217
  collectionAddress,
203
218
  currencyAddress: listingInput.listing.currencyAddress,
204
- currencySymbol: '',
219
+ currencySymbol: currency?.symbol || '',
220
+ tokenId: listingInput.listing.tokenId,
221
+ requestId: requestId || '',
205
222
  chainId: chainId.toString(),
206
223
  txnHash: hash || '',
207
224
  },
@@ -214,6 +231,7 @@ export const useTransactionSteps = ({
214
231
  } catch (error) {
215
232
  steps$.transaction.isExecuting.set(false);
216
233
  steps$.transaction.exist.set(false);
234
+
217
235
  if (callbacks?.onError && typeof callbacks.onError === 'function') {
218
236
  callbacks.onError(error as Error);
219
237
  }
@@ -1,6 +1,7 @@
1
1
  import type { Observable } from '@legendapp/state';
2
2
  import { type Address, type Hex, formatUnits } from 'viem';
3
3
  import { OrderbookKind, type Price } from '../../../../../types';
4
+ import { getSequenceMarketplaceRequestId } from '../../../../../utils/getSequenceMarketRequestId';
4
5
  import {
5
6
  type Step,
6
7
  StepType,
@@ -177,7 +178,6 @@ export const useTransactionSteps = ({
177
178
 
178
179
  if (orderId) {
179
180
  // no need to wait for receipt, because the order is already created
180
-
181
181
  steps$.transaction.isExecuting.set(false);
182
182
  steps$.transaction.exist.set(false);
183
183
  }
@@ -189,6 +189,20 @@ export const useTransactionSteps = ({
189
189
  formatUnits(BigInt(currencyValueRaw), currencyDecimal),
190
190
  );
191
191
 
192
+ let requestId = orderId;
193
+
194
+ if (
195
+ hash &&
196
+ (orderbookKind === OrderbookKind.sequence_marketplace_v1 ||
197
+ orderbookKind === OrderbookKind.sequence_marketplace_v2)
198
+ ) {
199
+ requestId = await getSequenceMarketplaceRequestId(
200
+ hash,
201
+ wallet.publicClient,
202
+ await wallet.address(),
203
+ );
204
+ }
205
+
192
206
  analytics.trackCreateOffer({
193
207
  props: {
194
208
  orderbookKind,
@@ -196,6 +210,7 @@ export const useTransactionSteps = ({
196
210
  currencyAddress: offerInput.offer.currencyAddress,
197
211
  currencySymbol: currency?.symbol || '',
198
212
  chainId: chainId.toString(),
213
+ requestId: requestId || '',
199
214
  txnHash: hash || '',
200
215
  },
201
216
  nums: {
@@ -207,6 +222,7 @@ export const useTransactionSteps = ({
207
222
  } catch (error) {
208
223
  steps$.transaction.isExecuting.set(false);
209
224
  steps$.transaction.exist.set(false);
225
+
210
226
  if (callbacks?.onError && typeof callbacks.onError === 'function') {
211
227
  callbacks.onError(error as Error);
212
228
  }
@@ -196,9 +196,12 @@ export const useTransactionSteps = ({
196
196
  analytics.trackSellItems({
197
197
  props: {
198
198
  marketplaceKind: marketplace,
199
+ userId: await wallet.address(),
199
200
  collectionAddress,
200
201
  currencyAddress: ordersData[0].currencyAddress,
201
202
  currencySymbol,
203
+ requestId: ordersData[0].orderId,
204
+ tokenId: collectibleId,
202
205
  chainId: chainId.toString(),
203
206
  txnHash: hash || '',
204
207
  },
@@ -211,6 +214,7 @@ export const useTransactionSteps = ({
211
214
  } catch (error) {
212
215
  steps$.transaction.isExecuting.set(false);
213
216
  steps$.transaction.exist.set(false);
217
+
214
218
  if (callbacks?.onError && typeof callbacks.onError === 'function') {
215
219
  callbacks.onError(error as Error);
216
220
  }
@@ -1,5 +1,5 @@
1
1
  import { fireEvent, render, screen, waitFor } from '@test';
2
- import { type Address, custom, zeroAddress } from 'viem';
2
+ import { type Address, type PublicClient, custom, zeroAddress } from 'viem';
3
3
  import { mainnet, polygon } from 'viem/chains';
4
4
  import { beforeEach, describe, expect, it, vi } from 'vitest';
5
5
  import { WalletKind } from '../../../../../_internal';
@@ -102,6 +102,8 @@ describe('ActionModal', () => {
102
102
  handleSendTransactionStep: vi.fn(),
103
103
  handleSignMessageStep: vi.fn(),
104
104
  hasTokenApproval: vi.fn(),
105
+ // @ts-expect-error
106
+ publicClient: vi.fn().mockResolvedValue({} as PublicClient),
105
107
  },
106
108
  isLoading: false,
107
109
  isError: false,
@@ -127,6 +129,8 @@ describe('ActionModal', () => {
127
129
  handleSendTransactionStep: vi.fn(),
128
130
  handleSignMessageStep: vi.fn(),
129
131
  hasTokenApproval: vi.fn(),
132
+ // @ts-expect-error
133
+ publicClient: vi.fn().mockResolvedValue({} as PublicClient),
130
134
  },
131
135
  isLoading: false,
132
136
  isError: false,
@@ -160,6 +164,8 @@ describe('ActionModal', () => {
160
164
  handleSendTransactionStep: vi.fn(),
161
165
  handleSignMessageStep: vi.fn(),
162
166
  hasTokenApproval: vi.fn(),
167
+ // @ts-expect-error
168
+ publicClient: vi.fn().mockResolvedValue({} as PublicClient),
163
169
  },
164
170
  isLoading: false,
165
171
  isError: false,
@@ -1,4 +1,10 @@
1
1
  export * from './api-types';
2
2
  export * from './sdk-config';
3
3
  export * from './types';
4
- export * from './builder-types';
4
+ export type * from '../react/_internal/api/builder.gen';
5
+ export type * from './../react/queries/marketplaceConfig';
6
+ export {
7
+ MarketplaceWallet,
8
+ FilterCondition,
9
+ MarketplaceType,
10
+ } from '../react/_internal/api/builder.gen';
@@ -1,18 +1,13 @@
1
+ import type { MarketplaceSettings } from '../react/_internal/api/builder.gen';
2
+
1
3
  export type Env = 'development' | 'next' | 'production';
2
4
 
3
5
  export type SdkConfig = {
4
6
  projectAccessKey: string;
5
7
  projectId: string;
6
- wallet?: {
7
- walletConnectProjectId?: string;
8
- embedded?: {
9
- waasConfigKey: string;
10
- googleClientId?: string;
11
- appleClientId?: string;
12
- appleRedirectURI?: string;
13
- };
14
- };
8
+ walletConnectProjectId?: string;
15
9
  _internal?: {
10
+ prefetchedMarketplaceSettings?: MarketplaceSettings;
16
11
  devAccessKey?: string;
17
12
  nextAccessKey?: string;
18
13
  builderEnv?: Env;
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Fetches the Content-Type header of a given URL and returns the primary type if it's supported.
3
+ * @param url The URL to send the request to.
4
+ * @returns A Promise that resolves with 'image', 'video', 'html', or null.
5
+ */
6
+ export function fetchContentType(
7
+ url: string,
8
+ ): Promise<'image' | 'video' | 'html' | null> {
9
+ return new Promise((resolve, reject) => {
10
+ if (typeof XMLHttpRequest === 'undefined') {
11
+ reject(new Error('XMLHttpRequest is not supported in this environment.'));
12
+ return;
13
+ }
14
+
15
+ const client = new XMLHttpRequest();
16
+ let settled = false;
17
+
18
+ const settle = (value: 'image' | 'video' | 'html' | null) => {
19
+ if (!settled) {
20
+ settled = true;
21
+ resolve(value);
22
+ client.abort();
23
+ }
24
+ };
25
+
26
+ const fail = (error: Error) => {
27
+ if (!settled) {
28
+ settled = true;
29
+ reject(error);
30
+ }
31
+ };
32
+
33
+ client.open('HEAD', url, true);
34
+
35
+ client.onreadystatechange = () => {
36
+ if (settled || client.readyState < XMLHttpRequest.HEADERS_RECEIVED) {
37
+ return;
38
+ }
39
+
40
+ if (client.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
41
+ const status = client.status;
42
+
43
+ if (status < 200 || status >= 300) {
44
+ settle(null);
45
+ return;
46
+ }
47
+
48
+ const contentType = client.getResponseHeader('Content-Type');
49
+
50
+ if (!contentType) {
51
+ settle(null);
52
+ return;
53
+ }
54
+
55
+ const primaryType = contentType.split('/')[0].toLowerCase();
56
+ let result: 'image' | 'video' | 'html' | null = null;
57
+
58
+ switch (primaryType) {
59
+ case 'image':
60
+ result = 'image';
61
+ break;
62
+ case 'video':
63
+ result = 'video';
64
+ break;
65
+ case 'text':
66
+ if (contentType.toLowerCase().includes('html')) {
67
+ result = 'html';
68
+ }
69
+ break;
70
+ }
71
+
72
+ settle(result);
73
+ return;
74
+ }
75
+ };
76
+
77
+ client.onerror = (errorEvent) => {
78
+ fail(
79
+ new Error(`XMLHttpRequest network error for URL: ${url}`, {
80
+ cause: errorEvent,
81
+ }),
82
+ );
83
+ };
84
+
85
+ client.onabort = () => {
86
+ if (!settled) {
87
+ settle(null);
88
+ }
89
+ };
90
+
91
+ try {
92
+ client.send();
93
+ } catch (error) {
94
+ fail(
95
+ new Error(`Error sending XMLHttpRequest for URL: ${url}`, {
96
+ cause: error,
97
+ }),
98
+ );
99
+ }
100
+ });
101
+ }
@@ -62,6 +62,7 @@ const KIND_TO_MARKETPLACE: Partial<
62
62
  [MarketplaceKind.looks_rare]: 'looksrare',
63
63
  [MarketplaceKind.x2y2]: 'x2y2',
64
64
  [MarketplaceKind.blur]: 'blur',
65
+ [MarketplaceKind.magic_eden]: 'magiceden',
65
66
  };
66
67
 
67
68
  type MarketplaceDetailsProp = {
@@ -69,7 +70,7 @@ type MarketplaceDetailsProp = {
69
70
  kind: MarketplaceKind;
70
71
  };
71
72
 
72
- // TODO: add suport for more marketplaces and improve detection of marketplace
73
+ // TODO: add support for more marketplaces and improve detection of marketplace
73
74
  export function getMarketplaceDetails({
74
75
  originName,
75
76
  kind,
@@ -0,0 +1,32 @@
1
+ import {
2
+ type Address,
3
+ type Hex,
4
+ type PublicClient,
5
+ parseEventLogs,
6
+ } from 'viem';
7
+ import { SequenceMarketplaceV1_ABI } from '..';
8
+
9
+ export const getSequenceMarketplaceRequestId = async (
10
+ hash: Hex,
11
+ publicClient: PublicClient,
12
+ walletAddress: Address,
13
+ ) => {
14
+ try {
15
+ const receipt = await publicClient.getTransactionReceipt({
16
+ hash: hash,
17
+ });
18
+
19
+ const logs = parseEventLogs({
20
+ abi: SequenceMarketplaceV1_ABI,
21
+ eventName: 'RequestCreated',
22
+ args: {
23
+ creator: walletAddress,
24
+ },
25
+ logs: receipt.logs,
26
+ });
27
+
28
+ return logs[0].args.requestId.toString();
29
+ } catch (error) {
30
+ console.error(error);
31
+ }
32
+ };
@@ -1,5 +1,5 @@
1
1
  import type { TransactionReceipt } from '@0xsequence/indexer';
2
- import { type Hex, custom } from 'viem';
2
+ import { type Hex, type PublicClient, custom } from 'viem';
3
3
  import { vi } from 'vitest';
4
4
  import { WalletKind } from '../../src';
5
5
  import type { WalletInstance } from '../../src/react/_internal/wallet/wallet';
@@ -30,6 +30,8 @@ export function createMockWallet(overrides?: Partial<MockWallet>): MockWallet {
30
30
  }),
31
31
  walletKind: WalletKind.unknown,
32
32
  hasTokenApproval: vi.fn().mockResolvedValue(true),
33
+ // @ts-expect-error
34
+ publicClient: vi.fn().mockResolvedValue({} as PublicClient),
33
35
  };
34
36
 
35
37
  return {
@@ -18,10 +18,10 @@ import {
18
18
  import { mainnet as wagmiMainet, polygon as wagmiPolygon } from 'viem/chains';
19
19
  import { http, type Config, WagmiProvider, createConfig } from 'wagmi';
20
20
  import { mock } from 'wagmi/connectors';
21
+ import { handlers as marketplaceConfigHandlers } from '../src/react/_internal/api/__mocks__/builder.msw';
21
22
  import { handlers as indexerHandlers } from '../src/react/_internal/api/__mocks__/indexer.msw';
22
23
  import { handlers as marketplaceHandlers } from '../src/react/_internal/api/__mocks__/marketplace.msw';
23
24
  import { handlers as metadataHandlers } from '../src/react/_internal/api/__mocks__/metadata.msw';
24
- import { handlers as marketplaceConfigHandlers } from '../src/react/hooks/options/__mocks__/marketplaceConfig.msw';
25
25
  import { TEST_ACCOUNTS, TEST_CHAIN, TEST_PRIVATE_KEYS } from './const';
26
26
 
27
27
  const tickHandler = mswHttp.post(