@0xsequence/marketplace-sdk 0.0.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 (258) hide show
  1. package/README.md +8 -0
  2. package/dist/chunk-3TYUQEFM.js +115 -0
  3. package/dist/chunk-3TYUQEFM.js.map +1 -0
  4. package/dist/chunk-4ESPWOBV.js +13 -0
  5. package/dist/chunk-4ESPWOBV.js.map +1 -0
  6. package/dist/chunk-4PFMUVE4.js +78 -0
  7. package/dist/chunk-4PFMUVE4.js.map +1 -0
  8. package/dist/chunk-5WRI5ZAA.js +31 -0
  9. package/dist/chunk-5WRI5ZAA.js.map +1 -0
  10. package/dist/chunk-6S4FYXP6.js +43 -0
  11. package/dist/chunk-6S4FYXP6.js.map +1 -0
  12. package/dist/chunk-7OO74L2K.js +41 -0
  13. package/dist/chunk-7OO74L2K.js.map +1 -0
  14. package/dist/chunk-BBB3XUB4.js +213 -0
  15. package/dist/chunk-BBB3XUB4.js.map +1 -0
  16. package/dist/chunk-BCNFYVAL.js +1 -0
  17. package/dist/chunk-BCNFYVAL.js.map +1 -0
  18. package/dist/chunk-D7QQP6MS.js +2 -0
  19. package/dist/chunk-D7QQP6MS.js.map +1 -0
  20. package/dist/chunk-DBFOPEV6.js +23 -0
  21. package/dist/chunk-DBFOPEV6.js.map +1 -0
  22. package/dist/chunk-EDTC7UES.js +176 -0
  23. package/dist/chunk-EDTC7UES.js.map +1 -0
  24. package/dist/chunk-G3D572BT.js +249 -0
  25. package/dist/chunk-G3D572BT.js.map +1 -0
  26. package/dist/chunk-HGBEC3WX.js +1285 -0
  27. package/dist/chunk-HGBEC3WX.js.map +1 -0
  28. package/dist/chunk-MJ4YU7RW.js +2 -0
  29. package/dist/chunk-MJ4YU7RW.js.map +1 -0
  30. package/dist/chunk-NJ2GXOPW.js +2 -0
  31. package/dist/chunk-NJ2GXOPW.js.map +1 -0
  32. package/dist/chunk-O5JXKTWP.js +1029 -0
  33. package/dist/chunk-O5JXKTWP.js.map +1 -0
  34. package/dist/chunk-O642NH7U.js +15 -0
  35. package/dist/chunk-O642NH7U.js.map +1 -0
  36. package/dist/chunk-QOJXWHRZ.js +71 -0
  37. package/dist/chunk-QOJXWHRZ.js.map +1 -0
  38. package/dist/chunk-QVFMD6S2.js +21 -0
  39. package/dist/chunk-QVFMD6S2.js.map +1 -0
  40. package/dist/chunk-RNUHUVLC.js +214 -0
  41. package/dist/chunk-RNUHUVLC.js.map +1 -0
  42. package/dist/chunk-SM7V6ZWI.js +2740 -0
  43. package/dist/chunk-SM7V6ZWI.js.map +1 -0
  44. package/dist/chunk-STO74F2I.js +14 -0
  45. package/dist/chunk-STO74F2I.js.map +1 -0
  46. package/dist/chunk-TZGLKJRF.js +198 -0
  47. package/dist/chunk-TZGLKJRF.js.map +1 -0
  48. package/dist/chunk-UYRQ5MJQ.js +1027 -0
  49. package/dist/chunk-UYRQ5MJQ.js.map +1 -0
  50. package/dist/chunk-VPGWEMWL.js +162 -0
  51. package/dist/chunk-VPGWEMWL.js.map +1 -0
  52. package/dist/chunk-ZE2LNX65.js +394 -0
  53. package/dist/chunk-ZE2LNX65.js.map +1 -0
  54. package/dist/create-config-Dz0gCiQ0.d.ts +8 -0
  55. package/dist/get-query-client-D46hbjk6.d.ts +5 -0
  56. package/dist/index.css +232 -0
  57. package/dist/index.d.ts +16 -0
  58. package/dist/index.js +76 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/marketplace-config-DZbtyrma.d.ts +57 -0
  61. package/dist/marketplace.gen-Ceofb9Cs.d.ts +904 -0
  62. package/dist/react/_internal/api/index.d.ts +51 -0
  63. package/dist/react/_internal/api/index.js +134 -0
  64. package/dist/react/_internal/api/index.js.map +1 -0
  65. package/dist/react/_internal/index.d.ts +22 -0
  66. package/dist/react/_internal/index.js +150 -0
  67. package/dist/react/_internal/index.js.map +1 -0
  68. package/dist/react/_internal/wagmi/index.d.ts +12 -0
  69. package/dist/react/_internal/wagmi/index.js +12 -0
  70. package/dist/react/_internal/wagmi/index.js.map +1 -0
  71. package/dist/react/hooks/index.d.ts +381 -0
  72. package/dist/react/hooks/index.js +82 -0
  73. package/dist/react/hooks/index.js.map +1 -0
  74. package/dist/react/index.css +233 -0
  75. package/dist/react/index.css.map +1 -0
  76. package/dist/react/index.d.ts +27 -0
  77. package/dist/react/index.js +113 -0
  78. package/dist/react/index.js.map +1 -0
  79. package/dist/react/ssr/index.d.ts +94 -0
  80. package/dist/react/ssr/index.js +351 -0
  81. package/dist/react/ssr/index.js.map +1 -0
  82. package/dist/react/ui/icons/index.css +25 -0
  83. package/dist/react/ui/icons/index.css.map +1 -0
  84. package/dist/react/ui/icons/index.d.ts +2 -0
  85. package/dist/react/ui/icons/index.js +12 -0
  86. package/dist/react/ui/icons/index.js.map +1 -0
  87. package/dist/react/ui/index.css +233 -0
  88. package/dist/react/ui/index.css.map +1 -0
  89. package/dist/react/ui/index.d.ts +112 -0
  90. package/dist/react/ui/index.js +34 -0
  91. package/dist/react/ui/index.js.map +1 -0
  92. package/dist/react/ui/modals/_internal/components/actionModal/index.css +44 -0
  93. package/dist/react/ui/modals/_internal/components/actionModal/index.css.map +1 -0
  94. package/dist/react/ui/modals/_internal/components/actionModal/index.d.ts +31 -0
  95. package/dist/react/ui/modals/_internal/components/actionModal/index.js +39 -0
  96. package/dist/react/ui/modals/_internal/components/actionModal/index.js.map +1 -0
  97. package/dist/react/ui/styles/index.css +36 -0
  98. package/dist/react/ui/styles/index.css.map +1 -0
  99. package/dist/react/ui/styles/index.d.ts +5 -0
  100. package/dist/react/ui/styles/index.js +13 -0
  101. package/dist/react/ui/styles/index.js.map +1 -0
  102. package/dist/sdk-config-xWkdBdrL.d.ts +24 -0
  103. package/dist/services-BIwQ1C1c.d.ts +20 -0
  104. package/dist/styles/index.css +233 -0
  105. package/dist/styles/index.css.map +1 -0
  106. package/dist/styles/index.d.ts +58 -0
  107. package/dist/styles/index.js +5019 -0
  108. package/dist/styles/index.js.map +1 -0
  109. package/dist/styles.css-BVaTR5nO.d.ts +3 -0
  110. package/dist/types/index.d.ts +12 -0
  111. package/dist/types/index.js +39 -0
  112. package/dist/types/index.js.map +1 -0
  113. package/dist/types-BrAQ8-w4.d.ts +12 -0
  114. package/dist/utils/abi/abi/standard/index.d.ts +25 -0
  115. package/dist/utils/abi/abi/standard/index.js +8 -0
  116. package/dist/utils/abi/abi/standard/index.js.map +1 -0
  117. package/dist/utils/abi/abi/token/index.d.ts +1125 -0
  118. package/dist/utils/abi/abi/token/index.js +13 -0
  119. package/dist/utils/abi/abi/token/index.js.map +1 -0
  120. package/dist/utils/abi/clients/index.d.ts +27 -0
  121. package/dist/utils/abi/clients/index.js +13 -0
  122. package/dist/utils/abi/clients/index.js.map +1 -0
  123. package/dist/utils/index.d.ts +23 -0
  124. package/dist/utils/index.js +37 -0
  125. package/dist/utils/index.js.map +1 -0
  126. package/package.json +74 -0
  127. package/src/consts.ts +2 -0
  128. package/src/index.ts +3 -0
  129. package/src/react/_internal/api/get-query-client.ts +32 -0
  130. package/src/react/_internal/api/index.ts +5 -0
  131. package/src/react/_internal/api/marketplace-api.ts +31 -0
  132. package/src/react/_internal/api/marketplace.gen.ts +1911 -0
  133. package/src/react/_internal/api/query-keys.ts +61 -0
  134. package/src/react/_internal/api/services.ts +101 -0
  135. package/src/react/_internal/consts.ts +1 -0
  136. package/src/react/_internal/get-provider.ts +6 -0
  137. package/src/react/_internal/index.ts +5 -0
  138. package/src/react/_internal/types.ts +13 -0
  139. package/src/react/_internal/wagmi/create-config.ts +62 -0
  140. package/src/react/_internal/wagmi/embedded.ts +87 -0
  141. package/src/react/_internal/wagmi/index.ts +3 -0
  142. package/src/react/_internal/wagmi/universal.ts +82 -0
  143. package/src/react/hooks/index.ts +17 -0
  144. package/src/react/hooks/options/marketplaceConfigOptions.ts +62 -0
  145. package/src/react/hooks/useBalanceOfCollectible.tsx +51 -0
  146. package/src/react/hooks/useCollectible.tsx +47 -0
  147. package/src/react/hooks/useCollection.tsx +42 -0
  148. package/src/react/hooks/useCollectionCounts.tsx +61 -0
  149. package/src/react/hooks/useConfig.tsx +15 -0
  150. package/src/react/hooks/useCurrencies.tsx +76 -0
  151. package/src/react/hooks/useFilters.tsx +39 -0
  152. package/src/react/hooks/useFloorOrder.tsx +28 -0
  153. package/src/react/hooks/useGenerateListingTransaction.tsx +63 -0
  154. package/src/react/hooks/useGenerateOfferTransaction.tsx +60 -0
  155. package/src/react/hooks/useGenerateSellTransaction.tsx +43 -0
  156. package/src/react/hooks/useHighestOffer.tsx +46 -0
  157. package/src/react/hooks/useListBalances.tsx +56 -0
  158. package/src/react/hooks/useListCollectibles.tsx +54 -0
  159. package/src/react/hooks/useListOffersForCollectible.tsx +53 -0
  160. package/src/react/hooks/useLowestListing.tsx +47 -0
  161. package/src/react/hooks/useMarketplaceConfig.tsx +10 -0
  162. package/src/react/hooks/useRoyaltyPercentage.tsx +45 -0
  163. package/src/react/hooks/useTransferTokens.tsx +81 -0
  164. package/src/react/index.ts +5 -0
  165. package/src/react/provider.tsx +24 -0
  166. package/src/react/ssr/create-ssr-client.ts +31 -0
  167. package/src/react/ssr/index.ts +1 -0
  168. package/src/react/ui/icons/ArrowUp.tsx +29 -0
  169. package/src/react/ui/icons/CalendarIcon.tsx +29 -0
  170. package/src/react/ui/icons/InfoIcon.tsx +36 -0
  171. package/src/react/ui/icons/InventoryIcon.tsx +41 -0
  172. package/src/react/ui/icons/MinusIcon.tsx +31 -0
  173. package/src/react/ui/icons/PlusIcon.tsx +29 -0
  174. package/src/react/ui/icons/PositiveCircleIcon.tsx +35 -0
  175. package/src/react/ui/icons/index.ts +7 -0
  176. package/src/react/ui/icons/styles.css.ts +35 -0
  177. package/src/react/ui/index.ts +6 -0
  178. package/src/react/ui/modals/Account/index.tsx +29 -0
  179. package/src/react/ui/modals/CreateListingModal/_store.ts +326 -0
  180. package/src/react/ui/modals/CreateListingModal/_utils/getCreateListingTransactionTitleMessage.ts +30 -0
  181. package/src/react/ui/modals/CreateListingModal/index.tsx +146 -0
  182. package/src/react/ui/modals/MakeOfferModal/_store.ts +296 -0
  183. package/src/react/ui/modals/MakeOfferModal/_utils/getMakeOfferTransactionTitleMessage.ts +28 -0
  184. package/src/react/ui/modals/MakeOfferModal/index.tsx +157 -0
  185. package/src/react/ui/modals/SellModal/_store.ts +274 -0
  186. package/src/react/ui/modals/SellModal/_utils/getSellTransactionTitleMessage.ts +28 -0
  187. package/src/react/ui/modals/SellModal/index.tsx +126 -0
  188. package/src/react/ui/modals/SellModal/utils.ts +38 -0
  189. package/src/react/ui/modals/SuccessfulPurchaseModal/_store.ts +58 -0
  190. package/src/react/ui/modals/SuccessfulPurchaseModal/index.tsx +186 -0
  191. package/src/react/ui/modals/SuccessfulPurchaseModal/styles.css.ts +52 -0
  192. package/src/react/ui/modals/TransferModal/_store.ts +58 -0
  193. package/src/react/ui/modals/TransferModal/_utils/getTransferTransactionTitleMessage.ts +28 -0
  194. package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/index.tsx +102 -0
  195. package/src/react/ui/modals/TransferModal/_views/followWalletInstructions/index.tsx +130 -0
  196. package/src/react/ui/modals/TransferModal/index.tsx +92 -0
  197. package/src/react/ui/modals/TransferModal/messages.ts +14 -0
  198. package/src/react/ui/modals/TransferModal/styles.css.ts +20 -0
  199. package/src/react/ui/modals/_internal/components/actionModal/ActionModal.tsx +94 -0
  200. package/src/react/ui/modals/_internal/components/actionModal/index.ts +3 -0
  201. package/src/react/ui/modals/_internal/components/actionModal/store.ts +19 -0
  202. package/src/react/ui/modals/_internal/components/actionModal/styles.css.ts +15 -0
  203. package/src/react/ui/modals/_internal/components/alertMessage/index.tsx +21 -0
  204. package/src/react/ui/modals/_internal/components/alertMessage/styles.css.ts +22 -0
  205. package/src/react/ui/modals/_internal/components/calendar/index.tsx +59 -0
  206. package/src/react/ui/modals/_internal/components/calendarPopover/index.tsx +41 -0
  207. package/src/react/ui/modals/_internal/components/calendarPopover/styles.css.ts +16 -0
  208. package/src/react/ui/modals/_internal/components/currencyOptionsSelect/index.tsx +76 -0
  209. package/src/react/ui/modals/_internal/components/currencyOptionsSelect/styles.css.ts +33 -0
  210. package/src/react/ui/modals/_internal/components/expirationDateSelect/index.tsx +127 -0
  211. package/src/react/ui/modals/_internal/components/expirationDateSelect/styles.css.ts +25 -0
  212. package/src/react/ui/modals/_internal/components/floorPriceText/index.tsx +54 -0
  213. package/src/react/ui/modals/_internal/components/priceInput/index.tsx +72 -0
  214. package/src/react/ui/modals/_internal/components/priceInput/styles.css.ts +23 -0
  215. package/src/react/ui/modals/_internal/components/priceInput/types.ts +4 -0
  216. package/src/react/ui/modals/_internal/components/quantityInput/index.tsx +168 -0
  217. package/src/react/ui/modals/_internal/components/quantityInput/styles.css.ts +30 -0
  218. package/src/react/ui/modals/_internal/components/switchChainModal/index.tsx +132 -0
  219. package/src/react/ui/modals/_internal/components/switchChainModal/store.ts +41 -0
  220. package/src/react/ui/modals/_internal/components/switchChainModal/styles.css.ts +37 -0
  221. package/src/react/ui/modals/_internal/components/timeAgo/index.tsx +32 -0
  222. package/src/react/ui/modals/_internal/components/tokenPreview/index.tsx +58 -0
  223. package/src/react/ui/modals/_internal/components/tokenPreview/styles.css.ts +11 -0
  224. package/src/react/ui/modals/_internal/components/transaction-footer/index.tsx +48 -0
  225. package/src/react/ui/modals/_internal/components/transactionDetails/index.tsx +80 -0
  226. package/src/react/ui/modals/_internal/components/transactionHeader/index.tsx +30 -0
  227. package/src/react/ui/modals/_internal/components/transactionPreview/consts.ts +27 -0
  228. package/src/react/ui/modals/_internal/components/transactionPreview/index.tsx +111 -0
  229. package/src/react/ui/modals/_internal/components/transactionPreview/useTransactionPreviewTitle.tsx +24 -0
  230. package/src/react/ui/modals/_internal/components/transactionStatusModal/index.tsx +123 -0
  231. package/src/react/ui/modals/_internal/components/transactionStatusModal/store.ts +87 -0
  232. package/src/react/ui/modals/_internal/components/transactionStatusModal/styles.css.ts +15 -0
  233. package/src/react/ui/modals/_internal/stores/accountModal.ts +3 -0
  234. package/src/react/ui/modals/modal-provider.tsx +27 -0
  235. package/src/react/ui/styles/index.ts +1 -0
  236. package/src/react/ui/styles/modal.css.ts +73 -0
  237. package/src/styles/index.ts +18 -0
  238. package/src/types/api-types.ts +48 -0
  239. package/src/types/index.ts +4 -0
  240. package/src/types/marketplace-config.ts +63 -0
  241. package/src/types/messages.ts +43 -0
  242. package/src/types/sdk-config.ts +23 -0
  243. package/src/types/types.ts +6 -0
  244. package/src/utils/abi/abi/standard/EIP2981.ts +15 -0
  245. package/src/utils/abi/abi/standard/index.ts +1 -0
  246. package/src/utils/abi/abi/token/ERC1155.ts +324 -0
  247. package/src/utils/abi/abi/token/ERC20.ts +185 -0
  248. package/src/utils/abi/abi/token/ERC721.ts +506 -0
  249. package/src/utils/abi/abi/token/index.ts +3 -0
  250. package/src/utils/abi/clients/ERC1155.ts +82 -0
  251. package/src/utils/abi/clients/ERC20.ts +101 -0
  252. package/src/utils/abi/clients/ERC721.ts +97 -0
  253. package/src/utils/abi/clients/index.ts +3 -0
  254. package/src/utils/address.ts +26 -0
  255. package/src/utils/get-public-rpc-client.ts +32 -0
  256. package/src/utils/index.ts +6 -0
  257. package/src/utils/network.ts +5 -0
  258. package/src/utils/price.ts +21 -0
