@0xsequence/marketplace-sdk 0.4.1 → 0.4.2

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 (67) hide show
  1. package/dist/{chunk-RZSZNVEH.js → chunk-2OJB35FS.js} +7 -7
  2. package/dist/{chunk-RZSZNVEH.js.map → chunk-2OJB35FS.js.map} +1 -1
  3. package/dist/{chunk-QMO2CUNM.js → chunk-4RKM3VUV.js} +2 -2
  4. package/dist/{chunk-7NJETFMF.js → chunk-FI723DGL.js} +3 -3
  5. package/dist/{chunk-7NJETFMF.js.map → chunk-FI723DGL.js.map} +1 -1
  6. package/dist/{chunk-UPLTM63S.js → chunk-MQ5WSFDH.js} +7 -7
  7. package/dist/{chunk-UPLTM63S.js.map → chunk-MQ5WSFDH.js.map} +1 -1
  8. package/dist/{chunk-IOTKCWOB.js → chunk-MTFS5SED.js} +1089 -1088
  9. package/dist/chunk-MTFS5SED.js.map +1 -0
  10. package/dist/{chunk-4ESPWOBV.js → chunk-NC4KGXXE.js} +3 -3
  11. package/dist/{chunk-4ESPWOBV.js.map → chunk-NC4KGXXE.js.map} +1 -1
  12. package/dist/{chunk-EVRILXOH.js → chunk-OPMDGQFB.js} +37 -35
  13. package/dist/{chunk-EVRILXOH.js.map → chunk-OPMDGQFB.js.map} +1 -1
  14. package/dist/{chunk-5GDO4ZBC.js → chunk-S5IPE7TH.js} +2 -2
  15. package/dist/{chunk-O642NH7U.js → chunk-TDTORZHC.js} +3 -3
  16. package/dist/{chunk-O642NH7U.js.map → chunk-TDTORZHC.js.map} +1 -1
  17. package/dist/{chunk-MIYMMP2K.js → chunk-WBJKZOQ7.js} +214 -134
  18. package/dist/chunk-WBJKZOQ7.js.map +1 -0
  19. package/dist/{chunk-KNX2LER4.js → chunk-ZWIRTV7A.js} +2 -2
  20. package/dist/index.js +4 -4
  21. package/dist/react/_internal/api/index.js +2 -2
  22. package/dist/react/_internal/index.js +3 -3
  23. package/dist/react/_internal/wagmi/index.js +2 -2
  24. package/dist/react/hooks/index.d.ts +5 -7
  25. package/dist/react/hooks/index.js +6 -6
  26. package/dist/react/index.js +10 -10
  27. package/dist/react/ui/components/index.js +10 -10
  28. package/dist/react/ui/index.d.ts +15 -8
  29. package/dist/react/ui/index.js +10 -10
  30. package/dist/react/ui/modals/_internal/components/actionModal/index.js +6 -6
  31. package/dist/react/ui/styles/index.js +1 -1
  32. package/dist/styles/index.js +4 -4
  33. package/dist/types/index.js +3 -3
  34. package/dist/utils/index.js +2 -2
  35. package/package.json +8 -8
  36. package/src/react/_internal/transaction-machine/execute-transaction.ts +70 -113
  37. package/src/react/_internal/transaction-machine/useTransactionMachine.ts +13 -32
  38. package/src/react/_internal/transaction-machine/utils.ts +50 -0
  39. package/src/react/_internal/transaction-machine/wallet.ts +180 -0
  40. package/src/react/hooks/useBuyCollectable.tsx +14 -5
  41. package/src/react/hooks/useCancelOrder.tsx +0 -3
  42. package/src/react/hooks/useCreateListing.tsx +0 -3
  43. package/src/react/hooks/useGenerateListingTransaction.tsx +1 -3
  44. package/src/react/hooks/useGenerateOfferTransaction.tsx +1 -3
  45. package/src/react/hooks/useMakeOffer.tsx +0 -3
  46. package/src/react/hooks/useSell.tsx +0 -3
  47. package/src/react/ui/modals/BuyModal/index.tsx +21 -5
  48. package/src/react/ui/modals/CreateListingModal/Modal.tsx +252 -0
  49. package/src/react/ui/modals/CreateListingModal/index.tsx +6 -284
  50. package/src/react/ui/modals/CreateListingModal/store.ts +76 -0
  51. package/src/react/ui/modals/MakeOfferModal/Modal.tsx +254 -0
  52. package/src/react/ui/modals/MakeOfferModal/index.tsx +8 -262
  53. package/src/react/ui/modals/MakeOfferModal/{_store.ts → store.ts} +24 -14
  54. package/src/react/ui/modals/SellModal/Modal.tsx +218 -0
  55. package/src/react/ui/modals/SellModal/index.tsx +8 -238
  56. package/src/react/ui/modals/SellModal/{_store.ts → store.ts} +13 -9
  57. package/src/react/ui/modals/_internal/components/transaction-footer/index.tsx +3 -2
  58. package/src/react/ui/modals/_internal/components/transactionStatusModal/index.tsx +2 -1
  59. package/src/react/ui/modals/modal-provider.tsx +3 -3
  60. package/src/utils/date.ts +2 -0
  61. package/tsconfig.tsbuildinfo +1 -1
  62. package/dist/chunk-IOTKCWOB.js.map +0 -1
  63. package/dist/chunk-MIYMMP2K.js.map +0 -1
  64. package/src/react/ui/modals/CreateListingModal/_store.ts +0 -55
  65. /package/dist/{chunk-QMO2CUNM.js.map → chunk-4RKM3VUV.js.map} +0 -0
  66. /package/dist/{chunk-5GDO4ZBC.js.map → chunk-S5IPE7TH.js.map} +0 -0
  67. /package/dist/{chunk-KNX2LER4.js.map → chunk-ZWIRTV7A.js.map} +0 -0
