@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.
Files changed (227) hide show
  1. package/.changeset/README.md +8 -0
  2. package/.changeset/config.json +11 -0
  3. package/.changeset/seven-doors-taste.md +5 -0
  4. package/CHANGELOG.md +13 -0
  5. package/dist/{chunk-MPBN3E54.js → chunk-2VHHJNXY.js} +3 -3
  6. package/dist/{chunk-FBUMNJQ4.js → chunk-3II5GLHE.js} +2 -2
  7. package/dist/chunk-3JU7SQVE.js +182 -0
  8. package/dist/chunk-3JU7SQVE.js.map +1 -0
  9. package/dist/{chunk-XTGMMNV5.js → chunk-A5ACY5YV.js} +2 -2
  10. package/dist/chunk-ABSYNRT5.js +128 -0
  11. package/dist/chunk-ABSYNRT5.js.map +1 -0
  12. package/dist/{chunk-XNA64MZQ.js → chunk-BCO4CYE4.js} +2 -2
  13. package/dist/{chunk-HTFORA4Q.js → chunk-BN36GABQ.js} +1883 -1010
  14. package/dist/chunk-BN36GABQ.js.map +1 -0
  15. package/dist/{chunk-4XK7XNJ7.js → chunk-BNAUZXPV.js} +73 -2
  16. package/dist/chunk-BNAUZXPV.js.map +1 -0
  17. package/dist/{chunk-Q5URKSC4.js → chunk-FMEEJFAF.js} +1 -1
  18. package/dist/{chunk-BBASZVT3.js → chunk-GBQVYNCD.js} +5 -6
  19. package/dist/chunk-GBQVYNCD.js.map +1 -0
  20. package/dist/{chunk-3AKOPSON.js → chunk-IZ44XPBH.js} +2 -9
  21. package/dist/chunk-IZ44XPBH.js.map +1 -0
  22. package/dist/{chunk-EAJ5K7QV.js → chunk-Q5RKAMYF.js} +3 -4
  23. package/dist/chunk-Q5RKAMYF.js.map +1 -0
  24. package/dist/{chunk-RBEPPVLT.js → chunk-X3QNSQER.js} +145 -355
  25. package/dist/chunk-X3QNSQER.js.map +1 -0
  26. package/dist/{index-CzTANLaA.d.ts → index-CnaFSNE9.d.ts} +6 -7
  27. package/dist/index.css +113 -31
  28. package/dist/index.css.map +1 -1
  29. package/dist/index.d.ts +2 -4
  30. package/dist/index.js +4 -4
  31. package/dist/listCollectibles-B0tbqnRd.d.ts +155 -0
  32. package/dist/react/_internal/api/index.d.ts +28 -2
  33. package/dist/react/_internal/api/index.js +3 -1
  34. package/dist/react/_internal/databeat/index.js +10 -9
  35. package/dist/react/_internal/index.d.ts +2 -3
  36. package/dist/react/_internal/index.js +4 -4
  37. package/dist/react/_internal/wagmi/index.js +2 -2
  38. package/dist/react/hooks/index.d.ts +259 -674
  39. package/dist/react/hooks/index.js +11 -20
  40. package/dist/react/hooks/options/index.d.ts +1 -2
  41. package/dist/react/hooks/options/index.js +4 -4
  42. package/dist/react/index.d.ts +7 -7
  43. package/dist/react/index.js +15 -24
  44. package/dist/react/queries/index.d.ts +25 -0
  45. package/dist/react/queries/index.js +48 -0
  46. package/dist/react/queries/index.js.map +1 -0
  47. package/dist/react/ssr/index.js +3 -3
  48. package/dist/react/ui/components/collectible-card/index.d.ts +1 -6
  49. package/dist/react/ui/components/collectible-card/index.js +13 -12
  50. package/dist/react/ui/components/marketplace-logos/index.js +1 -1
  51. package/dist/react/ui/icons/index.js +6 -6
  52. package/dist/react/ui/index.d.ts +18 -22
  53. package/dist/react/ui/index.js +13 -12
  54. package/dist/react/ui/modals/_internal/components/actionModal/index.d.ts +6 -11
  55. package/dist/react/ui/modals/_internal/components/actionModal/index.js +10 -9
  56. package/dist/types/index.js +2 -2
  57. package/dist/{types-Ct1uCT3M.d.ts → types-o_pKUpQG.d.ts} +2 -5
  58. package/dist/utils/index.d.ts +1 -5
  59. package/dist/utils/index.js +4 -4
  60. package/package.json +22 -16
  61. package/src/react/_internal/api/__mocks__/indexer.msw.ts +3 -1
  62. package/src/react/_internal/api/__mocks__/marketplace.msw.ts +1 -1
  63. package/src/react/_internal/api/__mocks__/metadata.msw.ts +14 -12
  64. package/src/react/_internal/api/index.ts +1 -0
  65. package/src/react/_internal/api/laos-api.ts +103 -0
  66. package/src/react/_internal/api/zod-schema.ts +3 -3
  67. package/src/react/_internal/types.ts +1 -10
  68. package/src/react/_internal/wallet/__tests__/wallet.test.ts +43 -0
  69. package/src/react/_internal/wallet/useWallet.ts +6 -3
  70. package/src/react/hooks/__tests__/useAutoSelectFeeOption.test.tsx +1 -1
  71. package/src/react/hooks/__tests__/useCancelOrder.test.tsx +1 -1
  72. package/src/react/hooks/__tests__/useCancelTransactionSteps.test.tsx +1 -1
  73. package/src/react/hooks/__tests__/useCollectible.test.tsx +2 -2
  74. package/src/react/hooks/__tests__/useCollection.test.tsx +2 -2
  75. package/src/react/hooks/__tests__/useComparePrices.test.tsx +1 -1
  76. package/src/react/hooks/__tests__/useConvertPriceToUSD.test.tsx +1 -1
  77. package/src/react/hooks/__tests__/useCountListingsForCollectible.test.tsx +1 -1
  78. package/src/react/hooks/__tests__/useCountOfCollectables.test.tsx +2 -2
  79. package/src/react/hooks/__tests__/useCountOffersForCollectible.test.tsx +1 -1
  80. package/src/react/hooks/__tests__/useCurrencies.test.tsx +2 -2
  81. package/src/react/hooks/__tests__/useCurrency.test.tsx +2 -2
  82. package/src/react/hooks/__tests__/useFilters.test.tsx +2 -2
  83. package/src/react/hooks/__tests__/useFloorOrder.test.tsx +2 -2
  84. package/src/react/hooks/__tests__/useGenerateCancelTransaction.test.tsx +1 -1
  85. package/src/react/hooks/__tests__/useGenerateListingTransaction.test.tsx +1 -1
  86. package/src/react/hooks/__tests__/useGenerateOfferTransaction.test.tsx +1 -1
  87. package/src/react/hooks/__tests__/useGenerateSellTransaction.test.tsx +1 -1
  88. package/src/react/hooks/__tests__/useListCollectibleActivities.test.tsx +2 -2
  89. package/src/react/hooks/__tests__/useListCollectibles.test.tsx +3 -2
  90. package/src/react/hooks/__tests__/useListCollectiblesPaginated.test.tsx +1 -1
  91. package/src/react/hooks/__tests__/useListCollectionActivities.test.tsx +1 -1
  92. package/src/react/hooks/__tests__/useListListingsForCollectible.test.tsx +1 -1
  93. package/src/react/hooks/__tests__/useListOffersForCollectible.test.tsx +1 -1
  94. package/src/react/hooks/__tests__/useLowestListing.test.tsx +1 -1
  95. package/src/react/hooks/__tests__/useRoyalty.test.tsx +1 -2
  96. package/src/react/hooks/index.ts +0 -1
  97. package/src/react/hooks/options/collectionOptions.ts +2 -3
  98. package/src/react/hooks/useAutoSelectFeeOption.tsx +1 -1
  99. package/src/react/hooks/useCancelOrder.tsx +3 -3
  100. package/src/react/hooks/useCancelTransactionSteps.tsx +1 -1
  101. package/src/react/hooks/useCheckoutOptions.tsx +1 -2
  102. package/src/react/hooks/useCollectible.tsx +2 -3
  103. package/src/react/hooks/useCollectionBalanceDetails.tsx +1 -2
  104. package/src/react/hooks/useComparePrices.tsx +2 -9
  105. package/src/react/hooks/useConvertPriceToUSD.tsx +1 -4
  106. package/src/react/hooks/useCountListingsForCollectible.tsx +1 -2
  107. package/src/react/hooks/useCountOfCollectables.tsx +1 -2
  108. package/src/react/hooks/useCountOffersForCollectible.tsx +1 -2
  109. package/src/react/hooks/useCurrencies.tsx +1 -4
  110. package/src/react/hooks/useCurrency.tsx +3 -8
  111. package/src/react/hooks/useFilters.tsx +5 -4
  112. package/src/react/hooks/useFloorOrder.tsx +1 -2
  113. package/src/react/hooks/useGenerateCancelTransaction.tsx +3 -6
  114. package/src/react/hooks/useGenerateListingTransaction.tsx +2 -3
  115. package/src/react/hooks/useGenerateOfferTransaction.tsx +2 -3
  116. package/src/react/hooks/useGenerateSellTransaction.tsx +3 -6
  117. package/src/react/hooks/useHighestOffer.tsx +1 -1
  118. package/src/react/hooks/useListCollectibles.tsx +33 -61
  119. package/src/react/hooks/useListCollectiblesPaginated.tsx +2 -6
  120. package/src/react/hooks/useListListingsForCollectible.tsx +1 -2
  121. package/src/react/hooks/useListOffersForCollectible.tsx +1 -2
  122. package/src/react/hooks/useLowestListing.tsx +1 -2
  123. package/src/react/hooks/useRoyalty.tsx +3 -8
  124. package/src/react/hooks/useTransferTokens.tsx +2 -2
  125. package/src/react/queries/balanceOfCollectible.ts +9 -32
  126. package/src/react/queries/getTokenSupplies.ts +38 -0
  127. package/src/react/queries/index.ts +5 -0
  128. package/src/react/queries/listCollectibles.ts +96 -0
  129. package/src/react/ui/components/_internals/action-button/ActionButton.tsx +1 -1
  130. package/src/react/ui/components/_internals/action-button/__tests__/ActionButton.test.tsx +1 -1
  131. package/src/react/ui/components/_internals/action-button/components/NonOwnerActions.tsx +4 -3
  132. package/src/react/ui/components/_internals/action-button/components/OwnerActions.tsx +1 -1
  133. package/src/react/ui/components/collectible-card/CollectibleCard.tsx +2 -3
  134. package/src/react/ui/components/collectible-card/__tests__/CollectibleCard.test.tsx +1 -1
  135. package/src/react/ui/modals/BuyModal/ERC1155QuantityModal.tsx +127 -0
  136. package/src/react/ui/modals/BuyModal/Modal.tsx +70 -85
  137. package/src/react/ui/modals/BuyModal/__tests__/Modal.test.tsx +85 -226
  138. package/src/react/ui/modals/BuyModal/__tests__/Modal1155.test.tsx +140 -0
  139. package/src/react/ui/modals/BuyModal/__tests__/store.test.ts +67 -76
  140. package/src/react/ui/modals/BuyModal/hooks/__tests__/useCheckoutOptions.test.tsx +1 -60
  141. package/src/react/ui/modals/BuyModal/hooks/__tests__/useFees.test.tsx +1 -1
  142. package/src/react/ui/modals/BuyModal/hooks/useCheckoutOptions.ts +29 -13
  143. package/src/react/ui/modals/BuyModal/hooks/useLoadData.ts +26 -21
  144. package/src/react/ui/modals/BuyModal/hooks/usePaymentModalParams.ts +200 -0
  145. package/src/react/ui/modals/BuyModal/index.tsx +4 -14
  146. package/src/react/ui/modals/BuyModal/store.ts +71 -76
  147. package/src/react/ui/modals/CreateListingModal/Modal.tsx +71 -7
  148. package/src/react/ui/modals/CreateListingModal/__tests__/Modal.test.tsx +2 -2
  149. package/src/react/ui/modals/CreateListingModal/hooks/useCreateListing.tsx +1 -1
  150. package/src/react/ui/modals/CreateListingModal/hooks/useGetTokenApproval.ts +1 -1
  151. package/src/react/ui/modals/CreateListingModal/hooks/useTransactionSteps.tsx +9 -5
  152. package/src/react/ui/modals/CreateListingModal/store.ts +7 -2
  153. package/src/react/ui/modals/MakeOfferModal/Modal.tsx +103 -6
  154. package/src/react/ui/modals/MakeOfferModal/__tests__/Modal.test.tsx +1 -1
  155. package/src/react/ui/modals/MakeOfferModal/hooks/useGetTokenApproval.tsx +1 -1
  156. package/src/react/ui/modals/MakeOfferModal/hooks/useMakeOffer.tsx +1 -1
  157. package/src/react/ui/modals/MakeOfferModal/hooks/useTransactionSteps.tsx +8 -4
  158. package/src/react/ui/modals/MakeOfferModal/store.ts +5 -3
  159. package/src/react/ui/modals/SellModal/Modal.tsx +76 -4
  160. package/src/react/ui/modals/SellModal/__tests__/Modal.test.tsx +1 -1
  161. package/src/react/ui/modals/SellModal/hooks/useGetTokenApproval.tsx +1 -1
  162. package/src/react/ui/modals/SellModal/hooks/useSell.tsx +1 -1
  163. package/src/react/ui/modals/SellModal/hooks/useTransactionSteps.tsx +16 -8
  164. package/src/react/ui/modals/SellModal/store.ts +5 -3
  165. package/src/react/ui/modals/TransferModal/_store.ts +15 -3
  166. package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/_components/TokenQuantityInput.tsx +58 -0
  167. package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/_components/TransferButton.tsx +56 -0
  168. package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/_components/WalletAddressInput.tsx +50 -0
  169. package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/index.tsx +94 -66
  170. package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/useHandleTransfer.tsx +22 -14
  171. package/src/react/ui/modals/TransferModal/index.tsx +72 -38
  172. package/src/react/ui/modals/_internal/components/actionModal/ActionModal.tsx +43 -42
  173. package/src/react/ui/modals/_internal/components/actionModal/store.ts +1 -2
  174. package/src/react/ui/modals/_internal/components/currencyOptionsSelect/index.tsx +2 -2
  175. package/src/react/ui/modals/_internal/components/expirationDateSelect/index.tsx +9 -1
  176. package/src/react/ui/modals/_internal/components/floorPriceText/index.tsx +27 -12
  177. package/src/react/ui/modals/_internal/components/priceInput/__tests__/index.test.tsx +1 -1
  178. package/src/react/ui/modals/_internal/components/priceInput/index.tsx +19 -3
  179. package/src/react/ui/modals/_internal/components/quantityInput/index.tsx +3 -0
  180. package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/_components/ActionButtons.tsx +60 -0
  181. package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/_components/BalanceIndicator.tsx +30 -0
  182. package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/index.tsx +126 -0
  183. package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/store.ts +25 -0
  184. package/src/react/ui/modals/_internal/components/selectWaasFeeOptions/useWaasFeeOptionManager.tsx +74 -0
  185. package/src/react/ui/modals/_internal/components/switchChainModal/index.tsx +1 -2
  186. package/src/react/ui/modals/_internal/components/switchChainModal/store.ts +1 -2
  187. package/src/react/ui/modals/_internal/components/tokenPreview/index.tsx +1 -1
  188. package/src/react/ui/modals/_internal/components/transaction-footer/index.tsx +4 -7
  189. package/src/react/ui/modals/_internal/components/transactionDetails/index.tsx +1 -1
  190. package/src/react/ui/modals/_internal/components/transactionPreview/index.tsx +1 -1
  191. package/src/react/ui/modals/_internal/components/transactionStatusModal/__tests__/TransactionStatusModal.test.tsx +1 -1
  192. package/src/react/ui/modals/_internal/components/transactionStatusModal/hooks/useTransactionStatus.ts +1 -1
  193. package/src/react/ui/modals/_internal/components/transactionStatusModal/index.tsx +6 -1
  194. package/src/react/ui/modals/_internal/components/transactionStatusModal/store.ts +2 -2
  195. package/src/react/ui/modals/_internal/components/waasFeeOptionsSelect/WaasFeeOptionsSelect.tsx +10 -31
  196. package/src/react/ui/modals/_internal/hooks/useSelectWaasFeeOptions.ts +53 -0
  197. package/src/react/ui/modals/_internal/types.ts +2 -1
  198. package/src/types/waas-types.ts +38 -0
  199. package/src/utils/network.ts +2 -4
  200. package/test/const.ts +1 -1
  201. package/test/setup.ts +10 -0
  202. package/test/test-utils.tsx +31 -5
  203. package/tsconfig.tsbuildinfo +1 -1
  204. package/dist/chunk-3AKOPSON.js.map +0 -1
  205. package/dist/chunk-4XK7XNJ7.js.map +0 -1
  206. package/dist/chunk-BBASZVT3.js.map +0 -1
  207. package/dist/chunk-EAJ5K7QV.js.map +0 -1
  208. package/dist/chunk-HTFORA4Q.js.map +0 -1
  209. package/dist/chunk-OFY7OFTL.js +0 -458
  210. package/dist/chunk-OFY7OFTL.js.map +0 -1
  211. package/dist/chunk-RBEPPVLT.js.map +0 -1
  212. package/src/react/hooks/__tests__/useGenerateBuyTransaction.test.tsx +0 -172
  213. package/src/react/hooks/useGenerateBuyTransaction.tsx +0 -80
  214. package/src/react/ui/modals/BuyModal/hooks/__tests__/useBuyCollectable.test.tsx +0 -349
  215. package/src/react/ui/modals/BuyModal/hooks/__tests__/useLoadData.test.tsx +0 -185
  216. package/src/react/ui/modals/BuyModal/hooks/useBuyCollectable.ts +0 -170
  217. package/src/react/ui/modals/BuyModal/modals/CheckoutModal.tsx +0 -47
  218. package/src/react/ui/modals/BuyModal/modals/Modal1155.tsx +0 -140
  219. package/src/react/ui/modals/BuyModal/modals/__tests__/CheckoutModal.test.tsx +0 -162
  220. package/src/react/ui/modals/BuyModal/modals/__tests__/Modal1155.test.tsx +0 -327
  221. package/src/react/ui/modals/_internal/components/waasFeeOptionsBox/index.tsx +0 -124
  222. package/src/react/ui/modals/_internal/components/waasFeeOptionsBox/store.ts +0 -12
  223. /package/dist/{chunk-MPBN3E54.js.map → chunk-2VHHJNXY.js.map} +0 -0
  224. /package/dist/{chunk-FBUMNJQ4.js.map → chunk-3II5GLHE.js.map} +0 -0
  225. /package/dist/{chunk-XTGMMNV5.js.map → chunk-A5ACY5YV.js.map} +0 -0
  226. /package/dist/{chunk-XNA64MZQ.js.map → chunk-BCO4CYE4.js.map} +0 -0
  227. /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 { use$ } from '@legendapp/state/react';
