@0xsequence/marketplace-sdk 0.3.11 → 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.
- package/dist/{chunk-3LOJQCTV.js → chunk-5GDO4ZBC.js} +5 -4
- package/dist/{chunk-3LOJQCTV.js.map → chunk-5GDO4ZBC.js.map} +1 -1
- package/dist/{chunk-E3ZFT6WR.js → chunk-EVRILXOH.js} +12 -2
- package/dist/chunk-EVRILXOH.js.map +1 -0
- package/dist/{chunk-N5F6IEAK.js → chunk-GSDUAHL3.js} +1 -1
- package/dist/chunk-GSDUAHL3.js.map +1 -0
- package/dist/{chunk-IRN77TJW.js → chunk-IOTKCWOB.js} +925 -667
- package/dist/chunk-IOTKCWOB.js.map +1 -0
- package/dist/{chunk-KRMV6FJE.js → chunk-KNX2LER4.js} +5 -6
- package/dist/{chunk-4FC3IG7C.js.map → chunk-KNX2LER4.js.map} +1 -1
- package/dist/{chunk-SBVLWSRZ.js → chunk-LF44FCG5.js} +2 -2
- package/dist/{chunk-SBVLWSRZ.js.map → chunk-LF44FCG5.js.map} +1 -1
- package/dist/{chunk-4FC3IG7C.js → chunk-LSMQVX77.js} +5 -6
- package/dist/{chunk-KRMV6FJE.js.map → chunk-LSMQVX77.js.map} +1 -1
- package/dist/{chunk-B3LFJJVS.js → chunk-MIYMMP2K.js} +90 -40
- package/dist/chunk-MIYMMP2K.js.map +1 -0
- package/dist/{chunk-Z7NLKEXF.js → chunk-QMO2CUNM.js} +2 -2
- package/dist/{chunk-L6GSYPCR.js → chunk-RZSZNVEH.js} +5 -5
- package/dist/{chunk-L6GSYPCR.js.map → chunk-RZSZNVEH.js.map} +1 -1
- package/dist/chunk-T5T6JNB2.js +171 -0
- package/dist/chunk-T5T6JNB2.js.map +1 -0
- package/dist/chunk-UPLTM63S.js +435 -0
- package/dist/chunk-UPLTM63S.js.map +1 -0
- package/dist/{chunk-Y7YO5TLE.js → chunk-XXML5K3X.js} +5 -2
- package/dist/chunk-XXML5K3X.js.map +1 -0
- package/dist/{create-config-CgtmCzvb.d.ts → create-config-8sffBvlt.d.ts} +1 -1
- package/dist/index.js +5 -5
- package/dist/react/_internal/api/index.js +2 -2
- package/dist/react/_internal/index.d.ts +1 -1
- package/dist/react/_internal/index.js +3 -3
- package/dist/react/_internal/wagmi/index.d.ts +1 -1
- package/dist/react/_internal/wagmi/index.js +2 -2
- package/dist/react/hooks/index.d.ts +666 -77
- package/dist/react/hooks/index.js +8 -8
- package/dist/react/index.css +17 -0
- package/dist/react/index.css.map +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +12 -12
- package/dist/react/ssr/index.js +1 -1
- package/dist/react/ssr/index.js.map +1 -1
- package/dist/react/ui/components/index.css +17 -0
- package/dist/react/ui/components/index.css.map +1 -1
- package/dist/react/ui/components/index.js +12 -12
- package/dist/react/ui/icons/index.js +4 -4
- package/dist/react/ui/icons/index.js.map +1 -1
- package/dist/react/ui/index.css +17 -0
- package/dist/react/ui/index.css.map +1 -1
- package/dist/react/ui/index.js +12 -12
- package/dist/react/ui/modals/_internal/components/actionModal/index.css +22 -0
- package/dist/react/ui/modals/_internal/components/actionModal/index.css.map +1 -1
- package/dist/react/ui/modals/_internal/components/actionModal/index.d.ts +17 -9
- package/dist/react/ui/modals/_internal/components/actionModal/index.js +8 -4
- package/dist/react/ui/styles/index.d.ts +1 -1
- package/dist/styles/index.d.ts +1 -1
- package/dist/styles/index.js +2 -2
- package/dist/types/index.js +3 -3
- package/dist/utils/index.js +2 -2
- package/package.json +25 -25
- package/src/react/_internal/api/marketplace-api.ts +3 -2
- package/src/react/_internal/transaction-machine/execute-transaction.ts +41 -19
- package/src/react/_internal/transaction-machine/useTransactionMachine.ts +43 -8
- package/src/react/hooks/useBuyCollectable.tsx +15 -8
- package/src/react/hooks/useCancelOrder.tsx +15 -7
- package/src/react/hooks/useCreateListing.tsx +75 -11
- package/src/react/hooks/useCurrencies.tsx +1 -2
- package/src/react/hooks/useCurrencyBalance.tsx +1 -1
- package/src/react/hooks/useCurrencyOptions.tsx +1 -1
- package/src/react/hooks/useMakeOffer.tsx +74 -12
- package/src/react/hooks/useSell.tsx +73 -12
- package/src/react/ui/components/_internals/action-button/ActionButton.tsx +1 -7
- package/src/react/ui/components/_internals/action-button/types.ts +7 -0
- package/src/react/ui/components/_internals/custom-select/CustomSelect.tsx +18 -15
- package/src/react/ui/components/collectible-card/CollectibleCard.tsx +5 -7
- package/src/react/ui/components/collectible-card/Footer.tsx +5 -7
- package/src/react/ui/components/collectible-card/styles.css.ts +1 -1
- package/src/react/ui/icons/ArrowUp.tsx +3 -0
- package/src/react/ui/icons/Bell.tsx +3 -0
- package/src/react/ui/icons/CalendarIcon.tsx +3 -0
- package/src/react/ui/icons/DiamondEye.tsx +3 -0
- package/src/react/ui/icons/InfoIcon.tsx +3 -0
- package/src/react/ui/icons/InventoryIcon.tsx +3 -0
- package/src/react/ui/icons/MinusIcon.tsx +3 -0
- package/src/react/ui/icons/PlusIcon.tsx +3 -0
- package/src/react/ui/icons/PositiveCircleIcon.tsx +3 -0
- package/src/react/ui/modals/BuyModal/index.tsx +25 -8
- package/src/react/ui/modals/CreateListingModal/_store.ts +5 -2
- package/src/react/ui/modals/CreateListingModal/index.tsx +66 -25
- package/src/react/ui/modals/MakeOfferModal/_store.ts +5 -2
- package/src/react/ui/modals/MakeOfferModal/index.tsx +87 -67
- package/src/react/ui/modals/SellModal/index.tsx +107 -57
- package/src/react/ui/modals/TransferModal/_store.ts +1 -1
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/index.tsx +4 -2
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/useHandleTransfer.tsx +5 -5
- package/src/react/ui/modals/TransferModal/index.tsx +1 -1
- package/src/react/ui/modals/_internal/components/actionModal/ActionModal.tsx +29 -8
- package/src/react/ui/modals/_internal/components/actionModal/ErrorModal.tsx +15 -5
- package/src/react/ui/modals/_internal/components/actionModal/LoadingModal.tsx +15 -5
- package/src/react/ui/modals/_internal/components/actionModal/store.ts +6 -0
- package/src/react/ui/modals/_internal/components/calendar/index.tsx +1 -1
- package/src/react/ui/modals/_internal/components/currencyImage/index.tsx +3 -3
- package/src/react/ui/modals/_internal/components/currencyOptionsSelect/index.tsx +11 -16
- package/src/react/ui/modals/_internal/components/expirationDateSelect/index.tsx +14 -19
- package/src/react/ui/modals/_internal/components/priceInput/index.tsx +34 -12
- package/src/react/ui/modals/_internal/components/quantityInput/index.tsx +3 -3
- package/src/react/ui/modals/_internal/components/switchChainModal/index.tsx +7 -4
- package/src/react/ui/modals/_internal/components/tokenPreview/index.tsx +1 -0
- package/src/react/ui/modals/_internal/components/transaction-footer/index.tsx +10 -8
- package/src/react/ui/modals/_internal/components/transactionDetails/index.tsx +9 -5
- package/src/react/ui/modals/_internal/components/transactionPreview/index.tsx +7 -4
- package/src/react/ui/modals/_internal/components/transactionPreview/useTransactionPreviewTitle.tsx +9 -11
- package/src/react/ui/modals/_internal/components/transactionStatusModal/index.tsx +60 -31
- package/src/react/ui/modals/_internal/components/transactionStatusModal/store.ts +6 -2
- package/src/react/ui/modals/_internal/components/transactionStatusModal/util/getFormattedType.ts +1 -1
- package/src/react/ui/modals/_internal/components/transactionStatusModal/util/getMessage.ts +8 -2
- package/src/react/ui/modals/_internal/components/transactionStatusModal/util/getTitle.ts +12 -3
- package/src/react/ui/modals/_internal/components/waasFeeOptionsBox/index.tsx +146 -0
- package/src/react/ui/modals/_internal/components/waasFeeOptionsBox/store.ts +12 -0
- package/src/react/ui/modals/_internal/components/waasFeeOptionsBox/styles.css.ts +53 -0
- package/src/react/ui/modals/_internal/components/waasFeeOptionsSelect/WaasFeeOptionsSelect.tsx +117 -0
- package/src/utils/_internal/error/transaction.ts +12 -2
- package/src/utils/price.ts +3 -4
- package/tsconfig.json +1 -21
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/chunk-B3LFJJVS.js.map +0 -1
- package/dist/chunk-E3ZFT6WR.js.map +0 -1
- package/dist/chunk-FFCNYF3S.js +0 -153
- package/dist/chunk-FFCNYF3S.js.map +0 -1
- package/dist/chunk-IRN77TJW.js.map +0 -1
- package/dist/chunk-N5F6IEAK.js.map +0 -1
- package/dist/chunk-NMCGA2TB.js +0 -98
- package/dist/chunk-NMCGA2TB.js.map +0 -1
- package/dist/chunk-Y7YO5TLE.js.map +0 -1
- /package/dist/{chunk-Z7NLKEXF.js.map → chunk-QMO2CUNM.js.map} +0 -0
|
@@ -4,32 +4,33 @@ 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 {
|
|
11
|
+
import type { QueryKey } from '@tanstack/react-query';
|
|
10
12
|
import { useEffect, useState } from 'react';
|
|
11
|
-
import {
|
|
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
|
-
hash
|
|
32
|
+
hash?: Hex;
|
|
33
|
+
orderId?: string;
|
|
33
34
|
price?: Price;
|
|
34
35
|
collectionAddress: Hex;
|
|
35
36
|
chainId: string;
|
|
@@ -56,6 +57,7 @@ const TransactionStatusModal = observer(() => {
|
|
|
56
57
|
const {
|
|
57
58
|
type,
|
|
58
59
|
hash,
|
|
60
|
+
orderId,
|
|
59
61
|
price,
|
|
60
62
|
collectionAddress,
|
|
61
63
|
chainId,
|
|
@@ -69,26 +71,11 @@ const TransactionStatusModal = observer(() => {
|
|
|
69
71
|
chainId,
|
|
70
72
|
collectibleId,
|
|
71
73
|
});
|
|
72
|
-
const [transactionStatus, setTransactionStatus] =
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
transactionStatus,
|
|
76
|
-
transactionType: type!,
|
|
77
|
-
});
|
|
78
|
-
const message = getTransactionStatusModalMessage({
|
|
79
|
-
transactionStatus,
|
|
80
|
-
transactionType: type!,
|
|
81
|
-
collectibleName: collectible?.name || '',
|
|
82
|
-
});
|
|
83
|
-
const { onError, onSuccess }: ModalCallbacks = callbacks || {};
|
|
84
|
-
const queryClient = getQueryClient();
|
|
85
|
-
const publicClient = chainId ? getPublicRpcClient(chainId) : null;
|
|
86
|
-
const waitForTransactionReceiptPromise =
|
|
87
|
-
publicClient?.waitForTransactionReceipt({
|
|
88
|
-
confirmations: confirmations || TRANSACTION_CONFIRMATIONS_DEFAULT,
|
|
89
|
-
hash: hash!,
|
|
90
|
-
});
|
|
74
|
+
const [transactionStatus, setTransactionStatus] = useState<TransactionStatus>(
|
|
75
|
+
orderId ? 'SUCCESS' : 'PENDING',
|
|
76
|
+
);
|
|
91
77
|
|
|
78
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
|
|
92
79
|
useEffect(() => {
|
|
93
80
|
if (!transactionStatusModal$.isOpen.get()) return;
|
|
94
81
|
|
|
@@ -98,9 +85,20 @@ const TransactionStatusModal = observer(() => {
|
|
|
98
85
|
if (receipt.status === 'success') {
|
|
99
86
|
console.log('receipt', receipt);
|
|
100
87
|
setTransactionStatus('SUCCESS');
|
|
88
|
+
if (callbacks?.onSuccess) {
|
|
89
|
+
callbacks.onSuccess(hash || '0x');
|
|
90
|
+
} else {
|
|
91
|
+
console.debug('onSuccess callback not provided:', hash);
|
|
92
|
+
}
|
|
101
93
|
}
|
|
102
94
|
})
|
|
103
95
|
.catch((error) => {
|
|
96
|
+
if (callbacks?.onError) {
|
|
97
|
+
callbacks.onError(error);
|
|
98
|
+
} else {
|
|
99
|
+
console.debug('onError callback not provided:', error);
|
|
100
|
+
}
|
|
101
|
+
|
|
104
102
|
if (error instanceof WaitForTransactionReceiptTimeoutError) {
|
|
105
103
|
setTransactionStatus('TIMEOUT');
|
|
106
104
|
return;
|
|
@@ -116,7 +114,36 @@ const TransactionStatusModal = observer(() => {
|
|
|
116
114
|
return () => {
|
|
117
115
|
setTransactionStatus('PENDING');
|
|
118
116
|
};
|
|
119
|
-
}, [
|
|
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
|
+
});
|
|
120
147
|
|
|
121
148
|
return (
|
|
122
149
|
<Root open={transactionStatusModal$.isOpen.get()}>
|
|
@@ -146,6 +173,7 @@ const TransactionStatusModal = observer(() => {
|
|
|
146
173
|
)}
|
|
147
174
|
|
|
148
175
|
<TransactionPreview
|
|
176
|
+
orderId={orderId}
|
|
149
177
|
price={price}
|
|
150
178
|
collectionAddress={collectionAddress}
|
|
151
179
|
chainId={chainId}
|
|
@@ -159,7 +187,8 @@ const TransactionStatusModal = observer(() => {
|
|
|
159
187
|
/>
|
|
160
188
|
|
|
161
189
|
<TransactionFooter
|
|
162
|
-
transactionHash={hash
|
|
190
|
+
transactionHash={hash}
|
|
191
|
+
orderId={orderId}
|
|
163
192
|
isConfirming={transactionStatus === 'PENDING'}
|
|
164
193
|
isConfirmed={transactionStatus === 'SUCCESS'}
|
|
165
194
|
isFailed={transactionStatus === 'FAILED'}
|
|
@@ -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;
|
|
@@ -21,6 +21,7 @@ export interface TransactionStatusModalState {
|
|
|
21
21
|
close: () => void;
|
|
22
22
|
state: {
|
|
23
23
|
hash: Hex | undefined;
|
|
24
|
+
orderId: string | undefined;
|
|
24
25
|
status: TransactionStatus;
|
|
25
26
|
type: TransactionType | undefined;
|
|
26
27
|
price: Price | undefined;
|
|
@@ -38,6 +39,7 @@ export const initialState: TransactionStatusModalState = {
|
|
|
38
39
|
isOpen: false,
|
|
39
40
|
open: ({
|
|
40
41
|
hash,
|
|
42
|
+
orderId,
|
|
41
43
|
price,
|
|
42
44
|
collectionAddress,
|
|
43
45
|
chainId,
|
|
@@ -51,6 +53,7 @@ export const initialState: TransactionStatusModalState = {
|
|
|
51
53
|
transactionStatusModal$.state.set({
|
|
52
54
|
...transactionStatusModal$.state.get(),
|
|
53
55
|
hash,
|
|
56
|
+
orderId,
|
|
54
57
|
price,
|
|
55
58
|
collectionAddress,
|
|
56
59
|
chainId,
|
|
@@ -71,6 +74,7 @@ export const initialState: TransactionStatusModalState = {
|
|
|
71
74
|
},
|
|
72
75
|
state: {
|
|
73
76
|
hash: undefined,
|
|
77
|
+
orderId: undefined,
|
|
74
78
|
status: 'PENDING',
|
|
75
79
|
price: undefined,
|
|
76
80
|
collectionAddress: '' as Hex,
|
package/src/react/ui/modals/_internal/components/transactionStatusModal/util/getFormattedType.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { TransactionType } from '../../../../../../_internal/transaction-machine
|
|
|
2
2
|
|
|
3
3
|
export function getFormattedType(
|
|
4
4
|
transactionType: TransactionType,
|
|
5
|
-
verb
|
|
5
|
+
verb = false,
|
|
6
6
|
): string {
|
|
7
7
|
switch (transactionType) {
|
|
8
8
|
case TransactionType.TRANSFER:
|
|
@@ -1,19 +1,25 @@
|
|
|
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({
|
|
6
6
|
transactionStatus,
|
|
7
7
|
transactionType,
|
|
8
8
|
collectibleName,
|
|
9
|
+
orderId,
|
|
9
10
|
}: {
|
|
10
11
|
transactionStatus: TransactionStatus;
|
|
11
12
|
transactionType: TransactionType;
|
|
12
13
|
collectibleName: string;
|
|
14
|
+
orderId?: string;
|
|
13
15
|
}): string {
|
|
14
16
|
// without this, the text will be "Your cancellation CollectibleXXX has failed." which sounds weird
|
|
15
17
|
const hideCollectibleName = transactionType === 'CANCEL';
|
|
16
18
|
|
|
19
|
+
if (orderId) {
|
|
20
|
+
return `You just ${getFormattedType(transactionType, true)}${!hideCollectibleName ? ` ${collectibleName}` : ''}. It's been confirmed on the blockchain!`;
|
|
21
|
+
}
|
|
22
|
+
|
|
17
23
|
switch (transactionStatus) {
|
|
18
24
|
case 'PENDING':
|
|
19
25
|
return `You just ${getFormattedType(transactionType, true)}${!hideCollectibleName ? ` ${collectibleName}` : ''}. It should be confirmed on the blockchain shortly.`;
|
|
@@ -1,14 +1,23 @@
|
|
|
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({
|
|
6
6
|
transactionStatus,
|
|
7
7
|
transactionType,
|
|
8
|
+
orderId,
|
|
8
9
|
}: {
|
|
9
10
|
transactionStatus: TransactionStatus;
|
|
10
|
-
transactionType: TransactionType;
|
|
11
|
+
transactionType: TransactionType | undefined;
|
|
12
|
+
orderId?: string;
|
|
11
13
|
}): string {
|
|
14
|
+
if (transactionType === undefined) {
|
|
15
|
+
return '';
|
|
16
|
+
}
|
|
17
|
+
if (orderId) {
|
|
18
|
+
return `Your ${getFormattedType(transactionType)} has processed`;
|
|
19
|
+
}
|
|
20
|
+
|
|
12
21
|
switch (transactionStatus) {
|
|
13
22
|
case 'PENDING':
|
|
14
23
|
return `Your ${getFormattedType(transactionType)} is processing`;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Box,
|
|
3
|
+
Button,
|
|
4
|
+
Skeleton,
|
|
5
|
+
Text,
|
|
6
|
+
WarningIcon,
|
|
7
|
+
} from '@0xsequence/design-system';
|
|
8
|
+
import { useWaasFeeOptions } from '@0xsequence/kit';
|
|
9
|
+
import { observer } from '@legendapp/state/react';
|
|
10
|
+
import { useEffect } from 'react';
|
|
11
|
+
import { type Hex, zeroAddress } from 'viem';
|
|
12
|
+
import { useAccount } from 'wagmi';
|
|
13
|
+
import { useCurrencyBalance } from '../../../../../hooks/useCurrencyBalance';
|
|
14
|
+
import WaasFeeOptionsSelect, {
|
|
15
|
+
type FeeOption,
|
|
16
|
+
} from '../waasFeeOptionsSelect/WaasFeeOptionsSelect';
|
|
17
|
+
import { waasFeeOptionsModal$ } from './store';
|
|
18
|
+
import { feeOptionsWrapper } from './styles.css';
|
|
19
|
+
|
|
20
|
+
type WaasFeeOptionsBoxProps = {
|
|
21
|
+
onFeeOptionsLoaded: () => void;
|
|
22
|
+
onFeeOptionConfirmed: () => void;
|
|
23
|
+
chainId: number;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const WaasFeeOptionsBox = observer(
|
|
27
|
+
({
|
|
28
|
+
onFeeOptionsLoaded,
|
|
29
|
+
onFeeOptionConfirmed,
|
|
30
|
+
chainId,
|
|
31
|
+
}: WaasFeeOptionsBoxProps) => {
|
|
32
|
+
const { address: userAddress } = useAccount();
|
|
33
|
+
const selectedFeeOption$ = waasFeeOptionsModal$.selectedFeeOption;
|
|
34
|
+
const [pendingFeeOptionConfirmation, confirmPendingFeeOption] =
|
|
35
|
+
useWaasFeeOptions();
|
|
36
|
+
const { data: currencyBalance, isLoading: currencyBalanceLoading } =
|
|
37
|
+
useCurrencyBalance({
|
|
38
|
+
chainId,
|
|
39
|
+
currencyAddress: (selectedFeeOption$.token.contractAddress.get() ||
|
|
40
|
+
zeroAddress) as Hex,
|
|
41
|
+
userAddress: userAddress as Hex,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (pendingFeeOptionConfirmation) {
|
|
47
|
+
onFeeOptionsLoaded();
|
|
48
|
+
}
|
|
49
|
+
}, [pendingFeeOptionConfirmation]);
|
|
50
|
+
|
|
51
|
+
const selectedFeeOption = selectedFeeOption$.get();
|
|
52
|
+
const insufficientBalance = (() => {
|
|
53
|
+
if (!selectedFeeOption?.value || !selectedFeeOption.token.decimals) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!currencyBalance?.value && currencyBalance?.value !== 0n) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
const feeValue = BigInt(selectedFeeOption.value);
|
|
63
|
+
return currencyBalance.value === 0n || currencyBalance.value < feeValue;
|
|
64
|
+
} catch {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
})();
|
|
68
|
+
|
|
69
|
+
const handleConfirmFeeOption = () => {
|
|
70
|
+
if (!selectedFeeOption?.token || !pendingFeeOptionConfirmation?.id)
|
|
71
|
+
return;
|
|
72
|
+
|
|
73
|
+
confirmPendingFeeOption(
|
|
74
|
+
pendingFeeOptionConfirmation?.id,
|
|
75
|
+
selectedFeeOption.token.contractAddress || zeroAddress,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
onFeeOptionConfirmed();
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
if (!pendingFeeOptionConfirmation) return null;
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<Box className={feeOptionsWrapper}>
|
|
85
|
+
<Text
|
|
86
|
+
fontSize="medium"
|
|
87
|
+
fontFamily="body"
|
|
88
|
+
fontWeight="bold"
|
|
89
|
+
marginBottom="2"
|
|
90
|
+
>
|
|
91
|
+
Select a fee option
|
|
92
|
+
</Text>
|
|
93
|
+
|
|
94
|
+
<WaasFeeOptionsSelect
|
|
95
|
+
options={(pendingFeeOptionConfirmation?.options as FeeOption[]) || []}
|
|
96
|
+
selectedFeeOption$={selectedFeeOption$}
|
|
97
|
+
/>
|
|
98
|
+
|
|
99
|
+
<Box
|
|
100
|
+
display="flex"
|
|
101
|
+
alignItems="center"
|
|
102
|
+
justifyContent="space-between"
|
|
103
|
+
width="full"
|
|
104
|
+
>
|
|
105
|
+
{currencyBalanceLoading ? (
|
|
106
|
+
<Skeleton style={{ height: 15 }} borderRadius="md" width="1/3" />
|
|
107
|
+
) : (
|
|
108
|
+
<Box display="flex" alignItems="center" gap="2">
|
|
109
|
+
{insufficientBalance && (
|
|
110
|
+
<WarningIcon color="negative" size="xs" />
|
|
111
|
+
)}
|
|
112
|
+
<Text
|
|
113
|
+
fontSize="small"
|
|
114
|
+
fontWeight="semibold"
|
|
115
|
+
fontFamily="body"
|
|
116
|
+
color={insufficientBalance ? 'negative' : 'text100'}
|
|
117
|
+
>
|
|
118
|
+
You have {currencyBalance?.formatted || '0'}{' '}
|
|
119
|
+
{selectedFeeOption?.token.symbol}
|
|
120
|
+
</Text>
|
|
121
|
+
</Box>
|
|
122
|
+
)}
|
|
123
|
+
|
|
124
|
+
<Button
|
|
125
|
+
disabled={
|
|
126
|
+
!selectedFeeOption?.token ||
|
|
127
|
+
insufficientBalance ||
|
|
128
|
+
currencyBalanceLoading
|
|
129
|
+
}
|
|
130
|
+
pending={currencyBalanceLoading}
|
|
131
|
+
onClick={handleConfirmFeeOption}
|
|
132
|
+
label={
|
|
133
|
+
<Box display="flex" alignItems="center" gap="2">
|
|
134
|
+
Confirm
|
|
135
|
+
</Box>
|
|
136
|
+
}
|
|
137
|
+
variant={insufficientBalance ? 'danger' : 'primary'}
|
|
138
|
+
size="xs"
|
|
139
|
+
/>
|
|
140
|
+
</Box>
|
|
141
|
+
</Box>
|
|
142
|
+
);
|
|
143
|
+
},
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
export default WaasFeeOptionsBox;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { observable } from '@legendapp/state';
|
|
2
|
+
import type { FeeOption } from '../waasFeeOptionsSelect/WaasFeeOptionsSelect';
|
|
3
|
+
|
|
4
|
+
type WaasFeeOptionsModalState = {
|
|
5
|
+
selectedFeeOption: FeeOption | undefined;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const initialState = {
|
|
9
|
+
selectedFeeOption: undefined,
|
|
10
|
+
} as WaasFeeOptionsModalState;
|
|
11
|
+
|
|
12
|
+
export const waasFeeOptionsModal$ = observable(initialState);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { atoms } from '@0xsequence/design-system';
|
|
2
|
+
import { globalStyle, style } from '@vanilla-extract/css';
|
|
3
|
+
|
|
4
|
+
export const feeOptionsWrapper = style([
|
|
5
|
+
atoms({
|
|
6
|
+
position: 'absolute',
|
|
7
|
+
background: 'buttonEmphasis',
|
|
8
|
+
backdropFilter: 'blur',
|
|
9
|
+
width: 'full',
|
|
10
|
+
left: '0',
|
|
11
|
+
borderRadius: 'lg',
|
|
12
|
+
display: 'flex',
|
|
13
|
+
flexDirection: 'column',
|
|
14
|
+
gap: '2',
|
|
15
|
+
padding: '4',
|
|
16
|
+
}),
|
|
17
|
+
{
|
|
18
|
+
bottom: '-140px',
|
|
19
|
+
},
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
export const dialogOverlay = style([
|
|
23
|
+
atoms({
|
|
24
|
+
background: 'backgroundBackdrop',
|
|
25
|
+
position: 'fixed',
|
|
26
|
+
inset: '0',
|
|
27
|
+
zIndex: '50',
|
|
28
|
+
}),
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
export const dialogContent = style([
|
|
32
|
+
atoms({
|
|
33
|
+
display: 'flex',
|
|
34
|
+
background: 'backgroundPrimary',
|
|
35
|
+
borderRadius: 'lg',
|
|
36
|
+
position: 'fixed',
|
|
37
|
+
zIndex: '50',
|
|
38
|
+
}),
|
|
39
|
+
{
|
|
40
|
+
top: '50%',
|
|
41
|
+
left: '50%',
|
|
42
|
+
transform: 'translate(-50%, -50%)',
|
|
43
|
+
padding: '24px',
|
|
44
|
+
},
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
export const cta = style({
|
|
48
|
+
borderRadius: '12px !important',
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
globalStyle(`${cta} > div`, {
|
|
52
|
+
justifyContent: 'center !important',
|
|
53
|
+
});
|
package/src/react/ui/modals/_internal/components/waasFeeOptionsSelect/WaasFeeOptionsSelect.tsx
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Box, Image, Text } from '@0xsequence/design-system';
|
|
2
|
+
import type { Observable } from '@legendapp/state';
|
|
3
|
+
import { observer } from '@legendapp/state/react';
|
|
4
|
+
import { useEffect } from 'react';
|
|
5
|
+
import { formatUnits } from 'viem';
|
|
6
|
+
import {
|
|
7
|
+
CustomSelect,
|
|
8
|
+
type SelectItem,
|
|
9
|
+
} from '../../../../components/_internals/custom-select/CustomSelect';
|
|
10
|
+
|
|
11
|
+
export type FeeOption = {
|
|
12
|
+
gasLimit: number;
|
|
13
|
+
to: string;
|
|
14
|
+
token: {
|
|
15
|
+
chainId: number;
|
|
16
|
+
contractAddress: string | null;
|
|
17
|
+
decimals: number;
|
|
18
|
+
logoURL: string;
|
|
19
|
+
name: string;
|
|
20
|
+
symbol: string;
|
|
21
|
+
tokenID: string | null;
|
|
22
|
+
type: string;
|
|
23
|
+
};
|
|
24
|
+
value: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const WaasFeeOptionsSelect = observer(
|
|
28
|
+
({
|
|
29
|
+
options,
|
|
30
|
+
selectedFeeOption$,
|
|
31
|
+
}: {
|
|
32
|
+
options: FeeOption[];
|
|
33
|
+
selectedFeeOption$: Observable<FeeOption | undefined>;
|
|
34
|
+
}) => {
|
|
35
|
+
const feeOptions = options
|
|
36
|
+
.filter((option) => option.token.contractAddress !== null)
|
|
37
|
+
.map((option) => {
|
|
38
|
+
const value = option.token.contractAddress ?? '';
|
|
39
|
+
return FeeOptionSelectItem({ value, option });
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (options.length > 0 && !selectedFeeOption$.get())
|
|
45
|
+
selectedFeeOption$.set(options[0]);
|
|
46
|
+
}, [options]);
|
|
47
|
+
|
|
48
|
+
if (options.length === 0 || !selectedFeeOption$.get()?.token) return null;
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<CustomSelect
|
|
52
|
+
items={feeOptions}
|
|
53
|
+
onValueChange={(value) => {
|
|
54
|
+
const selectedOption = options.find(
|
|
55
|
+
(option) => option.token.contractAddress === value,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
selectedFeeOption$.set(selectedOption);
|
|
59
|
+
}}
|
|
60
|
+
defaultValue={
|
|
61
|
+
selectedFeeOption$.get()?.token.contractAddress
|
|
62
|
+
? FeeOptionSelectItem({
|
|
63
|
+
value: selectedFeeOption$.get()?.token.contractAddress ?? '',
|
|
64
|
+
option: selectedFeeOption$.get() ?? options[0],
|
|
65
|
+
})
|
|
66
|
+
: undefined
|
|
67
|
+
}
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
},
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
function FeeOptionSelectItem({
|
|
74
|
+
value,
|
|
75
|
+
option,
|
|
76
|
+
}: {
|
|
77
|
+
value: string;
|
|
78
|
+
option: FeeOption;
|
|
79
|
+
}) {
|
|
80
|
+
return {
|
|
81
|
+
value,
|
|
82
|
+
content: (
|
|
83
|
+
<Box display="flex" alignItems="center" gap="2">
|
|
84
|
+
<Image
|
|
85
|
+
src={option.token.logoURL}
|
|
86
|
+
alt={option.token.symbol}
|
|
87
|
+
width="3"
|
|
88
|
+
height="3"
|
|
89
|
+
/>
|
|
90
|
+
|
|
91
|
+
<Box display="flex" gap="1">
|
|
92
|
+
<Text color="text100" fontSize="small" fontFamily="body">
|
|
93
|
+
Fee
|
|
94
|
+
</Text>
|
|
95
|
+
<Text
|
|
96
|
+
color="text50"
|
|
97
|
+
fontSize="small"
|
|
98
|
+
fontFamily="body"
|
|
99
|
+
fontWeight="semibold"
|
|
100
|
+
>
|
|
101
|
+
(in {option.token.symbol})
|
|
102
|
+
</Text>
|
|
103
|
+
|
|
104
|
+
<Text color="text100" fontSize="small" fontFamily="body">
|
|
105
|
+
:
|
|
106
|
+
</Text>
|
|
107
|
+
</Box>
|
|
108
|
+
|
|
109
|
+
<Text fontSize="small" fontFamily="body">
|
|
110
|
+
{formatUnits(BigInt(option.value), option.token.decimals || 0)}
|
|
111
|
+
</Text>
|
|
112
|
+
</Box>
|
|
113
|
+
),
|
|
114
|
+
} as SelectItem;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export default WaasFeeOptionsSelect;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Address } from 'viem';
|
|
1
|
+
import type { Address } from 'viem';
|
|
2
2
|
import { BaseError } from './base';
|
|
3
3
|
|
|
4
4
|
export type TransactionErrorType<name extends string = 'TransactionError'> =
|
|
@@ -84,6 +84,16 @@ export class InsufficientFundsError extends TransactionError {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
export class SignatureExecutionError extends TransactionError {
|
|
88
|
+
override name = 'SignatureExecutionError';
|
|
89
|
+
constructor(signature: string, cause?: Error) {
|
|
90
|
+
super(`Failed to execute signature: ${signature}`, {
|
|
91
|
+
details: cause?.message || 'The execution of the signature failed.',
|
|
92
|
+
cause,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
87
97
|
export class StepExecutionError extends TransactionError {
|
|
88
98
|
override name = 'StepExecutionError';
|
|
89
99
|
constructor(stepId: string, cause?: Error) {
|
|
@@ -253,7 +263,7 @@ export class InvalidCurrencyOptionsError extends TransactionError {
|
|
|
253
263
|
export class ProjectNotFoundError extends TransactionError {
|
|
254
264
|
override name = 'ProjectNotFoundError';
|
|
255
265
|
constructor(projectId: string, url: string) {
|
|
256
|
-
super(
|
|
266
|
+
super('Project not found', {
|
|
257
267
|
details: `Project id: ${projectId} not found at ${url}`,
|
|
258
268
|
});
|
|
259
269
|
}
|
package/src/utils/price.ts
CHANGED
|
@@ -11,11 +11,10 @@ export const calculatePriceDifferencePercentage = ({
|
|
|
11
11
|
basePriceRaw,
|
|
12
12
|
decimals,
|
|
13
13
|
}: CalculatePriceDifferencePercentageArgs) => {
|
|
14
|
-
const
|
|
15
|
-
formatUnits(inputPriceRaw - basePriceRaw, decimals),
|
|
16
|
-
);
|
|
14
|
+
const inputPrice = Number(formatUnits(inputPriceRaw, decimals));
|
|
17
15
|
const basePrice = Number(formatUnits(basePriceRaw, decimals));
|
|
16
|
+
const difference = inputPrice - basePrice;
|
|
18
17
|
const percentageDifference = (difference / basePrice) * 100;
|
|
19
18
|
|
|
20
|
-
return
|
|
19
|
+
return percentageDifference.toFixed(2);
|
|
21
20
|
};
|
package/tsconfig.json
CHANGED
|
@@ -1,24 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
"target": "ESNext",
|
|
4
|
-
"useDefineForClassFields": true,
|
|
5
|
-
"lib": ["dom", "dom.iterable", "esnext"],
|
|
6
|
-
|
|
7
|
-
"module": "ESNext",
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
|
|
10
|
-
"moduleResolution": "bundler",
|
|
11
|
-
"resolvePackageJsonImports": true,
|
|
12
|
-
"allowImportingTsExtensions": true,
|
|
13
|
-
"isolatedModules": true,
|
|
14
|
-
"moduleDetection": "force",
|
|
15
|
-
"noEmit": true,
|
|
16
|
-
"jsx": "react-jsx",
|
|
17
|
-
|
|
18
|
-
"strict": true,
|
|
19
|
-
"noUnusedLocals": true,
|
|
20
|
-
"noUnusedParameters": true,
|
|
21
|
-
"noFallthroughCasesInSwitch": true
|
|
22
|
-
},
|
|
2
|
+
"extends": "../../tsconfig.json",
|
|
23
3
|
"include": ["src", "tsup.config.ts"]
|
|
24
4
|
}
|