@0xsequence/marketplace-sdk 0.4.3 → 0.4.5

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 (78) hide show
  1. package/dist/{chunk-VYSWBIWC.js → chunk-CKOWM2ZR.js} +3 -3
  2. package/dist/{chunk-4VS5NKDD.js → chunk-FT3J32ZV.js} +2 -2
  3. package/dist/{chunk-IQXJZBMR.js → chunk-HTFBQVLV.js} +2 -2
  4. package/dist/{chunk-URX7ZHX4.js → chunk-KILOCWY2.js} +2 -2
  5. package/dist/{chunk-YZE7RXC2.js → chunk-KL5JPUPS.js} +10 -8
  6. package/dist/chunk-KL5JPUPS.js.map +1 -0
  7. package/dist/{chunk-ST6RH2IB.js → chunk-KZGDOIZY.js} +24 -575
  8. package/dist/chunk-KZGDOIZY.js.map +1 -0
  9. package/dist/{chunk-2AMLJ2TA.js → chunk-SEISACMH.js} +461 -251
  10. package/dist/chunk-SEISACMH.js.map +1 -0
  11. package/dist/{chunk-DNDPYQKV.js → chunk-YUETNNZQ.js} +1 -144
  12. package/dist/{chunk-DNDPYQKV.js.map → chunk-YUETNNZQ.js.map} +1 -1
  13. package/dist/{create-config-8sffBvlt.d.ts → create-config-DMBOGsJp.d.ts} +1 -1
  14. package/dist/index.d.ts +1 -1
  15. package/dist/index.js +16 -16
  16. package/dist/{marketplace-config-Bbxl-uKX.d.ts → marketplace-config-0Rft6_Hv.d.ts} +2 -0
  17. package/dist/react/_internal/api/index.js +2 -2
  18. package/dist/react/_internal/index.d.ts +2 -2
  19. package/dist/react/_internal/index.js +8 -8
  20. package/dist/react/_internal/wagmi/index.d.ts +3 -2
  21. package/dist/react/_internal/wagmi/index.js +2 -2
  22. package/dist/react/hooks/index.d.ts +4 -205
  23. package/dist/react/hooks/index.js +8 -11
  24. package/dist/react/index.d.ts +7 -4
  25. package/dist/react/index.js +16 -16
  26. package/dist/react/ssr/index.d.ts +14 -0
  27. package/dist/react/ssr/index.js +10 -32
  28. package/dist/react/ssr/index.js.map +1 -1
  29. package/dist/react/ui/components/index.js +11 -11
  30. package/dist/react/ui/index.d.ts +4 -1
  31. package/dist/react/ui/index.js +11 -11
  32. package/dist/react/ui/modals/_internal/components/actionModal/index.js +8 -8
  33. package/dist/react/ui/styles/index.d.ts +1 -1
  34. package/dist/styles/index.d.ts +1 -1
  35. package/dist/types/index.d.ts +1 -1
  36. package/dist/types/index.js +3 -3
  37. package/dist/utils/abi/index.js +5 -5
  38. package/dist/utils/index.js +7 -7
  39. package/package.json +1 -1
  40. package/src/react/hooks/index.ts +0 -1
  41. package/src/react/hooks/useCancelTransactionSteps.tsx +7 -4
  42. package/src/react/hooks/useCurrency.tsx +1 -1
  43. package/src/react/provider.tsx +18 -3
  44. package/src/react/ssr/create-ssr-client.ts +9 -5
  45. package/src/react/ui/modals/BuyModal/Modal.tsx +4 -0
  46. package/src/react/ui/modals/BuyModal/hooks/useBuyCollectable.ts +29 -2
  47. package/src/react/ui/modals/BuyModal/modals/Modal1155.tsx +8 -3
  48. package/src/react/ui/modals/BuyModal/store.ts +14 -0
  49. package/src/react/ui/modals/CreateListingModal/Modal.tsx +1 -1
  50. package/src/react/ui/modals/CreateListingModal/hooks/useCreateListing.tsx +21 -5
  51. package/src/react/ui/modals/CreateListingModal/hooks/useGetTokenApproval.ts +34 -28
  52. package/src/react/ui/modals/CreateListingModal/hooks/useTransactionSteps.tsx +43 -16
  53. package/src/react/ui/modals/MakeOfferModal/Modal.tsx +43 -9
  54. package/src/react/ui/modals/MakeOfferModal/hooks/useGetTokenApproval.tsx +34 -28
  55. package/src/react/ui/modals/MakeOfferModal/hooks/useMakeOffer.tsx +8 -8
  56. package/src/react/ui/modals/MakeOfferModal/hooks/useTransactionSteps.tsx +64 -22
  57. package/src/react/ui/modals/SellModal/hooks/useTransactionSteps.tsx +30 -12
  58. package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/useHandleTransfer.tsx +38 -54
  59. package/src/react/ui/modals/_internal/components/currencyImage/index.tsx +8 -10
  60. package/src/react/ui/modals/_internal/components/currencyOptionsSelect/index.tsx +9 -1
  61. package/src/react/ui/modals/_internal/components/priceInput/hooks/useBalanceCheck.ts +67 -0
  62. package/src/react/ui/modals/_internal/components/priceInput/hooks/usePriceInput.ts +54 -0
  63. package/src/react/ui/modals/_internal/components/priceInput/index.tsx +48 -71
  64. package/src/react/ui/modals/_internal/components/quantityInput/index.tsx +2 -1
  65. package/src/react/ui/modals/_internal/components/switchChainModal/index.tsx +2 -2
  66. package/src/react/ui/modals/_internal/components/transactionStatusModal/index.tsx +18 -9
  67. package/src/react/ui/modals/_internal/components/transactionStatusModal/util/getMessage.ts +12 -1
  68. package/src/react/ui/modals/_internal/types.ts +1 -1
  69. package/src/types/marketplace-config.ts +3 -0
  70. package/tsconfig.tsbuildinfo +1 -1
  71. package/dist/chunk-2AMLJ2TA.js.map +0 -1
  72. package/dist/chunk-ST6RH2IB.js.map +0 -1
  73. package/dist/chunk-YZE7RXC2.js.map +0 -1
  74. package/src/react/hooks/useBuyCollectable.tsx +0 -61
  75. /package/dist/{chunk-VYSWBIWC.js.map → chunk-CKOWM2ZR.js.map} +0 -0
  76. /package/dist/{chunk-4VS5NKDD.js.map → chunk-FT3J32ZV.js.map} +0 -0
  77. /package/dist/{chunk-IQXJZBMR.js.map → chunk-HTFBQVLV.js.map} +0 -0
  78. /package/dist/{chunk-URX7ZHX4.js.map → chunk-KILOCWY2.js.map} +0 -0
