Skip to content

Commit

Permalink
891: Fix LastLook expired transactions (#895)
Browse files Browse the repository at this point in the history
  • Loading branch information
piersss authored Apr 17, 2024
1 parent 56bd85d commit fc81ada
Show file tree
Hide file tree
Showing 28 changed files with 361 additions and 383 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"tls-browserify": "^0.2.2",
"truncate-eth-address": "^1.0.2",
"typescript": "^4.4.3",
"usehooks-ts": "^3.1.0",
"zlib-browserify": "^0.0.3"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useEffect, useMemo, useState } from "react";

import { useAppSelector } from "../../../../app/hooks";
import { SubmittedTransaction } from "../../../../entities/SubmittedTransaction/SubmittedTransaction";
import { isSubmittedOrder } from "../../../../entities/SubmittedTransaction/SubmittedTransactionHelpers";
import { selectOrderTransactions } from "../../../../features/transactions/transactionsSlice";
import { TransactionStatusType } from "../../../../types/transactionTypes";

Expand All @@ -21,7 +22,8 @@ const useSessionOrderTransaction = (
}

if (
transactions[0].nonce === nonce &&
isSubmittedOrder(transactions[0]) &&
transactions[0].order.nonce === nonce &&
transactions[0].status === TransactionStatusType.processing
) {
setProcessingTransactionHash(transactions[0].hash);
Expand Down
32 changes: 9 additions & 23 deletions src/components/@widgets/SwapWidget/SwapWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import nativeCurrency, {
} from "../../../constants/nativeCurrency";
import { InterfaceContext } from "../../../contexts/interface/Interface";
import { LastLookContext } from "../../../contexts/lastLook/LastLook";
import { ProtocolType } from "../../../entities/SubmittedTransaction/SubmittedTransaction";
import { AppErrorType } from "../../../errors/appError";
import transformUnknownErrorToAppError from "../../../errors/transformUnknownErrorToAppError";
import {
Expand Down Expand Up @@ -592,28 +591,15 @@ const SwapWidget: FC = () => {
setIsSwapping(false);
return;
}
const accepted = await LastLook.sendOrderForConsideration({

LastLook.sendOrderForConsideration({
locator: bestTradeOption!.pricing!.locator,
order: order,
});
setIsSwapping(false);
if (accepted) {
setShowOrderSubmitted(true);
LastLook.unsubscribeAllServers();
} else {
notifyError({
heading: t("orders.swapRejected"),
cta: t("orders.swapRejectedCallToAction"),
});

dispatch(
declineTransaction({
signerWallet: order.signerWallet,
nonce: order.nonce,
reason: "Pricing expired",
})
);
}
setIsSwapping(false);
setShowOrderSubmitted(true);
LastLook.unsubscribeAllServers();
} catch (e: any) {
setIsSwapping(false);
dispatch(clearTradeTermsQuoteAmount());
Expand Down Expand Up @@ -671,10 +657,10 @@ const SwapWidget: FC = () => {
]);

const takeBestOption = async () => {
if (bestTradeOption!.protocol === "request-for-quote-erc20") {
await swapWithRequestForQuote();
} else {
if (bestTradeOption?.isLastLook) {
await swapWithLastLook();
} else {
await swapWithRequestForQuote();
}
};

Expand Down Expand Up @@ -809,10 +795,10 @@ const SwapWidget: FC = () => {
<>
<StyledSwapWidget>
<SwapWidgetHeader
isLastLook={!!(bestTradeOption && bestTradeOption.isLastLook)}
title={isApproving ? t("orders.approve") : t("common.rfq")}
isQuote={!isRequestingQuotes && !showOrderSubmitted}
onGasFreeTradeButtonClick={() => setShowGasFeeInfo(true)}
protocol={bestTradeOption?.protocol as ProtocolType}
expiry={bestTradeOption?.order?.expiry}
/>
{!isApproving && !isSwapping && !showOrderSubmitted && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { FC, useMemo } from "react";
import { useTranslation } from "react-i18next";

import { RFQ_EXPIRY_BUFFER_MS } from "../../../../../constants/configParams";
import { ProtocolType } from "../../../../../entities/SubmittedTransaction/SubmittedTransaction";
import { WidgetHeader } from "../../../../../styled-components/WidgetHeader/WidgetHeader";
import { Title } from "../../../../Typography/Typography";
import {
Expand All @@ -14,18 +13,18 @@ import {
} from "./SwapWidgetHeader.styles";

interface SwapWidgetHeaderProps {
isLastLook: boolean;
title: string;
isQuote: boolean;
onGasFreeTradeButtonClick: () => void;
protocol?: ProtocolType;
expiry?: string;
}

const SwapWidgetHeader: FC<SwapWidgetHeaderProps> = ({
isLastLook,
title,
isQuote,
onGasFreeTradeButtonClick,
protocol,
expiry,
}) => {
const { t } = useTranslation();
Expand All @@ -40,14 +39,14 @@ const SwapWidgetHeader: FC<SwapWidgetHeaderProps> = ({
{title}
</Title>

{protocol === "last-look-erc20" && isQuote && (
{isLastLook && isQuote && (
<Button onClick={onGasFreeTradeButtonClick}>
<StyledIcon name="star" iconSize={0.875} />
{t("orders.gasFreeTrade")}
</Button>
)}

{protocol === "request-for-quote-erc20" && isQuote && (
{!isLastLook && isQuote && expiryTime && (
<Quote>
<NewQuoteText>{t("orders.newQuoteIn")}</NewQuoteText>
{expiryTime && <StyledTimer expiryTime={expiryTime} />}
Expand Down
15 changes: 11 additions & 4 deletions src/components/Toasts/ToastController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import {
SubmittedApprovalTransaction,
SubmittedDepositTransaction,
SubmittedTransaction,
SubmittedTransactionWithOrder,
SubmittedOrder,
SubmittedWithdrawTransaction,
SubmittedOrderUnderConsideration,
} from "../../entities/SubmittedTransaction/SubmittedTransaction";
import findEthOrTokenByAddress from "../../helpers/findEthOrTokenByAddress";
import { TransactionTypes } from "../../types/transactionTypes";
Expand All @@ -34,8 +35,7 @@ export const notifyTransaction = (
type === TransactionTypes.withdraw) &&
chainId
) {
const tx: SubmittedTransactionWithOrder =
transaction as SubmittedTransactionWithOrder;
const tx: SubmittedOrder = transaction as SubmittedOrder;
/* TODO: fix toaster for multiple tabs or apps
now that we have a listener, you can have multiple
tabs open that receives the same order event. Only one redux
Expand Down Expand Up @@ -140,7 +140,7 @@ export const notifyWithdrawal = (transaction: SubmittedWithdrawTransaction) => {
);
};

export const notifyOrder = (transaction: SubmittedTransactionWithOrder) => {
export const notifyOrder = (transaction: SubmittedOrder) => {
toast(
(t) => (
<TransactionToast
Expand Down Expand Up @@ -196,6 +196,13 @@ export const notifyOrderCreated = (order: FullOrderERC20) => {
);
};

export const notifyOrderExpiry = () => {
notifyError({
heading: i18n.t("orders.swapRejected"),
cta: i18n.t("orders.swapRejectedCallToAction"),
});
};

export const notifyCopySuccess = () => {
toast(
(t) => (
Expand Down
72 changes: 36 additions & 36 deletions src/components/Toasts/TransactionToast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import { TokenInfo } from "@airswap/utils";

import { formatUnits } from "ethers/lib/utils";

import { SubmittedTransaction } from "../../entities/SubmittedTransaction/SubmittedTransaction";
import {
SubmittedLastLookOrder,
SubmittedRFQOrder,
SubmittedTransaction,
} from "../../entities/SubmittedTransaction/SubmittedTransaction";
isApprovalTransaction,
isDepositTransaction,
isLastLookOrderTransaction,
isSubmittedOrder,
isWithdrawTransaction,
} from "../../entities/SubmittedTransaction/SubmittedTransactionHelpers";
import { TransactionTypes } from "../../types/transactionTypes";
import { InfoHeading } from "../Typography/Typography";
import {
Expand Down Expand Up @@ -62,6 +65,13 @@ const TransactionToast = ({
approvalToken,
}: TransactionToastProps) => {
const { t } = useTranslation();
const order =
isSubmittedOrder(transaction) ||
isWithdrawTransaction(transaction) ||
isDepositTransaction(transaction)
? transaction.order
: undefined;
const isApproval = isApprovalTransaction(transaction);

return (
<Container>
Expand All @@ -74,9 +84,7 @@ const TransactionToast = ({
</IconContainer>
<TextContainer>
<InfoHeading>
{type === TransactionTypes.order ||
type === TransactionTypes.deposit ||
type === TransactionTypes.withdraw
{!isApproval
? error
? t("toast.swapFail")
: t("toast.swapComplete")
Expand All @@ -86,37 +94,29 @@ const TransactionToast = ({
</InfoHeading>
<SwapAmounts>
{(() => {
if (
type === TransactionTypes.order ||
type === TransactionTypes.deposit ||
type === TransactionTypes.withdraw
) {
if (transaction && senderToken && signerToken) {
const tx =
transaction.protocol === "last-look-erc20"
? (transaction as SubmittedLastLookOrder)
: (transaction as SubmittedRFQOrder);
let translationKey = "wallet.transaction";
if (tx.protocol === "last-look-erc20") {
translationKey = "wallet.lastLookTransaction";
}
// @ts-ignore dynamic translation key
return t(translationKey, {
senderAmount: parseFloat(
Number(
formatUnits(tx.order.senderAmount, senderToken.decimals)
).toFixed(5)
),
senderToken: senderToken.symbol,
signerAmount: parseFloat(
Number(
formatUnits(tx.order.signerAmount, signerToken.decimals)
).toFixed(5)
),
signerToken: signerToken.symbol,
});
if (order && senderToken && signerToken) {
let translationKey = "wallet.transaction";
if (isLastLookOrderTransaction(transaction)) {
translationKey = "wallet.lastLookTransaction";
}

// @ts-ignore dynamic translation key
return t(translationKey, {
senderAmount: parseFloat(
Number(
formatUnits(order.senderAmount, senderToken.decimals)
).toFixed(5)
),
senderToken: senderToken.symbol,
signerAmount: parseFloat(
Number(
formatUnits(order.signerAmount, signerToken.decimals)
).toFixed(5)
),
signerToken: signerToken.symbol,
});
}

return t("toast.approve", { symbol: approvalToken?.symbol });
})()}
</SwapAmounts>
Expand Down
13 changes: 7 additions & 6 deletions src/components/TransactionsTab/TransactionsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { formatUnits } from "ethers/lib/utils";
import { AnimatePresence, useReducedMotion } from "framer-motion";

import { SubmittedTransaction } from "../../entities/SubmittedTransaction/SubmittedTransaction";
import { getSubmittedTransactionKey } from "../../entities/SubmittedTransaction/SubmittedTransactionHelpers";
import { BalancesState } from "../../features/balances/balancesSlice";
import useAddressOrEnsName from "../../hooks/useAddressOrEnsName";
import { useKeyPress } from "../../hooks/useKeyPress";
Expand Down Expand Up @@ -53,14 +54,14 @@ type TransactionsTabType = {
address: string;
chainId: number;
open: boolean;
protocolFee: number;
setTransactionsTabOpen: (x: boolean) => void;
onClearTransactionsChange: (value: ClearOrderType) => void;
/**
* Callback function for when disconnect button is clicked
*/
onDisconnectWalletClicked: () => void;
transactions: SubmittedTransaction[];
tokens: TokenInfo[];
balances: BalancesState;
isUnsupportedNetwork?: boolean;
};
Expand All @@ -69,11 +70,11 @@ const TransactionsTab = ({
address = "",
chainId,
open,
protocolFee,
setTransactionsTabOpen,
onClearTransactionsChange,
onDisconnectWalletClicked,
transactions = [],
tokens = [],
balances,
isUnsupportedNetwork = false,
}: TransactionsTabType) => {
Expand Down Expand Up @@ -225,9 +226,9 @@ const TransactionsTab = ({
<AnimatePresence initial={false}>
{pendingTransactions.map((transaction) => (
<AnimatedWalletTransaction
key={`${transaction.hash}-${transaction.nonce}-${transaction.expiry}-pending`}
key={getSubmittedTransactionKey(transaction)}
protocolFee={protocolFee}
transaction={transaction}
tokens={tokens}
chainId={chainId!}
/>
))}
Expand All @@ -243,9 +244,9 @@ const TransactionsTab = ({
<AnimatePresence initial={false}>
{completedTransactions.map((transaction) => (
<AnimatedWalletTransaction
key={`${transaction.hash}-${transaction.nonce}-${transaction.expiry}`}
key={getSubmittedTransactionKey(transaction)}
protocolFee={protocolFee}
transaction={transaction}
tokens={tokens}
chainId={chainId!}
/>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,14 @@ import { walletTransactionHeight } from "../WalletTransaction/WalletTransaction.
import { Container } from "./AnimatedWalletTransaction.styles";

interface AnimatedWalletTransactionProps {
/**
* The parent object of SubmittedOrder and SubmittedApproval
*/
protocolFee: number;
transaction: SubmittedTransaction;
/**
* All token metadata
*/
tokens: TokenInfo[];
/**
* chainId of current Ethereum net
*/
chainId: number;
}

const AnimatedWalletTransaction = ({
protocolFee,
transaction,
tokens,
chainId,
}: AnimatedWalletTransactionProps) => {
const theme = useTheme();
Expand Down Expand Up @@ -71,6 +62,7 @@ const AnimatedWalletTransaction = ({
<WalletTransaction
animate={{ borderColor: theme.colors.borderGrey }}
initial={!transactionTooOld && { borderColor: theme.colors.white }}
protocolFee={protocolFee}
transition={{
delay: heightAnimationDuration,
duration: borderAnimationDuration,
Expand Down
Loading

0 comments on commit fc81ada

Please sign in to comment.