@@ -0,0 +1,252 @@
1
+ import { Box } from '@0xsequence/design-system';
2
+ import { Show, observer } from '@legendapp/state/react';
3
+ import type { QueryKey } from '@tanstack/react-query';
4
+ import { useEffect, useState } from 'react';
5
+ import { parseUnits } from 'viem';
6
+ import { useAccount } from 'wagmi';
7
+ import { collectableKeys } from '../../../_internal';
8
+ import { ContractType } from '../../../_internal';
9
+ import { TransactionType } from '../../../_internal/transaction-machine/execute-transaction';
10
+ import {
11
+ useBalanceOfCollectible,
12
+ useCollectible,
13
+ useCollection,
14
+ } from '../../../hooks';
15
+ import { useCreateListing } from '../../../hooks/useCreateListing';
16
+ import {
17
+ ActionModal,
18
+ type ActionModalProps,
19
+ } from '../_internal/components/actionModal/ActionModal';
20
+ import { ErrorModal } from '../_internal/components/actionModal/ErrorModal';
21
+ import { LoadingModal } from '../_internal/components/actionModal/LoadingModal';
22
+ import ExpirationDateSelect from '../_internal/components/expirationDateSelect';
23
+ import FloorPriceText from '../_internal/components/floorPriceText';
24
+ import PriceInput from '../_internal/components/priceInput';
25
+ import QuantityInput from '../_internal/components/quantityInput';
26
+ import TokenPreview from '../_internal/components/tokenPreview';
27
+ import TransactionDetails from '../_internal/components/transactionDetails';
28
+ import { useTransactionStatusModal } from '../_internal/components/transactionStatusModal';
29
+ import { createListingModal$ } from './store';
30
+ import { dateToUnixTime } from '../../../../utils/date';
31
+
32
+ type TransactionStatusModalReturn = ReturnType<
33
+ typeof useTransactionStatusModal
34
+ >;
35
+
36
+ export const CreateListingModal = () => {
37
+ const { show: showTransactionStatusModal } = useTransactionStatusModal();
38
+ return (
39
+ <Show if={createListingModal$.isOpen}>
40
+ {() => <Modal showTransactionStatusModal={showTransactionStatusModal} />}
41
+ </Show>
42
+ );
43
+ };
44
+
45
+ const Modal = observer(
46
+ ({
47
+ showTransactionStatusModal,
48
+ }: {
49
+ showTransactionStatusModal: TransactionStatusModalReturn['show'];
50
+ }) => {
51
+ const state = createListingModal$.get();
52
+ const {
53
+ collectionAddress,
54
+ chainId,
55
+ listingPrice,
56
+ collectibleId,
57
+ orderbookKind,
58
+ callbacks,
59
+ } = state;
60
+ const currencyAddress = listingPrice.currency.contractAddress;
61
+ const {
62
+ data: collectible,
63
+ isLoading: collectableIsLoading,
64
+ isError: collectableIsError,
65
+ } = useCollectible({
66
+ chainId,
67
+ collectionAddress,
68
+ collectibleId,
69
+ });
70
+
71
+ const {
72
+ data: collection,
73
+ isLoading: collectionIsLoading,
74
+ isError: collectionIsError,
75
+ } = useCollection({
76
+ chainId,
77
+ collectionAddress,
78
+ });
79
+ const [approvalExecutedSuccess, setApprovalExecutedSuccess] =
80
+ useState(false);
81
+
82
+ const { address } = useAccount();
83
+
84
+ const { data: balance } = useBalanceOfCollectible({
85
+ chainId,
86
+ collectionAddress,
87
+ collectableId: collectibleId,
88
+ userAddress: address ?? undefined,
89
+ });
90
+
91
+ const { getListingSteps, isLoading: machineLoading } = useCreateListing({
92
+ orderbookKind,
93
+ chainId,
94
+ collectionAddress,
95
+ enabled: createListingModal$.isOpen.get(),
96
+ onApprovalSuccess: () => setApprovalExecutedSuccess(true),
97
+ onTransactionSent: (hash, orderId) => {
98
+ if (!hash && !orderId) return;
99
+
100
+ showTransactionStatusModal({
101
+ hash,
102
+ orderId,
103
+ collectionAddress,
104
+ chainId,
105
+ price: createListingModal$.listingPrice.get(),
106
+ collectibleId,
107
+ type: TransactionType.LISTING,
108
+ queriesToInvalidate: collectableKeys.all as unknown as QueryKey[],
109
+ callbacks,
110
+ });
111
+ createListingModal$.close();
112
+ },
113
+ });
114
+
115
+ const { isLoading, steps, refreshSteps } = getListingSteps({
116
+ contractType: collection?.type as ContractType,
117
+ listing: {
118
+ tokenId: collectibleId,
119
+ quantity: parseUnits(
120
+ createListingModal$.quantity.get(),
121
+ collectible?.decimals || 0,
122
+ ).toString(),
123
+ expiry: dateToUnixTime(createListingModal$.expiry.get()),
124
+ currencyAddress: listingPrice.currency.contractAddress,
125
+ pricePerToken: listingPrice.amountRaw,
126
+ },
127
+ });
128
+
129
+ useEffect(() => {
130
+ if (!currencyAddress) return;
131
+
132
+ refreshSteps();
133
+ }, [currencyAddress]);
134
+
135
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
136
+ const handleStepExecution = async (execute?: any) => {
137
+ if (!execute) return;
138
+ try {
139
+ await refreshSteps();
140
+ await execute();
141
+ } catch (error) {
142
+ if (callbacks?.onError) {
143
+ callbacks.onError(error as Error);
144
+ } else {
145
+ console.debug('onError callback not provided:', error);
146
+ }
147
+ }
148
+ };
149
+
150
+ if (collectableIsLoading || collectionIsLoading || machineLoading) {
151
+ return (
152
+ <LoadingModal
153
+ isOpen={createListingModal$.isOpen.get()}
154
+ chainId={Number(chainId)}
155
+ onClose={createListingModal$.close}
156
+ title="List item for sale"
157
+ />
158
+ );
159
+ }
160
+
161
+ if (collectableIsError || collectionIsError) {
162
+ return (
163
+ <ErrorModal
164
+ isOpen={createListingModal$.isOpen.get()}
165
+ chainId={Number(chainId)}
166
+ onClose={createListingModal$.close}
167
+ title="List item for sale"
168
+ />
169
+ );
170
+ }
171
+
172
+ const approvalNeeded = steps?.approval.isPending;
173
+
174
+ const ctas = [
175
+ {
176
+ label: 'Approve TOKEN',
177
+ onClick: () => handleStepExecution(() => steps?.approval.execute()),
178
+ hidden: !approvalNeeded || approvalExecutedSuccess,
179
+ pending: steps?.approval.isExecuting || isLoading,
180
+ variant: 'glass' as const,
181
+ disabled:
182
+ createListingModal$.invalidQuantity.get() ||
183
+ isLoading ||
184
+ listingPrice.amountRaw === '0' ||
185
+ steps?.transaction.isExecuting,
186
+ },
187
+ {
188
+ label: 'List item for sale',
189
+ onClick: () => handleStepExecution(() => steps?.transaction.execute()),
190
+ pending: steps?.transaction.isExecuting || isLoading,
191
+ disabled:
192
+ (!approvalExecutedSuccess && approvalNeeded) ||
193
+ listingPrice.amountRaw === '0' ||
194
+ isLoading ||
195
+ createListingModal$.invalidQuantity.get(),
196
+ },
197
+ ] satisfies ActionModalProps['ctas'];
198
+
199
+ return (
200
+ <ActionModal
201
+ isOpen={createListingModal$.isOpen.get()}
202
+ chainId={Number(chainId)}
203
+ onClose={() => createListingModal$.close()}
204
+ title="List item for sale"
205
+ ctas={ctas}
206
+ >
207
+ <TokenPreview
208
+ collectionName={collection?.name}
209
+ collectionAddress={collectionAddress}
210
+ collectibleId={collectibleId}
211
+ chainId={chainId}
212
+ />
213
+
214
+ <Box display="flex" flexDirection="column" width="full" gap="1">
215
+ <PriceInput
216
+ chainId={chainId}
217
+ collectionAddress={collectionAddress}
218
+ $listingPrice={createListingModal$.listingPrice}
219
+ />
220
+
221
+ {listingPrice.amountRaw !== '0' && (
222
+ <FloorPriceText
223
+ tokenId={collectibleId}
224
+ chainId={chainId}
225
+ collectionAddress={collectionAddress}
226
+ price={listingPrice}
227
+ />
228
+ )}
229
+ </Box>
230
+
231
+ {collection?.type === 'ERC1155' && balance && (
232
+ <QuantityInput
233
+ $quantity={createListingModal$.quantity}
234
+ $invalidQuantity={createListingModal$.invalidQuantity}
235
+ decimals={collectible?.decimals || 0}
236
+ maxQuantity={balance?.balance}
237
+ />
238
+ )}
239
+
240
+ <ExpirationDateSelect $date={createListingModal$.expiry} />
241
+
242
+ <TransactionDetails
243
+ collectibleId={collectibleId}
244
+ collectionAddress={collectionAddress}
245
+ chainId={chainId}
246
+ price={createListingModal$.listingPrice.get()}
247
+ currencyImageUrl={listingPrice.currency.imageUrl}
248
+ />
249
+ </ActionModal>
250
+ );
251
+ },
252
+ );
@@ -1,293 +1,15 @@
1
- import { Box } from '@0xsequence/design-system';
2
- import { Show, observer } from '@legendapp/state/react';
3
- import type { QueryKey } from '@tanstack/react-query';
4
- import { useEffect, useState } from 'react';
5
- import type { Hash, Hex } from 'viem';
6
- import { parseUnits } from 'viem';
7
- import { useAccount } from 'wagmi';
8
- import {
9
- type ContractType,
10
- type OrderbookKind,
11
- collectableKeys,
12
- } from '../../../_internal';
13
- import { TransactionType } from '../../../_internal/transaction-machine/execute-transaction';
14
- import {
15
- useBalanceOfCollectible,
16
- useCollectible,
17
- useCollection,
18
- } from '../../../hooks';
19
- import { useCreateListing } from '../../../hooks/useCreateListing';
20
- import {
21
- ActionModal,
22
- type ActionModalProps,
23
- } from '../_internal/components/actionModal/ActionModal';
24
- import { ErrorModal } from '../_internal/components/actionModal/ErrorModal';
25
- import { LoadingModal } from '../_internal/components/actionModal/LoadingModal';
26
- import ExpirationDateSelect from '../_internal/components/expirationDateSelect';
27
- import FloorPriceText from '../_internal/components/floorPriceText';
28
- import PriceInput from '../_internal/components/priceInput';
29
- import QuantityInput from '../_internal/components/quantityInput';
30
- import TokenPreview from '../_internal/components/tokenPreview';
31
- import TransactionDetails from '../_internal/components/transactionDetails';
32
- import { useTransactionStatusModal } from '../_internal/components/transactionStatusModal';
33
1
  import type { ModalCallbacks } from '../_internal/types';
