@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,200 @@
1
+ import type { SelectPaymentSettings } from '@0xsequence/checkout';
2
+ import type { TokenMetadata } from '@0xsequence/metadata';
3
+ import { skipToken, useQuery } from '@tanstack/react-query';
4
+ import type { Hash, Hex } from 'viem';
5
+ import type { SdkConfig, Step } from '../../../../..';
6
+ import { decodeERC20Approval } from '../../../../../utils/decode/erc20';
7
+ import {
8
+ type AdditionalFee,
9
+ type CheckoutOptions,
10
+ type MarketplaceKind,
11
+ StepType,
12
+ WalletKind,
13
+ getMarketplaceClient,
14
+ getQueryClient,
15
+ } from '../../../../_internal';
16
+ import type { WalletInstance } from '../../../../_internal/wallet/wallet';
17
+ import { useConfig } from '../../../../hooks';
18
+ import type { ModalCallbacks } from '../../_internal/types';
19
+ import {
20
+ buyModalStore,
21
+ useBuyModalProps,
22
+ useOnError,
23
+ useOnSuccess,
24
+ } from '../store';
25
+ import { useFees } from './useFees';
26
+
27
+ interface GetBuyCollectableParams {
28
+ chainId: number;
29
+ config: SdkConfig;
30
+ wallet: WalletInstance;
31
+ collectionAddress: string;
32
+ collectibleId: string;
33
+ marketplace: MarketplaceKind;
34
+ orderId: string;
35
+ quantity: number;
36
+ collectable: TokenMetadata;
37
+ checkoutOptions: CheckoutOptions;
38
+ fee: AdditionalFee;
39
+ callbacks: ModalCallbacks | undefined;
40
+ priceCurrencyAddress: string;
41
+ customCreditCardProviderCallback: ((buyStep: Step) => void) | undefined;
42
+ skipNativeBalanceCheck: boolean | undefined;
43
+ }
44
+
45
+ export const getBuyCollectableParams = async ({
46
+ chainId,
47
+ collectionAddress,
48
+ collectibleId,
49
+ callbacks,
50
+ priceCurrencyAddress,
51
+ customCreditCardProviderCallback,
52
+ config,
53
+ wallet,
54
+ marketplace,
55
+ orderId,
56
+ quantity,
57
+ collectable,
58
+ checkoutOptions,
59
+ fee,
60
+ }: GetBuyCollectableParams) => {
61
+ const marketplaceClient = getMarketplaceClient(chainId, config);
62
+ const { steps } = await marketplaceClient.generateBuyTransaction({
63
+ collectionAddress,
64
+ buyer: await wallet.address(),
65
+ marketplace: marketplace,
66
+ ordersData: [
67
+ {
68
+ orderId: orderId,
69
+ quantity: quantity.toString(),
70
+ tokenId: collectibleId,
71
+ },
72
+ ],
73
+ additionalFees: [fee],
74
+ walletType: WalletKind.unknown,
75
+ });
76
+
77
+ const buyStep = steps.find((step) => step.id === StepType.buy);
78
+ const approveStep = steps.find((step) => step.id === StepType.tokenApproval);
79
+
80
+ const approvedSpenderAddress = approveStep
81
+ ? decodeERC20Approval(approveStep.data as Hex).spender
82
+ : undefined;
83
+
84
+ if (!buyStep) {
85
+ throw new Error('Buy step not found');
86
+ }
87
+
88
+ return {
89
+ chain: chainId,
90
+ collectibles: [
91
+ {
92
+ tokenId: collectibleId,
93
+ quantity: quantity.toString(),
94
+ decimals: collectable.decimals,
95
+ },
96
+ ],
97
+ currencyAddress: priceCurrencyAddress,
98
+ price: buyStep.price,
99
+ targetContractAddress: buyStep.to,
100
+ approvedSpenderAddress,
101
+ txData: buyStep.data as Hex,
102
+ collectionAddress,
103
+ recipientAddress: await wallet.address(),
104
+ enableMainCurrencyPayment: true,
105
+ enableSwapPayments: !!checkoutOptions.swap,
106
+ creditCardProviders: customCreditCardProviderCallback
107
+ ? ['custom']
108
+ : checkoutOptions.nftCheckout || [],
109
+ onSuccess: (hash: string) => {
110
+ callbacks?.onSuccess?.({ hash: hash as Hash });
111
+ },
112
+ supplementaryAnalyticsInfo: {
113
+ orderId: orderId,
114
+ marketplaceKind: marketplace,
115
+ },
116
+ onError: callbacks?.onError,
117
+ onClose: () => {
118
+ const queryClient = getQueryClient();
119
+ queryClient.invalidateQueries();
120
+ buyModalStore.send({ type: 'close' });
121
+ },
122
+ ...(customCreditCardProviderCallback && {
123
+ customProviderCallback: () => {
124
+ customCreditCardProviderCallback(buyStep);
125
+ buyModalStore.send({ type: 'close' });
126
+ },
127
+ }),
128
+ } satisfies SelectPaymentSettings;
129
+ };
130
+
131
+ interface usePaymentModalParams {
132
+ wallet: WalletInstance | undefined | null;
133
+ quantity: number | undefined;
134
+ marketplace: MarketplaceKind | undefined;
135
+ collectable: TokenMetadata | undefined;
136
+ checkoutOptions: CheckoutOptions | undefined;
137
+ priceCurrencyAddress: string | undefined;
138
+ }
139
+
140
+ export const usePaymentModalParams = (args: usePaymentModalParams) => {
141
+ const {
142
+ wallet,
143
+ marketplace,
144
+ collectable,
145
+ checkoutOptions,
146
+ priceCurrencyAddress,
147
+ quantity,
148
+ } = args;
149
+
150
+ const {
151
+ chainId,
152
+ collectionAddress,
153
+ collectibleId,
154
+ orderId,
155
+ customCreditCardProviderCallback,
156
+ skipNativeBalanceCheck,
157
+ } = useBuyModalProps();
158
+ const config = useConfig();
159
+ const fee = useFees({
160
+ chainId,
161
+ collectionAddress,
162
+ });
163
+ const onSuccess = useOnSuccess();
164
+ const onError = useOnError();
165
+
166
+ const enabled =
167
+ !!wallet &&
168
+ !!marketplace &&
169
+ !!collectable &&
170
+ !!checkoutOptions &&
171
+ !!priceCurrencyAddress &&
172
+ !!quantity;
173
+
174
+ return useQuery({
175
+ queryKey: ['buyCollectableParams', args, quantity, fee],
176
+ queryFn: enabled
177
+ ? () =>
178
+ getBuyCollectableParams({
179
+ chainId,
180
+ config,
181
+ wallet,
182
+ collectionAddress,
183
+ collectibleId,
184
+ marketplace,
185
+ orderId,
186
+ quantity,
187
+ collectable,
188
+ checkoutOptions,
189
+ fee,
190
+ priceCurrencyAddress,
191
+ callbacks: {
192
+ onSuccess: onSuccess,
193
+ onError: onError,
194
+ },
195
+ customCreditCardProviderCallback,
196
+ skipNativeBalanceCheck,
197
+ })
198
+ : skipToken,
199
+ });
200
+ };
@@ -1,20 +1,10 @@
1
- import type { Hex } from 'viem';
2
- import type { Order } from '../../../_internal';
3
1
  import type { ModalCallbacks } from '../_internal/types';
