@0xsequence/marketplace-sdk 0.3.0 → 0.3.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 (166) hide show
  1. package/dist/chunk-22NLQ3AS.js +3078 -0
  2. package/dist/chunk-22NLQ3AS.js.map +1 -0
  3. package/dist/chunk-3OHM45R3.js +1294 -0
  4. package/dist/chunk-3OHM45R3.js.map +1 -0
  5. package/dist/{chunk-MQR6SHXZ.js → chunk-4YU2UPYH.js} +58 -103
  6. package/dist/chunk-4YU2UPYH.js.map +1 -0
  7. package/dist/chunk-7NJETFMF.js +21 -0
  8. package/dist/chunk-7NJETFMF.js.map +1 -0
  9. package/dist/{chunk-UYRQ5MJQ.js → chunk-FUM4OGOQ.js} +4 -4
  10. package/dist/chunk-FUM4OGOQ.js.map +1 -0
  11. package/dist/{chunk-7OO74L2K.js → chunk-GJAKQ5Q3.js} +40 -1
  12. package/dist/chunk-GJAKQ5Q3.js.map +1 -0
  13. package/dist/chunk-MCI3KOSQ.js +2 -0
  14. package/dist/{chunk-BJE7AG6V.js → chunk-O7UQGT43.js} +698 -23
  15. package/dist/chunk-O7UQGT43.js.map +1 -0
  16. package/dist/{chunk-CSN7YD5Q.js → chunk-Q57TEA3Z.js} +20 -2
  17. package/dist/chunk-Q57TEA3Z.js.map +1 -0
  18. package/dist/{chunk-VEX7FDL6.js → chunk-SBVLWSRZ.js} +2 -2
  19. package/dist/{chunk-VEX7FDL6.js.map → chunk-SBVLWSRZ.js.map} +1 -1
  20. package/dist/{chunk-6S4FYXP6.js → chunk-SPW24Y7I.js} +40 -1
  21. package/dist/chunk-SPW24Y7I.js.map +1 -0
  22. package/dist/chunk-UISBTKFF.js +1 -0
  23. package/dist/{chunk-OUWB3FHZ.js → chunk-WA433WAJ.js} +9 -33
  24. package/dist/chunk-WA433WAJ.js.map +1 -0
  25. package/dist/{chunk-O5JXKTWP.js → chunk-WFE6OCYF.js} +4 -4
  26. package/dist/chunk-WFE6OCYF.js.map +1 -0
  27. package/dist/chunk-XX4EVWBF.js +1292 -0
  28. package/dist/chunk-XX4EVWBF.js.map +1 -0
  29. package/dist/chunk-Y7YO5TLE.js +53 -0
  30. package/dist/chunk-Y7YO5TLE.js.map +1 -0
  31. package/dist/index.css +1 -50
  32. package/dist/index.d.ts +3 -5
  33. package/dist/index.js +158 -73
  34. package/dist/index.js.map +1 -1
  35. package/dist/react/hooks/index.css +82 -0
  36. package/dist/react/hooks/index.css.map +1 -0
  37. package/dist/react/hooks/index.d.ts +401 -462
  38. package/dist/react/hooks/index.js +26 -6
  39. package/dist/react/index.css +56 -91
  40. package/dist/react/index.css.map +1 -1
  41. package/dist/react/index.d.ts +2 -2
  42. package/dist/react/index.js +32 -13
  43. package/dist/react/ui/components/index.css +86 -121
  44. package/dist/react/ui/components/index.css.map +1 -1
  45. package/dist/react/ui/components/index.d.ts +10 -4
  46. package/dist/react/ui/components/index.js +12 -11
  47. package/dist/react/ui/icons/index.js +3 -2
  48. package/dist/react/ui/icons/index.js.map +1 -1
  49. package/dist/react/ui/index.css +56 -91
  50. package/dist/react/ui/index.css.map +1 -1
  51. package/dist/react/ui/index.d.ts +29 -31
  52. package/dist/react/ui/index.js +14 -11
  53. package/dist/react/ui/modals/_internal/components/actionModal/index.js +5 -16
  54. package/dist/react/ui/modals/_internal/components/actionModal/index.js.map +1 -1
  55. package/dist/react/ui/styles/index.d.ts +1 -1
  56. package/dist/styles/index.css +1 -50
  57. package/dist/styles/index.css.map +1 -1
  58. package/dist/styles/index.d.ts +1 -5
  59. package/dist/styles/index.js +8 -10
  60. package/dist/utils/abi/index.d.ts +2 -0
  61. package/dist/utils/abi/index.js +21 -0
  62. package/dist/utils/abi/marketplace/index.d.ts +805 -0
  63. package/dist/utils/abi/marketplace/index.js +12 -0
  64. package/dist/utils/abi/{abi/token → token}/index.js +1 -2
  65. package/dist/utils/index.d.ts +5 -5
  66. package/dist/utils/index.js +12 -14
  67. package/package.json +17 -15
  68. package/src/react/_internal/transaction-machine/execute-transaction.ts +592 -0
  69. package/src/react/_internal/transaction-machine/useTransactionMachine.ts +66 -0
  70. package/src/react/hooks/index.ts +4 -0
  71. package/src/react/hooks/useBuyCollectable.tsx +38 -0
  72. package/src/react/hooks/useCancelOrder.tsx +38 -0
  73. package/src/react/hooks/useCheckoutOptions.tsx +9 -6
  74. package/src/react/hooks/useCreateListing.tsx +65 -0
  75. package/src/react/hooks/useGenerateBuyTransaction.tsx +71 -0
  76. package/src/react/hooks/useListListingsForCollectible.tsx +1 -1
  77. package/src/react/hooks/useMakeOffer.tsx +62 -0
  78. package/src/react/hooks/useRoyaltyPercentage.tsx +1 -1
  79. package/src/react/hooks/useSell.tsx +62 -0
  80. package/src/react/ui/components/_internals/action-button/ActionButton.tsx +107 -115
  81. package/src/react/ui/components/_internals/custom-select/CustomSelect.tsx +63 -0
  82. package/src/react/ui/components/_internals/custom-select/styles.css.ts +64 -0
  83. package/src/react/ui/components/collectible-card/CollectibleCard.tsx +127 -130
  84. package/src/react/ui/components/collectible-card/Footer.tsx +65 -58
  85. package/src/react/ui/icons/Bell.tsx +2 -2
  86. package/src/react/ui/index.ts +1 -0
  87. package/src/react/ui/modals/BuyModal/_store.ts +53 -0
  88. package/src/react/ui/modals/BuyModal/index.tsx +119 -0
  89. package/src/react/ui/modals/CreateListingModal/_store.ts +35 -312
  90. package/src/react/ui/modals/CreateListingModal/index.tsx +185 -126
  91. package/src/react/ui/modals/MakeOfferModal/_store.ts +34 -276
  92. package/src/react/ui/modals/MakeOfferModal/index.tsx +195 -136
  93. package/src/react/ui/modals/SellModal/_store.ts +29 -262
  94. package/src/react/ui/modals/SellModal/index.tsx +156 -121
  95. package/src/react/ui/modals/SuccessfulPurchaseModal/_store.ts +17 -3
  96. package/src/react/ui/modals/SuccessfulPurchaseModal/index.tsx +3 -2
  97. package/src/react/ui/modals/TransferModal/index.tsx +9 -16
  98. package/src/react/ui/modals/_internal/components/actionModal/ActionModal.tsx +1 -0
  99. package/src/react/ui/modals/_internal/components/actionModal/ErrorModal.tsx +18 -0
  100. package/src/react/ui/modals/_internal/components/actionModal/LoadingModal.tsx +18 -0
  101. package/src/react/ui/modals/_internal/components/calendarPopover/index.tsx +1 -0
  102. package/src/react/ui/modals/_internal/components/calendarPopover/overrides.css +8 -0
  103. package/src/react/ui/modals/_internal/components/calendarPopover/styles.css.ts +10 -4
  104. package/src/react/ui/modals/_internal/components/currencyOptionsSelect/index.tsx +10 -13
  105. package/src/react/ui/modals/_internal/components/expirationDateSelect/index.tsx +23 -9
  106. package/src/react/ui/modals/_internal/components/priceInput/index.tsx +7 -18
  107. package/src/react/ui/modals/_internal/components/switchChainModal/index.tsx +17 -44
  108. package/src/react/ui/modals/_internal/components/switchChainModal/store.ts +10 -8
  109. package/src/react/ui/modals/_internal/components/tokenPreview/index.tsx +14 -3
  110. package/src/react/ui/modals/_internal/components/transactionDetails/index.tsx +4 -2
  111. package/src/react/ui/modals/_internal/components/transactionHeader/index.tsx +4 -4
  112. package/src/react/ui/modals/_internal/components/transactionPreview/index.tsx +4 -2
  113. package/src/react/ui/modals/_internal/components/transactionStatusModal/index.tsx +13 -10
  114. package/src/react/ui/modals/_internal/types.ts +13 -0
  115. package/src/react/ui/modals/modal-provider.tsx +4 -2
  116. package/src/styles/index.ts +0 -2
  117. package/src/utils/abi/index.ts +2 -0
  118. package/src/utils/abi/marketplace/index.ts +3 -0
  119. package/src/utils/abi/marketplace/sequence-marketplace-v1.ts +463 -0
  120. package/src/utils/abi/marketplace/sequence-marketplace-v2.ts +802 -0
  121. package/src/utils/index.ts +2 -3
  122. package/src/utils/network.ts +4 -2
  123. package/tsconfig.tsbuildinfo +1 -1
  124. package/dist/chunk-6JWGELXL.js +0 -214
  125. package/dist/chunk-6JWGELXL.js.map +0 -1
  126. package/dist/chunk-6S4FYXP6.js.map +0 -1
  127. package/dist/chunk-7OO74L2K.js.map +0 -1
  128. package/dist/chunk-BCNFYVAL.js +0 -1
  129. package/dist/chunk-BJE7AG6V.js.map +0 -1
  130. package/dist/chunk-CSN7YD5Q.js.map +0 -1
  131. package/dist/chunk-D7QQP6MS.js +0 -2
  132. package/dist/chunk-DBFOPEV6.js +0 -23
  133. package/dist/chunk-DBFOPEV6.js.map +0 -1
  134. package/dist/chunk-MQR6SHXZ.js.map +0 -1
  135. package/dist/chunk-O5JXKTWP.js.map +0 -1
  136. package/dist/chunk-OUWB3FHZ.js.map +0 -1
  137. package/dist/chunk-PE2LLUTJ.js +0 -213
  138. package/dist/chunk-PE2LLUTJ.js.map +0 -1
  139. package/dist/chunk-QVFMD6S2.js +0 -21
  140. package/dist/chunk-QVFMD6S2.js.map +0 -1
  141. package/dist/chunk-QXLZPSSR.js +0 -3316
  142. package/dist/chunk-QXLZPSSR.js.map +0 -1
  143. package/dist/chunk-UYRQ5MJQ.js.map +0 -1
  144. package/dist/utils/abi/abi/standard/index.d.ts +0 -25
  145. package/dist/utils/abi/abi/standard/index.js +0 -8
  146. package/dist/utils/abi/clients/index.d.ts +0 -27
  147. package/dist/utils/abi/clients/index.js +0 -13
  148. package/src/react/ui/modals/_internal/components/currencyOptionsSelect/styles.css.ts +0 -33
  149. package/src/react/ui/modals/_internal/components/expirationDateSelect/styles.css.ts +0 -25
  150. package/src/utils/abi/abi/standard/index.ts +0 -1
  151. package/src/utils/abi/clients/ERC1155.ts +0 -82
  152. package/src/utils/abi/clients/ERC20.ts +0 -101
  153. package/src/utils/abi/clients/ERC721.ts +0 -97
  154. package/src/utils/abi/clients/index.ts +0 -3
  155. /package/dist/{chunk-BCNFYVAL.js.map → chunk-MCI3KOSQ.js.map} +0 -0
  156. /package/dist/{chunk-D7QQP6MS.js.map → chunk-UISBTKFF.js.map} +0 -0
  157. /package/dist/utils/abi/{abi/standard/index.js.map → index.js.map} +0 -0
  158. /package/dist/utils/abi/{abi/token → marketplace}/index.js.map +0 -0
  159. /package/dist/utils/abi/{abi/token → token}/index.d.ts +0 -0
  160. /package/dist/utils/abi/{clients → token}/index.js.map +0 -0
  161. /package/src/react/hooks/{useGenerateCancleTransaction.tsx → useGenerateCancelTransaction.tsx} +0 -0
  162. /package/src/utils/abi/{abi/standard → marketplace}/EIP2981.ts +0 -0
  163. /package/src/utils/abi/{abi/token → token}/ERC1155.ts +0 -0
  164. /package/src/utils/abi/{abi/token → token}/ERC20.ts +0 -0
  165. /package/src/utils/abi/{abi/token → token}/ERC721.ts +0 -0
  166. /package/src/utils/abi/{abi/token → token}/index.ts +0 -0
