@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.
- package/CHANGELOG.md +32 -0
- package/dist/chunk-2PSNAIAT.js +1 -0
- package/dist/chunk-2PSNAIAT.js.map +1 -0
- package/dist/{chunk-WXKV5N4T.js → chunk-35WWD5V6.js} +3 -3
- package/dist/{chunk-ZSCZLHKX.js → chunk-4XLXOEXQ.js} +2 -2
- package/dist/{chunk-TGFX3TMV.js → chunk-7IYKUVC3.js} +314 -147
- package/dist/chunk-7IYKUVC3.js.map +1 -0
- package/dist/{chunk-BB2PTJHI.js → chunk-D7RVSZAQ.js} +131 -83
- package/dist/chunk-D7RVSZAQ.js.map +1 -0
- package/dist/chunk-DWTLVJAW.js +42 -0
- package/dist/chunk-DWTLVJAW.js.map +1 -0
- package/dist/{chunk-SJU6QZHM.js → chunk-EODKQL6Y.js} +2 -2
- package/dist/{chunk-6SEJI7YS.js → chunk-G3447GIP.js} +39 -20
- package/dist/chunk-G3447GIP.js.map +1 -0
- package/dist/{chunk-QMWMJVTX.js → chunk-HHYNOPPI.js} +2 -2
- package/dist/{chunk-ALICO7NG.js → chunk-KGM2WLSP.js} +15 -158
- package/dist/chunk-KGM2WLSP.js.map +1 -0
- package/dist/chunk-MAD64DLJ.js +81 -0
- package/dist/chunk-MAD64DLJ.js.map +1 -0
- package/dist/chunk-N7BPFK46.js +1 -0
- package/dist/chunk-N7BPFK46.js.map +1 -0
- package/dist/chunk-NX52D7NX.js +135 -0
- package/dist/chunk-NX52D7NX.js.map +1 -0
- package/dist/chunk-O34GCB47.js +32 -0
- package/dist/chunk-O34GCB47.js.map +1 -0
- package/dist/{chunk-LDZZUYG7.js → chunk-YALXP2PW.js} +3 -3
- package/dist/{chunk-V3NVAVHV.js → chunk-YBOFRP65.js} +2 -2
- package/dist/{chunk-BGY4WXER.js → chunk-YEGD7PWE.js} +3 -2
- package/dist/{chunk-BGY4WXER.js.map → chunk-YEGD7PWE.js.map} +1 -1
- package/dist/{create-config-qDML4ZNn.d.ts → create-config-DwrnzwpM.d.ts} +2 -2
- package/dist/{index-DtWR0b_l.d.ts → index-DGsVBflk.d.ts} +3 -12
- package/dist/index.css +7 -5
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +13 -4
- package/dist/index.js +14 -6
- package/dist/{lowestListing-W7P4EkC3.d.ts → lowestListing-BQHIuvNF.d.ts} +2 -2
- package/dist/{marketplace.gen-DS-MmGEB.d.ts → marketplace.gen-DQzWciwC.d.ts} +5 -4
- package/dist/marketplaceConfig-B4Fdsmxu.d.ts +17 -0
- package/dist/react/_internal/api/index.d.ts +3 -3
- package/dist/react/_internal/api/index.js +4 -3
- package/dist/react/_internal/databeat/index.d.ts +2 -1
- package/dist/react/_internal/databeat/index.js +13 -9
- package/dist/react/_internal/index.d.ts +6 -6
- package/dist/react/_internal/index.js +13 -10
- package/dist/react/_internal/wagmi/index.d.ts +6 -5
- package/dist/react/_internal/wagmi/index.js +2 -2
- package/dist/react/hooks/index.d.ts +9 -8
- package/dist/react/hooks/index.js +12 -8
- package/dist/react/hooks/options/index.d.ts +4 -4
- package/dist/react/hooks/options/index.js +7 -4
- package/dist/react/index.css +2650 -0
- package/dist/react/index.css.map +1 -1
- package/dist/react/index.d.ts +8 -8
- package/dist/react/index.js +19 -14
- package/dist/react/queries/index.d.ts +3 -3
- package/dist/react/queries/index.js +6 -3
- package/dist/react/ssr/index.d.ts +3 -3
- package/dist/react/ssr/index.js +6 -3
- package/dist/react/ssr/index.js.map +1 -1
- package/dist/react/ui/components/collectible-card/index.css +2650 -0
- package/dist/react/ui/components/collectible-card/index.css.map +1 -1
- package/dist/react/ui/components/collectible-card/index.d.ts +1 -1
- package/dist/react/ui/components/collectible-card/index.js +17 -12
- package/dist/react/ui/icons/index.js +8 -5
- package/dist/react/ui/index.css +2650 -0
- package/dist/react/ui/index.css.map +1 -1
- package/dist/react/ui/index.d.ts +2 -1
- package/dist/react/ui/index.js +17 -12
- package/dist/react/ui/modals/_internal/components/actionModal/index.js +13 -9
- package/dist/sdk-config-txlivEKe.d.ts +133 -0
- package/dist/{services-BOX67E7W.d.ts → services-BI_w8Eq4.d.ts} +4 -4
- package/dist/types/index.d.ts +5 -4
- package/dist/types/index.js +9 -6
- package/dist/{types-CJLhc2VZ.d.ts → types-isjvwapz.d.ts} +3 -3
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +6 -3
- package/package.json +3 -3
- package/src/index.ts +1 -0
- package/src/react/{hooks/options/__mocks__/marketplaceConfig.msw.ts → _internal/api/__mocks__/builder.msw.ts} +70 -63
- package/src/react/_internal/api/__mocks__/metadata.msw.ts +30 -10
- package/src/react/_internal/api/builder-api.ts +32 -0
- package/src/react/_internal/api/builder.gen.ts +215 -0
- package/src/react/_internal/api/marketplace.gen.ts +6 -6
- package/src/react/_internal/api/services.ts +9 -2
- package/src/react/_internal/databeat/types.ts +1 -0
- package/src/react/_internal/wagmi/__tests__/create-config.test.ts +16 -41
- package/src/react/_internal/wagmi/create-config.ts +3 -16
- package/src/react/_internal/wagmi/get-connectors.ts +31 -21
- package/src/react/_internal/wallet/__tests__/wallet.test.ts +30 -0
- package/src/react/_internal/wallet/wallet.ts +25 -2
- package/src/react/hooks/__tests__/__snapshots__/useMarketplaceConfig.test.tsx.snap +96 -0
- package/src/react/hooks/__tests__/useCollection.test.tsx +4 -5
- package/src/react/hooks/__tests__/useCurrencies.test.tsx +1 -1
- package/src/react/hooks/__tests__/useInventory.test.tsx +15 -16
- package/src/react/hooks/__tests__/useListCollections.test.tsx +18 -163
- package/src/react/hooks/__tests__/useMarketplaceConfig.test.tsx +10 -11
- package/src/react/hooks/options/index.ts +1 -1
- package/src/react/hooks/useAutoSelectFeeOption.tsx +1 -0
- package/src/react/hooks/useMarketplaceConfig.tsx +2 -2
- package/src/react/queries/marketplaceConfig.ts +101 -0
- package/src/react/ssr/__tests__/__snapshots__/create-ssr-client.test.ts.snap +1 -0
- package/src/react/ssr/create-ssr-client.ts +1 -1
- package/src/react/ui/components/collectible-card/CollectibleCard.tsx +2 -2
- package/src/react/ui/components/collectible-card/__tests__/CollectibleAsset.test.tsx +72 -42
- package/src/react/ui/components/collectible-card/{CollectibleAsset.tsx → collectible-asset/CollectibleAsset.tsx} +44 -44
- package/src/react/ui/components/collectible-card/collectible-asset/CollectibleAssetSkeleton.tsx +14 -0
- package/src/react/ui/components/collectible-card/collectible-asset/utils.ts +36 -0
- package/src/react/ui/modals/BuyModal/hooks/usePaymentModalParams.ts +6 -1
- package/src/react/ui/modals/BuyModal/store.ts +1 -0
- package/src/react/ui/modals/CreateListingModal/hooks/useTransactionSteps.tsx +20 -2
- package/src/react/ui/modals/MakeOfferModal/hooks/useTransactionSteps.tsx +17 -1
- package/src/react/ui/modals/SellModal/hooks/useTransactionSteps.tsx +4 -0
- package/src/react/ui/modals/_internal/components/actionModal/ActionModal.test.tsx +7 -1
- package/src/types/index.ts +7 -1
- package/src/types/sdk-config.ts +4 -9
- package/src/utils/fetchContentType.ts +101 -0
- package/src/utils/getMarketplaceDetails.ts +2 -1
- package/src/utils/getSequenceMarketRequestId.ts +32 -0
- package/test/mocks/wallet.ts +3 -1
- package/test/test-utils.tsx +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/builder-types-BY6eD6vD.d.ts +0 -82
- package/dist/chunk-6SEJI7YS.js.map +0 -1
- package/dist/chunk-ALICO7NG.js.map +0 -1
- package/dist/chunk-BB2PTJHI.js.map +0 -1
- package/dist/chunk-HGKWWZWY.js +0 -58
- package/dist/chunk-HGKWWZWY.js.map +0 -1
- package/dist/chunk-TGFX3TMV.js.map +0 -1
- package/dist/sdk-config-DIzJk_tI.d.ts +0 -26
- package/src/react/hooks/options/__tests__/marketplaceConfigOptions.test.tsx +0 -134
- package/src/react/hooks/options/marketplaceConfigOptions.ts +0 -71
- package/src/types/builder-types.ts +0 -88
- /package/dist/{chunk-WXKV5N4T.js.map → chunk-35WWD5V6.js.map} +0 -0
- /package/dist/{chunk-ZSCZLHKX.js.map → chunk-4XLXOEXQ.js.map} +0 -0
- /package/dist/{chunk-SJU6QZHM.js.map → chunk-EODKQL6Y.js.map} +0 -0
- /package/dist/{chunk-QMWMJVTX.js.map → chunk-HHYNOPPI.js.map} +0 -0
- /package/dist/{chunk-LDZZUYG7.js.map → chunk-YALXP2PW.js.map} +0 -0
- /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 '
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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 (
|
|
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 (
|
|
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={
|
|
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)}
|
package/src/react/ui/components/collectible-card/collectible-asset/CollectibleAssetSkeleton.tsx
ADDED
|
@@ -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
|
-
|
|
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
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Observable } from '@legendapp/state';
|
|
2
2
|
import { type Address, type Hex, formatUnits } from 'viem';
|
|
3
|
-
import
|
|
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,
|
package/src/types/index.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
export * from './api-types';
|
|
2
2
|
export * from './sdk-config';
|
|
3
3
|
export * from './types';
|
|
4
|
-
export * from '
|
|
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';
|
package/src/types/sdk-config.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
+
};
|
package/test/mocks/wallet.ts
CHANGED
|
@@ -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 {
|
package/test/test-utils.tsx
CHANGED
|
@@ -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(
|