4
- import type { Hex } from 'viem';
5
- import { ContractType, type TokenMetadata } from '../../../_internal';
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 { useBuyCollectable } from './hooks/useBuyCollectable';
8
+ import { ERC1155QuantityModal } from './ERC1155QuantityModal';
9
9
  import { useLoadData } from './hooks/useLoadData';
10
- import { CheckoutModal } from './modals/CheckoutModal';
11
- import type { BuyInput } from './modals/CheckoutModal';
12
- import { ERC1155QuantityModal } from './modals/Modal1155';
13
- import { buyModal$ } from './store';
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 = use$(buyModal$.isOpen);
20
+ const isOpen = useIsOpen();
17
21
 
18
- if (!isOpen) return null;
22
+ if (!isOpen) {
23
+ return null;
24
+ }
19
25
 
20
26
  return <BuyModalContent />;
21
27
  };
22
28
 
23
29
  const BuyModalContent = () => {
24
- const chainId = String(use$(buyModal$.state.order.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 { collection, collectable, checkoutOptions, isLoading, isError } =
38
- useLoadData({
39
- chainId: Number(chainId),
40
- collectionAddress,
41
- collectibleId,
42
- orderId: order.orderId,
43
- marketplace: order.marketplace,
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
- buy,
48
- isLoading: buyIsLoading,
49
- isError: buyIsError,
50
- } = useBuyCollectable({
51
- chainId,
52
- collectionAddress,
53
- callbacks,
54
- tokenId: collectibleId,
55
- priceCurrencyAddress: order.priceCurrencyAddress,
56
- setCheckoutModalIsLoading,
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
- const buyAction = (input: BuyInput) => {
64
- if (buy && checkoutOptions) {
65
- buy({ ...input, checkoutOptions });
66
- buyModal$.state.purchaseProcessing.set(true);
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
- checkoutModalIsLoading ||
81
+ isPaymentModalParamsLoading ||
75
82
  !collection ||
76
83
  !collectable ||
77
- !checkoutOptions ||
78
- buyIsLoading
84
+ !order
79
85
  ) {
80
86
  return (
81
87
  <LoadingModal
82
- isOpen={isOpen}
83
- chainId={Number(chainId)}
84
- onClose={buyModal$.close}
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 (buyIsError || isError) {
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 (buyModal$.state.purchaseProcessing.get()) {
102
- return null;
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, waitFor } from '@test';
2
- import { beforeEach, describe, expect, it, vi } from 'vitest';
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
- vi.mock('@0xsequence/kit', () => ({
30
- useWaasFeeOptions: vi.fn().mockReturnValue([]),
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
- vi.clearAllMocks();
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
- const mockOrderBasic = {
66
- ...mockOrder,
67
- marketplace: MarketplaceKind.sequence_marketplace_v2,
68
- collectionContractAddress: '0x123',
69
- tokenId: '1',
70
- quantityRemaining: '1',
71
- priceCurrencyAddress: '0x0',
72
- chainId: 1,
73
- priceAmount: '1000000000000000000',
74
- };
75
-
76
- // Test loading error
77
- (useLoadData as Mock).mockReturnValue({
78
- collection: { type: ContractType.ERC721 },
79
- collectable: { decimals: 0 },
80
- checkoutOptions: { someOption: true },
81
- isLoading: false,
82
- isError: true,
83
- });
84
-
85
- buyModal$.open({
86
- order: mockOrderBasic,
87
- callbacks: {},
88
- chainId: '1',
89
- collectionAddress: '0x123',
90
- tokenId: '1',
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
- const mockOrderERC1155 = {
138
- ...mockOrder,
139
- marketplace: MarketplaceKind.sequence_marketplace_v2,
140
- collectionContractAddress: '0x123',
141
- tokenId: '1',
142
- quantityRemaining: '10',
143
- priceCurrencyAddress: '0x0',
144
- chainId: 1,
145
- quantityDecimals: 0,
146
- priceAmount: '1000000000000000000',
147
- };
148
-
149
- (useLoadData as Mock).mockReturnValue({
150
- collection: { type: ContractType.ERC1155 },
151
- collectable: { decimals: 0 },
152
- checkoutOptions: { someOption: true },
153
- isLoading: false,
154
- isError: false,
155
- });
156
-
157
- (useBuyCollectable as Mock).mockReturnValue({
158
- buy: vi.fn(),
159
- isLoading: false,
160
- isError: false,
161
- });
162
-
163
- buyModal$.open({
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.skip('should not render ERC1155QuantityModal when contract type is ERC721', async () => {
184
- const mockBuy = vi.fn();
185
- const mockOrderERC721 = {
186
- ...mockOrder,
187
- marketplace: MarketplaceKind.sequence_marketplace_v2,
188
- collectionContractAddress: '0x123',
189
- tokenId: '1',
190
- quantityRemaining: '1',
191
- priceCurrencyAddress: '0x0',
192
- chainId: 1,
193
- priceAmount: '1000000000000000000',
194
- };
195
-
196
- // First, mock loading state
197
- (useLoadData as Mock).mockReturnValue({
198
- collection: null,
199
- collectable: null,
200
- checkoutOptions: null,
201
- isLoading: true,
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
  });