@0xsequence/marketplace-sdk 0.4.0 → 0.4.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 (133) hide show
  1. package/dist/{chunk-P3EQRM7K.js → chunk-5GDO4ZBC.js} +5 -4
  2. package/dist/{chunk-P3EQRM7K.js.map → chunk-5GDO4ZBC.js.map} +1 -1
  3. package/dist/{chunk-QTQH5I2E.js → chunk-EVRILXOH.js} +2 -2
  4. package/dist/chunk-EVRILXOH.js.map +1 -0
  5. package/dist/{chunk-GVDLVCR5.js → chunk-GSDUAHL3.js} +1 -1
  6. package/dist/chunk-GSDUAHL3.js.map +1 -0
  7. package/dist/{chunk-6HEMV2OR.js → chunk-IOTKCWOB.js} +890 -644
  8. package/dist/chunk-IOTKCWOB.js.map +1 -0
  9. package/dist/{chunk-AY2MZHZN.js → chunk-KNX2LER4.js} +5 -6
  10. package/dist/{chunk-PAHT6PTD.js.map → chunk-KNX2LER4.js.map} +1 -1
  11. package/dist/{chunk-SBVLWSRZ.js → chunk-LF44FCG5.js} +2 -2
  12. package/dist/{chunk-SBVLWSRZ.js.map → chunk-LF44FCG5.js.map} +1 -1
  13. package/dist/{chunk-PAHT6PTD.js → chunk-LSMQVX77.js} +5 -6
  14. package/dist/{chunk-AY2MZHZN.js.map → chunk-LSMQVX77.js.map} +1 -1
  15. package/dist/{chunk-6AYHE7ZA.js → chunk-MIYMMP2K.js} +79 -33
  16. package/dist/chunk-MIYMMP2K.js.map +1 -0
  17. package/dist/{chunk-EK5ZSW4M.js → chunk-QMO2CUNM.js} +2 -2
  18. package/dist/{chunk-L6GSYPCR.js → chunk-RZSZNVEH.js} +5 -5
  19. package/dist/{chunk-L6GSYPCR.js.map → chunk-RZSZNVEH.js.map} +1 -1
  20. package/dist/chunk-T5T6JNB2.js +171 -0
  21. package/dist/chunk-T5T6JNB2.js.map +1 -0
  22. package/dist/chunk-UPLTM63S.js +435 -0
  23. package/dist/chunk-UPLTM63S.js.map +1 -0
  24. package/dist/{chunk-Y7YO5TLE.js → chunk-XXML5K3X.js} +5 -2
  25. package/dist/chunk-XXML5K3X.js.map +1 -0
  26. package/dist/{create-config-CgtmCzvb.d.ts → create-config-8sffBvlt.d.ts} +1 -1
  27. package/dist/index.js +4 -4
  28. package/dist/react/_internal/api/index.js +2 -2
  29. package/dist/react/_internal/index.d.ts +1 -1
  30. package/dist/react/_internal/index.js +3 -3
  31. package/dist/react/_internal/wagmi/index.d.ts +1 -1
  32. package/dist/react/_internal/wagmi/index.js +2 -2
  33. package/dist/react/hooks/index.d.ts +663 -74
  34. package/dist/react/hooks/index.js +7 -7
  35. package/dist/react/index.css +17 -0
  36. package/dist/react/index.css.map +1 -1
  37. package/dist/react/index.d.ts +1 -1
  38. package/dist/react/index.js +11 -11
  39. package/dist/react/ssr/index.js +1 -1
  40. package/dist/react/ssr/index.js.map +1 -1
  41. package/dist/react/ui/components/index.css +17 -0
  42. package/dist/react/ui/components/index.css.map +1 -1
  43. package/dist/react/ui/components/index.js +11 -11
  44. package/dist/react/ui/icons/index.js +4 -4
  45. package/dist/react/ui/icons/index.js.map +1 -1
  46. package/dist/react/ui/index.css +17 -0
  47. package/dist/react/ui/index.css.map +1 -1
  48. package/dist/react/ui/index.js +11 -11
  49. package/dist/react/ui/modals/_internal/components/actionModal/index.css +22 -0
  50. package/dist/react/ui/modals/_internal/components/actionModal/index.css.map +1 -1
  51. package/dist/react/ui/modals/_internal/components/actionModal/index.d.ts +17 -9
  52. package/dist/react/ui/modals/_internal/components/actionModal/index.js +8 -4
  53. package/dist/react/ui/styles/index.d.ts +1 -1
  54. package/dist/styles/index.d.ts +1 -1
  55. package/dist/styles/index.js +2 -2
  56. package/dist/types/index.js +3 -3
  57. package/dist/utils/index.js +2 -2
  58. package/package.json +25 -25
  59. package/src/react/_internal/api/marketplace-api.ts +3 -2
  60. package/src/react/_internal/transaction-machine/execute-transaction.ts +28 -12
  61. package/src/react/_internal/transaction-machine/useTransactionMachine.ts +43 -8
  62. package/src/react/hooks/useBuyCollectable.tsx +13 -6
  63. package/src/react/hooks/useCancelOrder.tsx +14 -7
  64. package/src/react/hooks/useCreateListing.tsx +74 -10
  65. package/src/react/hooks/useCurrencies.tsx +1 -1
  66. package/src/react/hooks/useCurrencyBalance.tsx +1 -1
  67. package/src/react/hooks/useCurrencyOptions.tsx +1 -1
  68. package/src/react/hooks/useMakeOffer.tsx +73 -11
  69. package/src/react/hooks/useSell.tsx +72 -11
  70. package/src/react/ui/components/_internals/action-button/ActionButton.tsx +1 -7
  71. package/src/react/ui/components/_internals/action-button/types.ts +7 -0
  72. package/src/react/ui/components/_internals/custom-select/CustomSelect.tsx +18 -15
  73. package/src/react/ui/components/collectible-card/CollectibleCard.tsx +5 -7
  74. package/src/react/ui/components/collectible-card/Footer.tsx +5 -7
  75. package/src/react/ui/components/collectible-card/styles.css.ts +1 -1
  76. package/src/react/ui/icons/ArrowUp.tsx +3 -0
  77. package/src/react/ui/icons/Bell.tsx +3 -0
  78. package/src/react/ui/icons/CalendarIcon.tsx +3 -0
  79. package/src/react/ui/icons/DiamondEye.tsx +3 -0
  80. package/src/react/ui/icons/InfoIcon.tsx +3 -0
  81. package/src/react/ui/icons/InventoryIcon.tsx +3 -0
  82. package/src/react/ui/icons/MinusIcon.tsx +3 -0
  83. package/src/react/ui/icons/PlusIcon.tsx +3 -0
  84. package/src/react/ui/icons/PositiveCircleIcon.tsx +3 -0
  85. package/src/react/ui/modals/BuyModal/index.tsx +25 -8
  86. package/src/react/ui/modals/CreateListingModal/_store.ts +5 -2
  87. package/src/react/ui/modals/CreateListingModal/index.tsx +62 -23
  88. package/src/react/ui/modals/MakeOfferModal/_store.ts +5 -2
  89. package/src/react/ui/modals/MakeOfferModal/index.tsx +83 -65
  90. package/src/react/ui/modals/SellModal/index.tsx +107 -57
  91. package/src/react/ui/modals/TransferModal/_store.ts +1 -1
  92. package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/index.tsx +4 -2
  93. package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/useHandleTransfer.tsx +5 -5
  94. package/src/react/ui/modals/TransferModal/index.tsx +1 -1
  95. package/src/react/ui/modals/_internal/components/actionModal/ActionModal.tsx +29 -8
  96. package/src/react/ui/modals/_internal/components/actionModal/ErrorModal.tsx +15 -5
  97. package/src/react/ui/modals/_internal/components/actionModal/LoadingModal.tsx +15 -5
  98. package/src/react/ui/modals/_internal/components/actionModal/store.ts +6 -0
  99. package/src/react/ui/modals/_internal/components/calendar/index.tsx +1 -1
  100. package/src/react/ui/modals/_internal/components/currencyImage/index.tsx +3 -3
  101. package/src/react/ui/modals/_internal/components/currencyOptionsSelect/index.tsx +11 -10
  102. package/src/react/ui/modals/_internal/components/expirationDateSelect/index.tsx +14 -19
  103. package/src/react/ui/modals/_internal/components/priceInput/index.tsx +34 -12
  104. package/src/react/ui/modals/_internal/components/quantityInput/index.tsx +3 -3
  105. package/src/react/ui/modals/_internal/components/switchChainModal/index.tsx +7 -4
  106. package/src/react/ui/modals/_internal/components/tokenPreview/index.tsx +1 -0
  107. package/src/react/ui/modals/_internal/components/transaction-footer/index.tsx +3 -3
  108. package/src/react/ui/modals/_internal/components/transactionDetails/index.tsx +9 -5
  109. package/src/react/ui/modals/_internal/components/transactionPreview/index.tsx +4 -4
  110. package/src/react/ui/modals/_internal/components/transactionPreview/useTransactionPreviewTitle.tsx +1 -1
  111. package/src/react/ui/modals/_internal/components/transactionStatusModal/index.tsx +51 -29
  112. package/src/react/ui/modals/_internal/components/transactionStatusModal/store.ts +2 -2
  113. package/src/react/ui/modals/_internal/components/transactionStatusModal/util/getFormattedType.ts +1 -1
  114. package/src/react/ui/modals/_internal/components/transactionStatusModal/util/getMessage.ts +2 -2
  115. package/src/react/ui/modals/_internal/components/transactionStatusModal/util/getTitle.ts +6 -3
  116. package/src/react/ui/modals/_internal/components/waasFeeOptionsBox/index.tsx +146 -0
  117. package/src/react/ui/modals/_internal/components/waasFeeOptionsBox/store.ts +12 -0
  118. package/src/react/ui/modals/_internal/components/waasFeeOptionsBox/styles.css.ts +53 -0
  119. package/src/react/ui/modals/_internal/components/waasFeeOptionsSelect/WaasFeeOptionsSelect.tsx +117 -0
  120. package/src/utils/_internal/error/transaction.ts +2 -2
  121. package/src/utils/price.ts +3 -4
  122. package/tsconfig.json +1 -21
  123. package/tsconfig.tsbuildinfo +1 -1
  124. package/dist/chunk-6AYHE7ZA.js.map +0 -1
  125. package/dist/chunk-6HEMV2OR.js.map +0 -1
  126. package/dist/chunk-FFCNYF3S.js +0 -153
  127. package/dist/chunk-FFCNYF3S.js.map +0 -1
  128. package/dist/chunk-GVDLVCR5.js.map +0 -1
  129. package/dist/chunk-NMCGA2TB.js +0 -98
  130. package/dist/chunk-NMCGA2TB.js.map +0 -1
  131. package/dist/chunk-QTQH5I2E.js.map +0 -1
  132. package/dist/chunk-Y7YO5TLE.js.map +0 -1
  133. /package/dist/{chunk-EK5ZSW4M.js.map → chunk-QMO2CUNM.js.map} +0 -0