@@ -0,0 +1,59 @@
1
+ 'use client';
2
+
3
+ import { DayPicker, type PropsSingle } from 'react-day-picker';
4
+ import 'react-day-picker/style.css';
5
+
6
+ export type CalendarProps = React.PropsWithChildren<PropsSingle> & {
7
+ selectedDate?: Date;
8
+ setSelectedDate?: (date: Date) => void;
9
+ };
10
+
11
+ function Calendar({ ...props }: CalendarProps) {
12
+ const { selectedDate, setSelectedDate } = props;
13
+
14
+ return (
15
+ <DayPicker
16
+ disabled={{
17
+ before: new Date(),
18
+ }}
19
+ selected={selectedDate as unknown as Date}
20
+ onDayClick={setSelectedDate}
21
+ defaultMonth={selectedDate}
22
+ modifiersStyles={{
23
+ selected: {
24
+ color: 'hsl(var(--foreground))',
25
+ background: 'hsl(var(--primary))',
26
+ border: 'none',
27
+ },
28
+ }}
29
+ styles={{
30
+ root: {
31
+ width: 'max-content',
32
+ margin: 0,
33
+ color: 'hsl(var(--foreground))',
34
+ background: 'hsl(var(--background))',
35
+ border: `1px solid hsl(var(--border))`,
36
+ borderRadius: 'var(--radius)',
37
+ padding: '0.5rem',
38
+ position: 'relative',
39
+ },
40
+ day: {
41
+ margin: 0,
42
+ width: '1rem',
43
+ height: '1rem',
44
+ },
45
+ day_button: {
46
+ margin: 0,
47
+ width: '1.8rem',
48
+ height: '1.5rem',
49
+ padding: 0,
50
+ border: 'none',
51
+ },
52
+ }}
53
+ {...props}
54
+ />
55
+ );
56
+ }
57
+ Calendar.displayName = 'Calendar';
58
+
59
+ export default Calendar;
@@ -0,0 +1,41 @@
1
+ 'use client';
2
+
3
+ import { Button } from '@0xsequence/design-system';
4
+ import { Content, Portal, Root, Trigger } from '@radix-ui/react-popover';
5
+ import { format } from 'date-fns';
6
+ import SvgCalendarIcon from '../../../../icons/CalendarIcon';
7
+ import Calendar from '../calendar';
8
+ import { dateSelectButton, dateSelectPopoverContent } from './styles.css';
9
+
10
+ type CalendarPopoverProps = {
11
+ selectedDate: Date;
12
+ setSelectedDate: (date: Date) => void;
13
+ };
14
+
15
+ export default function CalendarPopover({
16
+ selectedDate,
17
+ setSelectedDate,
18
+ }: CalendarPopoverProps) {
19
+ return (
20
+ <Root>
21
+ <Trigger asChild>
22
+ <Button
23
+ leftIcon={SvgCalendarIcon}
24
+ className={dateSelectButton}
25
+ variant="ghost"
26
+ label={format(selectedDate, 'dd/MM/yyyy HH:mm')}
27
+ shape="square"
28
+ />
29
+ </Trigger>
30
+ <Portal>
31
+ <Content className={dateSelectPopoverContent} sideOffset={5}>
32
+ <Calendar
33
+ selectedDate={selectedDate}
34
+ setSelectedDate={setSelectedDate}
35
+ mode="single"
36
+ />
37
+ </Content>
38
+ </Portal>
39
+ </Root>
40
+ );
41
+ }
@@ -0,0 +1,16 @@
1
+ import { style } from '@vanilla-extract/css';
2
+
3
+ export const dateSelectButton = style({
4
+ flex: '3 !important',
5
+ padding: '10px 8px !important',
6
+ height: '36px !important',
7
+ border: '1px solid #4F4F4F !important',
8
+ borderRadius: '4px !important',
9
+ fontWeight: '400 !important',
10
+ fontSize: '12px !important',
11
+ });
12
+
13
+ export const dateSelectPopoverContent = style({
14
+ zIndex: 20,
15
+ pointerEvents: 'all',
16
+ });
@@ -0,0 +1,76 @@
1
+ import { Box, Select, Skeleton } from '@0xsequence/design-system';
2
+ import type { ChainId } from '@internal';
3
+ import type { Observable } from '@legendapp/state';
4
+ import { observer } from '@legendapp/state/react';
5
+ import { useCurrencies } from '@react-hooks/useCurrencies';
6
+ import type { Currency } from '@types';
7
+ import { useEffect, useState } from 'react';
8
+ import { currencySelect } from './styles.css';
9
+
10
+ // TODO: this should be exported from design system
11
+ type SelectOption = {
12
+ label: string;
13
+ value: string;
14
+ };
15
+
16
+ type CurrencyOptionsSelectProps = {
17
+ collectionAddress: string;
18
+ chainId: ChainId;
19
+ $selectedCurrency: Observable<Currency | null | undefined>;
20
+ };
21
+
22
+ const CurrencyOptionsSelect = observer(function CurrencyOptionsSelect({
23
+ chainId,
24
+ collectionAddress,
25
+ $selectedCurrency,
26
+ }: CurrencyOptionsSelectProps) {
27
+ const [value, setValue] = useState<string | null>(null);
28
+ const { data: currencies, isLoading: currenciesLoading } = useCurrencies({
29
+ collectionAddress,
30
+ chainId,
31
+ });
32
+
33
+ useEffect(() => {
34
+ if (
35
+ currencies &&
36
+ currencies.length > 0 &&
37
+ !$selectedCurrency.contractAddress.get()
38
+ ) {
39
+ $selectedCurrency.set(currencies[0]);
40
+ }
41
+ }, [currencies]);
42
+
43
+ if (!currencies || currenciesLoading) {
44
+ return <Skeleton borderRadius="lg" width="20" height="7" marginRight="3" />;
45
+ }
46
+
47
+ const options = currencies.map(
48
+ (currency) =>
49
+ ({
50
+ label: currency.name,
51
+ value: currency.contractAddress,
52
+ }) satisfies SelectOption,
53
+ );
54
+
55
+ const onChange = (value: string) => {
56
+ // biome-ignore lint/style/noNonNullAssertion: This can not be undefined
57
+ const c = currencies.find(
58
+ (currency) => currency.contractAddress === value,
59
+ )!;
60
+ setValue(value);
61
+ $selectedCurrency.set(c);
62
+ };
63
+
64
+ return (
65
+ <Box className={currencySelect}>
66
+ <Select
67
+ name="currencies"
68
+ value={value || options?.[0]?.value}
69
+ onValueChange={(value) => onChange(value)}
70
+ options={options}
71
+ />
72
+ </Box>
73
+ );
74
+ });
75
+
76
+ export default CurrencyOptionsSelect;
@@ -0,0 +1,33 @@
1
+ import { atoms } from '@0xsequence/design-system';
2
+ import { globalStyle, style } from '@vanilla-extract/css';
3
+
4
+ export const currencySelect = style([
5
+ atoms({
6
+ height: 'full',
7
+ }),
8
+ ]);
9
+
10
+ globalStyle(`${currencySelect} > label`, {
11
+ height: '100%',
12
+ });
13
+
14
+ globalStyle(`${currencySelect} > label > button`, {
15
+ background: '#FFFFFF1A',
16
+ borderRadius: 30,
17
+ padding: '12px',
18
+ marginRight: 8,
19
+ marginTop: 4,
20
+ marginBottom: 4,
21
+ height: 28,
22
+ border: 'none',
23
+ boxShadow: 'none',
24
+ });
25
+
26
+ globalStyle(`${currencySelect} > label > button > span`, {
27
+ fontSize: 10,
28
+ });
29
+
30
+ globalStyle(`${currencySelect} > label > button > span > svg`, {
31
+ width: 16,
32
+ height: 16,
33
+ });
@@ -0,0 +1,127 @@
1
+ import { useState } from 'react';
2
+
3
+ import { Box, Select, Text } from '@0xsequence/design-system';
4
+ import type { Observable } from '@legendapp/state';
5
+ import { observer } from '@legendapp/state/react';
6
+ import { addDays, isSameDay } from 'date-fns';
7
+ import CalendarPopover from '../calendarPopover';
8
+ import { rangeSelect } from './styles.css';
9
+
10
+ export const PRESET_RANGES = {
11
+ TODAY: {
12
+ label: 'Today',
13
+ value: 'today',
14
+ offset: 0,
15
+ },
16
+ TOMORROW: {
17
+ label: 'Tomorrow',
18
+ value: 'tomorrow',
19
+ offset: 1,
20
+ },
21
+ IN_3_DAYS: {
22
+ label: 'In 3 days',
23
+ value: '3_days',
24
+ offset: 3,
25
+ },
26
+ ONE_WEEK: {
27
+ label: '1 week',
28
+ value: '1_week',
29
+ offset: 7,
30
+ },
31
+ ONE_MONTH: {
32
+ label: '1 month',
33
+ value: '1_month',
34
+ offset: 30,
35
+ },
36
+ } as const;
37
+
38
+ export type rangeType =
39
+ (typeof PRESET_RANGES)[keyof typeof PRESET_RANGES]['value'];
40
+
41
+ type ExpirationDateSelectProps = {
42
+ className?: string;
43
+ $date: Observable<Date>;
44
+ };
45
+
46
+ const ExpirationDateSelect = observer(function ExpirationDateSelect({
47
+ className,
48
+ $date,
49
+ }: ExpirationDateSelectProps) {
50
+ const [_, setRange] = useState<rangeType>('1_week');
51
+ function handleSelectPresetRange(range: rangeType) {
52
+ setRange(range);
53
+
54
+ const presetRange = Object.values(PRESET_RANGES).find(
55
+ (preset) => preset.value === range,
56
+ );
57
+
58
+ if (!presetRange) {
59
+ return;
60
+ }
61
+
62
+ const newDate = addDays(new Date(), presetRange.offset);
63
+
64
+ $date.set(newDate);
65
+ }
66
+
67
+ function handleDateValueChange(date: Date) {
68
+ const presetRange = Object.values(PRESET_RANGES).find((preset) =>
69
+ isSameDay(new Date(date), addDays(new Date(), preset.offset)),
70
+ );
71
+
72
+ if (presetRange) {
73
+ setRange(presetRange.value);
74
+ }
75
+
76
+ $date.set(date);
77
+ }
78
+
79
+ return (
80
+ <Box width="full" position="relative">
81
+ <Text
82
+ fontSize={'small'}
83
+ fontWeight={'medium'}
84
+ textAlign={'left'}
85
+ width={'full'}
86
+ color={'text100'}
87
+ >
88
+ Set expiry
89
+ </Text>
90
+
91
+ <Box
92
+ className={className}
93
+ width={'full'}
94
+ display={'flex'}
95
+ alignItems={'center'}
96
+ gap={'2'}
97
+ marginTop={'0.5'}
98
+ >
99
+ <Box className={rangeSelect} position={'absolute'} right={'2'}>
100
+ <Select
101
+ name="expirationDate"
102
+ options={Object.values(PRESET_RANGES)}
103
+ defaultValue={undefined}
104
+ value={
105
+ Object.values(PRESET_RANGES).find((preset) =>
106
+ isSameDay(
107
+ new Date($date.get()),
108
+ addDays(new Date(), preset.offset),
109
+ ),
110
+ )?.value
111
+ }
112
+ onValueChange={(value) =>
113
+ handleSelectPresetRange(value as rangeType)
114
+ }
115
+ />
116
+ </Box>
117
+
118
+ <CalendarPopover
119
+ selectedDate={$date.get()}
120
+ setSelectedDate={(date) => handleDateValueChange(date)}
121
+ />
122
+ </Box>
123
+ </Box>
124
+ );
125
+ });
126
+
127
+ export default ExpirationDateSelect;
@@ -0,0 +1,25 @@
1
+ import { globalStyle, style } from '@vanilla-extract/css';
2
+
3
+ export const rangeSelect = style({
4
+ flex: 2,
5
+ });
6
+
7
+ globalStyle(`${rangeSelect} > label > button`, {
8
+ background: '#FFFFFF1A',
9
+ borderRadius: 30,
10
+ padding: '12px',
11
+ marginTop: 4,
12
+ marginBottom: 4,
13
+ height: 28,
14
+ border: 'none',
15
+ boxShadow: 'none',
16
+ });
17
+
18
+ globalStyle(`${rangeSelect} > label > button > span`, {
19
+ fontSize: 10,
20
+ });
21
+
22
+ globalStyle(`${rangeSelect} > label > button > span > svg`, {
23
+ width: 16,
24
+ height: 16,
25
+ });
@@ -0,0 +1,54 @@
1
+ import { Text } from '@0xsequence/design-system';
2
+ import type { Price } from '@types';
3
+ import { calculatePriceDifferencePercentage } from '../../../../../../utils';
4
+ import { useLowestListing } from '@react-hooks/useLowestListing';
5
+
6
+ export default function FloorPriceText({
7
+ chainId,
8
+ collectionAddress,
9
+ tokenId,
10
+ price,
11
+ }: {
12
+ chainId: string;
13
+ collectionAddress: string;
14
+ tokenId: string;
15
+ price: Price;
16
+ }) {
17
+ const { data: listing, isLoading: listingLoading } = useLowestListing({
18
+ tokenId: tokenId,
19
+ chainId,
20
+ collectionAddress,
21
+ filters: {
22
+ currencies: [price.currency.contractAddress],
23
+ },
24
+ });
25
+
26
+ const floorPriceRaw = listing?.order?.priceAmount;
27
+
28
+ if (!floorPriceRaw || listingLoading || price.amountRaw === '0') {
29
+ return null;
30
+ }
31
+
32
+ const floorPriceDifference = calculatePriceDifferencePercentage({
33
+ inputPriceRaw: BigInt(price.amountRaw),
34
+ basePriceRaw: BigInt(floorPriceRaw),
35
+ decimals: price.currency.decimals,
36
+ });
37
+
38
+ const floorPriceDifferenceText =
39
+ floorPriceRaw === price.amountRaw
40
+ ? 'Same as floor price'
41
+ : `${floorPriceDifference}% ${floorPriceRaw > price.amountRaw ? 'below' : 'above'} floor price`;
42
+
43
+ return (
44
+ <Text
45
+ fontSize={'small'}
46
+ fontWeight={'medium'}
47
+ textAlign={'left'}
48
+ width={'full'}
49
+ color={'text50'}
50
+ >
51
+ {floorPriceDifferenceText}
52
+ </Text>
53
+ );
54
+ }
@@ -0,0 +1,72 @@
1
+ import { Box, NumericInput, TokenImage } from '@0xsequence/design-system';
2
+ import type { Observable } from '@legendapp/state';
3
+ import { observer } from '@legendapp/state/react';
4
+ import type { Price } from '@types';
5
+ import { useState } from 'react';
6
+ import CurrencyOptionsSelect from '../currencyOptionsSelect';
7
+ import { priceInputWrapper } from './styles.css';
8
+ import { parseUnits } from 'viem';
9
+
10
+ type PriceInputProps = {
11
+ collectionAddress: string;
12
+ chainId: string;
13
+ $listingPrice: Observable<Price | undefined>;
14
+ error?: string;
15
+ };
16
+
17
+ const PriceInput = observer(function PriceInput({
18
+ chainId,
19
+ collectionAddress,
20
+ $listingPrice,
21
+ error,
22
+ }: PriceInputProps) {
23
+ const [inputPrice, setInputPrice] = useState('');
24
+ const changeListingPrice = (value: string) => {
25
+ setInputPrice(value);
26
+ const parsedAmount = parseUnits(
27
+ value,
28
+ Number($listingPrice.currency.decimals.get()),
29
+ );
30
+ $listingPrice.amountRaw.set(parsedAmount.toString());
31
+ };
32
+
33
+ return (
34
+ <Box className={priceInputWrapper} position="relative">
35
+ <Box
36
+ position="absolute"
37
+ bottom="3"
38
+ left="2"
39
+ display="flex"
40
+ alignItems="center"
41
+ >
42
+ <TokenImage src={$listingPrice.currency.imageUrl.get()} size="xs" />
43
+ </Box>
44
+
45
+ <NumericInput
46
+ name="listingPrice"
47
+ decimals={$listingPrice?.currency.decimals.get()}
48
+ label="Enter price"
49
+ labelLocation="top"
50
+ placeholder="0.00"
51
+ controls={
52
+ <CurrencyOptionsSelect
53
+ $selectedCurrency={$listingPrice?.currency}
54
+ collectionAddress={collectionAddress}
55
+ chainId={chainId}
56
+ />
57
+ }
58
+ numeric={true}
59
+ value={inputPrice}
60
+ onChange={(event) => changeListingPrice(event.target.value)}
61
+ width="full"
62
+ />
63
+ {error && (
64
+ <Box color="negative" fontSize="small">
65
+ {error}
66
+ </Box>
67
+ )}
68
+ </Box>
69
+ );
70
+ });
71
+
72
+ export default PriceInput;
@@ -0,0 +1,23 @@
1
+ import { globalStyle, style } from '@vanilla-extract/css';
2
+
3
+ export const priceInputWrapper = style({
4
+ display: 'flex',
5
+ flexDirection: 'column',
6
+ width: '100%',
7
+ });
8
+
9
+ globalStyle(`${priceInputWrapper} > label`, {
10
+ gap: 2,
11
+ });
12
+
13
+ globalStyle(`${priceInputWrapper} > label > div > div`, {
14
+ height: 36,
15
+ fontSize: 12,
16
+ borderRadius: 4,
17
+ paddingLeft: 28,
18
+ paddingRight: 0,
19
+ });
20
+
21
+ globalStyle(`${priceInputWrapper} > label > div > div > input`, {
22
+ fontSize: 12,
23
+ });
@@ -0,0 +1,4 @@
1
+ export type SelectedCurrency = {
2
+ symbol: string;
3
+ decimals: number;
4
+ };
@@ -0,0 +1,168 @@
1
+ import { Box, IconButton, NumericInput } from '@0xsequence/design-system';
2
+ import type { Observable } from '@legendapp/state';
3
+ import { useCollectible } from '@react-hooks/useCollectible';
4
+ import SvgMinusIcon from '../../../../icons/MinusIcon';
5
+ import SvgPlusIcon from '../../../../icons/PlusIcon';
6
+ import { quantityInputWrapper } from './styles.css';
7
+
8
+ type QuantityInputProps = {
9
+ $quantity: Observable<string>;
10
+ chainId: string;
11
+ collectionAddress: string;
12
+ collectibleId: string;
13
+ };
14
+
15
+ export default function QuantityInput({
16
+ $quantity,
17
+ chainId,
18
+ collectionAddress,
19
+ collectibleId,
20
+ }: QuantityInputProps) {
21
+ const { data: collectable, isLoading: collectableLoading } = useCollectible({
22
+ chainId,
23
+ collectionAddress,
24
+ collectibleId,
25
+ });
26
+
27
+ const quantityDecimals =
28
+ collectable && ((collectable.decimals || 0) as number | undefined);
29
+
30
+ function handleChangeQuantity(value: string) {
31
+ if (!isValidInput(value)) return;
32
+
33
+ const formattedValue = formatQuantity(value);
34
+ if (formattedValue !== null) {
35
+ $quantity.set(formattedValue);
36
+ }
37
+ }
38
+
39
+ function handleIncrement() {
40
+ if (!isValidInput()) return;
41
+
42
+ const newQuantity = incrementQuantity();
43
+ if (newQuantity !== null) {
44
+ $quantity.set(newQuantity);
45
+ }
46
+ }
47
+
48
+ function handleDecrement() {
49
+ if (!isValidInput()) return;
50
+
51
+ const newQuantity = decrementQuantity();
52
+ if (newQuantity !== null) {
53
+ $quantity.set(newQuantity);
54
+ }
55
+ }
56
+
57
+ function isValidInput(value?: string): boolean {
58
+ return (
59
+ collectable !== undefined &&
60
+ quantityDecimals !== undefined &&
61
+ (value === undefined || value !== '')
62
+ );
63
+ }
64
+
65
+ function formatQuantity(value: string): string | null {
66
+ if (quantityDecimals === 0 && value.includes('.')) {
67
+ return null;
68
+ }
69
+
70
+ if (quantityDecimals && quantityDecimals > 0) {
71
+ const decimalIndex = value.indexOf('.');
72
+ if (
73
+ decimalIndex !== -1 &&
74
+ value.length - decimalIndex > quantityDecimals + 1
75
+ ) {
76
+ return null;
77
+ }
78
+ }
79
+
80
+ return value;
81
+ }
82
+
83
+ const quantity = $quantity.get();
84
+
85
+ function incrementQuantity(): string | null {
86
+ if (!isValidInput()) return null;
87
+
88
+ if (!quantity) {
89
+ return quantityDecimals === 0
90
+ ? '1'
91
+ : `1.${'0'.repeat(quantityDecimals!)}`;
92
+ }
93
+
94
+ const newValue =
95
+ quantityDecimals === 0
96
+ ? (Number.parseInt(quantity) + 1).toString()
97
+ : (Number.parseFloat(quantity) + 1).toFixed(quantityDecimals);
98
+
99
+ return newValue;
100
+ }
101
+
102
+ function decrementQuantity(): string | null {
103
+ if (!quantity) {
104
+ return '1';
105
+ }
106
+
107
+ const newValue = Number.parseFloat(quantity) - 1;
108
+ if (newValue < 0) {
109
+ return null;
110
+ }
111
+
112
+ return quantityDecimals === 0
113
+ ? newValue.toString()
114
+ : newValue.toFixed(quantityDecimals);
115
+ }
116
+
117
+ function getPlaceholder(decimals: number) {
118
+ if (decimals === 0) {
119
+ return '0';
120
+ } else {
121
+ return '0.' + '0'.repeat(decimals);
122
+ }
123
+ }
124
+
125
+ if (collectableLoading) {
126
+ return null;
127
+ }
128
+
129
+ return (
130
+ <Box className={quantityInputWrapper}>
131
+ <NumericInput
132
+ name={'quantity'}
133
+ decimals={quantityDecimals || 0}
134
+ paddingLeft={'1'}
135
+ label={'Enter quantity'}
136
+ labelLocation="top"
137
+ placeholder={getPlaceholder(quantityDecimals || 0)}
138
+ controls={
139
+ <Box
140
+ display={'flex'}
141
+ alignItems={'center'}
142
+ gap={'1'}
143
+ marginRight={'2'}
144
+ >
145
+ <IconButton
146
+ disabled={Number.parseFloat(quantity) === 0 || !quantity}
147
+ onClick={handleDecrement}
148
+ background={'buttonGlass'}
149
+ size="xs"
150
+ icon={SvgMinusIcon}
151
+ />
152
+
153
+ <IconButton
154
+ onClick={handleIncrement}
155
+ background={'buttonGlass'}
156
+ size="xs"
157
+ icon={SvgPlusIcon}
158
+ />
159
+ </Box>
160
+ }
161
+ numeric={true}
162
+ value={$quantity.get()}
163
+ onChange={(e) => handleChangeQuantity(e.target.value)}
164
+ width={'full'}
165
+ />
166
+ </Box>
167
+ );
168
+ }