Skip to content

Commit 5e367b3

Browse files
authored
🍉 feat: bridge and gas fees; fix: handled prepare failure (#24)
* 🍉 feat: bridge and gas fees; fix: handled prepare failure * feat: added routedId to txModal
1 parent a4f1997 commit 5e367b3

File tree

6 files changed

+194
-28
lines changed

6 files changed

+194
-28
lines changed

src/components/RouteDetails/ReviewModal.tsx

Lines changed: 141 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useDispatch, useSelector } from "react-redux";
2-
import { useContext, useEffect, useState } from "react";
2+
import { ReactNode, useContext, useEffect, useState } from "react";
33
import { CustomizeContext } from "../../providers/CustomizeProvider";
44
import { BRIDGE_DISPLAY_NAMES } from "../../consts/";
55

@@ -15,6 +15,14 @@ import { setSelectedRoute } from "../../state/selectedRouteSlice";
1515
import { TxStepDetails } from "../TxModal/TxStepDetails";
1616
import { TokenDetailsRow } from "../common/TokenDetailsRow";
1717

18+
import {
19+
formatCurrencyAmount,
20+
timeInMinutes,
21+
truncateDecimalValue,
22+
} from "../../utils/";
23+
import { useGetFees } from "../../hooks/useGetFees";
24+
import { useGetGasLimitFromUserTxs } from "../../hooks/useGetGasLimitFromUserTxs";
25+
1826
export const ReviewModal = ({
1927
closeModal,
2028
style,
@@ -48,29 +56,80 @@ export const ReviewModal = ({
4856

4957
const refuelSourceToken = {
5058
amount: selectedRoute?.refuel?.fromAmount,
51-
asset: selectedRoute?.refuel?.fromAsset
52-
}
59+
asset: selectedRoute?.refuel?.fromAsset,
60+
};
5361
const refuelDestToken = {
5462
amount: selectedRoute?.refuel?.toAmount,
55-
asset: selectedRoute?.refuel?.toAsset
56-
}
63+
asset: selectedRoute?.refuel?.toAsset,
64+
};
5765

58-
function formattedGasFees(){
59-
const feesInUsd = selectedRoute?.route?.totalGasFeesInUsd?.toFixed(3);
60-
return `${feesInUsd} USD`;
61-
}
66+
// Source Gas Fees
67+
const sourceGasLimit = useGetGasLimitFromUserTxs(
68+
selectedRoute?.route,
69+
selectedRoute?.path?.fromToken?.chainId
70+
);
71+
const sourceNativeToken = selectedRoute?.route?.userTxs.filter(
72+
(tx) => tx.chainId === selectedRoute?.path?.fromToken?.chainId
73+
)[0]?.gasFees?.asset;
74+
const { feesInToken: sourceFeesInToken, feesInUsd: sourceFeesInUSD } =
75+
useGetFees(
76+
sourceGasLimit,
77+
sourceNativeToken?.chainId,
78+
sourceNativeToken?.decimals,
79+
selectedRoute?.route
80+
);
81+
82+
// Dest Gas Fees
83+
const destGasLimit = useGetGasLimitFromUserTxs(
84+
selectedRoute?.route,
85+
selectedRoute?.path?.fromToken?.chainId
86+
);
87+
const destNativeToken = selectedRoute?.route?.userTxs.filter(
88+
(tx) => tx.chainId === selectedRoute?.path?.toToken?.chainId
89+
)[0]?.gasFees?.asset;
90+
const { feesInToken: destFeesInToken, feesInUsd: destFeesInUSD } = useGetFees(
91+
destGasLimit,
92+
destNativeToken?.chainId,
93+
destNativeToken?.decimals,
94+
selectedRoute?.route
95+
);
96+
97+
// Extracting Bridge Step from fundMove userTx
98+
const fundMovrData = selectedRoute?.route?.userTxs.filter(
99+
(item) => item.userTxType === "fund-movr"
100+
)[0];
101+
const bridgeData =
102+
fundMovrData?.steps &&
103+
fundMovrData?.steps.filter((step) => step.type === "bridge")[0];
104+
105+
// Bridge Fee
106+
const bridgeFee = bridgeData?.protocolFees.feesInUsd;
107+
const bridgeFeeInToken = formatCurrencyAmount(
108+
bridgeData?.protocolFees.amount,
109+
bridgeData?.protocolFees.asset.decimals,
110+
5
111+
);
112+
const bridgeFeeTokenSymbol = bridgeData?.protocolFees.asset.symbol;
62113

63114
return (
64115
<Modal
65116
title="Review Quote"
66-
closeModal={showTxDetails ? () => setShowTxDetails(!showTxDetails) : closeModal}
117+
closeModal={
118+
showTxDetails ? () => setShowTxDetails(!showTxDetails) : closeModal
119+
}
67120
style={style}
68121
>
69122
<div className="skt-w flex flex-col justify-between flex-1 relative">
70123
<div className="skt-w w-full">
71-
<TokenDetailsRow
72-
srcDetails={{token: selectedRoute?.path?.fromToken, amount: selectedRoute?.amount}}
73-
destDetails={{token: selectedRoute?.path?.toToken, amount: selectedRoute?.route?.toAmount}}
124+
<TokenDetailsRow
125+
srcDetails={{
126+
token: selectedRoute?.path?.fromToken,
127+
amount: selectedRoute?.amount,
128+
}}
129+
destDetails={{
130+
token: selectedRoute?.path?.toToken,
131+
amount: selectedRoute?.route?.toAmount,
132+
}}
74133
srcRefuel={refuelSourceToken}
75134
destRefuel={refuelDestToken}
76135
/>
@@ -85,9 +144,32 @@ export const ReviewModal = ({
85144
}
86145
/>
87146
<RouteDetailRow
88-
label="Total Gas Fee"
89-
value={formattedGasFees()}
147+
label="Estimated Bridging Time"
148+
value={timeInMinutes(selectedRoute?.route?.serviceTime)}
90149
/>
150+
<RouteDetailRow label="Source Gas Fee">
151+
<FeeDisplay
152+
feeInToken={sourceFeesInToken}
153+
feeInUsd={sourceFeesInUSD}
154+
tokenSymbol={sourceNativeToken?.symbol}
155+
/>
156+
</RouteDetailRow>
157+
{!!destFeesInToken && (
158+
<RouteDetailRow label="Dest Gas Fee">
159+
<FeeDisplay
160+
feeInToken={destFeesInToken}
161+
feeInUsd={destFeesInUSD}
162+
tokenSymbol={destNativeToken?.symbol}
163+
/>
164+
</RouteDetailRow>
165+
)}
166+
<RouteDetailRow label="Bridge Fee">
167+
<FeeDisplay
168+
feeInToken={bridgeFeeInToken}
169+
feeInUsd={bridgeFee}
170+
tokenSymbol={bridgeFeeTokenSymbol}
171+
/>
172+
</RouteDetailRow>
91173
<RouteDetailRow
92174
label="Number of transactions"
93175
value={selectedRoute?.route?.totalUserTx}
@@ -115,7 +197,11 @@ export const ReviewModal = ({
115197

116198
{showTxDetails && (
117199
<div className="skt-w mb-3 flex-1 overflow-y-auto">
118-
<TxStepDetails activeRoute={selectedRoute?.route} forReview refuel={selectedRoute?.refuel}/>
200+
<TxStepDetails
201+
activeRoute={selectedRoute?.route}
202+
forReview
203+
refuel={selectedRoute?.refuel}
204+
/>
119205
</div>
120206
)}
121207
</div>
@@ -147,11 +233,49 @@ export const ReviewModal = ({
147233
);
148234
};
149235

150-
const RouteDetailRow = ({ label, value }: { label: string; value: string }) => {
236+
const RouteDetailRow = ({
237+
label,
238+
value,
239+
children,
240+
}: {
241+
label: string;
242+
value?: string;
243+
children?: ReactNode;
244+
}) => {
151245
return (
152246
<div className="skt-w w-full flex justify-between text-sm text-widget-secondary">
153247
<span>{label}</span>
154248
<span>{value}</span>
249+
{children}
155250
</div>
156251
);
157252
};
253+
254+
interface FeeDisplayProps {
255+
feeInToken: string;
256+
tokenSymbol: string | undefined;
257+
feeInUsd: number;
258+
}
259+
260+
const FeeDisplay = (props: FeeDisplayProps) => {
261+
const { feeInToken, tokenSymbol, feeInUsd } = props;
262+
if (!!feeInToken) {
263+
return (
264+
<span>
265+
{!!feeInToken && feeInToken !== "0" ? (
266+
<span>
267+
{truncateDecimalValue(feeInToken, 5)}{" "}
268+
<span className="font-medium">{tokenSymbol}</span>{" "}
269+
</span>
270+
) : (
271+
0
272+
)}
273+
{feeInUsd !== 0 && (
274+
<span className="opacity-80 font-normal">
275+
(${feeInUsd.toFixed(4)})
276+
</span>
277+
)}
278+
</span>
279+
);
280+
} else return null;
281+
};

src/components/TokenInput/TokenSelect.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export const TokenSelect = (props: Props) => {
109109
(style, item) =>
110110
item && (
111111
<Modal
112-
title="Token selector"
112+
title="Select Token"
113113
closeModal={() => setOpenTokenList(false)}
114114
style={style}
115115
>

src/components/TxModal/BridgingLoader.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ExternalLink } from "react-feather";
44
import { ethers } from "ethers";
55

66
import useMappedChainData from "../../hooks/useMappedChainData";
7-
import { getExplorerLink, ExplorerDataType } from "../../utils/";
7+
import { getExplorerLink, ExplorerDataType, timeInMinutes } from "../../utils/";
88
import { UserTxType } from "../../consts/";
99
import { TxDetails } from "../../types";
1010

@@ -14,7 +14,12 @@ import { TokenDetailsRow } from "../common/TokenDetailsRow";
1414
import { Stepper } from "../common/Stepper";
1515

1616
// This component is displayed when transaction of type 'fund-movr' (bridging tx) is in progress
17-
export const BridgingLoader = ({ currentRoute, explorerParams, txDetails, refuelEnabled }) => {
17+
export const BridgingLoader = ({
18+
currentRoute,
19+
explorerParams,
20+
txDetails,
21+
refuelEnabled,
22+
}) => {
1823
const mappedChainData = useMappedChainData();
1924
const [srcTxHash, setSrcTxHash] = useState("");
2025
const [destTxHash, setDestTxHash] = useState("");
@@ -23,10 +28,6 @@ export const BridgingLoader = ({ currentRoute, explorerParams, txDetails, refuel
2328
const [showSupportLink, setShowSupportLink] = useState(false);
2429
const [furtherStepsAvailable, setFurtherStepsAvailable] = useState(false);
2530

26-
const formatedTime = (time: number) => {
27-
return Math.floor(time / 60) + "m";
28-
};
29-
3031
useEffect(() => {
3132
const srcUrl = getExplorerLink(
3233
mappedChainData?.[explorerParams.srcChainId]?.explorers[0],
@@ -149,7 +150,7 @@ export const BridgingLoader = ({ currentRoute, explorerParams, txDetails, refuel
149150
) : (
150151
<span>
151152
Estimated wait time is{" "}
152-
{formatedTime(bridgeDetails?.serviceTime)}
153+
{timeInMinutes(bridgeDetails?.serviceTime)}
153154
{furtherStepsAvailable &&
154155
", please come back later to sign the next transaction."}
155156
</span>

src/components/TxModal/index.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,12 @@ export const TxModal = ({ style }) => {
222222
}
223223

224224
// This checks the status of the transaction. The status can be ready, completed and pending.
225-
const currentStatus = await userTx.submit(sendTx.hash);
225+
let currentStatus;
226+
try {
227+
currentStatus = await userTx.submit(sendTx.hash);
228+
} catch (e) {
229+
currentStatus = PrepareTxStatus.PENDING;
230+
}
226231

227232
// If current status is completed mark route as completed else continue the route.
228233
if (currentStatus && currentStatus !== PrepareTxStatus.COMPLETED) {
@@ -370,9 +375,19 @@ export const TxModal = ({ style }) => {
370375
: selectedRoute?.refuel?.toAsset,
371376
};
372377

378+
const modalTitle = (
379+
<span className="flex items-center gap-1">
380+
Bridging transaction{" "}
381+
<span className="text-xs text-widget-primary text-opacity-70 font-normal">
382+
{currentRoute?.route?.activeRouteId
383+
? ` - #${currentRoute?.route?.activeRouteId}`
384+
: ""}
385+
</span>
386+
</span>
387+
);
373388
return (
374389
<Modal
375-
title="Bridging transaction"
390+
title={modalTitle}
376391
closeModal={closeTxModal}
377392
disableClose={isApproving || txInProgress}
378393
style={style}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Route } from "@socket.tech/socket-v2-sdk";
2+
import { ethers } from "ethers";
3+
import { useEffect, useState } from "react";
4+
5+
export const useGetGasLimitFromUserTxs = (route: Route, chainId: number) => {
6+
const [totalGasLimit, setTotalGasLimit] = useState<string>("");
7+
8+
useEffect(() => {
9+
if (route && chainId) {
10+
const gasLimit = route?.userTxs.reduce((acc, curr) => {
11+
if (curr.chainId === chainId) {
12+
return acc.add(ethers.BigNumber.from(curr.gasFees?.gasLimit) || 0);
13+
}
14+
return acc;
15+
}, ethers.BigNumber.from(0));
16+
17+
setTotalGasLimit(gasLimit.toString());
18+
}
19+
}, [route, chainId]);
20+
21+
return totalGasLimit;
22+
};

src/utils/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,8 @@ export function formatRGB(color: string) {
121121
// Filters the tokens of a particular chain from the standard token list
122122
export function filterTokensByChain(tokens: Currency[], chainId: number) {
123123
return tokens.filter((x: Currency) => x.chainId === chainId);
124-
}
124+
}
125+
126+
export const timeInMinutes = (time: number) => {
127+
return Math.floor(time / 60) + "m";
128+
};

0 commit comments

Comments
 (0)