@@ -0,0 +1,38 @@
1
+ import {
2
+ type CancelInput,
3
+ TransactionType,
4
+ } from '../_internal/transaction-machine/execute-transaction';
5
+ import {
6
+ useTransactionMachine,
7
+ type UseTransactionMachineConfig,
8
+ } from '../_internal/transaction-machine/useTransactionMachine';
9
+
10
+ interface UseCancelOrderArgs extends Omit<UseTransactionMachineConfig, 'type'> {
11
+ onSuccess?: (hash: string) => void;
12
+ onError?: (error: Error) => void;
13
+ onTransactionSent?: (hash: string) => void;
14
+ }
15
+
16
+ export const useCancelOrder = ({
17
+ onSuccess,
18
+ onError,
19
+ onTransactionSent,
20
+ ...config
21
+ }: UseCancelOrderArgs) => {
22
+ const machine = useTransactionMachine(
23
+ {
24
+ ...config,
25
+ type: TransactionType.CANCEL,
26
+ },
27
+ onSuccess,
28
+ onError,
29
+ onTransactionSent,
30
+ );
31
+
32
+ return {
33
+ cancel: (props: CancelInput) => machine?.start({ props }),
34
+ onError,
35
+ onSuccess,
36
+ onTransactionSent,
37
+ };
38
+ };
@@ -9,15 +9,15 @@ import {
9
9
  getMarketplaceClient,
10
10
  } from '../_internal';
