Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add using skipClient.balances #259

Merged
merged 20 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions packages/widget-v2/src/components/AssetChainInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type AssetChainInputProps = {
selectedAsset?: AssetAtom;
priceChangePercentage?: number;
isWaitingToUpdateInputValue?: boolean;
badPriceWarning?: boolean;
};

export const AssetChainInput = ({
Expand All @@ -33,10 +34,13 @@ export const AssetChainInput = ({
handleChangeChain,
priceChangePercentage,
isWaitingToUpdateInputValue,
badPriceWarning,
}: AssetChainInputProps) => {
const theme = useTheme();
const [showPriceChangePercentage, setShowPriceChangePercentage] =
const [_showPriceChangePercentage, setShowPriceChangePercentage] =
useState(false);

const showPriceChangePercentage = _showPriceChangePercentage || badPriceWarning;
const assetDetails = useGetAssetDetails({
assetDenom: selectedAsset?.denom,
amount: value,
Expand Down Expand Up @@ -170,6 +174,7 @@ export const AssetChainInput = ({
{priceChangePercentage ? (
<Row align="center" gap={6}>
<SmallTextButton
color={badPriceWarning ? theme.error.text : undefined}
onMouseEnter={() => setShowPriceChangePercentage(true)}
onMouseLeave={() => setShowPriceChangePercentage(false)}
>
Expand All @@ -180,14 +185,16 @@ export const AssetChainInput = ({
direction={(priceChangePercentage ?? 0) > 0 ? "up" : "down"}
style={{ scale: showPriceChangePercentage ? "1" : "0.7" }}
/>
{showPriceChangePercentage && (
{(showPriceChangePercentage) && (
<SmallText color={priceChangeColor}>
{priceChangePercentage}%
</SmallText>
)}
</Row>
) : (
<SmallText>{assetDetails.formattedUsdAmount ?? 0}</SmallText>
<SmallText color={badPriceWarning ? theme.error.text : undefined}>
{assetDetails.formattedUsdAmount ?? 0}
</SmallText>
)}
{assetDetails?.chainName ? (
<GhostButton
Expand All @@ -213,15 +220,17 @@ const StyledAssetChainInputWrapper = styled(Column)`
background-color: ${(props) => props.theme.primary.background.normal};
`;

const StyledInput = styled.input <{ isWaitingToUpdateInputValue?: boolean }>`
const StyledInput = styled.input<{ isWaitingToUpdateInputValue?: boolean }>`
all: unset;
font-size: 38px;
font-weight: 300;
width: 100%;
color: ${(props) => props.theme.primary.text.normal};
background-color: ${(props) => props.theme.primary.background.normal};

${(props) => props.isWaitingToUpdateInputValue && "animation: pulse 2s cubic-bezier(.4,0,.6,1) infinite;"}
${(props) =>
props.isWaitingToUpdateInputValue &&
"animation: pulse 2s cubic-bezier(.4,0,.6,1) infinite;"}
@keyframes pulse {
0% {
opacity: 0.5;
Expand Down
2 changes: 2 additions & 0 deletions packages/widget-v2/src/components/Typography.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export const SmallText = styled.p<TextProps>`
color: ${({ theme }) => theme.primary.text.lowContrast};
margin: 0;
font-size: 13px;
line-height: 13px;
${textProps}
`;

Expand All @@ -50,6 +51,7 @@ export const SmallTextButton = styled(SmallText).attrs({ as: "button" })`
export const Text = styled(SmallText)`
color: ${(props) => props.theme.primary.text.normal};
font-size: 20px;
line-height: 20px;
font-weight: 500;
${textProps}
`;
Expand Down
4 changes: 3 additions & 1 deletion packages/widget-v2/src/constants/skipClientDefault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ export const endpointOptions = {
},
};

export const apiURL = `${appUrl}/api/widget/skip`;
export const devApiUrl = "https://api.dev.skip.build";

export const prodApiUrl = `${appUrl}/api/widget/skip`;
22 changes: 21 additions & 1 deletion packages/widget-v2/src/pages/SwapPage/SwapDetailModal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { css, styled } from "styled-components";
import { css, styled, useTheme } from "styled-components";
import { createModal, ModalProps } from "@/components/Modal";
import { Column, Row, Spacer } from "@/components/Layout";
import { SmallText } from "@/components/Typography";
Expand All @@ -16,6 +16,7 @@ import { getBrandButtonTextColor } from "@/utils/colors";
import { QuestionMarkIcon } from "@/icons/QuestionMarkIcon";

export const SwapDetailModal = createModal((modalProps: ModalProps) => {
const theme = useTheme();
const { data: route } = useAtomValue(skipRouteAtom);
const { data: chains } = useAtomValue(skipChainsAtom);
const [swapSettings, setSwapSettings] = useAtom(swapSettingsAtom);
Expand All @@ -28,6 +29,10 @@ export const SwapDetailModal = createModal((modalProps: ModalProps) => {

const clientOperations = route && getClientOperations(route.operations);

const usesEvmInOperations = useMemo(() => {
return clientOperations?.find(operation => operation.toChainID === "1");
}, [clientOperations]);

const axelarTransferOperation = useMemo(() => {
if (!clientOperations) return;
return clientOperations?.find(
Expand Down Expand Up @@ -199,6 +204,15 @@ export const SwapDetailModal = createModal((modalProps: ModalProps) => {
</Column>
)}

{
usesEvmInOperations && <StyledEvmWarningMessage>
<SwapDetailText color={theme.warning.text}>
This swap contains at least one EVM chain, so it might take longer.
<br /> Read more about common finality times.
</SwapDetailText>
</StyledEvmWarningMessage>
}

<SwapDetailText justify="space-between">
<SwapPageFooterItems showRouteInfo />
</SwapDetailText>
Expand Down Expand Up @@ -242,6 +256,12 @@ const SwapDetailText = styled(Row).attrs({
letter-spacing: 0.26px;
`;

const StyledEvmWarningMessage = styled.div`
padding: 12px;
border-radius: 5px;
background-color: ${({ theme }) => theme.warning.background};
`;

const Tooltip = styled(SmallText).attrs({
normalTextColor: true,
})`
Expand Down
137 changes: 103 additions & 34 deletions packages/widget-v2/src/pages/SwapPage/SwapPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useMemo, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useAtom, useAtomValue, useSetAtom } from "jotai";
import { AssetChainInput } from "@/components/AssetChainInput";
import { Column, Row } from "@/components/Layout";
Expand All @@ -9,6 +9,7 @@ import {
getChainsContainingAsset,
skipChainsAtom,
skipRouteAtom,
skipBalancesRequestAtom,
} from "@/state/skipClient";
import {
sourceAssetAtom,
Expand All @@ -32,6 +33,11 @@ import { currentPageAtom, Routes } from "@/state/router";
import { GhostButton, GhostButtonProps } from "@/components/Button";
import { ConnectedWalletModal } from "@/modals/ConnectedWalletModal/ConnectedWalletModal";
import styled, { css } from "styled-components";
import {
useInsufficientSourceBalance,
useSetMaxAmount,
} from "./useSetMaxAmount";
import { useSourceBalance } from "./useSourceBalance";

export const SwapPage = () => {
const [container, setContainer] = useState<HTMLDivElement>();
Expand All @@ -42,7 +48,6 @@ export const SwapPage = () => {
const [isWaitingForNewRoute] = useAtom(isWaitingForNewRouteAtom);
const [destinationAsset, setDestinationAsset] = useAtom(destinationAssetAtom);
const [swapDirection] = useAtom(swapDirectionAtom);
const setSwapDirection = useSetAtom(swapDirectionAtom);
const [{ data: assets }] = useAtom(skipAssetsAtom);
const [{ data: chains }] = useAtom(skipChainsAtom);
const {
Expand All @@ -55,9 +60,38 @@ export const SwapPage = () => {
const selectWalletmodal = useModal(WalletSelectorModal);
const setSwapExecutionState = useSetAtom(swapExecutionStateAtom);
const setCurrentPage = useSetAtom(currentPageAtom);
const setSkipBalancesRequest = useSetAtom(skipBalancesRequestAtom);
const connectedWalletModal = useModal(ConnectedWalletModal);
const sourceBalance = useSourceBalance();
const insufficientBalance = useInsufficientSourceBalance();

const handleMaxButton = useSetMaxAmount();

const sourceAccount = useAccount(sourceAsset?.chainID);

useEffect(() => {
if (isWaitingForNewRoute) return;
if (!sourceAsset || !sourceAccount) return;
const { chainID, denom } = sourceAsset;
const { address } = sourceAccount;
if (!denom || !chainID || !address) return;

setSkipBalancesRequest({
chains: {
[chainID]: {
address,
denoms: [denom],
},
},
});
}, [
isWaitingForNewRoute,
setSkipBalancesRequest,
sourceAccount,
sourceAsset,
sourceAsset?.chainID,
]);

const sourceDetails = useGetAssetDetails({
assetDenom: sourceAsset?.denom,
amount: sourceAsset?.amount,
Expand All @@ -70,6 +104,19 @@ export const SwapPage = () => {
chainId: destinationAsset?.chainID,
});

const formattedBalance = useMemo(() => {
if (sourceBalance === undefined) return "";

const amount = sourceBalance?.amount;
let formattedBalanceAmount = sourceBalance?.formattedAmount;

if (amount === "0") {
formattedBalanceAmount = amount;
}

return `${formattedBalanceAmount} ${sourceDetails?.symbol}`;
}, [sourceBalance, sourceDetails?.symbol]);

const chainsContainingSourceAsset = useMemo(() => {
if (!chains || !assets || !sourceAsset?.symbol) return;
const result = getChainsContainingAsset(
Expand Down Expand Up @@ -158,14 +205,19 @@ export const SwapPage = () => {

const swapButton = useMemo(() => {
if (isWaitingForNewRoute) {
return <MainButton label="Finding Best Route..." loading={true} />;
return <MainButton label="Finding Best Route..." loading />;
}

if (isRouteError) {
return <MainButton label={routeError.message} disabled={true} />;
return <MainButton label={routeError.message} disabled />;
}

if (sourceAccount?.address) {
if (insufficientBalance) {
return (
<MainButton label="Insufficient balance" disabled icon={ICONS.swap} />
);
}
return (
<MainButton
label="Swap"
Expand Down Expand Up @@ -194,6 +246,7 @@ export const SwapPage = () => {
}, [
isWaitingForNewRoute,
isRouteError,
insufficientBalance,
sourceAccount?.address,
sourceAsset?.chainID,
routeError?.message,
Expand Down Expand Up @@ -237,27 +290,47 @@ export const SwapPage = () => {
}}
rightContent={
sourceAccount && (
<Row gap={6} style={{
paddingRight: 13
}}>
<TransparentButton onClick={() => {
connectedWalletModal.show();
}} style={{
padding: "8px 13px",
alignItems: "center",
gap: 8
}}>
{sourceAccount && <img style={{ objectFit: "cover" }} src={sourceAccount?.wallet.logo} height={16} width={16} />}
125 ATOM
</TransparentButton>
<TransparentButton onClick={() => {
connectedWalletModal.show();
}} style={{
padding: "8px 13px",
alignItems: "center",
}}>
Max
</TransparentButton>
<Row
gap={6}
style={{
paddingRight: 13,
}}
>
{formattedBalance && (
<>
<TransparentButton
onClick={() => {
connectedWalletModal.show();
}}
style={{
padding: "8px 13px",
alignItems: "center",
gap: 8,
}}
>
{sourceAccount && (
<img
style={{ objectFit: "cover" }}
src={sourceAccount?.wallet.logo}
height={16}
width={16}
/>
)}
{formattedBalance}
</TransparentButton>

<TransparentButton
disabled={!sourceBalance || sourceBalance?.amount === "0"}
onClick={handleMaxButton}
style={{
padding: "8px 13px",
alignItems: "center",
}}
>
Max
</TransparentButton>
</>
)}
</Row>
)
}
Expand All @@ -271,10 +344,7 @@ export const SwapPage = () => {
swapDirection === "swap-out" && isWaitingForNewRoute
}
value={sourceAsset?.amount}
onChangeValue={(newValue) => {
setSourceAssetAmount(newValue);
setSwapDirection("swap-in");
}}
onChangeValue={setSourceAssetAmount}
/>
<SwapPageBridge />
<AssetChainInput
Expand All @@ -286,15 +356,14 @@ export const SwapPage = () => {
}
value={destinationAsset?.amount}
priceChangePercentage={priceChangePercentage}
onChangeValue={(newValue) => {
setDestinationAssetAmount(newValue);
setSwapDirection("swap-out");
}}
badPriceWarning={route?.warning?.type === "BAD_PRICE_WARNING"}
onChangeValue={setDestinationAssetAmount}
/>
</Column>
{swapButton}
<SwapPageFooter
showRouteInfo
disabled={isRouteError || isWaitingForNewRoute}
onClick={() =>
swapDetailsModal.show({
drawer: true,
Expand All @@ -304,7 +373,7 @@ export const SwapPage = () => {
})
}
/>
</Column >
</Column>
<div
id="swap-flow-settings-container"
ref={(element) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/widget-v2/src/pages/SwapPage/SwapPageBridge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const SwapPageBridge = () => {
const [spin, setSpin] = useState(false);
const invertSwap = useSetAtom(invertSwapAtom);
const onInvertSwap = () => {
invertSwap("swap-out");
invertSwap();

let spinTimeout = undefined;
clearTimeout(spinTimeout);
Expand Down
Loading
Loading