4
- import { buyModal$ } from './store';
5
-
6
- export type ShowBuyModalArgs = {
7
- chainId: string;
8
- collectionAddress: Hex;
9
- tokenId: string;
10
- order: Order;
11
- customProviderCallback?: (args: { data: string; value: string }) => void;
12
- };
2
+ import { type BuyModalProps, buyModalStore } from './store';
13
3
 
14
4
  export const useBuyModal = (callbacks?: ModalCallbacks) => {
15
5
  return {
16
- show: (args: ShowBuyModalArgs) =>
17
- buyModal$.open({ ...args, defaultCallbacks: callbacks }),
18
- close: () => buyModal$.close(),
6
+ show: (args: BuyModalProps) =>
7
+ buyModalStore.send({ type: 'open', props: args, ...callbacks }),
8
+ close: () => buyModalStore.send({ type: 'close' }),
19
9
  };
20
10
  };
@@ -1,82 +1,77 @@
1
- import { observable } from '@legendapp/state';
2
- import type { ShowBuyModalArgs } from '.';
3
- import type { Order } from '../../../_internal';
4
- import type { ModalCallbacks } from '../_internal/types';
1
+ import { createStore } from '@xstate/store';
2
+ import { useSelector } from '@xstate/store/react';
3
+ import type { Address, Hash } from 'viem';
4
+ import type { MarketplaceKind, Step } from '../../../_internal';
5
5
 