11
11
  import { useConfig } from './useConfig';
12
+ import { useAccount } from 'wagmi';
13
+ import type { Hex } from 'viem';
12
14
 
13
15
  const UseCheckoutOptionsSchema = z.object({
14
16
  chainId: ChainIdSchema.pipe(z.coerce.string()),
15
- walletAddress: AddressSchema,
16
17
  orders: z.array(
17
18
  z.object({
18
19
  collectionAddress: AddressSchema,
19
20
  orderId: z.string(),
20
- quantity: z.number(),
21
21
  marketplace: z.nativeEnum(MarketplaceKind),
22
22
  }),
23
23
  ),
@@ -31,7 +31,7 @@ export type UseCheckoutOptionsReturn = Awaited<
31
31
  >;
32
32
 
33
33
  const fetchCheckoutOptions = async (
34
- args: UseCheckoutOptionsArgs,
34
+ args: UseCheckoutOptionsArgs & { walletAddress: Hex },
35
35
  config: SdkConfig,
36
36
  ) => {
37
37
  const marketplaceClient = getMarketplaceClient(args.chainId, config);
@@ -41,14 +41,13 @@ const fetchCheckoutOptions = async (
41
41
  contractAddress: order.collectionAddress,
42
42
  orderId: order.orderId,
43
43
  marketplace: order.marketplace,
44
- quantity: order.quantity,
45
44
  })),
46
45
  additionalFee: 0, //TODO: add additional fee
47
46
  });