@@ -1,16 +1,26 @@
1
1
  import { Box, Spinner } from '@0xsequence/design-system';
2
- import type { Observable } from '@legendapp/state';
3
2
  import { ActionModal } from './ActionModal';
4
- import type { ActionModalState } from './store';
5
3
 
6
4
  interface LoadingModalProps {
7
- store: Observable<ActionModalState>;
5
+ isOpen: boolean;
6
+ chainId: number;
8
7
  onClose: () => void;
9
8
  title: string;
10
9
  }
11
10
 
12
- export const LoadingModal = ({ store, onClose, title }: LoadingModalProps) => (
13
- <ActionModal store={store} onClose={onClose} title={title} ctas={[]}>
11
+ export const LoadingModal = ({
12
+ isOpen,
13
+ chainId,
14
+ onClose,
15
+ title,
16
+ }: LoadingModalProps) => (
17
+ <ActionModal
18
+ isOpen={isOpen}
19
+ chainId={chainId}
20
+ onClose={onClose}
21
+ title={title}
22
+ ctas={[]}
23
+ >
14
24
  <Box display="flex" justifyContent="center" alignItems="center" padding="4">
15
25
  <Spinner size="lg" />
16
26
  </Box>
@@ -1,12 +1,18 @@
1
1
  import { type Observable, observable } from '@legendapp/state';
2
+ import type { ChainId } from '../../../../../_internal';
3
+ import type { Address } from 'viem';
2
4
 
3
5
  export interface ActionModalState {
4
6
  isOpen: boolean;
7
+ chainId: ChainId | null;
8
+ collectionAddress: Address | null;
5
9
  }
6
10
 
7
11
  export function createActionModalStore() {
8
12
  return observable<ActionModalState>({
9
13
  isOpen: false,
14
+ chainId: null,
15
+ collectionAddress: null,
10
16
  });
11
17
  }
12
18
 
@@ -32,7 +32,7 @@ function Calendar({ ...props }: CalendarProps) {
32
32
  margin: 0,
33
33
  color: 'hsl(var(--foreground))',
34
34
  background: 'hsl(var(--background))',
35
- border: `1px solid hsl(var(--border))`,
35
+ border: '1px solid hsl(var(--border))',
36
36
  borderRadius: 'var(--radius)',
37
37
  padding: '0.5rem',
38
38
  position: 'relative',
@@ -1,8 +1,8 @@
1
1
  import { Box, TokenImage } from '@0xsequence/design-system';
2
+ import type { Observable } from '@legendapp/state';
2
3
  import { useState } from 'react';
3
- import { Address } from 'viem';
4
- import { Price } from '../../../../../../types';
5
- import { Observable } from '@legendapp/state';
4
+ import type { Address } from 'viem';
5
+ import type { Price } from '../../../../../../types';
6
6
 
7
7
  function CurrencyImage({
8
8
  $listingPrice,
@@ -5,14 +5,11 @@ import { useEffect } from 'react';
5
5
  import type { Hex } from 'viem';
6
6
  import type { ChainId, Currency } from '../../../../../_internal';
7
7
  import { useCurrencies } from '../../../../../hooks';
8
- import { CustomSelect } from '../../../../components/_internals/custom-select/CustomSelect';
9
8
  import { useCurrencyOptions } from '../../../../../hooks/useCurrencyOptions';
10
-
11
- // TODO: this should be exported from design system
12
- type SelectOption = {
13
- label: string;
14
- value: string;
15
- };
9
+ import {
10
+ CustomSelect,
11
+ type SelectItem,
12
+ } from '../../../../components/_internals/custom-select/CustomSelect';
16
13
 
17
14
  type CurrencyOptionsSelectProps = {
18
15
  collectionAddress: Hex;
@@ -33,6 +30,7 @@ const CurrencyOptionsSelect = observer(function CurrencyOptionsSelect({
33
30
  });
34
31
 
35
32
  // set default currency
33
+ // biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
36
34
  useEffect(() => {
37
35
  if (
38
36
  currencies &&
@@ -52,7 +50,8 @@ const CurrencyOptionsSelect = observer(function CurrencyOptionsSelect({
52
50
  ({
53
51
  label: currency.symbol,
54
52
  value: currency.contractAddress,
55
- }) satisfies SelectOption,
53
+ content: currency.symbol,
54
+ }) as SelectItem,
56
55
  );
57
56
 
58
57
  const onChange = (value: string) => {
@@ -65,9 +64,11 @@ const CurrencyOptionsSelect = observer(function CurrencyOptionsSelect({
65
64
  return (
66
65
  <CustomSelect
67
66
  items={options}
68
- value={currency.symbol}
69
67
  onValueChange={onChange}
70
- defaultValue={currency.contractAddress}
68
+ defaultValue={{
69
+ value: currency.contractAddress,
70
+ content: currency.symbol,
71
+ }}
71
72
  />
72
73
  );
73
74
  });
@@ -1,11 +1,10 @@
1
- import { useState } from 'react';
2
-
3
1
  import { Box, Skeleton, Text } from '@0xsequence/design-system';
4
2
  import type { Observable } from '@legendapp/state';
5
3
  import { observer } from '@legendapp/state/react';
6
- import { addDays, isSameDay } from 'date-fns';
4
+ import { addDays } from 'date-fns';
7
5
  import { CustomSelect } from '../../../../components/_internals/custom-select/CustomSelect';
8
6
  import CalendarPopover from '../calendarPopover';
7
+ import { useState } from 'react';
9
8
 
10
9
  export const PRESET_RANGES = {
11
10
  TODAY: {
@@ -35,7 +34,7 @@ export const PRESET_RANGES = {
35
34
  },
36
35
  } as const;
37
36
 
38
- export type rangeType =
37
+ export type RangeType =
39
38
  (typeof PRESET_RANGES)[keyof typeof PRESET_RANGES]['value'];
40
39
 
41
40
  type ExpirationDateSelectProps = {
@@ -47,15 +46,16 @@ const ExpirationDateSelect = observer(function ExpirationDateSelect({
47
46
  className,
48
47
  $date,
49
48
  }: ExpirationDateSelectProps) {
50
- const defaultRange = '1_week';
51
- const [range, setRange] = useState<rangeType>(defaultRange);
52
- function handleSelectPresetRange(range: rangeType) {
53
- setRange(range);
49
+ const defaultRange = '1_week' as RangeType;
50
+ const [selectedRange, setSelectedRange] = useState<RangeType>(defaultRange);
54
51
 
52
+ function handleSelectPresetRange(range: RangeType) {
55
53
  const presetRange = Object.values(PRESET_RANGES).find(
56
54
  (preset) => preset.value === range,
57
55
  );
58
56
 
57
+ setSelectedRange(range);
58
+
59
59
  if (!presetRange) {
60
60
  return;
61
61
  }
@@ -66,14 +66,6 @@ const ExpirationDateSelect = observer(function ExpirationDateSelect({
66
66
  }
67
67
 
68
68
  function handleDateValueChange(date: Date) {
69
- const presetRange = Object.values(PRESET_RANGES).find((preset) =>
70
- isSameDay(new Date(date), addDays(new Date(), preset.offset)),
71
- );
72
-
73
- if (presetRange) {
74
- setRange(presetRange.value);
75
- }
76
-
77
69
  $date.set(date);
78
70
  }
79
71
 
@@ -112,12 +104,15 @@ const ExpirationDateSelect = observer(function ExpirationDateSelect({
112
104
  items={Object.values(PRESET_RANGES).map((preset) => ({
113
105
  label: preset.label,
114
106
  value: preset.value,
107
+ content: preset.label,
115
108
  }))}
116
- value={range}
117
109
  onValueChange={(value) =>
118
- handleSelectPresetRange(value as rangeType)
110
+ handleSelectPresetRange(value as RangeType)
119
111
  }
120
- defaultValue={defaultRange}
112
+ defaultValue={{
113
+ value: selectedRange,
114
+ content: selectedRange,
115
+ }}
121
116
  />
122
117
  </Box>
123
118
 
@@ -1,19 +1,20 @@
1
- import { Box, NumericInput } from '@0xsequence/design-system';
1
+ import { Box, NumericInput, Text } from '@0xsequence/design-system';
2
2
  import type { Observable } from '@legendapp/state';
3
3
  import { observer } from '@legendapp/state/react';
4
- import { useState } from 'react';
4
+ import { useEffect, useState } from 'react';
5
5
  import { type Hex, parseUnits } from 'viem';
6
6
  import { useAccount } from 'wagmi';
7
7
  import type { Price } from '../../../../../../types';
8
- import CurrencyOptionsSelect from '../currencyOptionsSelect';
9
- import { priceInputCurrencyImage, priceInputWrapper } from './styles.css';
10
8
  import { useCurrencyBalance } from '../../../../../hooks/useCurrencyBalance';
11
9
  import CurrencyImage from '../currencyImage';
10
+ import CurrencyOptionsSelect from '../currencyOptionsSelect';
11
+ import { priceInputCurrencyImage, priceInputWrapper } from './styles.css';
12
12
 
13
13
  type PriceInputProps = {
14
14
  collectionAddress: Hex;
15
15
  chainId: string;
16
16
  $listingPrice: Observable<Price | undefined>;
17
+ onPriceChange?: () => void;
17
18
  checkBalance?: {
18
19
  enabled: boolean;
19
20
  callback: (state: boolean) => void;
@@ -24,6 +25,7 @@ const PriceInput = observer(function PriceInput({
24
25
  chainId,
25
26
  collectionAddress,
26
27
  $listingPrice,
28
+ onPriceChange,
27
29
  checkBalance,
28
30
  }: PriceInputProps) {
29
31
  const [balanceError, setBalanceError] = useState('');
@@ -38,6 +40,17 @@ const PriceInput = observer(function PriceInput({
38
40
 
39
41
  const [value, setValue] = useState('');
40
42
 
43
+ const changeListingPrice = (value: string) => {
44
+ setValue(value);
45
+ try {
46
+ const parsedAmount = parseUnits(value, Number(currencyDecimals));
47
+ $listingPrice.amountRaw.set(parsedAmount.toString());
48
+ onPriceChange?.();
49
+ } catch {
50
+ $listingPrice.amountRaw.set('0');
51
+ }
52
+ };
53
+
41
54
  const checkInsufficientBalance = (priceAmountRaw: string) => {
42
55
  const hasInsufficientBalance =
43
56
  isBalanceSuccess &&
@@ -56,12 +69,13 @@ const PriceInput = observer(function PriceInput({
56
69
  }
57
70
  };
58
71
 
59
- const changeListingPrice = (value: string) => {
60
- setValue(value);
61
- const parsedAmount = parseUnits(value, Number(currencyDecimals));
62
- $listingPrice.amountRaw.set(parsedAmount.toString());
63
- checkBalance && checkInsufficientBalance(parsedAmount.toString());
64
- };
72
+ // biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
73
+ useEffect(() => {
74
+ const priceAmountRaw = $listingPrice.amountRaw.get();
75
+ if (priceAmountRaw && priceAmountRaw !== '0') {
76
+ checkInsufficientBalance(priceAmountRaw);
77
+ }
78
+ }, [$listingPrice.currency.get()]);
65
79
 
66
80
  return (
67
81
  <Box className={priceInputWrapper} position="relative">
@@ -91,10 +105,18 @@ const PriceInput = observer(function PriceInput({
91
105
  onChange={(event) => changeListingPrice(event.target.value)}
92
106
  width="full"
93
107
  />
108
+
94
109
  {balanceError && (
95
- <Box color="negative" fontSize="small">
110
+ <Text
111
+ color="negative"
112
+ fontSize="xsmall"
113
+ fontFamily="body"
114
+ fontWeight="semibold"
115
+ position="absolute"
116
+ style={{ bottom: '-13px' }}
117
+ >
96
118
  {balanceError}
97
- </Box>
119
+ </Text>
98
120
  )}
99
121
  </Box>
100
122
  );
@@ -23,7 +23,7 @@ export default function QuantityInput({
23
23
 
24
24
  let formattedValue = sanitizedValue;
25
25
  if (decimalParts.length > 2) {
26
- formattedValue = decimalParts[0] + '.' + decimalParts[1];
26
+ formattedValue = `${decimalParts[0]}.${decimalParts[1]}`;
27
27
  }
28
28
 
29
29
  const finalValue = formatQuantity(formattedValue);
@@ -32,7 +32,7 @@ export default function QuantityInput({
32
32
  }
33
33
 
34
34
  function validateQuantity(value: string) {
35
- if (!value || value.trim() === '' || isNaN(Number(value))) {
35
+ if (!value || value.trim() === '' || Number.isNaN(Number(value))) {
36
36
  $invalidQuantity.set(true);
37
37
  return;
38
38
  }
@@ -49,7 +49,7 @@ export default function QuantityInput({
49
49
  }
50
50
 
51
51
  function formatQuantity(value: string) {
52
- if (!value || isNaN(Number(value))) {
52
+ if (!value || Number.isNaN(Number(value))) {
53
53
  return '0';
54
54
  }
55
55
 
@@ -30,7 +30,7 @@ export type ShowSwitchChainModalArgs = {
30
30
  export const useSwitchChainModal = () => {
31
31
  return {
32
32
  show: (args: ShowSwitchChainModalArgs) => switchChainModal$.open(args),
33
- close: () => switchChainModal$.close(),
33
+ close: () => switchChainModal$.delete(),
34
34
  isSwitching$: switchChainModal$.state.isSwitching,
35
35
  };
36
36
  };
@@ -38,18 +38,21 @@ export const useSwitchChainModal = () => {
38
38
  const SwitchChainModal = observer(() => {
39
39
  const chainIdToSwitchTo = switchChainModal$.state.chainIdToSwitchTo.get();
40
40
  const isSwitching$ = switchChainModal$.state.isSwitching;
41
- const chainName = getPresentableChainName(chainIdToSwitchTo!);
41
+ const chainName = chainIdToSwitchTo
42
+ ? getPresentableChainName(chainIdToSwitchTo)
43
+ : '';
42
44
  const { switchChainAsync } = useSwitchChain();
43
45
 
44
46
  async function handleSwitchChain() {
45
47
  isSwitching$.set(true);
46
48
 
47
49
  try {
48
- await switchChainAsync({ chainId: Number(chainIdToSwitchTo!) });
50
+ if (!chainIdToSwitchTo) return;
51
+ await switchChainAsync({ chainId: Number(chainIdToSwitchTo) });
49
52
 
50
53
  switchChainModal$.state.onSuccess?.();
51
54
 
52
- switchChainModal$.close();
55
+ switchChainModal$.delete();
53
56
  } catch (error) {
54
57
  switchChainModal$.state.onError?.(error as SwitchChainErrorType);
55
58
  } finally {
@@ -44,6 +44,7 @@ export default function TokenPreview({
44
44
  width={'9'}
45
45
  height={'9'}
46
46
  borderRadius={'xs'}
47
+ style={{ objectFit: 'cover' }}
47
48
  />
48
49
 
49
50
  <Box display={'flex'} flexDirection={'column'} marginLeft={'3'}>
@@ -1,8 +1,8 @@
1
- import { ChainId, networks } from '@0xsequence/network';
1
+ import { type ChainId, networks } from '@0xsequence/network';
2
+ import type { Hex } from 'viem';
3
+ import { Box, Text, Spinner } from '@0xsequence/design-system';
2
4
  import { truncateMiddle } from '../../../../../../utils';
3
5
  import SvgPositiveCircleIcon from '../../../../icons/PositiveCircleIcon';
4
- import { Box, Spinner, Text } from '@0xsequence/design-system';
5
- import type { Hex } from 'viem';
6
6
 
7
7
  type TransactionFooterProps = {
8
8
  transactionHash: Hex | undefined;
@@ -12,6 +12,8 @@ type TransactionDetailsProps = {
12
12
  chainId: string;
13
13
  price?: Price;
14
14
  currencyImageUrl?: string;
15
+ // We use a placeholder price for create listing modal
16
+ showPlaceholderPrice?: boolean;
15
17
  };
16
18
 
17
19
  //TODO: Move this
@@ -22,6 +24,7 @@ export default function TransactionDetails({
22
24
  collectionAddress,
23
25
  chainId,
24
26
  price,
27
+ showPlaceholderPrice,
25
28
  currencyImageUrl,
26
29
  }: TransactionDetailsProps) {
27
30
  const { data, isLoading: marketplaceConfigLoading } = useMarketplaceConfig();
@@ -43,18 +46,18 @@ export default function TransactionDetails({
43
46
  let formattedAmount =
44
47
  price && formatUnits(BigInt(price.amountRaw), price.currency.decimals);
45
48
 
46
- if (royaltyPercentage !== undefined && formattedAmount) {
49
+ if (royaltyPercentage !== undefined && formattedAmount && price) {
47
50
  formattedAmount = (
48
51
  Number.parseFloat(formattedAmount) -
49
52
  (Number.parseFloat(formattedAmount) * Number(royaltyPercentage)) / 100
50
- ).toString();
53
+ ).toFixed(price.currency.decimals);
51
54
  }
52
55
 
53
- if (marketplaceFeePercentage !== undefined && formattedAmount) {
56
+ if (marketplaceFeePercentage !== undefined && formattedAmount && price) {
54
57
  formattedAmount = (
55
58
  Number.parseFloat(formattedAmount) -
56
59
  (Number.parseFloat(formattedAmount) * marketplaceFeePercentage) / 100
57
- ).toString();
60
+ ).toFixed(price.currency.decimals);
58
61
  }
59
62
 
60
63
  return (
@@ -75,7 +78,8 @@ export default function TransactionDetails({
75
78
  <Skeleton width="16" height={'4'} />
76
79
  ) : (
77
80
  <Text fontSize={'small'} color={'text100'} fontFamily="body">
78
- {formattedAmount} {price.currency.symbol}
81
+ {showPlaceholderPrice ? '0' : formattedAmount}{' '}
82
+ {price.currency.symbol}
79
83
  </Text>
80
84
  )}
81
85
  </Box>
@@ -5,15 +5,15 @@ import {
5
5
  Skeleton,
6
6
  Text,
7
7
  } from '@0xsequence/design-system';
8
+ import type { TokenMetadata } from '@0xsequence/metadata';
8
9
  import { observer } from '@legendapp/state/react';
9
10
  import { type Hex, formatUnits } from 'viem';
10
11
  import type { Price } from '../../../../../../types';
11
12
  import { useCollection } from '../../../../../hooks';
13
+ import ChessTileImage from '../../../../images/chess-tile.png';
12
14
  import TimeAgo from '../timeAgo';
13
15
  import { transactionStatusModal$ } from '../transactionStatusModal/store';
14
16
  import { useTransactionPreviewTitle } from './useTransactionPreviewTitle';
15
- import type { TokenMetadata } from '@0xsequence/metadata';
16
- import ChessTileImage from '../../../../images/chess-tile.png';
17
17
 
18
18
  type TransactionPreviewProps = {
19
19
  orderId?: string;
@@ -58,7 +58,7 @@ const TransactionPreview = observer(
58
58
  const collectibleName = collectible?.name;
59
59
  const collectionName = collection?.name;
60
60
  const priceFormatted = price
61
- ? formatUnits(BigInt(price!.amountRaw), price!.currency.decimals)
61
+ ? formatUnits(BigInt(price?.amountRaw), price?.currency.decimals)
62
62
  : undefined;
63
63
 
64
64
  if (collectibleLoading || collectionLoading) {
@@ -134,7 +134,7 @@ const TransactionPreview = observer(
134
134
  fontWeight="medium"
135
135
  fontFamily="body"
136
136
  >
137
- {priceFormatted} {price!.currency.symbol}
137
+ {priceFormatted} {price?.currency.symbol}
138
138
  </Text>
139
139
  </Box>
140
140
  )}
@@ -1,6 +1,6 @@
1
+ import type { TransactionType } from '../../../../../_internal/transaction-machine/execute-transaction';
1
2
  import type { ConfirmationStatus } from '../transactionStatusModal/store';
2
3
  import { TRANSACTION_TITLES } from './consts';
3
- import { TransactionType } from '../../../../../_internal/transaction-machine/execute-transaction';
4
4
 
5
5
  export function useTransactionPreviewTitle(
6
6
  orderId: string | undefined,
@@ -4,29 +4,29 @@ import {
4
4
  Skeleton,
5
5
  Text,
6
6
  } from '@0xsequence/design-system';
7
+ import { TRANSACTION_CONFIRMATIONS_DEFAULT } from '@0xsequence/kit';
8
+ import type { ChainId } from '@0xsequence/network';
7
9
  import { observer } from '@legendapp/state/react';
8
10
  import { Close, Content, Overlay, Portal, Root } from '@radix-ui/react-dialog';
9
- import { type QueryKey } from '@tanstack/react-query';
11
+ import type { QueryKey } from '@tanstack/react-query';
10
12
  import { useEffect, useState } from 'react';
11
- import { WaitForTransactionReceiptTimeoutError, type Hex } from 'viem';
13
+ import { type Hex, WaitForTransactionReceiptTimeoutError } from 'viem';
12
14
  import type { Price } from '../../../../../../types';
15
+ import { getPublicRpcClient } from '../../../../../../utils';
13
16
  import { getQueryClient } from '../../../../../_internal';
17
+ import type { TransactionType } from '../../../../../_internal/transaction-machine/execute-transaction';
14
18
  import { useCollectible } from '../../../../../hooks';
19
+ import type { ModalCallbacks } from '../../types';
15
20
  import TransactionFooter from '../transaction-footer';
16
21
  import TransactionPreview from '../transactionPreview';
17
- import { TransactionStatus, transactionStatusModal$ } from './store';
22
+ import { type TransactionStatus, transactionStatusModal$ } from './store';
18
23
  import {
19
24
  closeButton,
20
25
  dialogOverlay,
21
26
  transactionStatusModalContent,
22
27
  } from './styles.css';
23
- import { ChainId } from '@0xsequence/network';
24
- import { getPublicRpcClient } from '../../../../../../utils';
25
- import { TRANSACTION_CONFIRMATIONS_DEFAULT } from '@0xsequence/kit';
26
- import { TransactionType } from '../../../../../_internal/transaction-machine/execute-transaction';
27
- import { ModalCallbacks } from '../../types';
28
- import { getTransactionStatusModalTitle } from './util/getTitle';
29
28
  import { getTransactionStatusModalMessage } from './util/getMessage';
29
+ import { getTransactionStatusModalTitle } from './util/getTitle';
30
30
 
31
31
  export type ShowTransactionStatusModalArgs = {
32
32
  hash?: Hex;
@@ -74,26 +74,8 @@ const TransactionStatusModal = observer(() => {
74
74
  const [transactionStatus, setTransactionStatus] = useState<TransactionStatus>(
75
75
  orderId ? 'SUCCESS' : 'PENDING',
76
76
  );
77
- const title = getTransactionStatusModalTitle({
78
- transactionStatus,
79
- transactionType: type!,
80
- orderId,
81
- });
82
- const message = getTransactionStatusModalMessage({
83
- transactionStatus,
84
- transactionType: type!,
85
- collectibleName: collectible?.name || '',
86
- orderId,
87
- });
88
- const { onError, onSuccess }: ModalCallbacks = callbacks || {};
89
- const queryClient = getQueryClient();
90
- const publicClient = chainId ? getPublicRpcClient(chainId) : null;
91
- const waitForTransactionReceiptPromise =
92
- publicClient?.waitForTransactionReceipt({
93
- confirmations: confirmations || TRANSACTION_CONFIRMATIONS_DEFAULT,
94
- hash: hash!,
95
- });
96
77
 
78
+ // biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
97
79
  useEffect(() => {
98
80
  if (!transactionStatusModal$.isOpen.get()) return;
99
81
 
@@ -103,9 +85,20 @@ const TransactionStatusModal = observer(() => {
103
85
  if (receipt.status === 'success') {
104
86
  console.log('receipt', receipt);
105
87
  setTransactionStatus('SUCCESS');
88
+ if (callbacks?.onSuccess) {
89
+ callbacks.onSuccess(hash || '0x');
90
+ } else {
91
+ console.debug('onSuccess callback not provided:', hash);
92
+ }
106
93
  }
107
94
  })
108
95
  .catch((error) => {
96
+ if (callbacks?.onError) {
97
+ callbacks.onError(error);
98
+ } else {
99
+ console.debug('onError callback not provided:', error);
100
+ }
101
+
109
102
  if (error instanceof WaitForTransactionReceiptTimeoutError) {
110
103
  setTransactionStatus('TIMEOUT');
111
104
  return;
@@ -121,7 +114,36 @@ const TransactionStatusModal = observer(() => {
121
114
  return () => {
122
115
  setTransactionStatus('PENDING');
123
116
  };
124
- }, [onSuccess, onError, transactionStatusModal$.isOpen.get()]);
117
+ }, [
118
+ callbacks?.onSuccess,
119
+ callbacks?.onError,
120
+ transactionStatusModal$.isOpen.get(),
121
+ ]);
122
+
123
+ if (!type) {
124
+ return null;
125
+ }
126
+
127
+ const title = getTransactionStatusModalTitle({
128
+ transactionStatus,
129
+ transactionType: type,
130
+ orderId,
131
+ });
132
+
133
+ const message = getTransactionStatusModalMessage({
134
+ transactionStatus,
135
+ transactionType: type,
136
+ collectibleName: collectible?.name || '',
137
+ orderId,
138
+ });
139
+
140
+ const queryClient = getQueryClient();
141
+ const publicClient = chainId ? getPublicRpcClient(chainId) : null;
142
+ const waitForTransactionReceiptPromise =
143
+ publicClient?.waitForTransactionReceipt({
144
+ confirmations: confirmations || TRANSACTION_CONFIRMATIONS_DEFAULT,
145
+ hash: hash || '0x',
146
+ });
125
147
 
126
148
  return (
127
149
  <Root open={transactionStatusModal$.isOpen.get()}>
@@ -3,8 +3,8 @@ import type { QueryKey } from '@tanstack/react-query';
3
3
  import type { Hex } from 'viem';
4
4
  import type { ShowTransactionStatusModalArgs } from '.';
5
5
  import type { Price } from '../../../../../../types';
6
- import { TransactionType } from '../../../../../_internal/transaction-machine/execute-transaction';
7
- import { ModalCallbacks } from '../../types';
6
+ import type { TransactionType } from '../../../../../_internal/transaction-machine/execute-transaction';
7
+ import type { ModalCallbacks } from '../../types';
8
8
 
9
9
  export type ConfirmationStatus = {
10
10
  isConfirming: boolean;
@@ -2,7 +2,7 @@ import { TransactionType } from '../../../../../../_internal/transaction-machine
2
2
 
3
3
  export function getFormattedType(
4
4
  transactionType: TransactionType,
5
- verb: boolean = false,
5
+ verb = false,
6
6
  ): string {
7
7
  switch (transactionType) {
8
8
  case TransactionType.TRANSFER:
@@ -1,5 +1,5 @@
1
- import { TransactionType } from '../../../../../../_internal/transaction-machine/execute-transaction';
2
- import { TransactionStatus } from '../store';
1
+ import type { TransactionType } from '../../../../../../_internal/transaction-machine/execute-transaction';
2
+ import type { TransactionStatus } from '../store';
3
3
  import { getFormattedType } from './getFormattedType';
4
4
 
5
5
  export function getTransactionStatusModalMessage({
@@ -1,5 +1,5 @@
1
- import { TransactionType } from '../../../../../../_internal/transaction-machine/execute-transaction';
2
- import { TransactionStatus } from '../store';
1
+ import type { TransactionType } from '../../../../../../_internal/transaction-machine/execute-transaction';
2
+ import type { TransactionStatus } from '../store';
3
3
  import { getFormattedType } from './getFormattedType';
4
4
 
5
5
  export function getTransactionStatusModalTitle({
@@ -8,9 +8,12 @@ export function getTransactionStatusModalTitle({
8
8
  orderId,
9
9
  }: {
10
10
  transactionStatus: TransactionStatus;
11
- transactionType: TransactionType;
11
+ transactionType: TransactionType | undefined;
12
12
  orderId?: string;
13
13
  }): string {
14
+ if (transactionType === undefined) {
15
+ return '';
16
+ }
14
17
  if (orderId) {
15
18
  return `Your ${getFormattedType(transactionType)} has processed`;
16
19
  }