6
- const buyState = {
7
- order: undefined as unknown as Order,
8
- quantity: '1',
9
- invalidQuantity: false,
10
- checkoutModalIsLoading: false,
11
- checkoutModalLoaded: false,
12
- purchaseProcessing: false,
13
- customProviderCallback: null,
14
- } as const;
6
+ export type BuyModalProps = {
7
+ orderId: string;
8
+ chainId: number;
9
+ collectionAddress: Address;
10
+ collectibleId: string;
11
+ marketplace: MarketplaceKind;
12
+ customCreditCardProviderCallback?: (buyStep: Step) => void;
13
+ skipNativeBalanceCheck?: boolean;
14
+ };
15
15
 
16
- export interface BuyModalState {
17
- isOpen: boolean;
18
- open: (
19
- args: ShowBuyModalArgs & {
20
- callbacks?: ModalCallbacks;
21
- defaultCallbacks?: ModalCallbacks;
22
- },
23
- ) => void;
24
- close: () => void;
25
- state: {
26
- order: Order;
27
- quantity: string;
28
- invalidQuantity: boolean;
29
- checkoutModalIsLoading: boolean;
30
- checkoutModalLoaded: boolean;
31
- purchaseProcessing: boolean;
32
- customProviderCallback?:
33
- | ((args: { data: string; value: string }) => void)
34
- | null;
35
- };
36
- setCheckoutModalIsLoading: (isLoading: boolean) => void;
37
- setCheckoutModalLoaded: (isLoaded: boolean) => void;
38
- setPurchaseProcessing: (isProcessing: boolean) => void;
39
- callbacks?: ModalCallbacks;
40
- }
16
+ export type onSuccessCallback = ({
17
+ hash,
18
+ orderId,
19
+ }: {
20
+ hash?: Hash;
21
+ orderId?: string;
22
+ }) => void;
23
+ export type onErrorCallback = (error: Error) => void;
41
24
 