34
- import { createListingModal$ } from './_store';
2
+ import { createListingModal$, OpenCreateListingModalArgs } from './store';
35
3
 
36
- export type ShowCreateListingModalArgs = {
37
- collectionAddress: Hex;
38
- chainId: string;
39
- collectibleId: string;
40
- orderbookKind: OrderbookKind;
41
- onSuccess?: (hash?: Hash) => void;
42
- onError?: (error: Error) => void;
43
- };
4
+ type ShowCreateListingModalArgs = Exclude<
5
+ OpenCreateListingModalArgs,
6
+ 'callbacks'
7
+ >;
44
8
 
45
9
  export const useCreateListingModal = (callbacks?: ModalCallbacks) => {
46
10
  return {
47
11
  show: (args: ShowCreateListingModalArgs) =>
48
- createListingModal$.open({ ...args, defaultCallbacks: callbacks }),
12
+ createListingModal$.open({ ...args, callbacks }),
49
13
  close: () => createListingModal$.close(),
50
14
  };
51
15
  };
52
-
53
- export const CreateListingModal = () => {
54
- const { show: showTransactionStatusModal } = useTransactionStatusModal();
55
- return (
56
- <Show if={createListingModal$.isOpen}>
57
- <Modal showTransactionStatusModal={showTransactionStatusModal} />
58
- </Show>
59
- );
60
- };
61
-
62
- type TransactionStatusModalReturn = ReturnType<
63
- typeof useTransactionStatusModal
64
- >;
65
-
66
- export const Modal = observer(
67
- ({
68
- showTransactionStatusModal,
69
- }: {
70
- showTransactionStatusModal: TransactionStatusModalReturn['show'];
71
- }) => {
72
- const state = createListingModal$.get();
73
- const {
74
- collectionAddress,
75
- chainId,
76
- listingPrice,
77
- listingPriceChanged,
78
- collectibleId,
79
- orderbookKind,
80
- callbacks,
81
- } = state;
82
- const currencyAddress = listingPrice.currency.contractAddress;
83
- const {
84
- data: collectible,
85
- isLoading: collectableIsLoading,
86
- isError: collectableIsError,
87
- } = useCollectible({
88
- chainId,
89
- collectionAddress,
90
- collectibleId,
91
- });
92
-
93
- const {
94
- data: collection,
95
- isLoading: collectionIsLoading,
96
- isError: collectionIsError,
97
- } = useCollection({
98
- chainId,
99
- collectionAddress,
100
- });
101
- const [approvalExecutedSuccess, setApprovalExecutedSuccess] =
102
- useState(false);
103
-
104
- const { address } = useAccount();
105
-
106
- const { data: balance } = useBalanceOfCollectible({
107
- chainId,
108
- collectionAddress,
109
- collectableId: collectibleId,
110
- userAddress: address ?? undefined,
111
- });
112
-
113
- const { getListingSteps, isLoading: machineLoading, createListing} = useCreateListing({
114
- orderbookKind,
115
- chainId,
116
- collectionAddress,
117
- enabled: createListingModal$.isOpen.get(),
118
- onSwitchChainRefused: () => createListingModal$.close(),
119
- onApprovalSuccess: () => setApprovalExecutedSuccess(true),
120
- onTransactionSent: (hash, orderId) => {
121
- if (!hash && !orderId) return;
122
-
123
- showTransactionStatusModal({
124
- hash,
125
- orderId,
126
- collectionAddress,
127
- chainId,
128
- price: createListingModal$.listingPrice.get(),
129
- collectibleId,
130
- type: TransactionType.LISTING,
131
- queriesToInvalidate: collectableKeys.all as unknown as QueryKey[],
132
- callbacks,
133
- });
134
- createListingModal$.close();
135
- },
136
- });
137
-
138
- useEffect(() => {
139
- if (!currencyAddress) return;
140
-
141
- refreshSteps();
142
- }, [currencyAddress]);
143
-
144
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
145
- const handleStepExecution = async (execute?: any) => {
146
- if (!execute) return;
147
- try {
148
- await refreshSteps();
149
- await execute();
150
- } catch (error) {
151
- if (callbacks?.onError) {
152
- callbacks.onError(error as Error);
153
- } else {
154
- console.debug('onError callback not provided:', error);
155
- }
156
- }
157
- };
158
-
159
- if (collectableIsLoading || collectionIsLoading || machineLoading) {
160
- return (
161
- <LoadingModal
162
- isOpen={createListingModal$.isOpen.get()}
163
- chainId={Number(chainId)}
164
- onClose={createListingModal$.close}
165
- title="List item for sale"
166
- />
167
- );
168
- }
169
-
170
- if (collectableIsError || collectionIsError) {
171
- return (
172
- <ErrorModal
173
- isOpen={createListingModal$.isOpen.get()}
174
- chainId={Number(chainId)}
175
- onClose={createListingModal$.close}
176
- title="List item for sale"
177
- />
178
- );
179
- }
180
-
181
- const dateToUnixTime = (date: Date) =>
182
- Math.floor(date.getTime() / 1000).toString();
183
-
184
- const { isLoading, steps, refreshSteps } = getListingSteps({
185
- contractType: collection?.type as ContractType,
186
- listing: {
187
- tokenId: collectibleId,
188
- quantity: parseUnits(
189
- createListingModal$.quantity.get(),
190
- collectible?.decimals || 0,
191
- ).toString(),
192
- expiry: dateToUnixTime(createListingModal$.expiry.get()),
193
- currencyAddress: listingPrice.currency.contractAddress,
194
- pricePerToken: listingPrice.amountRaw,
195
- },
196
- });
197
- const approvalNeeded = steps?.approval.isPending;
198
-
199
- const ctas = [
200
- {
201
- label: 'Approve TOKEN',
202
- onClick: () => handleStepExecution(() => steps?.approval.execute()),
203
- hidden: !approvalNeeded || approvalExecutedSuccess,
204
- pending: steps?.approval.isExecuting || isLoading,
205
- variant: 'glass' as const,
206
- disabled:
207
- createListingModal$.invalidQuantity.get() ||
208
- isLoading ||
209
- !listingPriceChanged ||
210
- listingPrice.amountRaw === '0' ||
211
- steps?.transaction.isExecuting,
212
- },
213
- {
214
- label: 'List item for sale',
215
- onClick: () => createListing({
216
- contractType: collection?.type as ContractType,
217
- listing: {
218
- tokenId: collectibleId,
219
- quantity: parseUnits(
220
- createListingModal$.quantity.get(),
221
- collectible?.decimals || 0,
222
- ).toString(),
223
- expiry: dateToUnixTime(createListingModal$.expiry.get()),
224
- currencyAddress: listingPrice.currency.contractAddress,
225
- pricePerToken: listingPrice.amountRaw,
226
- },
227
- }),
228
- pending: steps?.transaction.isExecuting || isLoading,
229
- disabled:
230
- (!approvalExecutedSuccess && approvalNeeded) ||
231
- listingPrice.amountRaw === '0' ||
232
- isLoading ||
233
- createListingModal$.invalidQuantity.get() ||
234
- !listingPriceChanged,
235
- },
236
- ] satisfies ActionModalProps['ctas'];
237
-
238
- return (
239
- <ActionModal
240
- isOpen={createListingModal$.isOpen.get()}
241
- chainId={Number(chainId)}
242
- onClose={() => createListingModal$.close()}
243
- title="List item for sale"
244
- ctas={ctas}
245
- >
246
- <TokenPreview
247
- collectionName={collection?.name}
248
- collectionAddress={collectionAddress}
249
- collectibleId={collectibleId}
250
- chainId={chainId}
251
- />
252
-
253
- <Box display="flex" flexDirection="column" width="full" gap="1">
254
- <PriceInput
255
- chainId={chainId}
256
- collectionAddress={collectionAddress}
257
- $listingPrice={createListingModal$.listingPrice}
258
- onPriceChange={() => createListingModal$.listingPriceChanged.set(true)}
259
- />
260
-
261
- {listingPrice.amountRaw !== '0' && listingPriceChanged && (
262
- <FloorPriceText
263
- tokenId={collectibleId}
264
- chainId={chainId}
265
- collectionAddress={collectionAddress}
266
- price={listingPrice}
267
- />
268
- )}
269
- </Box>
270
-
271
- {collection?.type === 'ERC1155' && balance && (
272
- <QuantityInput
273
- $quantity={createListingModal$.quantity}
274
- $invalidQuantity={createListingModal$.invalidQuantity}
275
- decimals={collectible?.decimals || 0}
276
- maxQuantity={balance?.balance}
277
- />
278
- )}
279
-
280
- <ExpirationDateSelect $date={createListingModal$.expiry} />
281
-
282
- <TransactionDetails
283
- collectibleId={collectibleId}
284
- collectionAddress={collectionAddress}
285
- chainId={chainId}
286
- price={createListingModal$.listingPrice.get()}
287
- showPlaceholderPrice={!listingPriceChanged}
288
- currencyImageUrl={listingPrice.currency.imageUrl}
289
- />
290
- </ActionModal>
291
- );
292
- },
293
- );
@@ -0,0 +1,76 @@
1
+ import { observable } from '@legendapp/state';
2
+ import { addDays } from 'date-fns/addDays';
3
+ import type { Hex } from 'viem';
4
+ import { type Currency, OrderbookKind } from '../../../../types';
5
+ import type { ModalCallbacks } from '../_internal/types';
6
+ import { CollectionType } from '../../../_internal';
7
+
8
+ type CreateListingState = {
9
+ isOpen: boolean;
10
+ collectionAddress: Hex;
11
+ chainId: string;
12
+ collectibleId: string;
13
+ collectionName: string;
14
+ orderbookKind: OrderbookKind;
15
+ collectionType: CollectionType | undefined;
16
+ listingPrice: {
17
+ amountRaw: string;
18
+ currency: Currency;
19
+ };
20
+ quantity: string;
21
+ invalidQuantity: boolean;
22
+ expiry: Date;
23
+ callbacks?: ModalCallbacks;
24
+ };
25
+
26
+ export type OpenCreateListingModalArgs = {
27
+ collectionAddress: Hex;
28
+ chainId: string;
29
+ collectibleId: string;
30
+ orderbookKind: OrderbookKind;
31
+ callbacks?: ModalCallbacks;
32
+ };
33
+
34
+ type Actions = {
35
+ open: (args: OpenCreateListingModalArgs) => void;
36
+ close: () => void;
37
+ };
38
+
39
+ const initialState: CreateListingState = {
40
+ isOpen: false,
41
+ collectionAddress: '' as Hex,
42
+ chainId: '',
43
+ collectibleId: '',
44
+ orderbookKind: OrderbookKind.sequence_marketplace_v2,
45
+ collectionName: '',
46
+ collectionType: undefined,
47
+ listingPrice: {
48
+ // to see if approval is needed when modal opens
49
+ amountRaw: '1',
50
+ currency: {} as Currency,
51
+ },
52
+ quantity: '1',
53
+ invalidQuantity: false,
54
+ expiry: new Date(addDays(new Date(), 7).toJSON()),
55
+ callbacks: undefined as ModalCallbacks | undefined,
56
+ };
57
+
58
+ const actions: Actions = {
59
+ open: (args) => {
60
+ createListingModal$.collectionAddress.set(args.collectionAddress);
61
+ createListingModal$.chainId.set(args.chainId);
62
+ createListingModal$.collectibleId.set(args.collectibleId);
63
+ createListingModal$.orderbookKind.set(args.orderbookKind);
64
+ createListingModal$.callbacks.set(args.callbacks);
65
+ createListingModal$.isOpen.set(true);
66
+ },
67
+ close: () => {
68
+ createListingModal$.isOpen.set(false);
69
+ createListingModal$.set({ ...initialState, ...actions });
70
+ },
71
+ };
72
+
73
+ export const createListingModal$ = observable<CreateListingState & Actions>({
74
+ ...initialState,
75
+ ...actions,
76
+ });