@0xsequence/marketplace-sdk 2.0.0 → 2.0.1
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 +8 -0
- package/dist/BellIcon.js +1 -1
- package/dist/Card.js +1 -1
- package/dist/ShopCard.d.ts +4 -4
- package/dist/collectible.js +2 -2
- package/dist/collectible.js.map +1 -1
- package/dist/collection.js +1 -1
- package/dist/create-config.d.ts +8 -8
- package/dist/currency.js +3 -3
- package/dist/currency.js.map +1 -1
- package/dist/expirationDateSelect.js +1 -1
- package/dist/filters.d.ts +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index10.d.ts +2 -2
- package/dist/index11.d.ts +14 -14
- package/dist/index12.d.ts +25 -25
- package/dist/index14.d.ts +2 -2
- package/dist/index16.d.ts +2 -2
- package/dist/index17.d.ts +85 -85
- package/dist/index18.d.ts +36 -36
- package/dist/index21.d.ts +14 -14
- package/dist/index22.d.ts +4 -4
- package/dist/index23.d.ts +11 -11
- package/dist/index26.d.ts +3 -3
- package/dist/index27.d.ts +3 -3
- package/dist/index28.d.ts +9 -9
- package/dist/index31.d.ts +4 -4
- package/dist/index33.d.ts +2 -2
- package/dist/index34.d.ts +3 -3
- package/dist/index36.d.ts +2 -2
- package/dist/index37.d.ts +2 -0
- package/dist/index38.d.ts +3 -3
- package/dist/index4.d.ts +458 -458
- package/dist/index40.d.ts +2 -2
- package/dist/index8.d.ts +10 -2
- package/dist/inventory.d.ts +3 -3
- package/dist/inventory.js +2 -2
- package/dist/inventory.js.map +1 -1
- package/dist/marketplace2.js +2 -2
- package/dist/marketplace2.js.map +1 -1
- package/dist/metadata.d.ts +72 -72
- package/dist/primary-sale-checkout-options.d.ts +3 -3
- package/dist/quantityInput.js +1 -1
- package/dist/ranges.d.ts +16 -16
- package/dist/react/ssr/index.d.ts +2 -2
- package/dist/react/ssr/index.js +2 -2
- package/dist/react/ui/components/marketplace-logos/index.d.ts +21 -21
- package/dist/react/ui/modals/_internal/components/baseModal/index.d.ts +6 -6
- package/dist/react/ui/modals/_internal/components/calendarDropdown/index.d.ts +2 -2
- package/dist/react/ui/modals/_internal/components/currencyImage/index.d.ts +2 -2
- package/dist/react/ui/modals/_internal/components/currencyOptionsSelect/index.d.ts +2 -2
- package/dist/react/ui/modals/_internal/components/floorPriceText/index.d.ts +2 -2
- package/dist/react/ui/modals/_internal/components/priceInput/index.d.ts +2 -4
- package/dist/react/ui/modals/_internal/components/selectWaasFeeOptions/index.d.ts +2 -2
- package/dist/react/ui/modals/_internal/components/switchChainErrorModal/index.d.ts +2 -2
- package/dist/react/ui/modals/_internal/components/timeAgo/index.d.ts +2 -2
- package/dist/react/ui/modals/_internal/components/tokenPreview/index.d.ts +2 -2
- package/dist/react/ui/modals/_internal/components/transaction-footer/index.d.ts +3 -3
- package/dist/react/ui/modals/_internal/components/transactionStatusModal/index.d.ts +2 -2
- package/dist/react.js +114 -43
- package/dist/react.js.map +1 -1
- package/dist/styles/index.css +15 -0
- package/dist/token-balances.d.ts +27 -27
- package/dist/transaction-footer.js +1 -1
- package/dist/utils/index.d.ts +2 -2
- package/dist/utils/index.js +2 -2
- package/dist/utils.js +12 -1
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/react/hooks/currency/list.test.tsx +23 -2
- package/src/react/hooks/transactions/useMarketTransactionSteps.tsx +55 -15
- package/src/react/queries/collectible/market-list.ts +5 -3
- package/src/react/queries/currency/list.ts +8 -5
- package/src/react/queries/inventory/inventory.ts +5 -3
- package/src/react/queries/marketplace/filters.ts +5 -3
- package/src/react/ui/modals/BuyModal/components/BuyModalContent.tsx +40 -6
- package/src/react/ui/modals/BuyModal/hooks/useMarketPlatformFee.ts +5 -5
- package/src/react/ui/modals/CreateListingModal/internal/store.ts +5 -2
- package/src/react/ui/modals/MakeOfferModal/internal/context.ts +20 -1
- package/src/react/ui/modals/MakeOfferModal/internal/helpers/validation.ts +16 -1
- package/src/react/ui/modals/MakeOfferModal/internal/store.ts +5 -2
- package/src/react/ui/modals/SellModal/internal/store.ts +5 -2
- package/src/react/ui/modals/_internal/components/baseModal/errors/ModalInitializationError.tsx +8 -6
- package/src/react/ui/modals/_internal/components/priceInput/index.tsx +2 -9
- package/src/react/ui/modals/_internal/components/transactionDetails/index.tsx +5 -2
- package/src/styles/styles.ts +18 -0
- package/src/utils/collection.ts +19 -0
- package/src/utils/index.ts +1 -0
|
@@ -10,12 +10,14 @@ import {
|
|
|
10
10
|
Text,
|
|
11
11
|
} from '@0xsequence/design-system';
|
|
12
12
|
import { TrailsWidget } from '0xtrails/widget';
|
|
13
|
+
import { useRef, useState } from 'react';
|
|
13
14
|
import {
|
|
14
15
|
getSequenceApiUrl,
|
|
15
16
|
getSequenceIndexerUrl,
|
|
16
17
|
getSequenceNodeGatewayUrl,
|
|
17
18
|
getTrailsApiUrl,
|
|
18
19
|
} from '../../../../_internal/api/services';
|
|
20
|
+
import { cn } from '../../../../ssr';
|
|
19
21
|
import { ModalInitializationError } from '../../_internal/components/baseModal/errors/ModalInitializationError';
|
|
20
22
|
import { MODAL_OVERLAY_PROPS } from '../../_internal/components/consts';
|
|
21
23
|
import { useBuyModalContext } from '../internal/buyModalContext';
|
|
@@ -56,12 +58,12 @@ export const BuyModalContent = () => {
|
|
|
56
58
|
if (error) {
|
|
57
59
|
return (
|
|
58
60
|
<Modal
|
|
59
|
-
isDismissible={
|
|
61
|
+
isDismissible={true}
|
|
60
62
|
onClose={close}
|
|
61
63
|
overlayProps={MODAL_OVERLAY_PROPS}
|
|
62
64
|
contentProps={{
|
|
63
65
|
style: {
|
|
64
|
-
width: '
|
|
66
|
+
width: '400px',
|
|
65
67
|
height: 'auto',
|
|
66
68
|
},
|
|
67
69
|
className: 'overflow-y-auto',
|
|
@@ -101,10 +103,7 @@ export const BuyModalContent = () => {
|
|
|
101
103
|
|
|
102
104
|
{isLoading && (
|
|
103
105
|
<div className="flex w-full items-center justify-center py-8">
|
|
104
|
-
<
|
|
105
|
-
<Spinner size="lg" />
|
|
106
|
-
<Text className="text-text-80">Loading payment options...</Text>
|
|
107
|
-
</div>
|
|
106
|
+
<ProgressiveLoadingMessage />
|
|
108
107
|
</div>
|
|
109
108
|
)}
|
|
110
109
|
|
|
@@ -159,3 +158,38 @@ export const BuyModalContent = () => {
|
|
|
159
158
|
</Dialog>
|
|
160
159
|
);
|
|
161
160
|
};
|
|
161
|
+
|
|
162
|
+
const ProgressiveLoadingMessage = () => {
|
|
163
|
+
const [showSecondaryMessage, setShowSecondaryMessage] = useState(false);
|
|
164
|
+
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
|
165
|
+
|
|
166
|
+
if (!timerRef.current) {
|
|
167
|
+
timerRef.current = setTimeout(() => {
|
|
168
|
+
setShowSecondaryMessage(true);
|
|
169
|
+
}, 3000);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<div className="flex items-center gap-4">
|
|
174
|
+
<div
|
|
175
|
+
className={cn(
|
|
176
|
+
'transition-all duration-300',
|
|
177
|
+
showSecondaryMessage ? 'h-10 w-10' : 'h-5 w-5',
|
|
178
|
+
)}
|
|
179
|
+
>
|
|
180
|
+
<Spinner className="h-full w-full transition-all duration-150" />
|
|
181
|
+
</div>
|
|
182
|
+
|
|
183
|
+
<div className="flex flex-col gap-2">
|
|
184
|
+
<p className="animate-pulse text-text-100">
|
|
185
|
+
Loading payment options...
|
|
186
|
+
</p>
|
|
187
|
+
{showSecondaryMessage && (
|
|
188
|
+
<p className="text-small text-text-50">
|
|
189
|
+
This is taking longer than expected.
|
|
190
|
+
</p>
|
|
191
|
+
)}
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
);
|
|
195
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { skipToken } from '@tanstack/react-query';
|
|
2
2
|
import { avalanche, optimism } from 'viem/chains';
|
|
3
|
-
import {
|
|
3
|
+
import { findMarketCollection } from '../../../../../utils';
|
|
4
4
|
import type { AdditionalFee } from '../../../../_internal';
|
|
5
5
|
import { useMarketplaceConfig } from '../../../../hooks';
|
|
6
6
|
|
|
@@ -28,10 +28,10 @@ export const useMarketPlatformFee = (params: FeesParams | typeof skipToken) => {
|
|
|
28
28
|
const { chainId, collectionAddress } = params;
|
|
29
29
|
|
|
30
30
|
// Find collection in market collections only (not shop collections)
|
|
31
|
-
const marketCollection =
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
const marketCollection = findMarketCollection(
|
|
32
|
+
marketplaceConfig?.market?.collections ?? [],
|
|
33
|
+
collectionAddress,
|
|
34
|
+
chainId,
|
|
35
35
|
);
|
|
36
36
|
|
|
37
37
|
const avalancheOrOptimism =
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Address } from '@0xsequence/api-client';
|
|
2
2
|
import { createStore } from '@xstate/store';
|
|
3
3
|
import { useSelector } from '@xstate/store/react';
|
|
4
|
+
import { findMarketCollection } from '../../../../../utils';
|
|
4
5
|
import { useMarketplaceConfig } from '../../../hooks';
|
|
5
6
|
|
|
6
7
|
export type OpenCreateListingModalArgs = {
|
|
@@ -109,8 +110,10 @@ export const useCreateListingModalState = () => {
|
|
|
109
110
|
} = useSelector(createListingModalStore, (state) => state.context);
|
|
110
111
|
|
|
111
112
|
const { data: marketplaceConfig } = useMarketplaceConfig();
|
|
112
|
-
const orderbookKind =
|
|
113
|
-
|
|
113
|
+
const orderbookKind = findMarketCollection(
|
|
114
|
+
marketplaceConfig?.market.collections ?? [],
|
|
115
|
+
collectionAddress,
|
|
116
|
+
chainId,
|
|
114
117
|
)?.destinationMarketplace;
|
|
115
118
|
|
|
116
119
|
const closeModal = () => createListingModalStore.send({ type: 'close' });
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
useCollectionMetadata,
|
|
12
12
|
useConfig,
|
|
13
13
|
useConnectorMetadata,
|
|
14
|
+
useCurrencyConvertToUSD,
|
|
14
15
|
useCurrencyList,
|
|
15
16
|
useTokenCurrencyBalance,
|
|
16
17
|
} from '../../../../hooks';
|
|
@@ -106,6 +107,18 @@ export function useMakeOfferModalContext() {
|
|
|
106
107
|
},
|
|
107
108
|
});
|
|
108
109
|
|
|
110
|
+
const { data: usdConversion } = useCurrencyConvertToUSD({
|
|
111
|
+
chainId: state.chainId,
|
|
112
|
+
currencyAddress: selectedCurrency?.contractAddress ?? zeroAddress,
|
|
113
|
+
amountRaw: state.priceInput?.toString(),
|
|
114
|
+
query: {
|
|
115
|
+
enabled:
|
|
116
|
+
state.orderbookKind === OrderbookKind.opensea &&
|
|
117
|
+
!!selectedCurrency?.contractAddress &&
|
|
118
|
+
!!state.priceInput,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
109
122
|
const expiryDate = useMemo(
|
|
110
123
|
() => new Date(Date.now() + state.expiryDays * 24 * 60 * 60 * 1000),
|
|
111
124
|
[state.expiryDays],
|
|
@@ -139,6 +152,7 @@ export function useMakeOfferModalContext() {
|
|
|
139
152
|
balance: balanceDnum,
|
|
140
153
|
lowestListing: lowestListingDnum,
|
|
141
154
|
orderbookKind: state.orderbookKind,
|
|
155
|
+
usdAmount: usdConversion?.usdAmount,
|
|
142
156
|
});
|
|
143
157
|
|
|
144
158
|
const formIsValid = isFormValid(validation);
|
|
@@ -359,6 +373,7 @@ export function useMakeOfferModalContext() {
|
|
|
359
373
|
quantity: validation.quantity,
|
|
360
374
|
balance: validation.balance,
|
|
361
375
|
openseaCriteria: validation.openseaCriteria,
|
|
376
|
+
openseaMinPrice: validation.openseaMinPrice,
|
|
362
377
|
},
|
|
363
378
|
errors: {
|
|
364
379
|
price: state.isPriceTouched ? validation.price.error : undefined,
|
|
@@ -369,6 +384,9 @@ export function useMakeOfferModalContext() {
|
|
|
369
384
|
openseaCriteria: state.isPriceTouched
|
|
370
385
|
? validation.openseaCriteria?.error
|
|
371
386
|
: undefined,
|
|
387
|
+
openseaMinPrice: state.isPriceTouched
|
|
388
|
+
? validation.openseaMinPrice?.error
|
|
389
|
+
: undefined,
|
|
372
390
|
},
|
|
373
391
|
},
|
|
374
392
|
|
|
@@ -415,7 +433,8 @@ export function useMakeOfferModalContext() {
|
|
|
415
433
|
this.form.errors.price ||
|
|
416
434
|
this.form.errors.quantity ||
|
|
417
435
|
this.form.errors.balance ||
|
|
418
|
-
this.form.errors.openseaCriteria
|
|
436
|
+
this.form.errors.openseaCriteria ||
|
|
437
|
+
this.form.errors.openseaMinPrice
|
|
419
438
|
);
|
|
420
439
|
},
|
|
421
440
|
|
|
@@ -11,6 +11,7 @@ export type OfferValidation = {
|
|
|
11
11
|
quantity: FieldValidation;
|
|
12
12
|
balance: FieldValidation;
|
|
13
13
|
openseaCriteria?: FieldValidation;
|
|
14
|
+
openseaMinPrice?: FieldValidation;
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
export function validateOfferForm({
|
|
@@ -19,12 +20,14 @@ export function validateOfferForm({
|
|
|
19
20
|
balance,
|
|
20
21
|
lowestListing,
|
|
21
22
|
orderbookKind,
|
|
23
|
+
usdAmount,
|
|
22
24
|
}: {
|
|
23
25
|
price: Dnum;
|
|
24
26
|
quantity: Dnum;
|
|
25
27
|
balance?: Dnum;
|
|
26
28
|
lowestListing?: Dnum;
|
|
27
29
|
orderbookKind?: string;
|
|
30
|
+
usdAmount?: number;
|
|
28
31
|
}): OfferValidation {
|
|
29
32
|
const validation: OfferValidation = {
|
|
30
33
|
price: { isValid: true, error: null },
|
|
@@ -67,6 +70,15 @@ export function validateOfferForm({
|
|
|
67
70
|
};
|
|
68
71
|
}
|
|
69
72
|
|
|
73
|
+
// OpenSea minimum price validation ($0.01 USD)
|
|
74
|
+
if (orderbookKind === 'opensea' && usdAmount !== undefined) {
|
|
75
|
+
const meetsMinPrice = usdAmount >= 0.01;
|
|
76
|
+
validation.openseaMinPrice = {
|
|
77
|
+
isValid: meetsMinPrice,
|
|
78
|
+
error: meetsMinPrice ? null : 'Lowest price must be at least $0.01',
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
70
82
|
return validation;
|
|
71
83
|
}
|
|
72
84
|
|
|
@@ -75,7 +87,8 @@ export function isFormValid(validation: OfferValidation): boolean {
|
|
|
75
87
|
validation.price.isValid &&
|
|
76
88
|
validation.quantity.isValid &&
|
|
77
89
|
validation.balance.isValid &&
|
|
78
|
-
(validation.openseaCriteria?.isValid ?? true)
|
|
90
|
+
(validation.openseaCriteria?.isValid ?? true) &&
|
|
91
|
+
(validation.openseaMinPrice?.isValid ?? true)
|
|
79
92
|
);
|
|
80
93
|
}
|
|
81
94
|
|
|
@@ -87,6 +100,8 @@ export function getValidationErrors(validation: OfferValidation): string[] {
|
|
|
87
100
|
if (validation.balance.error) errors.push(validation.balance.error);
|
|
88
101
|
if (validation.openseaCriteria?.error)
|
|
89
102
|
errors.push(validation.openseaCriteria.error);
|
|
103
|
+
if (validation.openseaMinPrice?.error)
|
|
104
|
+
errors.push(validation.openseaMinPrice.error);
|
|
90
105
|
|
|
91
106
|
return errors;
|
|
92
107
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Address } from '@0xsequence/api-client';
|
|
2
2
|
import { createStore } from '@xstate/store';
|
|
3
3
|
import { useSelector } from '@xstate/store/react';
|
|
4
|
+
import { findMarketCollection } from '../../../../../utils';
|
|
4
5
|
import { useMarketplaceConfig } from '../../../hooks';
|
|
5
6
|
|
|
6
7
|
export type OpenMakeOfferModalArgs = {
|
|
@@ -109,8 +110,10 @@ export const useMakeOfferModalState = () => {
|
|
|
109
110
|
} = useSelector(makeOfferModalStore, (state) => state.context);
|
|
110
111
|
|
|
111
112
|
const { data: marketplaceConfig } = useMarketplaceConfig();
|
|
112
|
-
const orderbookKind =
|
|
113
|
-
|
|
113
|
+
const orderbookKind = findMarketCollection(
|
|
114
|
+
marketplaceConfig?.market.collections ?? [],
|
|
115
|
+
collectionAddress,
|
|
116
|
+
chainId,
|
|
114
117
|
)?.destinationMarketplace;
|
|
115
118
|
|
|
116
119
|
const closeModal = () => makeOfferModalStore.send({ type: 'close' });
|
|
@@ -2,6 +2,7 @@ import type { Address } from '@0xsequence/api-client';
|
|
|
2
2
|
import { createStore } from '@xstate/store';
|
|
3
3
|
import { useSelector } from '@xstate/store/react';
|
|
4
4
|
import { zeroAddress } from 'viem';
|
|
5
|
+
import { findMarketCollection } from '../../../../../utils';
|
|
5
6
|
import type { Order } from '../../../../_internal';
|
|
6
7
|
import { useMarketplaceConfig } from '../../../hooks';
|
|
7
8
|
|
|
@@ -56,8 +57,10 @@ export const useSellModalState = () => {
|
|
|
56
57
|
);
|
|
57
58
|
|
|
58
59
|
const { data: marketplaceConfig } = useMarketplaceConfig();
|
|
59
|
-
const orderbookKind =
|
|
60
|
-
|
|
60
|
+
const orderbookKind = findMarketCollection(
|
|
61
|
+
marketplaceConfig?.market.collections ?? [],
|
|
62
|
+
collectionAddress,
|
|
63
|
+
chainId,
|
|
61
64
|
)?.destinationMarketplace;
|
|
62
65
|
|
|
63
66
|
const closeModal = () => sellModalStore.send({ type: 'close' });
|
package/src/react/ui/modals/_internal/components/baseModal/errors/ModalInitializationError.tsx
CHANGED
|
@@ -17,7 +17,7 @@ export const ModalInitializationError = ({
|
|
|
17
17
|
const [showTechnicalDetails, setShowTechnicalDetails] = useState(false);
|
|
18
18
|
|
|
19
19
|
return (
|
|
20
|
-
<div className="flex min-h-[400px] flex-col items-center justify-center p-
|
|
20
|
+
<div className="flex min-h-[400px] flex-col items-center justify-center p-6 text-white">
|
|
21
21
|
<div className="mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-red-500">
|
|
22
22
|
<WarningIcon className="h-8 w-8 text-white" />
|
|
23
23
|
</div>
|
|
@@ -29,7 +29,7 @@ export const ModalInitializationError = ({
|
|
|
29
29
|
refresh the page.
|
|
30
30
|
</p>
|
|
31
31
|
|
|
32
|
-
{error.
|
|
32
|
+
{(error.cause as string) && (
|
|
33
33
|
<button
|
|
34
34
|
type="button"
|
|
35
35
|
onClick={() => setShowTechnicalDetails(!showTechnicalDetails)}
|
|
@@ -50,19 +50,21 @@ export const ModalInitializationError = ({
|
|
|
50
50
|
d="M19 9l-7 7-7-7"
|
|
51
51
|
/>
|
|
52
52
|
</svg>
|
|
53
|
-
|
|
53
|
+
{showTechnicalDetails
|
|
54
|
+
? 'Hide technical details'
|
|
55
|
+
: 'Show technical details'}
|
|
54
56
|
</button>
|
|
55
57
|
)}
|
|
56
58
|
|
|
57
|
-
{showTechnicalDetails && error.
|
|
59
|
+
{showTechnicalDetails && (error.cause as string) && (
|
|
58
60
|
<div className="mb-8 max-h-64 w-full max-w-md overflow-y-auto rounded-lg border border-red-900 bg-[#2b0000] p-4">
|
|
59
61
|
<pre className="whitespace-pre-wrap break-words text-red-100 text-xs">
|
|
60
|
-
{error.
|
|
62
|
+
{error.cause as string}
|
|
61
63
|
</pre>
|
|
62
64
|
</div>
|
|
63
65
|
)}
|
|
64
66
|
|
|
65
|
-
<div className="flex w-full
|
|
67
|
+
<div className="flex w-full flex-col space-y-3">
|
|
66
68
|
{onTryAgain && (
|
|
67
69
|
<Button
|
|
68
70
|
onClick={onTryAgain}
|
|
@@ -36,7 +36,6 @@ type PriceInputProps = {
|
|
|
36
36
|
};
|
|
37
37
|
disabled?: boolean;
|
|
38
38
|
orderbookKind?: OrderbookKind;
|
|
39
|
-
setOpenseaLowestPriceCriteriaMet?: (state: boolean) => void;
|
|
40
39
|
modalType?: 'listing' | 'offer';
|
|
41
40
|
// Fee data for enhanced balance checking in offers
|
|
42
41
|
feeData?: {
|
|
@@ -55,7 +54,6 @@ export default function PriceInput({
|
|
|
55
54
|
includeNativeCurrency,
|
|
56
55
|
disabled,
|
|
57
56
|
orderbookKind,
|
|
58
|
-
setOpenseaLowestPriceCriteriaMet,
|
|
59
57
|
modalType,
|
|
60
58
|
feeData,
|
|
61
59
|
}: PriceInputProps) {
|
|
@@ -81,8 +79,7 @@ export default function PriceInput({
|
|
|
81
79
|
enabled:
|
|
82
80
|
orderbookKind === OrderbookKind.opensea &&
|
|
83
81
|
!!currencyAddress &&
|
|
84
|
-
!!priceAmountRaw
|
|
85
|
-
!!setOpenseaLowestPriceCriteriaMet,
|
|
82
|
+
!!priceAmountRaw,
|
|
86
83
|
},
|
|
87
84
|
});
|
|
88
85
|
|
|
@@ -164,17 +161,13 @@ export default function PriceInput({
|
|
|
164
161
|
|
|
165
162
|
const openseaLowestPriceCriteriaMet =
|
|
166
163
|
orderbookKind === OrderbookKind.opensea &&
|
|
167
|
-
|
|
164
|
+
conversion?.usdAmount !== undefined &&
|
|
168
165
|
conversion.usdAmount >= 0.01;
|
|
169
166
|
|
|
170
167
|
if (checkBalance?.enabled) {
|
|
171
168
|
checkBalance.callback(balanceError);
|
|
172
169
|
}
|
|
173
170
|
|
|
174
|
-
if (setOpenseaLowestPriceCriteriaMet) {
|
|
175
|
-
setOpenseaLowestPriceCriteriaMet(openseaLowestPriceCriteriaMet);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
171
|
const [value, setValue] = useState('0');
|
|
179
172
|
const prevCurrencyDecimals = useRef(currencyDecimals);
|
|
180
173
|
const [openseaDecimalError, setOpenseaDecimalError] = useState<string | null>(
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import { useEffect, useState } from 'react';
|
|
12
12
|
import { DEFAULT_MARKETPLACE_FEE_PERCENTAGE } from '../../../../../../consts';
|
|
13
13
|
import type { Price } from '../../../../../../types';
|
|
14
|
+
import { findMarketCollection } from '../../../../../../utils';
|
|
14
15
|
import { calculateEarningsAfterFees } from '../../../../../../utils/price';
|
|
15
16
|
import { useMarketplaceConfig, useRoyalty } from '../../../../../hooks';
|
|
16
17
|
|
|
@@ -37,8 +38,10 @@ export default function TransactionDetails({
|
|
|
37
38
|
const { data, isLoading: marketplaceConfigLoading } = useMarketplaceConfig();
|
|
38
39
|
|
|
39
40
|
const marketplaceFeePercentage = includeMarketplaceFee
|
|
40
|
-
?
|
|
41
|
-
|
|
41
|
+
? findMarketCollection(
|
|
42
|
+
data?.market.collections ?? [],
|
|
43
|
+
collectionAddress,
|
|
44
|
+
chainId,
|
|
42
45
|
)?.feePercentage || DEFAULT_MARKETPLACE_FEE_PERCENTAGE
|
|
43
46
|
: 0;
|
|
44
47
|
// royaltyPercentage is an array of [recipient, percentage]
|
package/src/styles/styles.ts
CHANGED
|
@@ -1855,6 +1855,17 @@ export const styles = String.raw`/* Modified Tailwind CSS, to avoid issues with
|
|
|
1855
1855
|
--tw-tracking: var(--tracking-normal);
|
|
1856
1856
|
letter-spacing: var(--tracking-normal);
|
|
1857
1857
|
}
|
|
1858
|
+
.text-small {
|
|
1859
|
+
font-family: "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
1860
|
+
font-size: var(--text-xs);
|
|
1861
|
+
line-height: var(--tw-leading, var(--text-xs--line-height));
|
|
1862
|
+
--tw-leading: calc(var(--spacing) * 4);
|
|
1863
|
+
line-height: calc(var(--spacing) * 4);
|
|
1864
|
+
--tw-font-weight: var(--font-weight-medium);
|
|
1865
|
+
font-weight: var(--font-weight-medium);
|
|
1866
|
+
--tw-tracking: var(--tracking-wide);
|
|
1867
|
+
letter-spacing: var(--tracking-wide);
|
|
1868
|
+
}
|
|
1858
1869
|
.font-body {
|
|
1859
1870
|
font-family: "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
1860
1871
|
}
|
|
@@ -1985,6 +1996,9 @@ export const styles = String.raw`/* Modified Tailwind CSS, to avoid issues with
|
|
|
1985
1996
|
.break-words {
|
|
1986
1997
|
overflow-wrap: break-word;
|
|
1987
1998
|
}
|
|
1999
|
+
.wrap-anywhere {
|
|
2000
|
+
overflow-wrap: anywhere;
|
|
2001
|
+
}
|
|
1988
2002
|
.text-ellipsis {
|
|
1989
2003
|
text-overflow: ellipsis;
|
|
1990
2004
|
}
|
|
@@ -2313,6 +2327,10 @@ export const styles = String.raw`/* Modified Tailwind CSS, to avoid issues with
|
|
|
2313
2327
|
--tw-duration: 100ms;
|
|
2314
2328
|
transition-duration: 100ms;
|
|
2315
2329
|
}
|
|
2330
|
+
.duration-150 {
|
|
2331
|
+
--tw-duration: 150ms;
|
|
2332
|
+
transition-duration: 150ms;
|
|
2333
|
+
}
|
|
2316
2334
|
.duration-200 {
|
|
2317
2335
|
--tw-duration: 200ms;
|
|
2318
2336
|
transition-duration: 200ms;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MarketCollection } from '@0xsequence/api-client';
|
|
2
|
+
import { compareAddress } from './address';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Finds a market collection matching both the collection address and chain ID.
|
|
6
|
+
* Always use this instead of manually searching market.collections to avoid
|
|
7
|
+
* multi-chain bugs where the same collection address exists on different chains.
|
|
8
|
+
*/
|
|
9
|
+
export const findMarketCollection = (
|
|
10
|
+
collections: MarketCollection[],
|
|
11
|
+
collectionAddress: string,
|
|
12
|
+
chainId: string | number,
|
|
13
|
+
): MarketCollection | undefined => {
|
|
14
|
+
return collections.find(
|
|
15
|
+
(collection) =>
|
|
16
|
+
compareAddress(collection.itemsAddress, collectionAddress) &&
|
|
17
|
+
Number(collection.chainId) === Number(chainId),
|
|
18
|
+
);
|
|
19
|
+
};
|