42
- export const initialState: BuyModalState = {
25
+ const initialContext = {
43
26
  isOpen: false,
44
- open: ({
45
- callbacks,
46
- defaultCallbacks,
47
- ...args
48
- }: ShowBuyModalArgs & {
49
- callbacks?: ModalCallbacks;
50
- defaultCallbacks?: ModalCallbacks;
51
- }) => {
52
- buyModal$.state.set({
53
- quantity: args.order.quantityAvailableFormatted,
54
- order: args.order,
55
- invalidQuantity: false,
56
- checkoutModalIsLoading: false,
57
- checkoutModalLoaded: false,
58
- purchaseProcessing: false,
59
- customProviderCallback: args.customProviderCallback,
60
- });
61
- buyModal$.callbacks.set(callbacks || defaultCallbacks);
62
- buyModal$.isOpen.set(true);
63
- },
64
- close: () => {
65
- buyModal$.isOpen.set(false);
66
- buyModal$.callbacks.set(undefined);
67
- buyModal$.state.set(buyState);
68
- },
69
- state: buyState,
70
- setCheckoutModalIsLoading: (isLoading: boolean) => {
71
- buyModal$.state.checkoutModalIsLoading.set(isLoading);
72
- },
73
- setCheckoutModalLoaded: (isLoaded: boolean) => {
74
- buyModal$.state.checkoutModalLoaded.set(isLoaded);
75
- },
76
- setPurchaseProcessing: (isProcessing: boolean) => {
77
- buyModal$.state.purchaseProcessing.set(isProcessing);
78
- },
79
- callbacks: undefined,
27
+ props: null as unknown as BuyModalProps,
28
+ onError: (() => {}) as onErrorCallback,
29
+ onSuccess: (() => {}) as onSuccessCallback,
30
+ quantity: undefined as number | undefined,
80
31
  };
81
32
 
82
- export const buyModal$ = observable(initialState);
33
+ export const buyModalStore = createStore({
34
+ context: { ...initialContext },
35
+ on: {
36
+ open: (
37
+ context,
38
+ event: {
39
+ props: BuyModalProps;
40
+ onError?: onErrorCallback;
41
+ onSuccess?: onSuccessCallback;
42
+ },
43
+ ) => ({
44
+ ...context,
45
+ props: event.props,
46
+ onError: event.onError ?? context.onError,
47
+ onSuccess: event.onSuccess ?? context.onSuccess,
48
+ isOpen: true,
49
+ }),
50
+
51
+ close: (context) => ({
52
+ ...context,
53
+ isOpen: false,
54
+ quantity: undefined,
55
+ }),
56
+
57
+ setQuantity: (context, event: { quantity: number }) => ({
58
+ ...context,
59
+ quantity: event.quantity,
60
+ }),
61
+ },
62
+ });
63
+
64
+ export const useIsOpen = () =>
65
+ useSelector(buyModalStore, (state) => state.context.isOpen);
66
+
67
+ export const useBuyModalProps = () =>
68
+ useSelector(buyModalStore, (state) => state.context.props);
69
+
70
+ export const useOnError = () =>
71
+ useSelector(buyModalStore, (state) => state.context.onError);
72
+
73
+ export const useOnSuccess = () =>
74
+ useSelector(buyModalStore, (state) => state.context.onSuccess);
75
+
76
+ export const useQuantity = () =>
77
+ useSelector(buyModalStore, (state) => state.context.quantity);
@@ -3,8 +3,10 @@
3
3
  import { Show, observer } from '@legendapp/state/react';
4
4
  import { parseUnits } from 'viem';
5
5
  import { useAccount } from 'wagmi';
6
+ import type { FeeOption } from '../../../../types/waas-types';
6
7
  import { dateToUnixTime } from '../../../../utils/date';
7
8
  import type { ContractType } from '../../../_internal';
9
+ import { useWallet } from '../../../_internal/wallet/useWallet';
8
10
  import {
9
11
  useBalanceOfCollectible,
10
12
  useCollectible,
@@ -20,8 +22,11 @@ import ExpirationDateSelect from '../_internal/components/expirationDateSelect';
20
22
  import FloorPriceText from '../_internal/components/floorPriceText';
21
23
  import PriceInput from '../_internal/components/priceInput';
22
24
  import QuantityInput from '../_internal/components/quantityInput';
25
+ import SelectWaasFeeOptions from '../_internal/components/selectWaasFeeOptions';
26
+ import { selectWaasFeeOptions$ } from '../_internal/components/selectWaasFeeOptions/store';
23
27
  import TokenPreview from '../_internal/components/tokenPreview';
24
28
  import TransactionDetails from '../_internal/components/transactionDetails';
29
+ import { useSelectWaasFeeOptions } from '../_internal/hooks/useSelectWaasFeeOptions';
25
30
  import { useCreateListing } from './hooks/useCreateListing';
26
31
  import { createListingModal$ } from './store';
27
32
 
@@ -38,8 +43,23 @@ const Modal = observer(() => {
38
43
  collectibleId,
39
44
  orderbookKind,
40
45
  callbacks,
46
+ listingIsBeingProcessed,
41
47
  } = state;
42
48
  const steps$ = createListingModal$.steps;
49
+ const { wallet } = useWallet();
50
+
51
+ const {
52
+ shouldHideActionButton: shouldHideListButton,
53
+ waasFeeOptionsShown,
54
+ getActionLabel,
55
+ isTestnet,
56
+ } = useSelectWaasFeeOptions({
57
+ chainId,
58
+ isProcessing: listingIsBeingProcessed,
59
+ feeOptionsVisible: selectWaasFeeOptions$.isVisible.get(),
60
+ selectedFeeOption:
61
+ selectWaasFeeOptions$.selectedFeeOption.get() as FeeOption,
62
+ });
43
63
 
44
64
  const {
45
65
  data: collectible,
@@ -73,7 +93,7 @@ const Modal = observer(() => {
73
93
  const { address } = useAccount();
74
94
 
75
95
  const { data: balance } = useBalanceOfCollectible({
76
- chainId: Number(chainId),
96
+ chainId,
77
97
  collectionAddress,
78
98
  collectableId: collectibleId,
79
99
  userAddress: address ?? undefined,
@@ -125,6 +145,27 @@ const Modal = observer(() => {
125
145
  );
126
146
  }
127
147
 
148
+ const handleCreateListing = async () => {
149
+ createListingModal$.listingIsBeingProcessed.set(true);
150
+
151
+ try {
152
+ if (wallet?.isWaaS) {
153
+ selectWaasFeeOptions$.isVisible.set(true);
154
+ }
155
+
156
+ await createListing({
157
+ isTransactionExecuting: wallet?.isWaaS ? !isTestnet : false,
158
+ });
159
+ } catch (error) {
160
+ console.error('Create listing failed:', error);
161
+ } finally {
162
+ createListingModal$.listingIsBeingProcessed.set(false);
163
+ steps$.transaction.isExecuting.set(false);
164
+ }
165
+ };
166
+
167
+ const listCtaLabel = getActionLabel('List item for sale');
168
+
128
169
  const ctas = [
129
170
  {
130
171
  label: 'Approve TOKEN',
@@ -140,16 +181,19 @@ const Modal = observer(() => {
140
181
  isLoading,
141
182
  },
142
183
  {
143
- label: 'List item for sale',
144
- onClick: () => createListing(),
145
- pending: steps$?.transaction.isExecuting.get(),
184
+ label: listCtaLabel,
185
+ onClick: handleCreateListing,
186
+ pending:
187
+ steps$?.transaction.isExecuting.get() ||
188
+ createListingModal$.listingIsBeingProcessed.get(),
146
189
  testid: 'create-listing-submit-button',
147
190
  disabled:
148
191
  steps$.approval.exist.get() ||
149
192
  tokenApprovalIsLoading ||
150
193
  listingPrice.amountRaw === '0' ||
151
194
  createListingModal$.invalidQuantity.get() ||
152
- isLoading,
195
+ isLoading ||
196
+ listingIsBeingProcessed,
153
197
  },
154
198
  ] satisfies ActionModalProps['ctas'];
155
199
 
@@ -157,11 +201,15 @@ const Modal = observer(() => {
157
201
  <ActionModal
158
202
  isOpen={createListingModal$.isOpen.get()}
159
203
  chainId={Number(chainId)}
160
- onClose={() => createListingModal$.close()}
204
+ onClose={() => {
205
+ createListingModal$.close();
206
+ selectWaasFeeOptions$.hide();
207
+ }}
161
208
  title="List item for sale"
162
209
  ctas={ctas}
163
210
  modalLoading={modalLoading}
164
211
  spinnerContainerClassname="h-[220px]"
212
+ hideCtas={shouldHideListButton}
165
213
  >
166
214
  <TokenPreview
167
215
  collectionName={collection?.name}
@@ -174,6 +222,7 @@ const Modal = observer(() => {
174
222
  chainId={chainId}
175
223
  collectionAddress={collectionAddress}
176
224
  $price={createListingModal$.listingPrice}
225
+ disabled={shouldHideListButton}
177
226
  />
178
227
 
179
228
  {listingPrice.amountRaw !== '0' && (
@@ -191,9 +240,13 @@ const Modal = observer(() => {
191
240
  $invalidQuantity={createListingModal$.invalidQuantity}
192
241
  decimals={collectible?.decimals || 0}
193
242
  maxQuantity={balance?.balance}
243
+ disabled={shouldHideListButton}
194
244
  />
195
245
  )}
196
- <ExpirationDateSelect $date={createListingModal$.expiry} />
246
+ <ExpirationDateSelect
247
+ $date={createListingModal$.expiry}
248
+ disabled={shouldHideListButton}
249
+ />
197
250
  <TransactionDetails
198
251
  collectibleId={collectibleId}
199
252
  collectionAddress={collectionAddress}
@@ -202,6 +255,17 @@ const Modal = observer(() => {
202
255
  currencyImageUrl={listingPrice.currency.imageUrl}
203
256
  includeMarketplaceFee={false}
204
257
  />
258
+
259
+ {waasFeeOptionsShown && (
260
+ <SelectWaasFeeOptions
261
+ chainId={Number(chainId)}
262
+ onCancel={() => {
263
+ createListingModal$.listingIsBeingProcessed.set(false);
264
+ steps$.transaction.isExecuting.set(false);
265
+ }}
266
+ titleOnConfirm="Processing listing..."
267
+ />
268
+ )}
205
269
  </ActionModal>
206
270
  );
207
271
  });
@@ -24,7 +24,7 @@ vi.mock('@0xsequence/kit', () => ({
24
24
 
25
25
  const defaultArgs = {
26
26
  collectionAddress: zeroAddress,
27
- chainId: '1',
27
+ chainId: 1,
28
28
  collectibleId: '1',
29
29
  };
30
30
 
@@ -85,7 +85,7 @@ describe.skip('CreateListingModal', () => {
85
85
  // Reopen modal
86
86
  createListingModal$.open({
87
87
  collectionAddress: '0x456',
88
- chainId: '1',
88
+ chainId: 1,
89
89
  collectibleId: '2',
90
90
  });
91
91
 
@@ -20,7 +20,7 @@ export interface ListingInput {
20
20
 
21
21
  interface UseCreateListingArgs {
22
22
  listingInput: ListingInput;
23
- chainId: string;
23
+ chainId: number;
24
24
  collectionAddress: string;
25
25
  orderbookKind?: OrderbookKind;
26
26
  callbacks?: ModalCallbacks;
@@ -14,7 +14,7 @@ import {
14
14
  import { useWallet } from '../../../../_internal/wallet/useWallet';
15
15
 
16
16
  export interface UseGetTokenApprovalDataArgs {
17
- chainId: string;
17
+ chainId: number;
18
18
  tokenId: string;
19
19
  collectionAddress: string;
20
20
  currencyAddress: string;
@@ -27,7 +27,7 @@ import { useTransactionStatusModal } from '../../_internal/components/transactio
27
27
  import type { ModalCallbacks } from '../../_internal/types';
28
28
  interface UseTransactionStepsArgs {
29
29
  listingInput: ListingInput;
30
- chainId: string;
30
+ chainId: number;
31
31
  collectionAddress: string;
32
32
  orderbookKind: OrderbookKind;
33
33
  callbacks?: ModalCallbacks;
@@ -49,7 +49,7 @@ export const useTransactionSteps = ({
49
49
  const { show: showTransactionStatusModal } = useTransactionStatusModal();
50
50
  const sdkConfig = useConfig();
51
51
  const { data: currencies } = useCurrencies({
52
- chainId: Number(chainId),
52
+ chainId,
53
53
  });
54
54
  const currency = currencies?.find(
55
55
  (currency) =>
@@ -115,11 +115,15 @@ export const useTransactionSteps = ({
115
115
  }
116
116
  };
117
117
 
118
- const createListing = async () => {
118
+ const createListing = async ({
119
+ isTransactionExecuting,
120
+ }: {
121
+ isTransactionExecuting: boolean;
122
+ }) => {
119
123
  if (!wallet) return;
120
124
 
121
125
  try {
122
- steps$.transaction.isExecuting.set(true);
126
+ steps$.transaction.isExecuting.set(isTransactionExecuting);
123
127
  const steps = await getListingSteps();
124
128
  const transactionStep = steps?.find(
125
129
  (step) => step.id === StepType.createListing,
@@ -199,7 +203,7 @@ export const useTransactionSteps = ({
199
203
  collectionAddress,
200
204
  currencyAddress: listingInput.listing.currencyAddress,
201
205
  currencySymbol: '',
202
- chainId,
206
+ chainId: chainId.toString(),
203
207
  txnHash: hash || '',
204
208
  },
205
209
  nums: {
@@ -18,11 +18,12 @@ type CreateListingState = BaseModalState & {
18
18
  invalidQuantity: boolean;
19
19
  expiry: Date;
20
20
  steps: TransactionSteps;
21
+ listingIsBeingProcessed: boolean;
21
22
  };
22
23
 
23
24
  export type OpenCreateListingModalArgs = {
24
25
  collectionAddress: Hex;
25
- chainId: string;
26
+ chainId: number;
26
27
  collectibleId: string;
27
28
  orderbookKind?: OrderbookKind;
28
29
  callbacks?: ModalCallbacks;
@@ -58,7 +59,7 @@ const steps = {
58
59
  const initialState: CreateListingState = {
59
60
  isOpen: false,
60
61
  collectionAddress: '' as Hex,
61
- chainId: '',
62
+ chainId: 0,
62
63
  collectibleId: '',
63
64
  orderbookKind: OrderbookKind.sequence_marketplace_v2,
64
65
  collectionName: '',
@@ -69,6 +70,7 @@ const initialState: CreateListingState = {
69
70
  expiry: new Date(addDays(new Date(), 7).toJSON()),
70
71
  callbacks: undefined as ModalCallbacks | undefined,
71
72
  steps: { ...steps },
73
+ listingIsBeingProcessed: false,
72
74
  };
73
75
 
74
76
  const actions: Actions = {
@@ -85,6 +87,9 @@ const actions: Actions = {
85
87
  createListingModal$.set({ ...initialState, ...actions });
86
88
  createListingModal$.listingPrice.set({ ...listingPrice });
87
89
  createListingModal$.steps.set({ ...steps });
90
+ createListingModal$.listingIsBeingProcessed.set(false);
91
+ createListingModal$.steps.approval.isExecuting.set(false);
92
+ createListingModal$.steps.transaction.isExecuting.set(false);
88
93
  },
89
94
  };
90
95