@0xsequence/marketplace-sdk 0.7.0 → 0.8.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/.changeset/README.md +8 -0
- package/.changeset/config.json +11 -0
- package/.changeset/seven-doors-taste.md +5 -0
- package/CHANGELOG.md +13 -0
- package/dist/{chunk-MPBN3E54.js → chunk-2VHHJNXY.js} +3 -3
- package/dist/{chunk-FBUMNJQ4.js → chunk-3II5GLHE.js} +2 -2
- package/dist/chunk-3JU7SQVE.js +182 -0
- package/dist/chunk-3JU7SQVE.js.map +1 -0
- package/dist/{chunk-XTGMMNV5.js → chunk-A5ACY5YV.js} +2 -2
- package/dist/chunk-ABSYNRT5.js +128 -0
- package/dist/chunk-ABSYNRT5.js.map +1 -0
- package/dist/{chunk-XNA64MZQ.js → chunk-BCO4CYE4.js} +2 -2
- package/dist/{chunk-HTFORA4Q.js → chunk-BN36GABQ.js} +1883 -1010
- package/dist/chunk-BN36GABQ.js.map +1 -0
- package/dist/{chunk-4XK7XNJ7.js → chunk-BNAUZXPV.js} +73 -2
- package/dist/chunk-BNAUZXPV.js.map +1 -0
- package/dist/{chunk-Q5URKSC4.js → chunk-FMEEJFAF.js} +1 -1
- package/dist/{chunk-BBASZVT3.js → chunk-GBQVYNCD.js} +5 -6
- package/dist/chunk-GBQVYNCD.js.map +1 -0
- package/dist/{chunk-3AKOPSON.js → chunk-IZ44XPBH.js} +2 -9
- package/dist/chunk-IZ44XPBH.js.map +1 -0
- package/dist/{chunk-EAJ5K7QV.js → chunk-Q5RKAMYF.js} +3 -4
- package/dist/chunk-Q5RKAMYF.js.map +1 -0
- package/dist/{chunk-RBEPPVLT.js → chunk-X3QNSQER.js} +145 -355
- package/dist/chunk-X3QNSQER.js.map +1 -0
- package/dist/{index-CzTANLaA.d.ts → index-CnaFSNE9.d.ts} +6 -7
- package/dist/index.css +113 -31
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +2 -4
- package/dist/index.js +4 -4
- package/dist/listCollectibles-B0tbqnRd.d.ts +155 -0
- package/dist/react/_internal/api/index.d.ts +28 -2
- package/dist/react/_internal/api/index.js +3 -1
- package/dist/react/_internal/databeat/index.js +10 -9
- package/dist/react/_internal/index.d.ts +2 -3
- package/dist/react/_internal/index.js +4 -4
- package/dist/react/_internal/wagmi/index.js +2 -2
- package/dist/react/hooks/index.d.ts +259 -674
- package/dist/react/hooks/index.js +11 -20
- package/dist/react/hooks/options/index.d.ts +1 -2
- package/dist/react/hooks/options/index.js +4 -4
- package/dist/react/index.d.ts +7 -7
- package/dist/react/index.js +15 -24
- package/dist/react/queries/index.d.ts +25 -0
- package/dist/react/queries/index.js +48 -0
- package/dist/react/queries/index.js.map +1 -0
- package/dist/react/ssr/index.js +3 -3
- package/dist/react/ui/components/collectible-card/index.d.ts +1 -6
- package/dist/react/ui/components/collectible-card/index.js +13 -12
- package/dist/react/ui/components/marketplace-logos/index.js +1 -1
- package/dist/react/ui/icons/index.js +6 -6
- package/dist/react/ui/index.d.ts +18 -22
- package/dist/react/ui/index.js +13 -12
- package/dist/react/ui/modals/_internal/components/actionModal/index.d.ts +6 -11
- package/dist/react/ui/modals/_internal/components/actionModal/index.js +10 -9
- package/dist/types/index.js +2 -2
- package/dist/{types-Ct1uCT3M.d.ts → types-o_pKUpQG.d.ts} +2 -5
- package/dist/utils/index.d.ts +1 -5
- package/dist/utils/index.js +4 -4
- package/package.json +22 -16
- package/src/react/_internal/api/__mocks__/indexer.msw.ts +3 -1
- package/src/react/_internal/api/__mocks__/marketplace.msw.ts +1 -1
- package/src/react/_internal/api/__mocks__/metadata.msw.ts +14 -12
- package/src/react/_internal/api/index.ts +1 -0
- package/src/react/_internal/api/laos-api.ts +103 -0
- package/src/react/_internal/api/zod-schema.ts +3 -3
- package/src/react/_internal/types.ts +1 -10
- package/src/react/_internal/wallet/__tests__/wallet.test.ts +43 -0
- package/src/react/_internal/wallet/useWallet.ts +6 -3
- package/src/react/hooks/__tests__/useAutoSelectFeeOption.test.tsx +1 -1
- package/src/react/hooks/__tests__/useCancelOrder.test.tsx +1 -1
- package/src/react/hooks/__tests__/useCancelTransactionSteps.test.tsx +1 -1
- package/src/react/hooks/__tests__/useCollectible.test.tsx +2 -2
- package/src/react/hooks/__tests__/useCollection.test.tsx +2 -2
- package/src/react/hooks/__tests__/useComparePrices.test.tsx +1 -1
- package/src/react/hooks/__tests__/useConvertPriceToUSD.test.tsx +1 -1
- package/src/react/hooks/__tests__/useCountListingsForCollectible.test.tsx +1 -1
- package/src/react/hooks/__tests__/useCountOfCollectables.test.tsx +2 -2
- package/src/react/hooks/__tests__/useCountOffersForCollectible.test.tsx +1 -1
- package/src/react/hooks/__tests__/useCurrencies.test.tsx +2 -2
- package/src/react/hooks/__tests__/useCurrency.test.tsx +2 -2
- package/src/react/hooks/__tests__/useFilters.test.tsx +2 -2
- package/src/react/hooks/__tests__/useFloorOrder.test.tsx +2 -2
- package/src/react/hooks/__tests__/useGenerateCancelTransaction.test.tsx +1 -1
- package/src/react/hooks/__tests__/useGenerateListingTransaction.test.tsx +1 -1
- package/src/react/hooks/__tests__/useGenerateOfferTransaction.test.tsx +1 -1
- package/src/react/hooks/__tests__/useGenerateSellTransaction.test.tsx +1 -1
- package/src/react/hooks/__tests__/useListCollectibleActivities.test.tsx +2 -2
- package/src/react/hooks/__tests__/useListCollectibles.test.tsx +3 -2
- package/src/react/hooks/__tests__/useListCollectiblesPaginated.test.tsx +1 -1
- package/src/react/hooks/__tests__/useListCollectionActivities.test.tsx +1 -1
- package/src/react/hooks/__tests__/useListListingsForCollectible.test.tsx +1 -1
- package/src/react/hooks/__tests__/useListOffersForCollectible.test.tsx +1 -1
- package/src/react/hooks/__tests__/useLowestListing.test.tsx +1 -1
- package/src/react/hooks/__tests__/useRoyalty.test.tsx +1 -2
- package/src/react/hooks/index.ts +0 -1
- package/src/react/hooks/options/collectionOptions.ts +2 -3
- package/src/react/hooks/useAutoSelectFeeOption.tsx +1 -1
- package/src/react/hooks/useCancelOrder.tsx +3 -3
- package/src/react/hooks/useCancelTransactionSteps.tsx +1 -1
- package/src/react/hooks/useCheckoutOptions.tsx +1 -2
- package/src/react/hooks/useCollectible.tsx +2 -3
- package/src/react/hooks/useCollectionBalanceDetails.tsx +1 -2
- package/src/react/hooks/useComparePrices.tsx +2 -9
- package/src/react/hooks/useConvertPriceToUSD.tsx +1 -4
- package/src/react/hooks/useCountListingsForCollectible.tsx +1 -2
- package/src/react/hooks/useCountOfCollectables.tsx +1 -2
- package/src/react/hooks/useCountOffersForCollectible.tsx +1 -2
- package/src/react/hooks/useCurrencies.tsx +1 -4
- package/src/react/hooks/useCurrency.tsx +3 -8
- package/src/react/hooks/useFilters.tsx +5 -4
- package/src/react/hooks/useFloorOrder.tsx +1 -2
- package/src/react/hooks/useGenerateCancelTransaction.tsx +3 -6
- package/src/react/hooks/useGenerateListingTransaction.tsx +2 -3
- package/src/react/hooks/useGenerateOfferTransaction.tsx +2 -3
- package/src/react/hooks/useGenerateSellTransaction.tsx +3 -6
- package/src/react/hooks/useHighestOffer.tsx +1 -1
- package/src/react/hooks/useListCollectibles.tsx +33 -61
- package/src/react/hooks/useListCollectiblesPaginated.tsx +2 -6
- package/src/react/hooks/useListListingsForCollectible.tsx +1 -2
- package/src/react/hooks/useListOffersForCollectible.tsx +1 -2
- package/src/react/hooks/useLowestListing.tsx +1 -2
- package/src/react/hooks/useRoyalty.tsx +3 -8
- package/src/react/hooks/useTransferTokens.tsx +2 -2
- package/src/react/queries/balanceOfCollectible.ts +9 -32
- package/src/react/queries/getTokenSupplies.ts +38 -0
- package/src/react/queries/index.ts +5 -0
- package/src/react/queries/listCollectibles.ts +96 -0
- package/src/react/ui/components/_internals/action-button/ActionButton.tsx +1 -1
- package/src/react/ui/components/_internals/action-button/__tests__/ActionButton.test.tsx +1 -1
- package/src/react/ui/components/_internals/action-button/components/NonOwnerActions.tsx +4 -3
- package/src/react/ui/components/_internals/action-button/components/OwnerActions.tsx +1 -1
- package/src/react/ui/components/collectible-card/CollectibleCard.tsx +2 -3
- package/src/react/ui/components/collectible-card/__tests__/CollectibleCard.test.tsx +1 -1
- package/src/react/ui/modals/BuyModal/ERC1155QuantityModal.tsx +127 -0
- package/src/react/ui/modals/BuyModal/Modal.tsx +70 -85
- package/src/react/ui/modals/BuyModal/__tests__/Modal.test.tsx +85 -226
- package/src/react/ui/modals/BuyModal/__tests__/Modal1155.test.tsx +140 -0
- package/src/react/ui/modals/BuyModal/__tests__/store.test.ts +67 -76
- package/src/react/ui/modals/BuyModal/hooks/__tests__/useCheckoutOptions.test.tsx +1 -60
- package/src/react/ui/modals/BuyModal/hooks/__tests__/useFees.test.tsx +1 -1
- package/src/react/ui/modals/BuyModal/hooks/useCheckoutOptions.ts +29 -13
- package/src/react/ui/modals/BuyModal/hooks/useLoadData.ts +26 -21
- package/src/react/ui/modals/BuyModal/hooks/usePaymentModalParams.ts +200 -0
- package/src/react/ui/modals/BuyModal/index.tsx +4 -14
- package/src/react/ui/modals/BuyModal/store.ts +71 -76
- package/src/react/ui/modals/CreateListingModal/Modal.tsx +71 -7
- package/src/react/ui/modals/CreateListingModal/__tests__/Modal.test.tsx +2 -2
- package/src/react/ui/modals/CreateListingModal/hooks/useCreateListing.tsx +1 -1
- package/src/react/ui/modals/CreateListingModal/hooks/useGetTokenApproval.ts +1 -1
- package/src/react/ui/modals/CreateListingModal/hooks/useTransactionSteps.tsx +9 -5
- package/src/react/ui/modals/CreateListingModal/store.ts +7 -2
- package/src/react/ui/modals/MakeOfferModal/Modal.tsx +103 -6
- package/src/react/ui/modals/MakeOfferModal/__tests__/Modal.test.tsx +1 -1
- package/src/react/ui/modals/MakeOfferModal/hooks/useGetTokenApproval.tsx +1 -1
- package/src/react/ui/modals/MakeOfferModal/hooks/useMakeOffer.tsx +1 -1
- package/src/react/ui/modals/MakeOfferModal/hooks/useTransactionSteps.tsx +8 -4
- package/src/react/ui/modals/MakeOfferModal/store.ts +5 -3
- package/src/react/ui/modals/SellModal/Modal.tsx +76 -4
- package/src/react/ui/modals/SellModal/__tests__/Modal.test.tsx +1 -1
- package/src/react/ui/modals/SellModal/hooks/useGetTokenApproval.tsx +1 -1
- package/src/react/ui/modals/SellModal/hooks/useSell.tsx +1 -1
- package/src/react/ui/modals/SellModal/hooks/useTransactionSteps.tsx +16 -8
- package/src/react/ui/modals/SellModal/store.ts +5 -3
- package/src/react/ui/modals/TransferModal/_store.ts +15 -3
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/_components/TokenQuantityInput.tsx +58 -0
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/_components/TransferButton.tsx +56 -0
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/_components/WalletAddressInput.tsx +50 -0
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/index.tsx +94 -66
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/useHandleTransfer.tsx +22 -14
- package/src/react/ui/modals/TransferModal/index.tsx +72 -38
- package/src/react/ui/modals/_internal/components/actionModal/ActionModal.tsx +43 -42
- package/src/react/ui/modals/_internal/components/actionModal/store.ts +1 -2
- package/src/react/ui/modals/_internal/components/currencyOptionsSelect/index.tsx +2 -2
- package/src/react/ui/modals/_internal/components/expirationDateSelect/index.tsx +9 -1
- package/src/react/ui/modals/_internal/components/floorPriceText/index.tsx +27 -12
- package/src/react/ui/modals/_internal/components/priceInput/__tests__/index.test.tsx +1 -1
- package/src/react/ui/modals/_internal/components/priceInput/index.tsx +19 -3
- package/src/react/ui/modals/_internal/components/quantityInput/index.tsx +3 -0
- package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/_components/ActionButtons.tsx +60 -0
- package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/_components/BalanceIndicator.tsx +30 -0
- package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/index.tsx +126 -0
- package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/store.ts +25 -0
- package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/useWaasFeeOptionManager.tsx +74 -0
- package/src/react/ui/modals/_internal/components/switchChainModal/index.tsx +1 -2
- package/src/react/ui/modals/_internal/components/switchChainModal/store.ts +1 -2
- package/src/react/ui/modals/_internal/components/tokenPreview/index.tsx +1 -1
- package/src/react/ui/modals/_internal/components/transaction-footer/index.tsx +4 -7
- package/src/react/ui/modals/_internal/components/transactionDetails/index.tsx +1 -1
- package/src/react/ui/modals/_internal/components/transactionPreview/index.tsx +1 -1
- package/src/react/ui/modals/_internal/components/transactionStatusModal/__tests__/TransactionStatusModal.test.tsx +1 -1
- package/src/react/ui/modals/_internal/components/transactionStatusModal/hooks/useTransactionStatus.ts +1 -1
- package/src/react/ui/modals/_internal/components/transactionStatusModal/index.tsx +6 -1
- package/src/react/ui/modals/_internal/components/transactionStatusModal/store.ts +2 -2
- package/src/react/ui/modals/_internal/components/waasFeeOptionsSelect/WaasFeeOptionsSelect.tsx +10 -31
- package/src/react/ui/modals/_internal/hooks/useSelectWaasFeeOptions.ts +53 -0
- package/src/react/ui/modals/_internal/types.ts +2 -1
- package/src/types/waas-types.ts +38 -0
- package/src/utils/network.ts +2 -4
- package/test/const.ts +1 -1
- package/test/setup.ts +10 -0
- package/test/test-utils.tsx +31 -5
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/chunk-3AKOPSON.js.map +0 -1
- package/dist/chunk-4XK7XNJ7.js.map +0 -1
- package/dist/chunk-BBASZVT3.js.map +0 -1
- package/dist/chunk-EAJ5K7QV.js.map +0 -1
- package/dist/chunk-HTFORA4Q.js.map +0 -1
- package/dist/chunk-OFY7OFTL.js +0 -458
- package/dist/chunk-OFY7OFTL.js.map +0 -1
- package/dist/chunk-RBEPPVLT.js.map +0 -1
- package/src/react/hooks/__tests__/useGenerateBuyTransaction.test.tsx +0 -172
- package/src/react/hooks/useGenerateBuyTransaction.tsx +0 -80
- package/src/react/ui/modals/BuyModal/hooks/__tests__/useBuyCollectable.test.tsx +0 -349
- package/src/react/ui/modals/BuyModal/hooks/__tests__/useLoadData.test.tsx +0 -185
- package/src/react/ui/modals/BuyModal/hooks/useBuyCollectable.ts +0 -170
- package/src/react/ui/modals/BuyModal/modals/CheckoutModal.tsx +0 -47
- package/src/react/ui/modals/BuyModal/modals/Modal1155.tsx +0 -140
- package/src/react/ui/modals/BuyModal/modals/__tests__/CheckoutModal.test.tsx +0 -162
- package/src/react/ui/modals/BuyModal/modals/__tests__/Modal1155.test.tsx +0 -327
- package/src/react/ui/modals/_internal/components/waasFeeOptionsBox/index.tsx +0 -124
- package/src/react/ui/modals/_internal/components/waasFeeOptionsBox/store.ts +0 -12
- /package/dist/{chunk-MPBN3E54.js.map → chunk-2VHHJNXY.js.map} +0 -0
- /package/dist/{chunk-FBUMNJQ4.js.map → chunk-3II5GLHE.js.map} +0 -0
- /package/dist/{chunk-XTGMMNV5.js.map → chunk-A5ACY5YV.js.map} +0 -0
- /package/dist/{chunk-XNA64MZQ.js.map → chunk-BCO4CYE4.js.map} +0 -0
- /package/dist/{chunk-Q5URKSC4.js.map → chunk-FMEEJFAF.js.map} +0 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { use$, useObservable } from '@legendapp/state/react';
|
|
4
|
+
import * as dn from 'dnum';
|
|
5
|
+
|
|
6
|
+
import { Text, TokenImage } from '@0xsequence/design-system';
|
|
7
|
+
import { DEFAULT_MARKETPLACE_FEE_PERCENTAGE } from '../../../../consts';
|
|
8
|
+
import { compareAddress } from '../../../../utils/address';
|
|
9
|
+
import type { Order } from '../../../_internal';
|
|
10
|
+
import { useCurrency, useMarketplaceConfig } from '../../../hooks';
|
|
11
|
+
import { ActionModal } from '../_internal/components/actionModal';
|
|
12
|
+
import QuantityInput from '../_internal/components/quantityInput';
|
|
13
|
+
import { buyModalStore, useBuyModalProps, useIsOpen } from './store';
|
|
14
|
+
|
|
15
|
+
export const ERC1155QuantityModal = ({ order }: { order: Order }) => {
|
|
16
|
+
const { chainId } = useBuyModalProps();
|
|
17
|
+
const isOpen = useIsOpen();
|
|
18
|
+
|
|
19
|
+
const localQuantity$ = useObservable('1');
|
|
20
|
+
const localQuantity = use$(localQuantity$);
|
|
21
|
+
const invalidQuantity$ = useObservable(false);
|
|
22
|
+
const invalidQuantity = use$(invalidQuantity$);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<ActionModal
|
|
26
|
+
isOpen={isOpen}
|
|
27
|
+
chainId={chainId}
|
|
28
|
+
onClose={() => buyModalStore.send({ type: 'close' })}
|
|
29
|
+
title="Select Quantity"
|
|
30
|
+
disableAnimation={true}
|
|
31
|
+
ctas={[
|
|
32
|
+
{
|
|
33
|
+
label: 'Buy now',
|
|
34
|
+
onClick: () => {
|
|
35
|
+
buyModalStore.send({
|
|
36
|
+
type: 'setQuantity',
|
|
37
|
+
quantity: Number(localQuantity),
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
disabled: invalidQuantity,
|
|
41
|
+
},
|
|
42
|
+
]}
|
|
43
|
+
>
|
|
44
|
+
<div className="flex w-full flex-col gap-4">
|
|
45
|
+
<QuantityInput
|
|
46
|
+
$quantity={localQuantity$}
|
|
47
|
+
$invalidQuantity={invalidQuantity$}
|
|
48
|
+
decimals={order.quantityDecimals}
|
|
49
|
+
maxQuantity={order.quantityRemaining}
|
|
50
|
+
/>
|
|
51
|
+
|
|
52
|
+
<TotalPrice order={order} quantityStr={localQuantity} />
|
|
53
|
+
</div>
|
|
54
|
+
</ActionModal>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const TotalPrice = ({
|
|
59
|
+
order,
|
|
60
|
+
quantityStr,
|
|
61
|
+
}: { order: Order; quantityStr: string }) => {
|
|
62
|
+
const { data: marketplaceConfig } = useMarketplaceConfig();
|
|
63
|
+
const { data: currency, isLoading: isCurrencyLoading } = useCurrency({
|
|
64
|
+
chainId: order.chainId,
|
|
65
|
+
currencyAddress: order.priceCurrencyAddress,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
let error: null | string = null;
|
|
69
|
+
let formattedPrice = '0';
|
|
70
|
+
|
|
71
|
+
if (currency) {
|
|
72
|
+
try {
|
|
73
|
+
const price = dn.from(order.priceAmount, currency.decimals);
|
|
74
|
+
|
|
75
|
+
const totalPriceWithoutFees = dn.multiply(quantityStr, price);
|
|
76
|
+
const marketplaceFeePercentage =
|
|
77
|
+
marketplaceConfig?.collections.find((collection) =>
|
|
78
|
+
compareAddress(collection.address, order.collectionContractAddress),
|
|
79
|
+
)?.feePercentage || DEFAULT_MARKETPLACE_FEE_PERCENTAGE;
|
|
80
|
+
|
|
81
|
+
const feeMultiplier = dn.from(
|
|
82
|
+
1 + marketplaceFeePercentage / 100,
|
|
83
|
+
currency.decimals,
|
|
84
|
+
);
|
|
85
|
+
const totalPrice = dn.multiply(totalPriceWithoutFees, feeMultiplier);
|
|
86
|
+
|
|
87
|
+
formattedPrice = dn.format(totalPrice, { trailingZeros: false });
|
|
88
|
+
} catch (e) {
|
|
89
|
+
console.error('Error formatting price', e);
|
|
90
|
+
error = 'Unable to calculate total price';
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return error ? (
|
|
95
|
+
<Text className="font-body font-medium text-xs" color="text50">
|
|
96
|
+
{error}
|
|
97
|
+
</Text>
|
|
98
|
+
) : (
|
|
99
|
+
<div className="flex justify-between">
|
|
100
|
+
<Text className="font-body font-medium text-xs" color="text50">
|
|
101
|
+
Total Price
|
|
102
|
+
</Text>
|
|
103
|
+
|
|
104
|
+
<div className="flex items-center gap-0.5">
|
|
105
|
+
{isCurrencyLoading || !currency ? (
|
|
106
|
+
<div className="flex items-center gap-2">
|
|
107
|
+
<Text className="font-body text-text-50 text-xs">Loading...</Text>
|
|
108
|
+
</div>
|
|
109
|
+
) : (
|
|
110
|
+
<>
|
|
111
|
+
{currency.imageUrl && (
|
|
112
|
+
<TokenImage src={currency.imageUrl} size="xs" />
|
|
113
|
+
)}
|
|
114
|
+
|
|
115
|
+
<Text className="font-body font-bold text-text-100 text-xs">
|
|
116
|
+
{formattedPrice}
|
|
117
|
+
</Text>
|
|
118
|
+
|
|
119
|
+
<Text className="font-body font-bold text-text-80 text-xs">
|
|
120
|
+
{currency?.symbol}
|
|
121
|
+
</Text>
|
|
122
|
+
</>
|
|
123
|
+
)}
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
};
|
|
@@ -1,121 +1,106 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import { ContractType
|
|
3
|
+
import { useSelectPaymentModal } from '@0xsequence/checkout';
|
|
4
|
+
import { useEffect } from 'react';
|
|
5
|
+
import { ContractType } from '../../../_internal';
|
|
6
6
|
import { ErrorModal } from '../_internal/components/actionModal/ErrorModal';
|
|
7
7
|
import { LoadingModal } from '../_internal/components/actionModal/LoadingModal';
|
|
8
|
-
import {
|
|
8
|
+
import { ERC1155QuantityModal } from './ERC1155QuantityModal';
|
|
9
9
|
import { useLoadData } from './hooks/useLoadData';
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
import { usePaymentModalParams } from './hooks/usePaymentModalParams';
|
|
11
|
+
import {
|
|
12
|
+
buyModalStore,
|
|
13
|
+
useBuyModalProps,
|
|
14
|
+
useIsOpen,
|
|
15
|
+
useOnError,
|
|
16
|
+
useQuantity,
|
|
17
|
+
} from './store';
|
|
14
18
|
|
|
15
19
|
export const BuyModal = () => {
|
|
16
|
-
const isOpen =
|
|
20
|
+
const isOpen = useIsOpen();
|
|
17
21
|
|
|
18
|
-
if (!isOpen)
|
|
22
|
+
if (!isOpen) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
19
25
|
|
|
20
26
|
return <BuyModalContent />;
|
|
21
27
|
};
|
|
22
28
|
|
|
23
29
|
const BuyModalContent = () => {
|
|
24
|
-
const chainId =
|
|
25
|
-
const collectionAddress = use$(
|
|
26
|
-
buyModal$.state.order.collectionContractAddress,
|
|
27
|
-
) as Hex;
|
|
28
|
-
const buyModalState = use$(buyModal$.state);
|
|
29
|
-
const collectibleId = use$(buyModal$.state.order.tokenId);
|
|
30
|
-
const callbacks = use$(buyModal$.callbacks);
|
|
31
|
-
const order = use$(buyModal$.state.order);
|
|
32
|
-
const isOpen = use$(buyModal$.isOpen);
|
|
33
|
-
const checkoutModalIsLoading = use$(buyModal$.state.checkoutModalIsLoading);
|
|
34
|
-
const setCheckoutModalIsLoading = use$(buyModal$.setCheckoutModalIsLoading);
|
|
35
|
-
const setCheckoutModalLoaded = use$(buyModal$.setCheckoutModalLoaded);
|
|
30
|
+
const { chainId, skipNativeBalanceCheck } = useBuyModalProps();
|
|
36
31
|
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
32
|
+
const onError = useOnError();
|
|
33
|
+
|
|
34
|
+
const { openSelectPaymentModal } = useSelectPaymentModal();
|
|
35
|
+
const quantity = useQuantity();
|
|
36
|
+
|
|
37
|
+
const {
|
|
38
|
+
collection,
|
|
39
|
+
collectable,
|
|
40
|
+
wallet,
|
|
41
|
+
isLoading,
|
|
42
|
+
isError,
|
|
43
|
+
order,
|
|
44
|
+
checkoutOptions,
|
|
45
|
+
} = useLoadData();
|
|
45
46
|
|
|
46
47
|
const {
|
|
47
|
-
|
|
48
|
-
isLoading:
|
|
49
|
-
isError:
|
|
50
|
-
} =
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
setCheckoutModalLoaded,
|
|
58
|
-
...(buyModalState?.customProviderCallback && {
|
|
59
|
-
customProviderCallback: buyModalState.customProviderCallback,
|
|
60
|
-
}),
|
|
48
|
+
data: paymentModalParams,
|
|
49
|
+
isLoading: isPaymentModalParamsLoading,
|
|
50
|
+
isError: isPaymentModalParamsError,
|
|
51
|
+
} = usePaymentModalParams({
|
|
52
|
+
wallet,
|
|
53
|
+
quantity,
|
|
54
|
+
marketplace: order?.marketplace,
|
|
55
|
+
collectable: collectable,
|
|
56
|
+
checkoutOptions: checkoutOptions,
|
|
57
|
+
priceCurrencyAddress: order?.priceCurrencyAddress,
|
|
61
58
|
});
|
|
62
59
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
} else {
|
|
68
|
-
console.error('buy is null or undefined');
|
|
60
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: we want to set this on collection change
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
if (collection?.type === ContractType.ERC721 && !quantity) {
|
|
63
|
+
buyModalStore.send({ type: 'setQuantity', quantity: 1 });
|
|
69
64
|
}
|
|
70
|
-
};
|
|
65
|
+
}, [collection]);
|
|
66
|
+
|
|
67
|
+
if (isError || isPaymentModalParamsError) {
|
|
68
|
+
onError(new Error('Error loading data'));
|
|
69
|
+
return (
|
|
70
|
+
<ErrorModal
|
|
71
|
+
isOpen={true}
|
|
72
|
+
chainId={chainId}
|
|
73
|
+
onClose={() => buyModalStore.send({ type: 'close' })}
|
|
74
|
+
title="Error"
|
|
75
|
+
/>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
71
78
|
|
|
72
79
|
if (
|
|
73
80
|
isLoading ||
|
|
74
|
-
|
|
81
|
+
isPaymentModalParamsLoading ||
|
|
75
82
|
!collection ||
|
|
76
83
|
!collectable ||
|
|
77
|
-
!
|
|
78
|
-
buyIsLoading
|
|
84
|
+
!order
|
|
79
85
|
) {
|
|
80
86
|
return (
|
|
81
87
|
<LoadingModal
|
|
82
|
-
isOpen={
|
|
83
|
-
chainId={
|
|
84
|
-
onClose={
|
|
88
|
+
isOpen={true}
|
|
89
|
+
chainId={chainId}
|
|
90
|
+
onClose={() => buyModalStore.send({ type: 'close' })}
|
|
85
91
|
title="Loading Sequence Pay"
|
|
86
92
|
/>
|
|
87
93
|
);
|
|
88
94
|
}
|
|
89
95
|
|
|
90
|
-
if (
|
|
91
|
-
return
|
|
92
|
-
<ErrorModal
|
|
93
|
-
isOpen={isOpen}
|
|
94
|
-
chainId={Number(chainId)}
|
|
95
|
-
onClose={buyModal$.close}
|
|
96
|
-
title="Error"
|
|
97
|
-
/>
|
|
98
|
-
);
|
|
96
|
+
if (collection.type === ContractType.ERC1155 && !quantity) {
|
|
97
|
+
return <ERC1155QuantityModal order={order} />;
|
|
99
98
|
}
|
|
100
99
|
|
|
101
|
-
if (
|
|
102
|
-
|
|
100
|
+
if (paymentModalParams) {
|
|
101
|
+
openSelectPaymentModal({
|
|
102
|
+
...paymentModalParams,
|
|
103
|
+
skipNativeBalanceCheck,
|
|
104
|
+
});
|
|
103
105
|
}
|
|
104
|
-
|
|
105
|
-
return collection.type === ContractType.ERC721 ? (
|
|
106
|
-
<CheckoutModal
|
|
107
|
-
buy={buyAction}
|
|
108
|
-
collectable={collectable as TokenMetadata}
|
|
109
|
-
order={order}
|
|
110
|
-
/>
|
|
111
|
-
) : (
|
|
112
|
-
<ERC1155QuantityModal
|
|
113
|
-
buy={buyAction}
|
|
114
|
-
collectable={collectable as TokenMetadata}
|
|
115
|
-
order={order}
|
|
116
|
-
chainId={chainId}
|
|
117
|
-
collectionAddress={collectionAddress}
|
|
118
|
-
collectibleId={collectibleId}
|
|
119
|
-
/>
|
|
120
|
-
);
|
|
121
106
|
};
|
|
@@ -1,58 +1,24 @@
|
|
|
1
|
-
import { cleanup, render, screen
|
|
2
|
-
import { beforeEach, describe, expect, it
|
|
3
|
-
import type { Mock } from 'vitest';
|
|
4
|
-
import type { Order } from '../../../../_internal';
|
|
5
|
-
import { MarketplaceKind } from '../../../../_internal';
|
|
6
|
-
import { ContractType } from '../../../../_internal';
|
|
7
|
-
import { BuyModal } from '../Modal';
|
|
8
|
-
import { useBuyCollectable } from '../hooks/useBuyCollectable';
|
|
9
|
-
import { useLoadData } from '../hooks/useLoadData';
|
|
10
|
-
import { buyModal$ } from '../store';
|
|
11
|
-
|
|
12
|
-
const mockOrder = {
|
|
13
|
-
orderId: '1',
|
|
14
|
-
priceAmount: '1000000000000000000',
|
|
15
|
-
priceCurrencyAddress: '0x0',
|
|
16
|
-
quantityRemaining: '1',
|
|
17
|
-
createdAt: new Date().toISOString(),
|
|
18
|
-
marketplace: MarketplaceKind.sequence_marketplace_v2,
|
|
19
|
-
} as Order;
|
|
20
|
-
|
|
21
|
-
vi.mock('../hooks/useLoadData', () => ({
|
|
22
|
-
useLoadData: vi.fn(),
|
|
23
|
-
}));
|
|
24
|
-
|
|
25
|
-
vi.mock('../hooks/useBuyCollectable', () => ({
|
|
26
|
-
useBuyCollectable: vi.fn(),
|
|
27
|
-
}));
|
|
1
|
+
import { WebSdkWrapper, cleanup, render, screen } from '@test';
|
|
2
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
28
3
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
4
|
+
import { server } from '@test';
|
|
5
|
+
import type { Address } from 'viem';
|
|
6
|
+
import { mockOrder } from '../../../../_internal/api/__mocks__/marketplace.msw';
|
|
7
|
+
import { BuyModal } from '../Modal';
|
|
8
|
+
import { buyModalStore } from '../store';
|
|
32
9
|
|
|
33
10
|
describe('BuyModal', () => {
|
|
34
11
|
beforeEach(() => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
(useLoadData as Mock).mockReturnValue({
|
|
38
|
-
collection: null,
|
|
39
|
-
collectable: null,
|
|
40
|
-
checkoutOptions: null,
|
|
41
|
-
isLoading: false,
|
|
42
|
-
isError: false,
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
(useBuyCollectable as Mock).mockReturnValue({
|
|
46
|
-
buy: vi.fn(),
|
|
47
|
-
isLoading: false,
|
|
48
|
-
isError: false,
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
buyModal$.close();
|
|
12
|
+
buyModalStore.send({ type: 'close' });
|
|
13
|
+
});
|
|
52
14
|
|
|
15
|
+
afterEach(() => {
|
|
53
16
|
cleanup();
|
|
17
|
+
// Reset server handlers
|
|
18
|
+
server.resetHandlers();
|
|
54
19
|
});
|
|
55
20
|
|
|
21
|
+
// Currently this is the only test we can run without the provider
|
|
56
22
|
it('should not render when isOpen is false', () => {
|
|
57
23
|
render(<BuyModal />);
|
|
58
24
|
|
|
@@ -62,190 +28,83 @@ describe('BuyModal', () => {
|
|
|
62
28
|
});
|
|
63
29
|
|
|
64
30
|
it.skip('should render error modal when there is an error', async () => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
render(<BuyModal />);
|
|
94
|
-
|
|
95
|
-
// Should show error modal
|
|
96
|
-
await waitFor(() => {
|
|
97
|
-
expect(screen.getByTestId('error-modal')).toBeInTheDocument();
|
|
98
|
-
expect(
|
|
99
|
-
screen.getByText('Error loading item details'),
|
|
100
|
-
).toBeInTheDocument();
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
// Cleanup
|
|
104
|
-
cleanup();
|
|
105
|
-
|
|
106
|
-
// Test buy error
|
|
107
|
-
(useLoadData as Mock).mockReturnValue({
|
|
108
|
-
collection: { type: ContractType.ERC721 },
|
|
109
|
-
collectable: { decimals: 0 },
|
|
110
|
-
checkoutOptions: { someOption: true },
|
|
111
|
-
isLoading: false,
|
|
112
|
-
isError: false,
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
(useBuyCollectable as Mock).mockReturnValue({
|
|
116
|
-
buy: vi.fn(),
|
|
117
|
-
isLoading: false,
|
|
118
|
-
isError: true,
|
|
119
|
-
status: 'error',
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
buyModal$.open({
|
|
123
|
-
order: mockOrderBasic,
|
|
124
|
-
callbacks: {},
|
|
125
|
-
chainId: '1',
|
|
126
|
-
collectionAddress: '0x123',
|
|
127
|
-
tokenId: '1',
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
render(<BuyModal />);
|
|
131
|
-
|
|
132
|
-
// Should show error modal for buy error too
|
|
133
|
-
expect(screen.getByText('Error')).toBeInTheDocument();
|
|
31
|
+
// server.use(
|
|
32
|
+
// http.post(mockMetadataEndpoint("GetContractInfo"), () => {
|
|
33
|
+
// return new HttpResponse(null, {
|
|
34
|
+
// status: 404,
|
|
35
|
+
// })
|
|
36
|
+
// }),
|
|
37
|
+
// );
|
|
38
|
+
// buyModalStore.send({
|
|
39
|
+
// type: 'open',
|
|
40
|
+
// props: {
|
|
41
|
+
// orderId: mockOrder.orderId,
|
|
42
|
+
// chainId: mockOrder.chainId,
|
|
43
|
+
// collectionAddress: mockOrder.collectionContractAddress as Address,
|
|
44
|
+
// collectibleId: "1",
|
|
45
|
+
// marketplace: mockOrder.marketplace,
|
|
46
|
+
// },
|
|
47
|
+
// });
|
|
48
|
+
// render(
|
|
49
|
+
// <WebSdkWrapper>
|
|
50
|
+
// <BuyModal />
|
|
51
|
+
// </WebSdkWrapper>
|
|
52
|
+
// );
|
|
53
|
+
// // Should show error modal
|
|
54
|
+
// await waitFor(() => {
|
|
55
|
+
// expect(screen.getByText("Error")).toBeInTheDocument();
|
|
56
|
+
// }, { timeout: 1000 });
|
|
134
57
|
});
|
|
135
58
|
|
|
136
59
|
it.skip('should render ERC1155QuantityModal when contract type is ERC1155', async () => {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
(
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
order: mockOrderERC1155,
|
|
165
|
-
callbacks: {},
|
|
166
|
-
chainId: '1',
|
|
167
|
-
collectionAddress: '0x123',
|
|
168
|
-
tokenId: '1',
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
// Initialize quantity state
|
|
172
|
-
buyModal$.state.quantity.set('1');
|
|
173
|
-
buyModal$.state.checkoutModalLoaded.set(false);
|
|
174
|
-
buyModal$.state.checkoutModalIsLoading.set(false);
|
|
175
|
-
|
|
176
|
-
render(<BuyModal />);
|
|
177
|
-
|
|
178
|
-
await waitFor(() => {
|
|
179
|
-
expect(screen.getByText('Select Quantity')).toBeInTheDocument();
|
|
180
|
-
});
|
|
60
|
+
// // Create an ERC1155 mock collection
|
|
61
|
+
// const erc1155Collection = {
|
|
62
|
+
// ...mockCollection,
|
|
63
|
+
// contractType: ContractType.ERC1155,
|
|
64
|
+
// };
|
|
65
|
+
// const erc1155Order = {
|
|
66
|
+
// ...testOrder,
|
|
67
|
+
// quantityRemaining: "10",
|
|
68
|
+
// quantityRemainingFormatted: "10",
|
|
69
|
+
// };
|
|
70
|
+
// buyModalStore.send({
|
|
71
|
+
// type: 'open',
|
|
72
|
+
// props: {
|
|
73
|
+
// orderId: erc1155Order.orderId,
|
|
74
|
+
// chainId: erc1155Order.chainId,
|
|
75
|
+
// collectionAddress: erc1155Order.collectionContractAddress,
|
|
76
|
+
// collectibleId: erc1155Order.tokenId,
|
|
77
|
+
// marketplace: erc1155Order.marketplace,
|
|
78
|
+
// },
|
|
79
|
+
// });
|
|
80
|
+
// render(<BuyModal />);
|
|
81
|
+
// // First should show loading
|
|
82
|
+
// expect(screen.getByText("Loading Sequence Pay")).toBeInTheDocument();
|
|
83
|
+
// // Then should show quantity modal for ERC1155
|
|
84
|
+
// await waitFor(() => {
|
|
85
|
+
// expect(screen.getByText("Select Quantity")).toBeInTheDocument();
|
|
86
|
+
// }, { timeout: 5000 });
|
|
181
87
|
});
|
|
182
88
|
|
|
183
|
-
it
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
isError: false,
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
(useBuyCollectable as Mock).mockReturnValue({
|
|
206
|
-
buy: mockBuy,
|
|
207
|
-
isLoading: false,
|
|
208
|
-
isError: false,
|
|
209
|
-
status: 'ready',
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
buyModal$.open({
|
|
213
|
-
order: mockOrderERC721,
|
|
214
|
-
callbacks: {},
|
|
215
|
-
chainId: '1',
|
|
216
|
-
collectionAddress: '0x123',
|
|
217
|
-
tokenId: '1',
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
const { rerender } = render(<BuyModal />);
|
|
221
|
-
|
|
222
|
-
// Verify loading modal is shown
|
|
89
|
+
it('should show loading modal', async () => {
|
|
90
|
+
buyModalStore.send({
|
|
91
|
+
type: 'open',
|
|
92
|
+
props: {
|
|
93
|
+
orderId: mockOrder.orderId,
|
|
94
|
+
chainId: mockOrder.chainId,
|
|
95
|
+
collectionAddress: mockOrder.collectionContractAddress as Address,
|
|
96
|
+
collectibleId: '1',
|
|
97
|
+
marketplace: mockOrder.marketplace,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
render(
|
|
102
|
+
<WebSdkWrapper>
|
|
103
|
+
<BuyModal />
|
|
104
|
+
</WebSdkWrapper>,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// Should show loading modal
|
|
223
108
|
expect(screen.getByText('Loading Sequence Pay')).toBeInTheDocument();
|
|
224
|
-
|
|
225
|
-
// Then update the mock to simulate data loaded
|
|
226
|
-
(useLoadData as Mock).mockReturnValue({
|
|
227
|
-
collection: { type: ContractType.ERC721 },
|
|
228
|
-
collectable: { decimals: 0 },
|
|
229
|
-
checkoutOptions: { someOption: true },
|
|
230
|
-
isLoading: false,
|
|
231
|
-
isError: false,
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
// Force a re-render with the new mock values
|
|
235
|
-
rerender(<BuyModal />);
|
|
236
|
-
|
|
237
|
-
// Wait for loading to complete and verify the rest of the flow
|
|
238
|
-
await waitFor(() => {
|
|
239
|
-
expect(mockBuy).toHaveBeenCalledWith({
|
|
240
|
-
orderId: mockOrderERC721.orderId,
|
|
241
|
-
collectableDecimals: 0,
|
|
242
|
-
quantity: '1',
|
|
243
|
-
marketplace: mockOrderERC721.marketplace,
|
|
244
|
-
checkoutOptions: { someOption: true },
|
|
245
|
-
});
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
expect(screen.queryByText('Loading Sequence Pay')).not.toBeInTheDocument();
|
|
249
|
-
expect(screen.queryByText('Select Quantity')).not.toBeInTheDocument();
|
|
250
109
|
});
|
|
251
110
|
});
|