@@ -2,8 +2,11 @@ import { useSelectPaymentModal } from '@0xsequence/kit-checkout';
2
2
  import type { Hash, Hex } from 'viem';
3
3
  import type { ModalCallbacks } from '../../_internal/types';
4
4
  import {
5
+ balanceQueries,
5
6
  type CheckoutOptions,
7
+ collectableKeys,
6
8
  getMarketplaceClient,
9
+ getQueryClient,
7
10
  type MarketplaceKind,
8
11
  WalletKind,
9
12
  } from '../../../../_internal';
@@ -11,6 +14,7 @@ import { buyModal$ } from '../store';
11
14
  import { useFees } from './useFees';
12
15
  import { useConfig } from '../../../../hooks';
13
16
  import { useWallet } from '../../../../_internal/transaction-machine/useWallet';
17
+ import { QueryKey } from '@tanstack/react-query';
14
18
 
15
19
  interface UseBuyCollectableProps {
16
20
  chainId: string;
@@ -18,6 +22,8 @@ interface UseBuyCollectableProps {
18
22
  tokenId: string;
19
23
  callbacks?: ModalCallbacks;
20
24
  priceCurrencyAddress: string;
25
+ setCheckoutModalIsLoading: (isLoading: boolean) => void;
26
+ setCheckoutModalLoaded: (isLoaded: boolean) => void;
21
27
  }
22
28
 
23
29
  type BuyCollectableReturn =
@@ -42,6 +48,8 @@ export const useBuyCollectable = ({
42
48
  tokenId,
43
49
  callbacks,
44
50
  priceCurrencyAddress,
51
+ setCheckoutModalIsLoading,
52
+ setCheckoutModalLoaded,
45
53
  }: UseBuyCollectableProps): BuyCollectableReturn => {
46
54
  const { openSelectPaymentModal } = useSelectPaymentModal();
47
55
  const config = useConfig();
@@ -57,6 +65,13 @@ export const useBuyCollectable = ({
57
65
  return { status: 'error', buy: null, isLoading, isError: true };
58
66
  }
59
67
 
68
+ const invalidateQueries = async (queriesToInvalidate: QueryKey[]) => {
69
+ const queryClient = getQueryClient();
70
+ for (const queryKey of queriesToInvalidate) {
71
+ await queryClient.invalidateQueries({ queryKey });
72
+ }
73
+ };
74
+
60
75
  return {
61
76
  status: 'ready',
62
77
  isLoading,
@@ -76,6 +91,10 @@ export const useBuyCollectable = ({
76
91
  walletType: WalletKind.unknown,
77
92
  });
78
93
 
94
+ // these states are necessary to manage appearance of the quantity modal
95
+ setCheckoutModalLoaded(true);
96
+ setCheckoutModalIsLoading(false);
97
+
79
98
  const step = steps[0];
80
99
 
81
100
  openSelectPaymentModal({
@@ -96,10 +115,18 @@ export const useBuyCollectable = ({
96
115
  enableMainCurrencyPayment: true,
97
116
  enableSwapPayments: !!input.checkoutOptions.swap,
98
117
  creditCardProviders: input.checkoutOptions.nftCheckout || [],
99
- onSuccess: (hash: string) => callbacks?.onSuccess?.(hash as Hash),
118
+ onSuccess: (hash: string) => {
119
+ invalidateQueries([
120
+ collectableKeys.listings,
121
+ collectableKeys.listingsCount,
122
+ collectableKeys.lists,
123
+ collectableKeys.userBalances,
124
+ balanceQueries.all,
125
+ ]);
126
+ callbacks?.onSuccess?.({ hash: hash as Hash });
127
+ },
100
128
  onError: callbacks?.onError,
101
129
  onClose: () => {
102
- console.log('onClose');
103
130
  buyModal$.close();
104
131
  },
105
132
  });
@@ -17,9 +17,6 @@ interface ERC1155QuantityModalProps extends CheckoutModalProps {
17
17
 
18
18
  export const ERC1155QuantityModal = observer(
19
19
  ({ buy, collectable, order }: ERC1155QuantityModalProps) => {
20
- buyModal$.state.quantity.set(
21
- Math.min(Number(order.quantityRemaining), 1).toString(),
22
- );
23
20
  const currencyOptions = useCurrencyOptions({
24
21
  collectionAddress: order.collectionContractAddress as Address,
25
22
  });
@@ -36,6 +33,10 @@ export const ERC1155QuantityModal = observer(
36
33
  const pricePerToken = order.priceAmount;
37
34
  const totalPrice = (BigInt(quantity) * BigInt(pricePerToken)).toString();
38
35
 
36
+ if (buyModal$.state.checkoutModalLoaded.get()) {
37
+ return null;
38
+ }
39
+
39
40
  return (
40
41
  <ActionModal
41
42
  isOpen={buyModal$.isOpen.get()}
@@ -46,6 +47,8 @@ export const ERC1155QuantityModal = observer(
46
47
  {
47
48
  label: 'Buy now',
48
49
  onClick: () => {
50
+ buyModal$.state.checkoutModalIsLoading.set(true);
51
+
49
52
  buy({
50
53
  quantity: parseUnits(
51
54
  buyModal$.state.quantity.get(),
@@ -56,6 +59,8 @@ export const ERC1155QuantityModal = observer(
56
59
  marketplace: order.marketplace,
57
60
  });
58
61
  },
62
+ disabled: buyModal$.state.checkoutModalIsLoading.get(),
63
+ pending: buyModal$.state.checkoutModalIsLoading.get(),
59
64
  },
60
65
  ]}
61
66
  >
@@ -17,7 +17,11 @@ export interface BuyModalState {
17
17
  quantity: string;
18
18
  modalId: number;
19
19
  invalidQuantity: boolean;
20
+ checkoutModalIsLoading: boolean;
21
+ checkoutModalLoaded: boolean;
20
22
  };
23
+ setCheckoutModalIsLoading: (isLoading: boolean) => void;
24
+ setCheckoutModalLoaded: (isLoaded: boolean) => void;
21
25
  callbacks?: ModalCallbacks;
22
26
  }
23
27
 
@@ -36,6 +40,8 @@ export const initialState: BuyModalState = {
36
40
  order: args.order,
37
41
  modalId: buyModal$.state.modalId.get() + 1,
38
42
  invalidQuantity: false,
43
+ checkoutModalIsLoading: false,
44
+ checkoutModalLoaded: false,
39
45
  });
40
46
  buyModal$.callbacks.set(callbacks || defaultCallbacks);
41
47
  buyModal$.isOpen.set(true);
@@ -48,6 +54,14 @@ export const initialState: BuyModalState = {
48
54
  quantity: '1',
49
55
  modalId: 0,
50
56
  invalidQuantity: false,
57
+ checkoutModalIsLoading: false,
58
+ checkoutModalLoaded: false,
59
+ },
60
+ setCheckoutModalIsLoading: (isLoading: boolean) => {
61
+ buyModal$.state.checkoutModalIsLoading.set(isLoading);
62
+ },
63
+ setCheckoutModalLoaded: (isLoaded: boolean) => {
64
+ buyModal$.state.checkoutModalLoaded.set(isLoaded);
51
65
  },
52
66
  callbacks: undefined,
53
67
  };
@@ -159,7 +159,7 @@ const Modal = observer(() => {
159
159
  <PriceInput
160
160
  chainId={chainId}
161
161
  collectionAddress={collectionAddress}
162
- $listingPrice={createListingModal$.listingPrice}
162
+ $price={createListingModal$.listingPrice}
163
163
  />
164
164
 
165
165
  {listingPrice.amountRaw !== '0' && (
@@ -1,9 +1,10 @@
1
+ import type { Observable } from '@legendapp/state';
1
2
  import { useEffect } from 'react';
2
- import { Observable } from '@legendapp/state';
3
+ import { OrderbookKind, type TransactionSteps } from '../../../../_internal';
4
+ import type { ListingInput } from '../../../../_internal/transaction-machine/execute-transaction';
5
+ import { useMarketplaceConfig } from '../../../../hooks';
6
+ import type { ModalCallbacks } from '../../_internal/types';
3
7
  import { useGetTokenApprovalData } from './useGetTokenApproval';
4
- import { ListingInput } from '../../../../_internal/transaction-machine/execute-transaction';
5
- import { OrderbookKind, TransactionSteps } from '../../../../_internal';
6
- import { ModalCallbacks } from '../../_internal/types';
7
8
  import { useTransactionSteps } from './useTransactionSteps';
8
9
 
9
10
  interface UseCreateListingArgs {
@@ -20,11 +21,23 @@ export const useCreateListing = ({
20
21
  listingInput,
21
22
  chainId,
22
23
  collectionAddress,
23
- orderbookKind = OrderbookKind.sequence_marketplace_v2,
24
+ orderbookKind,
24
25
  steps$,
25
26
  callbacks,
26
27
  closeMainModal,
27
28
  }: UseCreateListingArgs) => {
29
+ const { data: marketplaceConfig, isLoading: marketplaceIsLoading } =
30
+ useMarketplaceConfig();
31
+
32
+ const collectionConfig = marketplaceConfig?.collections.find(
33
+ (c) => c.collectionAddress === collectionAddress,
34
+ );
35
+
36
+ orderbookKind =
37
+ orderbookKind ??
38
+ collectionConfig?.destinationMarketplace ??
39
+ OrderbookKind.sequence_marketplace_v2;
40
+
28
41
  const { data: tokenApproval, isLoading: tokenApprovalIsLoading } =
29
42
  useGetTokenApprovalData({
30
43
  chainId,
@@ -33,6 +46,9 @@ export const useCreateListing = ({
33
46
  currencyAddress: listingInput.listing.currencyAddress,
34
47
  contractType: listingInput.contractType,
35
48
  orderbook: orderbookKind,
49
+ query: {
50
+ enabled: !marketplaceIsLoading,
51
+ },
36
52
  });
37
53
 
38
54
  useEffect(() => {
@@ -1,15 +1,16 @@
1
+ import { skipToken, useQuery } from '@tanstack/react-query';
2
+ import { useConfig } from '../../../..';
3
+ import { dateToUnixTime } from '../../../../../utils/date';
1
4
  import {
2
5
  type ContractType,
3
6
  type CreateReq,
4
7
  type GenerateListingTransactionArgs,
5
- getMarketplaceClient,
6
8
  type OrderbookKind,
9
+ type QueryArg,
7
10
  StepType,
11
+ getMarketplaceClient,
8
12
  } from '../../../../_internal';
9
- import { useConfig } from '../../../..';
10
- import { dateToUnixTime } from '../../../../../utils/date';
11
13
  import { useWallet } from '../../../../_internal/transaction-machine/useWallet';
12
- import { useQuery } from '@tanstack/react-query';
13
14
 
14
15
  export interface UseGetTokenApprovalDataArgs {
15
16
  chainId: string;
@@ -18,6 +19,7 @@ export interface UseGetTokenApprovalDataArgs {
18
19
  currencyAddress: string;
19
20
  contractType: ContractType;
20
21
  orderbook: OrderbookKind;
22
+ query?: QueryArg;
21
23
  }
22
24
 
23
25
  const ONE_DAY_IN_SECONDS = 60 * 60 * 24;
@@ -37,34 +39,38 @@ export const useGetTokenApprovalData = (
37
39
  expiry: String(Number(dateToUnixTime(new Date())) + ONE_DAY_IN_SECONDS),
38
40
  } satisfies CreateReq;
39
41
 
42
+ const isEnabled = wallet && params.query?.enabled !== false;
43
+
40
44
  const { data, isLoading, isSuccess } = useQuery({
41
45
  queryKey: ['token-approval-data', params.currencyAddress],
42
- queryFn: async () => {
43
- const args = {
44
- collectionAddress: params.collectionAddress,
45
- owner: await wallet!.address(),
46
- walletType: wallet!.walletKind,
47
- contractType: params.contractType,
48
- orderbook: params.orderbook,
49
- listing,
50
- } satisfies GenerateListingTransactionArgs;
51
- const steps = await marketplaceClient
52
- .generateListingTransaction(args)
53
- .then((resp) => resp.steps);
46
+ queryFn: isEnabled
47
+ ? async () => {
48
+ const args = {
49
+ collectionAddress: params.collectionAddress,
50
+ owner: await wallet.address(),
51
+ walletType: wallet.walletKind,
52
+ contractType: params.contractType,
53
+ orderbook: params.orderbook,
54
+ listing,
55
+ } satisfies GenerateListingTransactionArgs;
56
+ const steps = await marketplaceClient
57
+ .generateListingTransaction(args)
58
+ .then((resp) => resp.steps);
54
59
 
55
- const tokenApprovalStep = steps.find(
56
- (step) => step.id === StepType.tokenApproval,
57
- );
58
- if (!tokenApprovalStep) {
59
- return {
60
- step: null,
61
- };
62
- }
60
+ const tokenApprovalStep = steps.find(
61
+ (step) => step.id === StepType.tokenApproval,
62
+ );
63
+ if (!tokenApprovalStep) {
64
+ return {
65
+ step: null,
66
+ };
67
+ }
63
68
 
64
- return {
65
- step: tokenApprovalStep,
66
- };
67
- },
69
+ return {
70
+ step: tokenApprovalStep,
71
+ };
72
+ }
73
+ : skipToken,
68
74
  });
69
75
 
70
76
  return {
@@ -1,29 +1,31 @@
1
+ import type { Observable } from '@legendapp/state';
2
+ import type { Address } from 'viem';
3
+ import type { OrderbookKind } from '../../../../../types';
1
4
  import {
2
5
  ExecuteType,
3
- getMarketplaceClient,
4
- Step,
6
+ type Step,
5
7
  StepType,
6
- TransactionSteps,
8
+ type TransactionSteps,
9
+ balanceQueries,
10
+ collectableKeys,
11
+ getMarketplaceClient,
7
12
  } from '../../../../_internal';
8
- import { OrderbookKind } from '../../../../../types';
9
- import { ModalCallbacks } from '../../_internal/types';
10
13
  import {
11
- ListingInput,
14
+ type ListingInput,
12
15
  TransactionType,
13
16
  } from '../../../../_internal/transaction-machine/execute-transaction';
14
- import { useTransactionStatusModal } from '../../_internal/components/transactionStatusModal';
15
- import { Address } from 'viem';
16
- import { Observable } from '@legendapp/state';
17
17
  import { useWallet } from '../../../../_internal/transaction-machine/useWallet';
18
- import { SignatureStep } from '../../../../_internal/transaction-machine/utils';
18
+ import type { SignatureStep } from '../../../../_internal/transaction-machine/utils';
19
19
  import { useConfig, useGenerateListingTransaction } from '../../../../hooks';
20
20
  import { useGetReceiptFromHash } from '../../../../hooks/useGetReceiptFromHash';
21
+ import { useTransactionStatusModal } from '../../_internal/components/transactionStatusModal';
22
+ import type { ModalCallbacks } from '../../_internal/types';
21
23
 
22
24
  interface UseTransactionStepsArgs {
23
25
  listingInput: ListingInput;
24
26
  chainId: string;
25
27
  collectionAddress: string;
26
- orderbookKind?: OrderbookKind;
28
+ orderbookKind: OrderbookKind;
27
29
  callbacks?: ModalCallbacks;
28
30
  closeMainModal: () => void;
29
31
  steps$: Observable<TransactionSteps>;
@@ -33,7 +35,7 @@ export const useTransactionSteps = ({
33
35
  listingInput,
34
36
  chainId,
35
37
  collectionAddress,
36
- orderbookKind = OrderbookKind.sequence_marketplace_v2,
38
+ orderbookKind,
37
39
  callbacks,
38
40
  closeMainModal,
39
41
  steps$,
@@ -77,7 +79,6 @@ export const useTransactionSteps = ({
77
79
  } else {
78
80
  console.debug('onError callback not provided:', error);
79
81
  }
80
- throw error;
81
82
  }
82
83
  };
83
84
 
@@ -103,7 +104,6 @@ export const useTransactionSteps = ({
103
104
  }
104
105
  } catch (error) {
105
106
  steps$.approval.isExecuting.set(false);
106
- throw error;
107
107
  }
108
108
  };
109
109
 
@@ -147,12 +147,39 @@ export const useTransactionSteps = ({
147
147
  hash,
148
148
  orderId,
149
149
  callbacks,
150
+ queriesToInvalidate: [
151
+ balanceQueries.all,
152
+ collectableKeys.lowestListings,
153
+ collectableKeys.listings,
154
+ collectableKeys.listingsCount,
155
+ collectableKeys.userBalances,
156
+ ],
150
157
  });
151
158
 
152
- steps$.transaction.isExecuting.set(false);
159
+ if (hash) {
160
+ await waitForReceipt(hash);
161
+
162
+ steps$.transaction.isExecuting.set(false);
163
+ steps$.transaction.exist.set(false);
164
+ if (callbacks?.onSuccess && typeof callbacks.onSuccess === 'function') {
165
+ callbacks.onSuccess({ hash });
166
+ }
167
+ }
168
+
169
+ if (orderId) {
170
+ steps$.transaction.isExecuting.set(false);
171
+ steps$.transaction.exist.set(false);
172
+
173
+ if (callbacks?.onSuccess && typeof callbacks.onSuccess === 'function') {
174
+ callbacks.onSuccess({ orderId });
175
+ }
176
+ }
153
177
  } catch (error) {
154
178
  steps$.transaction.isExecuting.set(false);
155
- throw error;
179
+ steps$.transaction.exist.set(false);
180
+ if (callbacks?.onError && typeof callbacks.onError === 'function') {
181
+ callbacks.onError(error as Error);
182
+ }
156
183
  }
157
184
  };
158
185
 
@@ -1,9 +1,14 @@
1
- import { Show, observer } from '@legendapp/state/react';
1
+ import { Show, observer, use$ } from '@legendapp/state/react';
2
2
  import { useState } from 'react';
3
- import { parseUnits } from 'viem';
3
+ import { parseUnits, zeroAddress } from 'viem';
4
4
  import { dateToUnixTime } from '../../../../utils/date';
5
- import { ContractType } from '../../../_internal';
6
- import { useCollectible, useCollection } from '../../../hooks';
5
+ import { ContractType, OrderbookKind } from '../../../_internal';
6
+ import {
7
+ useCollectible,
8
+ useCollection,
9
+ useCurrencies,
10
+ useCurrencyOptions,
11
+ } from '../../../hooks';
7
12
  import { useMakeOffer } from './hooks/useMakeOffer';
8
13
  import { ActionModal } from '../_internal/components/actionModal/ActionModal';
9
14
  import { ErrorModal } from '../_internal/components/actionModal/ErrorModal';
@@ -14,6 +19,7 @@ import PriceInput from '../_internal/components/priceInput';
14
19
  import QuantityInput from '../_internal/components/quantityInput';
15
20
  import TokenPreview from '../_internal/components/tokenPreview';
16
21
  import { makeOfferModal$ } from './store';
22
+ import { Box } from '@0xsequence/design-system';
17
23
 
18
24
  export const MakeOfferModal = () => {
19
25
  return <Show if={makeOfferModal$.isOpen}>{() => <Modal />}</Show>;
@@ -51,6 +57,18 @@ const Modal = observer(() => {
51
57
  chainId,
52
58
  collectionAddress,
53
59
  });
60
+ const currencyOptions = useCurrencyOptions({ collectionAddress });
61
+ const {
62
+ data: currencies,
63
+ isLoading: currenciesLoading,
64
+ isError: currenciesIsError,
65
+ } = useCurrencies({
66
+ chainId,
67
+ currencyOptions,
68
+ });
69
+
70
+ const selectedCurrency = use$(makeOfferModal$.offerPrice.currency);
71
+
54
72
  const { isLoading, executeApproval, makeOffer } = useMakeOffer({
55
73
  offerInput: {
56
74
  contractType: collection?.type as ContractType,
@@ -73,7 +91,7 @@ const Modal = observer(() => {
73
91
  steps$: steps$,
74
92
  });
75
93
 
76
- if (collectableIsLoading || collectionIsLoading) {
94
+ if (collectableIsLoading || collectionIsLoading || currenciesLoading) {
77
95
  return (
78
96
  <LoadingModal
79
97
  isOpen={makeOfferModal$.isOpen.get()}
@@ -84,7 +102,7 @@ const Modal = observer(() => {
84
102
  );
85
103
  }
86
104
 
87
- if (collectableIsError || collectionIsError) {
105
+ if (collectableIsError || collectionIsError || currenciesIsError) {
88
106
  return (
89
107
  <ErrorModal
90
108
  isOpen={makeOfferModal$.isOpen.get()}
@@ -95,6 +113,10 @@ const Modal = observer(() => {
95
113
  );
96
114
  }
97
115
 
116
+ const invalidCurrency =
117
+ selectedCurrency?.contractAddress === zeroAddress &&
118
+ orderbookKind !== OrderbookKind.sequence_marketplace_v2;
119
+
98
120
  const ctas = [
99
121
  {
100
122
  label: 'Approve TOKEN',
@@ -120,10 +142,15 @@ const Modal = observer(() => {
120
142
  insufficientBalance ||
121
143
  isLoading ||
122
144
  invalidQuantity ||
123
- offerPrice.amountRaw === '0',
145
+ invalidCurrency,
124
146
  },
125
147
  ];
126
148
 
149
+ const secondCurrencyAsDefault =
150
+ orderbookKind !== OrderbookKind.sequence_marketplace_v2 &&
151
+ currencies &&
152
+ currencies[0]?.contractAddress === zeroAddress;
153
+
127
154
  return (
128
155
  <>
129
156
  <ActionModal
@@ -143,8 +170,9 @@ const Modal = observer(() => {
143
170
  <PriceInput
144
171
  chainId={chainId}
145
172
  collectionAddress={collectionAddress}
146
- $listingPrice={makeOfferModal$.offerPrice}
173
+ $price={makeOfferModal$.offerPrice}
147
174
  onPriceChange={() => makeOfferModal$.offerPriceChanged.set(true)}
175
+ secondCurrencyAsDefault={secondCurrencyAsDefault}
148
176
  checkBalance={{
149
177
  enabled: true,
150
178
  callback: (state) => setInsufficientBalance(state),
@@ -170,8 +198,14 @@ const Modal = observer(() => {
170
198
  price={offerPrice}
171
199
  />
172
200
  )}
173
-
174
201
  <ExpirationDateSelect $date={makeOfferModal$.expiry} />
202
+
203
+ {invalidCurrency && (
204
+ <Box color="negative" fontSize="small">
205
+ Native currency offers are not supported on this marketplace. Please
206
+ select another currency to continue
207
+ </Box>
208
+ )}
175
209
  </ActionModal>
176
210
  </>
177
211
  );
@@ -1,15 +1,16 @@
1
+ import { skipToken, useQuery } from '@tanstack/react-query';
2
+ import { dateToUnixTime } from '../../../../../utils/date';
1
3
  import {
2
4
  type ContractType,
3
5
  type CreateReq,
4
- GenerateOfferTransactionArgs,
5
- getMarketplaceClient,
6
+ type GenerateOfferTransactionArgs,
6
7
  type OrderbookKind,
8
+ type QueryArg,
7
9
  StepType,
10
+ getMarketplaceClient,
8
11
  } from '../../../../_internal';
9
- import { useQuery } from '@tanstack/react-query';
10
12
  import { useWallet } from '../../../../_internal/transaction-machine/useWallet';
11
13
  import { useConfig } from '../../../../hooks/useConfig';
12
- import { dateToUnixTime } from '../../../../../utils/date';
13
14
 
14
15
  export interface UseGetTokenApprovalDataArgs {
15
16
  chainId: string;
@@ -18,6 +19,7 @@ export interface UseGetTokenApprovalDataArgs {
18
19
  currencyAddress: string;
19
20
  contractType: ContractType;
20
21
  orderbook: OrderbookKind;
22
+ query?: QueryArg;
21
23
  }
22
24
 
23
25
  const ONE_DAY_IN_SECONDS = 60 * 60 * 24;
@@ -37,34 +39,38 @@ export const useGetTokenApprovalData = (
37
39
  expiry: String(Number(dateToUnixTime(new Date())) + ONE_DAY_IN_SECONDS),
38
40
  } satisfies CreateReq;
39
41
 
42
+ const isEnabled = wallet && params.query?.enabled !== false;
43
+
40
44
  const { data, isLoading, isSuccess } = useQuery({
41
45
  queryKey: ['token-approval-data', params.currencyAddress],
42
- queryFn: async () => {
43
- const args = {
44
- collectionAddress: params.collectionAddress,
45
- maker: await wallet!.address(),
46
- walletType: wallet!.walletKind,
47
- contractType: params.contractType,
48
- orderbook: params.orderbook,
49
- offer,
50
- } satisfies GenerateOfferTransactionArgs;
51
- const steps = await marketplaceClient
52
- .generateOfferTransaction(args)
53
- .then((resp) => resp.steps);
46
+ queryFn: isEnabled
47
+ ? async () => {
48
+ const args = {
49
+ collectionAddress: params.collectionAddress,
50
+ maker: await wallet.address(),
51
+ walletType: wallet.walletKind,
52
+ contractType: params.contractType,
53
+ orderbook: params.orderbook,
54
+ offer,
55
+ } satisfies GenerateOfferTransactionArgs;
56
+ const steps = await marketplaceClient
57
+ .generateOfferTransaction(args)
58
+ .then((resp) => resp.steps);
54
59
 
55
- const tokenApprovalStep = steps.find(
56
- (step) => step.id === StepType.tokenApproval,
57
- );
58
- if (!tokenApprovalStep) {
59
- return {
60
- step: null,
61
- };
62
- }
60
+ const tokenApprovalStep = steps.find(
61
+ (step) => step.id === StepType.tokenApproval,
62
+ );
63
+ if (!tokenApprovalStep) {
64
+ return {
65
+ step: null,
66
+ };
67
+ }
63
68
 
64
- return {
65
- step: tokenApprovalStep,
66
- };
67
- },
69
+ return {
70
+ step: tokenApprovalStep,
71
+ };
72
+ }
73
+ : skipToken,
68
74
  enabled: !!wallet && !!params.collectionAddress && !!params.currencyAddress,
69
75
  });
70
76
 
@@ -1,17 +1,17 @@
1
- import { Observable } from '@legendapp/state';
2
- import { OrderbookKind } from '../../../../../types';
3
- import { OfferInput } from '../../../../_internal/transaction-machine/execute-transaction';
4
- import { ModalCallbacks } from '../../_internal/types';
1
+ import type { Observable } from '@legendapp/state';
2
+ import { useEffect } from 'react';
3
+ import type { OrderbookKind } from '../../../../../types';
4
+ import type { TransactionSteps } from '../../../../_internal';
5
+ import type { OfferInput } from '../../../../_internal/transaction-machine/execute-transaction';
6
+ import type { ModalCallbacks } from '../../_internal/types';
5
7
  import { useGetTokenApprovalData } from './useGetTokenApproval';
6
8
  import { useTransactionSteps } from './useTransactionSteps';
7
- import { useEffect } from 'react';
8
- import { TransactionSteps } from '../../../../_internal';
9
9
 
10
10
  interface UseMakeOfferArgs {
11
11
  offerInput: OfferInput;
12
12
  chainId: string;
13
13
  collectionAddress: string;
14
- orderbookKind?: OrderbookKind;
14
+ orderbookKind: OrderbookKind;
15
15
  callbacks?: ModalCallbacks;
16
16
  closeMainModal: () => void;
17
17
  steps$: Observable<TransactionSteps>;
@@ -21,7 +21,7 @@ export const useMakeOffer = ({
21
21
  offerInput,
22
22
  chainId,
23
23
  collectionAddress,
24
- orderbookKind = OrderbookKind.sequence_marketplace_v2,
24
+ orderbookKind,
25
25
  callbacks,
26
26
  closeMainModal,
27
27
  steps$,