48
47
  };
49
48
 
50
49
  export const checkoutOptionsOptions = (
51
- args: UseCheckoutOptionsArgs,
50
+ args: UseCheckoutOptionsArgs & { walletAddress: Hex },
52
51
  config: SdkConfig,
53
52
  ) => {
54
53
  return queryOptions({
@@ -58,6 +57,10 @@ export const checkoutOptionsOptions = (
58
57
  };
59
58
 
60
59
  export const useCheckoutOptions = (args: UseCheckoutOptionsArgs) => {
60
+ const { address } = useAccount();
61
61
  const config = useConfig();
62
- return useQuery(checkoutOptionsOptions(args, config));
62
+ return useQuery(
63
+ // biome-ignore lint/style/noNonNullAssertion: <explanation>
64
+ checkoutOptionsOptions({ walletAddress: address!, ...args }, config),
65
+ );
63
66
  };
@@ -0,0 +1,65 @@
1
+ import { useState, useCallback } from 'react';
2
+ import type { Hash } from 'viem';
3
+ import {
4
+ type ListingInput,
5
+ TransactionType,
6
+ type TransactionSteps,
7
+ } from '../_internal/transaction-machine/execute-transaction';
8
+ import {
9
+ useTransactionMachine,
10
+ type UseTransactionMachineConfig,
11
+ } from '../_internal/transaction-machine/useTransactionMachine';
12
+
13
+ interface UseCreateListingArgs
14
+ extends Omit<UseTransactionMachineConfig, 'type'> {
15
+ onSuccess?: (hash: Hash) => void;
16
+ onError?: (error: Error) => void;
17
+ onTransactionSent?: (hash: Hash) => void;
18
+ }
19
+
20
+ export const useCreateListing = ({
21
+ onSuccess,
22
+ onError,
23
+ onTransactionSent,
24
+ ...config
25
+ }: UseCreateListingArgs) => {
26
+ const [isLoading, setIsLoading] = useState(false);
27
+ const [steps, setSteps] = useState<TransactionSteps | null>(null);
28
+
29
+ const machine = useTransactionMachine(
30
+ {
31
+ ...config,
32
+ type: TransactionType.LISTING,
33
+ },
34
+ onSuccess,
35
+ onError,
36
+ onTransactionSent,
37
+ );
38
+
39
+ const loadSteps = useCallback(
40
+ async (props: ListingInput) => {
41
+ if (!machine) return;
42
+ setIsLoading(true);
43
+ try {
44
+ const generatedSteps = await machine.getTransactionSteps(props);
45
+ setSteps(generatedSteps);
46
+ } catch (error) {
47
+ onError?.(error as Error);
48
+ } finally {
49
+ setIsLoading(false);
50
+ }
51
+ },
52
+ [machine, onError],
53
+ );
54
+
55
+ return {
56
+ createListing: (props: ListingInput) => machine?.start({ props }),
57
+ getListingSteps: (props: ListingInput) => ({
58
+ isLoading,
59
+ steps,
60
+ refreshSteps: () => loadSteps(props),
61
+ }),
62
+ onError,
63
+ onSuccess,
64
+ };
65
+ };
@@ -0,0 +1,71 @@
1
+ import { queryOptions, useQuery } from '@tanstack/react-query';
2
+ import { z } from 'zod';
3
+ import type { SdkConfig } from '../../types';
4
+ import {
5
+ AddressSchema,
6
+ ChainIdSchema,
7
+ getMarketplaceClient,
8
+ MarketplaceKind,
9
+ QueryArgSchema,
10
+ WalletKind,
11
+ } from '../_internal';
12
+ import { useConfig } from './useConfig';
13
+ import { useAccount } from 'wagmi';
14
+ import type { Hex } from 'viem';
15
+
16
+ export const UseGenerateBuyTransactionArgsSchema = z.object({
17
+ chainId: ChainIdSchema.pipe(z.coerce.string()),
18
+ collectionAddress: AddressSchema,
19
+ marketplace: z.nativeEnum(MarketplaceKind),
20
+ ordersData: z.array(
21
+ z.object({
22
+ orderId: z.string(),
23
+ quantity: z.string(),
24
+ marketplace: z.string(),
25
+ }),
26
+ ),
27
+ walletType: z.nativeEnum(WalletKind).optional(),
28
+ query: QueryArgSchema,
29
+ });
30
+
31
+ type UseGenerateBuyTransactionArgs = z.infer<
32
+ typeof UseGenerateBuyTransactionArgsSchema
33
+ >;
34
+
35
+ export const fetchGenerateBuyTransaction = async (
36
+ args: UseGenerateBuyTransactionArgs & { buyer: Hex },
37
+ config: SdkConfig,
38
+ ) => {
39
+ const parsedArgs = UseGenerateBuyTransactionArgsSchema.parse(args);
40
+ const marketplaceClient = getMarketplaceClient(parsedArgs.chainId, config);
41
+
42
+ return marketplaceClient
43
+ .generateBuyTransaction({
44
+ ...parsedArgs,
45
+ buyer: args.buyer,
46
+ additionalFees: [], // TODO: Add additional fees
47
+ })
48
+ .then((data) => data.steps);
49
+ };
50
+
51
+ export const generateBuyTransactionOptions = (
52
+ args: UseGenerateBuyTransactionArgs & { buyer: Hex },
53
+ config: SdkConfig,
54
+ ) => {
55
+ return queryOptions({
56
+ queryKey: ['generateBuyTransaction', args],
57
+ queryFn: () => fetchGenerateBuyTransaction(args, config),
58
+ ...args.query,
59
+ });
60
+ };
61
+
62
+ export const useGenerateBuyTransaction = (
63
+ args: UseGenerateBuyTransactionArgs,
64
+ ) => {
65
+ const { address } = useAccount();
66
+ const config = useConfig();
67
+ return useQuery(
68
+ // biome-ignore lint/style/noNonNullAssertion: <explanation>
69
+ generateBuyTransactionOptions({ buyer: address!, ...args }, config),
70
+ );
71
+ };
@@ -47,7 +47,7 @@ export const listListingsForCollectibleOptions = (
47
47
  config: SdkConfig,
48
48
  ) => {
49
49
  return queryOptions({
50
- queryKey: [...collectableKeys.offers, args, config],
50
+ queryKey: [...collectableKeys.listings, args, config],
51
51
  queryFn: () => fetchListListingsForCollectible(config, args),
52
52
  });
53
53
  };
@@ -0,0 +1,62 @@
1
+ import { useState, useCallback } from 'react';
2
+ import type { Hash } from 'viem';
3
+ import {
4
+ type OfferInput,
5
+ TransactionType,
6
+ type TransactionSteps,
7
+ } from '../_internal/transaction-machine/execute-transaction';
8
+ import {
9
+ useTransactionMachine,
10
+ type UseTransactionMachineConfig,
11
+ } from '../_internal/transaction-machine/useTransactionMachine';
12
+
13
+ interface UseMakeOfferArgs extends Omit<UseTransactionMachineConfig, 'type'> {
14
+ onSuccess?: (hash: Hash) => void;
15
+ onError?: (error: Error) => void;
16
+ onTransactionSent?: (hash: Hash) => void;
17
+ }
18
+
19
+ export const useMakeOffer = ({
20
+ onSuccess,
21
+ onError,
22
+ onTransactionSent,
23
+ ...config
24
+ }: UseMakeOfferArgs) => {
25
+ const [isLoading, setIsLoading] = useState(false);
26
+ const [steps, setSteps] = useState<TransactionSteps | null>(null);
27
+
28
+ const machine = useTransactionMachine(
29
+ {
30
+ ...config,
31
+ type: TransactionType.OFFER,
32
+ },
33
+ onSuccess,
34
+ onError,
35
+ onTransactionSent,
36
+ );
37
+
38
+ const loadSteps = useCallback(
39
+ async (props: OfferInput) => {
40
+ if (!machine) return;
41
+ setIsLoading(true);
42
+ try {
43
+ const generatedSteps = await machine.getTransactionSteps(props);
44
+ setSteps(generatedSteps);
45
+ } catch (error) {
46
+ onError?.(error as Error);
47
+ } finally {
48
+ setIsLoading(false);
49
+ }
50
+ },
51
+ [machine, onError],
52
+ );
53
+
54
+ return {
55
+ makeOffer: (props: OfferInput) => machine?.start({ props }),
56
+ getMakeOfferSteps: (props: OfferInput) => ({
57
+ isLoading,
58
+ steps,
59
+ refreshSteps: () => loadSteps(props),
60
+ }),
61
+ };
62
+ };
@@ -2,7 +2,6 @@ import { queryOptions, useQuery } from '@tanstack/react-query';
2
2
  import type { Hex } from 'viem';
3
3
  import { getContract } from 'viem';
4
4
  import { z } from 'zod';
5
- import { EIP2981_ABI } from '../../utils/abi/abi/standard/EIP2981';
6
5
  import { getPublicRpcClient } from '../../utils/get-public-rpc-client';
7
6
  import {
8
7
  AddressSchema,
@@ -10,6 +9,7 @@ import {
10
9
  QueryArgSchema,
11
10
  collectableKeys,
12
11
  } from '../_internal';
12
+ import { EIP2981_ABI } from '../../utils';
13
13
 
14
14
  const UseRoyaletyPercentageSchema = z.object({
15
15
  chainId: ChainIdSchema.pipe(z.coerce.string()),
@@ -0,0 +1,62 @@
1
+ import { useState, useCallback } from 'react';
2
+ import type { Hash } from 'viem';
3
+ import {
4
+ type SellInput,
5
+ TransactionType,
6
+ type TransactionSteps,
7
+ } from '../_internal/transaction-machine/execute-transaction';
8
+ import {
9
+ useTransactionMachine,
10
+ type UseTransactionMachineConfig,
11
+ } from '../_internal/transaction-machine/useTransactionMachine';
12
+
13
+ interface UseSellArgs extends Omit<UseTransactionMachineConfig, 'type'> {
14
+ onSuccess?: (hash: Hash) => void;
15
+ onError?: (error: Error) => void;
16
+ onTransactionSent?: (hash: Hash) => void;
17
+ }
18
+
19
+ export const useSell = ({
20
+ onSuccess,
21
+ onError,
22
+ onTransactionSent,
23
+ ...config
24
+ }: UseSellArgs) => {
25
+ const [isLoading, setIsLoading] = useState(false);
26
+ const [steps, setSteps] = useState<TransactionSteps | null>(null);
27
+
28
+ const machine = useTransactionMachine(
29
+ {
30
+ ...config,
31
+ type: TransactionType.SELL,
32
+ },
33
+ onSuccess,
34
+ onError,
35
+ onTransactionSent,
36
+ );
37
+
38
+ const loadSteps = useCallback(
39
+ async (props: SellInput) => {
40
+ if (!machine) return;
41
+ setIsLoading(true);
42
+ try {
43
+ const generatedSteps = await machine.getTransactionSteps(props);
44
+ setSteps(generatedSteps);
45
+ } catch (error) {
46
+ onError?.(error as Error);
47
+ } finally {
48
+ setIsLoading(false);
49
+ }
50
+ },
51
+ [machine, onError],
52
+ );
53
+
54
+ return {
55
+ sell: (props: SellInput) => machine?.start({ props }),
56
+ getSellSteps: (props: SellInput) => ({
57
+ isLoading,
58
+ steps,
59
+ refreshSteps: () => loadSteps(props),
60
+ }),
61
+ };
62
+ };
@@ -3,141 +3,133 @@
3
3
  import { Button } from '@0xsequence/design-system';
4
4
  import { observer } from '@legendapp/state/react';
5
5
  import type { Hex } from 'viem';
6
- import { useAccount } from 'wagmi';
7
- import {
8
- useBalanceOfCollectible,
9
- useHighestOffer,
10
- useLowestListing,
11
- } from '../../../../hooks';
6
+ import type { Order } from '../../../../_internal';
7
+ import { useBuyModal } from '../../../modals/BuyModal';
12
8
  import { useCreateListingModal } from '../../../modals/CreateListingModal';
13
9
  import { useMakeOfferModal } from '../../../modals/MakeOfferModal';
14
10
  import { useSellModal } from '../../../modals/SellModal';
15
11
  import { useTransferModal } from '../../../modals/TransferModal';
16
12
 
13
+ export enum CollectibleCardAction {
14
+ BUY = 'Buy',
15
+ SELL = 'Sell',
16
+ LIST = 'Create listing',
17
+ OFFER = 'Make an offer',
18
+ TRANSFER = 'Transfer',
19
+ }
20
+
17
21
  type ActionButtonProps = {
18
22
  chainId: string;
19
- collectionAddress: string;
23
+ collectionAddress: Hex;
20
24
  tokenId: string;
21
25
  isTransfer?: boolean;
26
+ action: CollectibleCardAction;
27
+ isOwned: boolean;
28
+ highestOffer?: Order;
29
+ lowestListing?: Order;
22
30
  };
23
31
 
24
- export const ActionButton = observer(function AddToCartButton({
25
- collectionAddress,
26
- chainId,
27
- tokenId,
28
- isTransfer,
29
- }: ActionButtonProps) {
30
- const { address: accountAddress } = useAccount();
31
- //TODO: this should not call all of these endpoints on every card
32
- const { data: balance, isLoading: balanceLoading } = useBalanceOfCollectible({
33
- chainId,
32
+ export const ActionButton = observer(
33
+ ({
34
34
  collectionAddress,
35
- collectableId: tokenId,
36
- // biome-ignore lint/style/noNonNullAssertion: <explanation>
37
- userAddress: accountAddress!,
38
- });
39
- const { data: highestOffer, isLoading: highestOfferLoading } =
40
- useHighestOffer({
41
- collectionAddress: collectionAddress as Hex,
42
- chainId: String(chainId),
43
- tokenId: tokenId,
44
- });
45
- const { data: lowestListing, isLoading: lowestListingLoading } =
46
- useLowestListing({
47
- collectionAddress: collectionAddress as Hex,
48
- chainId: String(chainId),
49
- tokenId: tokenId,
50
- });
51
- const collectibleOwned = balance?.balance ?? 0;
35
+ chainId,
36
+ tokenId,
37
+ action,
38
+ highestOffer,
39
+ lowestListing,
40
+ }: ActionButtonProps) => {
41
+ const { show: showCreateListingModal } = useCreateListingModal();
42
+ const { show: showMakeOfferModal } = useMakeOfferModal();
43
+ const { show: showSellModal } = useSellModal();
44
+ const { show: showTransferModal } = useTransferModal();
45
+ const { show: showBuyModal } = useBuyModal();
52
46
 
53
- const { show: showCreateListingModal } = useCreateListingModal();
54
- const { show: showMakeOfferModal } = useMakeOfferModal();
55
- const { show: showSellModal } = useSellModal();
56
- const { show: showTransferModal } = useTransferModal();
47
+ if (action === CollectibleCardAction.BUY) {
48
+ if (!lowestListing)
49
+ throw new Error('lowestListing is required for BUY action');
57
50
 
58
- if (
59
- balanceLoading ||
60
- highestOfferLoading ||
61
- lowestListingLoading ||
62
- !accountAddress
63
- ) {
64
- return null;
65
- }
51
+ return (
52
+ <ActionButtonBody
53
+ label="Buy"
54
+ onClick={() =>
55
+ showBuyModal({
56
+ collectionAddress,
57
+ chainId: chainId,
58
+ tokenId: tokenId,
59
+ order: lowestListing,
60
+ })
61
+ }
62
+ />
63
+ );
64
+ }
66
65
 
67
- if (isTransfer && collectibleOwned) {
68
- return (
69
- <ActionButtonBody
70
- label="Transfer"
71
- onClick={() =>
72
- showTransferModal({
73
- collectionAddress: collectionAddress as Hex,
74
- chainId: chainId,
75
- tokenId: tokenId,
76
- })
77
- }
78
- />
79
- );
80
- }
66
+ if (action === CollectibleCardAction.SELL) {
67
+ if (!highestOffer)
68
+ throw new Error('highestOffer is required for SELL action');
81
69
 
82
- if (!collectibleOwned) {
83
- return (
84
- <ActionButtonBody
85
- label="Make an offer"
86
- onClick={() =>
87
- showMakeOfferModal({
88
- collectionAddress: collectionAddress as Hex,
89
- chainId: chainId,
90
- collectibleId: tokenId,
91
- })
92
- }
93
- />
94
- );
95
- }
70
+ return (
71
+ <ActionButtonBody
72
+ label="Sell"
73
+ onClick={() =>
74
+ showSellModal({
75
+ collectionAddress,
76
+ chainId: chainId,
77
+ tokenId: tokenId,
78
+ order: highestOffer,
79
+ })
80
+ }
81
+ />
82
+ );
83
+ }
96
84
 
97
- if (!collectibleOwned && lowestListing?.order) {
98
- return (
99
- <ActionButtonBody
100
- label="Add to cart"
101
- // eslint-disable-next-line @typescript-eslint/no-empty-function
102
- onClick={() => {}}
103
- />
104
- );
105
- }
85
+ if (action === CollectibleCardAction.LIST) {
86
+ return (
87
+ <ActionButtonBody
88
+ label="Create listing"
89
+ onClick={() =>
90
+ showCreateListingModal({
91
+ collectionAddress: collectionAddress as Hex,
92
+ chainId: chainId,
93
+ collectibleId: tokenId,
94
+ })
95
+ }
96
+ />
97
+ );
98
+ }
106
99
 
107
- if (collectibleOwned && !lowestListing?.order) {
108
- return (
109
- <ActionButtonBody
110
- label="Create listing"
111
- onClick={() =>
112
- showCreateListingModal({
113
- collectionAddress: collectionAddress as Hex,
114
- chainId: chainId,
115
- collectibleId: tokenId,
116
- })
117
- }
118
- />
119
- );
120
- }
100
+ if (action === CollectibleCardAction.OFFER) {
101
+ return (
102
+ <ActionButtonBody
103
+ label="Make an offer"
104
+ onClick={() =>
105
+ showMakeOfferModal({
106
+ collectionAddress: collectionAddress as Hex,
107
+ chainId: chainId,
108
+ collectibleId: tokenId,
109
+ })
110
+ }
111
+ />
112
+ );
113
+ }
121
114
 
122
- if (collectibleOwned && highestOffer?.order) {
123
- return (
124
- <ActionButtonBody
125
- label="Sell"
126
- onClick={() =>
127
- showSellModal({
128
- collectionAddress: collectionAddress as Hex,
129
- chainId: chainId,
130
- tokenId: tokenId,
131
- // biome-ignore lint/style/noNonNullAssertion: <explanation>
132
- order: highestOffer.order!,
133
- })
134
- }
135
- />
136
- );
137
- }
115
+ if (action === CollectibleCardAction.TRANSFER) {
116
+ return (
117
+ <ActionButtonBody
118
+ label="Transfer"
119
+ onClick={() =>
120
+ showTransferModal({
121
+ collectionAddress: collectionAddress as Hex,
122
+ chainId: chainId,
123
+ tokenId,
124
+ })
125
+ }
126
+ />
127
+ );
128
+ }
138
129
 
139
- return null;
140
- });
130
+ return null;
131
+ },
132
+ );
141
133
 
142
134
  type ActionButtonBodyProps = {
143
135
  label: string;
@@ -0,0 +1,63 @@
1
+ import React from 'react';
2
+ import * as Select from '@radix-ui/react-select';
3
+ import { CheckmarkIcon, ChevronDownIcon } from '@0xsequence/design-system';
4
+ import { content, item, itemIndicator, trigger } from './styles.css';
5
+
6
+ interface CustomSelectProps {
7
+ items: Array<{
8
+ value: string;
9
+ label: string;
10
+ disabled?: boolean;
11
+ }>;
12
+ placeholder?: string;
13
+ onValueChange?: (value: string) => void;
14
+ defaultValue?: string;
15
+ }
16
+
17
+ const CustomSelectItem = React.forwardRef<
18
+ HTMLDivElement,
19
+ Select.SelectItemProps
20
+ >(({ children, ...props }, forwardedRef) => {
21
+ return (
22
+ <Select.Item className={item} {...props} ref={forwardedRef}>
23
+ <Select.ItemText>{children}</Select.ItemText>
24
+ <Select.ItemIndicator className={itemIndicator}>
25
+ <CheckmarkIcon size="xs" />
26
+ </Select.ItemIndicator>
27
+ </Select.Item>
28
+ );
29
+ });
30
+
31
+ export const CustomSelect: React.FC<CustomSelectProps> = ({
32
+ items,
33
+ placeholder = 'Select an item...',
34
+ onValueChange,
35
+ defaultValue,
36
+ }) => {
37
+ return (
38
+ <Select.Root onValueChange={onValueChange} defaultValue={defaultValue}>
39
+ <Select.Trigger className={trigger}>
40
+ <Select.Value placeholder={placeholder} />
41
+ <Select.Icon>
42
+ <ChevronDownIcon size="xs" />
43
+ </Select.Icon>
44
+ </Select.Trigger>
45
+
46
+ <Select.Portal>
47
+ <Select.Content className={content}>
48
+ <Select.Viewport>
49
+ {items.map((item) => (
50
+ <CustomSelectItem
51
+ key={item.value}
52
+ value={item.value}
53
+ disabled={item.disabled}
54
+ >
55
+ {item.label}
56
+ </CustomSelectItem>
57
+ ))}
58
+ </Select.Viewport>
59
+ </Select.Content>
60
+ </Select.Portal>
61
+ </Select.Root>
62
+ );
63
+ };