Commit 8c372c61 authored by Jack Short's avatar Jack Short Committed by GitHub

fix: fixing pwat routing edge case (#5987)

* feat: implementing graphql endpoint

* changing from hook to function call

* initial gql routing works

* feat: initial pwatRouting setup

* sending correct amount

* removing console

* it is working

* sufficient balance

* 0 if no inputCurrency

* removing value to send if erc20

* removing console

* permit2 optional flag

* removing not necessary stuff

* mobile fixes

* overlay needs to be here

* changing swap amount to pool reserves

* refactoring routing logic

* no route found button state

* better price loading for insufficient liquidity

* refactoring graphql routing code

* overflow

* initial comments

* resetting bag status on input currency change

* locking

* done

* remove helper text for eth

* fix: pay with any token routing bug

* reordering button

* zindex

* price updated

* keeping debounce
parent 8c0998bd
...@@ -66,7 +66,7 @@ const BagContainer = styled.div<{ raiseZIndex: boolean; isProfilePage: boolean } ...@@ -66,7 +66,7 @@ const BagContainer = styled.div<{ raiseZIndex: boolean; isProfilePage: boolean }
border-radius: 16px; border-radius: 16px;
box-shadow: ${({ theme }) => theme.shallowShadow}; box-shadow: ${({ theme }) => theme.shallowShadow};
z-index: ${({ raiseZIndex, isProfilePage }) => z-index: ${({ raiseZIndex, isProfilePage }) =>
raiseZIndex ? (isProfilePage ? Z_INDEX.modalOverTooltip : Z_INDEX.modalBackdrop) : 3}; raiseZIndex ? (isProfilePage ? Z_INDEX.modalOverTooltip : Z_INDEX.modalBackdrop + 2) : 3};
@media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.sm}px`}) { @media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.sm}px`}) {
right: 0px; right: 0px;
...@@ -232,7 +232,8 @@ const Bag = () => { ...@@ -232,7 +232,8 @@ const Bag = () => {
const { route, routeResponse } = buildRouteResponse(data.nftRoute, !!tokenTradeInput) const { route, routeResponse } = buildRouteResponse(data.nftRoute, !!tokenTradeInput)
const updatedAssets = combineBuyItemsWithTxRoute(itemsToBuy, route) const { hasPriceAdjustment, updatedAssets } = combineBuyItemsWithTxRoute(itemsToBuy, route)
const shouldRefetchCalldata = hasPriceAdjustment && !!tokenTradeInput
const fetchedPriceChangedAssets = updatedAssets const fetchedPriceChangedAssets = updatedAssets
.filter((asset) => asset.updatedPriceInfo) .filter((asset) => asset.updatedPriceInfo)
...@@ -266,9 +267,13 @@ const Bag = () => { ...@@ -266,9 +267,13 @@ const Bag = () => {
if (hasAssets) { if (hasAssets) {
if (!shouldReview) { if (!shouldReview) {
if (shouldRefetchCalldata) {
setBagStatus(BagStatus.CONFIRM_QUOTE)
} else {
purchaseAssets(routeResponse) purchaseAssets(routeResponse)
setBagStatus(BagStatus.CONFIRMING_IN_WALLET) setBagStatus(BagStatus.CONFIRMING_IN_WALLET)
shouldLock = true shouldLock = true
}
} else if (!hasAssetsInReview) setBagStatus(BagStatus.CONFIRM_REVIEW) } else if (!hasAssetsInReview) setBagStatus(BagStatus.CONFIRM_REVIEW)
else { else {
setBagStatus(BagStatus.IN_REVIEW) setBagStatus(BagStatus.IN_REVIEW)
...@@ -289,7 +294,7 @@ const Bag = () => { ...@@ -289,7 +294,7 @@ const Bag = () => {
}) })
) )
const updatedAssets = combineBuyItemsWithTxRoute(itemsToBuy, routeData.route) const { updatedAssets } = combineBuyItemsWithTxRoute(itemsToBuy, routeData.route)
const fetchedPriceChangedAssets = updatedAssets const fetchedPriceChangedAssets = updatedAssets
.filter((asset) => asset.updatedPriceInfo) .filter((asset) => asset.updatedPriceInfo)
...@@ -405,12 +410,7 @@ const Bag = () => { ...@@ -405,12 +410,7 @@ const Bag = () => {
{isProfilePage ? <ProfileBagContent /> : <BagContent />} {isProfilePage ? <ProfileBagContent /> : <BagContent />}
</Column> </Column>
{hasAssetsToShow && !isProfilePage && ( {hasAssetsToShow && !isProfilePage && (
<BagFooter <BagFooter totalEthPrice={totalEthPrice} fetchAssets={fetchAssets} eventProperties={eventProperties} />
totalEthPrice={totalEthPrice}
bagStatus={bagStatus}
fetchAssets={fetchAssets}
eventProperties={eventProperties}
/>
)} )}
{isSellingAssets && isProfilePage && ( {isSellingAssets && isProfilePage && (
<Box <Box
......
...@@ -77,11 +77,11 @@ const TotalColumn = styled(Column)` ...@@ -77,11 +77,11 @@ const TotalColumn = styled(Column)`
const WarningIcon = styled(AlertTriangle)` const WarningIcon = styled(AlertTriangle)`
width: 14px; width: 14px;
margin-right: 4px; margin-right: 4px;
color: ${({ theme }) => theme.accentWarning}; color: inherit;
` `
const WarningText = styled(ThemedText.BodyPrimary)` const WarningText = styled(ThemedText.BodyPrimary)<{ $color: string }>`
align-items: center; align-items: center;
color: ${({ theme }) => theme.accentWarning}; color: ${({ $color }) => $color};
display: flex; display: flex;
justify-content: center; justify-content: center;
margin-bottom: 10px !important; margin-bottom: 10px !important;
...@@ -173,22 +173,22 @@ const ActionButton = ({ ...@@ -173,22 +173,22 @@ const ActionButton = ({
) )
} }
const Warning = ({ children }: PropsWithChildren<unknown>) => { interface HelperTextProps {
color: string
}
const Warning = ({ color, children }: PropsWithChildren<HelperTextProps>) => {
if (!children) { if (!children) {
return null return null
} }
return ( return (
<WarningText fontSize="14px" lineHeight="20px"> <WarningText fontSize="14px" lineHeight="20px" $color={color}>
<WarningIcon /> <WarningIcon />
{children} {children}
</WarningText> </WarningText>
) )
} }
interface HelperTextProps {
color: string
}
const Helper = ({ children, color }: PropsWithChildren<HelperTextProps>) => { const Helper = ({ children, color }: PropsWithChildren<HelperTextProps>) => {
if (!children) { if (!children) {
return null return null
...@@ -281,7 +281,6 @@ const FiatValue = ({ ...@@ -281,7 +281,6 @@ const FiatValue = ({
interface BagFooterProps { interface BagFooterProps {
totalEthPrice: BigNumber totalEthPrice: BigNumber
bagStatus: BagStatus
fetchAssets: () => void fetchAssets: () => void
eventProperties: Record<string, unknown> eventProperties: Record<string, unknown>
} }
...@@ -293,7 +292,7 @@ const PENDING_BAG_STATUSES = [ ...@@ -293,7 +292,7 @@ const PENDING_BAG_STATUSES = [
BagStatus.PROCESSING_TRANSACTION, BagStatus.PROCESSING_TRANSACTION,
] ]
export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperties }: BagFooterProps) => { export const BagFooter = ({ totalEthPrice, fetchAssets, eventProperties }: BagFooterProps) => {
const toggleWalletModal = useToggleWalletModal() const toggleWalletModal = useToggleWalletModal()
const theme = useTheme() const theme = useTheme()
const { account, chainId, connector } = useWeb3React() const { account, chainId, connector } = useWeb3React()
...@@ -309,11 +308,13 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti ...@@ -309,11 +308,13 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti
const { const {
isLocked: bagIsLocked, isLocked: bagIsLocked,
bagStatus,
setBagExpanded, setBagExpanded,
setBagStatus, setBagStatus,
} = useBag( } = useBag(
({ isLocked, setBagExpanded, setBagStatus }) => ({ ({ isLocked, bagStatus, setBagExpanded, setBagStatus }) => ({
isLocked, isLocked,
bagStatus,
setBagExpanded, setBagExpanded,
setBagStatus, setBagStatus,
}), }),
...@@ -389,12 +390,22 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti ...@@ -389,12 +390,22 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti
setBagStatus(BagStatus.ADDING_TO_BAG) setBagStatus(BagStatus.ADDING_TO_BAG)
}, [inputCurrency, setBagStatus]) }, [inputCurrency, setBagStatus])
const { buttonText, buttonTextColor, disabled, warningText, helperText, helperTextColor, handleClick, buttonColor } = const {
useMemo(() => { buttonText,
buttonTextColor,
disabled,
warningText,
warningTextColor,
helperText,
helperTextColor,
handleClick,
buttonColor,
} = useMemo(() => {
let handleClick = fetchAssets let handleClick = fetchAssets
let buttonText = <Trans>Something went wrong</Trans> let buttonText = <Trans>Something went wrong</Trans>
let disabled = true let disabled = true
let warningText = undefined let warningText = undefined
let warningTextColor = theme.accentWarning
let helperText = undefined let helperText = undefined
let helperTextColor = theme.textSecondary let helperTextColor = theme.textSecondary
let buttonColor = theme.accentAction let buttonColor = theme.accentAction
...@@ -418,6 +429,12 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti ...@@ -418,6 +429,12 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti
} }
disabled = false disabled = false
buttonText = <Trans>Connect wallet</Trans> buttonText = <Trans>Connect wallet</Trans>
} else if (bagStatus === BagStatus.FETCHING_FINAL_ROUTE || bagStatus === BagStatus.CONFIRMING_IN_WALLET) {
disabled = true
buttonText = <Trans>Proceed in wallet</Trans>
} else if (bagStatus === BagStatus.PROCESSING_TRANSACTION) {
disabled = true
buttonText = <Trans>Transaction pending</Trans>
} else if (usingPayWithAnyToken && tradeState !== TradeState.VALID) { } else if (usingPayWithAnyToken && tradeState !== TradeState.VALID) {
disabled = true disabled = true
buttonText = <Trans>Fetching Route</Trans> buttonText = <Trans>Fetching Route</Trans>
...@@ -446,12 +463,11 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti ...@@ -446,12 +463,11 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti
helperText = <Trans>An approval is needed to use this token. </Trans> helperText = <Trans>An approval is needed to use this token. </Trans>
buttonText = <Trans>Approve</Trans> buttonText = <Trans>Approve</Trans>
} }
} else if (bagStatus === BagStatus.FETCHING_FINAL_ROUTE || bagStatus === BagStatus.CONFIRMING_IN_WALLET) { } else if (bagStatus === BagStatus.CONFIRM_QUOTE) {
disabled = true disabled = false
buttonText = <Trans>Proceed in wallet</Trans> warningTextColor = theme.accentAction
} else if (bagStatus === BagStatus.PROCESSING_TRANSACTION) { warningText = <Trans>Price updated</Trans>
disabled = true buttonText = <Trans>Pay</Trans>
buttonText = <Trans>Transaction pending</Trans>
} else if (priceImpactWarning && priceImpactColor) { } else if (priceImpactWarning && priceImpactColor) {
disabled = false disabled = false
buttonColor = priceImpactColor buttonColor = priceImpactColor
...@@ -461,9 +477,7 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti ...@@ -461,9 +477,7 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti
} else if (sufficientBalance === true) { } else if (sufficientBalance === true) {
disabled = false disabled = false
buttonText = <Trans>Pay</Trans> buttonText = <Trans>Pay</Trans>
helperText = usingPayWithAnyToken ? ( helperText = usingPayWithAnyToken ? <Trans>Refunds for unavailable items will be given in ETH</Trans> : undefined
<Trans>Refunds for unavailable items will be given in ETH</Trans>
) : undefined
} }
return { return {
...@@ -471,6 +485,7 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti ...@@ -471,6 +485,7 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti
buttonTextColor, buttonTextColor,
disabled, disabled,
warningText, warningText,
warningTextColor,
helperText, helperText,
helperTextColor, helperTextColor,
handleClick, handleClick,
...@@ -478,6 +493,7 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti ...@@ -478,6 +493,7 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti
} }
}, [ }, [
fetchAssets, fetchAssets,
theme.accentWarning,
theme.textSecondary, theme.textSecondary,
theme.accentAction, theme.accentAction,
theme.accentTextLightPrimary, theme.accentTextLightPrimary,
...@@ -574,7 +590,7 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti ...@@ -574,7 +590,7 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti
properties={{ ...traceEventProperties }} properties={{ ...traceEventProperties }}
shouldLogImpression={connected && !disabled} shouldLogImpression={connected && !disabled}
> >
<Warning>{warningText}</Warning> <Warning color={warningTextColor}>{warningText}</Warning>
<Helper color={helperTextColor}>{helperText}</Helper> <Helper color={helperTextColor}>{helperText}</Helper>
<ActionButton <ActionButton
onClick={handleClick} onClick={handleClick}
......
...@@ -16,6 +16,6 @@ export const overlay = style([ ...@@ -16,6 +16,6 @@ export const overlay = style([
{ {
opacity: 0.72, opacity: 0.72,
overflow: 'hidden', overflow: 'hidden',
zIndex: Z_INDEX.modalBackdrop - 1, zIndex: Z_INDEX.modalBackdrop + 1,
}, },
]) ])
...@@ -143,7 +143,7 @@ const findNFTsPurchased = ( ...@@ -143,7 +143,7 @@ const findNFTsPurchased = (
) )
}) })
return combineBuyItemsWithTxRoute(transferredItems, txRoute) return combineBuyItemsWithTxRoute(transferredItems, txRoute).updatedAssets
} }
const findNFTsNotPurchased = (toBuy: GenieAsset[], nftsPurchased: UpdatedGenieAsset[]) => { const findNFTsNotPurchased = (toBuy: GenieAsset[], nftsPurchased: UpdatedGenieAsset[]) => {
......
...@@ -96,4 +96,5 @@ export enum BagStatus { ...@@ -96,4 +96,5 @@ export enum BagStatus {
FETCHING_FINAL_ROUTE = 'Fetching final route', FETCHING_FINAL_ROUTE = 'Fetching final route',
CONFIRMING_IN_WALLET = 'Confirming in wallet', CONFIRMING_IN_WALLET = 'Confirming in wallet',
PROCESSING_TRANSACTION = 'Processing', PROCESSING_TRANSACTION = 'Processing',
CONFIRM_QUOTE = 'Confirm quote',
} }
...@@ -19,8 +19,11 @@ const isTheSame = (item: GenieAsset, routeAsset: BuyItem | PriceInfo) => { ...@@ -19,8 +19,11 @@ const isTheSame = (item: GenieAsset, routeAsset: BuyItem | PriceInfo) => {
} }
} }
const isPriceDiff = (oldPrice: string, newPrice: string) => { const getPriceDiff = (oldPrice: string, newPrice: string): { hasPriceDiff: boolean; hasVisiblePriceDiff: boolean } => {
return formatWeiToDecimal(oldPrice) !== formatWeiToDecimal(newPrice) const hasPriceDiff = oldPrice !== newPrice
const hasVisiblePriceDiff = formatWeiToDecimal(oldPrice) !== formatWeiToDecimal(newPrice)
return { hasPriceDiff, hasVisiblePriceDiff }
} }
const isAveragePriceOfPooledAssets = ( const isAveragePriceOfPooledAssets = (
...@@ -28,7 +31,7 @@ const isAveragePriceOfPooledAssets = ( ...@@ -28,7 +31,7 @@ const isAveragePriceOfPooledAssets = (
numberOfAssetsInPool: number, numberOfAssetsInPool: number,
expectedPrice: string expectedPrice: string
): boolean => { ): boolean => {
return !isPriceDiff(calcAvgGroupPoolPrice(asset, numberOfAssetsInPool), expectedPrice) return !getPriceDiff(calcAvgGroupPoolPrice(asset, numberOfAssetsInPool), expectedPrice).hasVisiblePriceDiff
} }
const isAveragedPrice = ( const isAveragedPrice = (
...@@ -74,11 +77,11 @@ const itemInRouteAndSamePool = ( ...@@ -74,11 +77,11 @@ const itemInRouteAndSamePool = (
export const combineBuyItemsWithTxRoute = ( export const combineBuyItemsWithTxRoute = (
items: UpdatedGenieAsset[], items: UpdatedGenieAsset[],
txRoute?: RoutingItem[] txRoute?: RoutingItem[]
): UpdatedGenieAsset[] => { ): { hasPriceAdjustment: boolean; updatedAssets: UpdatedGenieAsset[] } => {
return items.map((item) => { let hasPriceAdjustment = false
const updatedAssets = items.map((item) => {
const route = getRouteForItem(item, txRoute) const route = getRouteForItem(item, txRoute)
// if the item is not found in txRoute, it means it's no longer for sale
if (txRoute && !route) { if (txRoute && !route) {
return { return {
...item, ...item,
...@@ -86,15 +89,21 @@ export const combineBuyItemsWithTxRoute = ( ...@@ -86,15 +89,21 @@ export const combineBuyItemsWithTxRoute = (
} }
} }
const newPriceInfo = item.updatedPriceInfo ? item.updatedPriceInfo : item.priceInfo let newPriceInfo = item.updatedPriceInfo ? item.updatedPriceInfo : item.priceInfo
// if the price changed
if (route && 'priceInfo' in route.assetOut) { if (route && 'priceInfo' in route.assetOut) {
if (isPriceDiff(newPriceInfo.basePrice, route.assetOut.priceInfo.basePrice)) { const { hasPriceDiff, hasVisiblePriceDiff } = getPriceDiff(
newPriceInfo.basePrice,
route.assetOut.priceInfo.basePrice
)
newPriceInfo = route.assetOut.priceInfo
hasPriceAdjustment = hasPriceDiff
if (hasVisiblePriceDiff) {
if (!isAveragedPrice(item, items, route, txRoute)) { if (!isAveragedPrice(item, items, route, txRoute)) {
return { return {
...item, ...item,
updatedPriceInfo: route.assetOut.priceInfo, updatedPriceInfo: newPriceInfo,
} }
} }
} }
...@@ -107,4 +116,6 @@ export const combineBuyItemsWithTxRoute = ( ...@@ -107,4 +116,6 @@ export const combineBuyItemsWithTxRoute = (
orderSource: route && 'orderSource' in route.assetOut ? route.assetOut.orderSource : undefined, orderSource: route && 'orderSource' in route.assetOut ? route.assetOut.orderSource : undefined,
} }
}) })
return { hasPriceAdjustment, updatedAssets }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment