diff --git a/src/app/features/container/container.tsx b/src/app/features/container/container.tsx
index ab925cf0238..4379f003915 100644
--- a/src/app/features/container/container.tsx
+++ b/src/app/features/container/container.tsx
@@ -69,9 +69,11 @@ export function Container() {
const displayHeader = !isLandingPage(pathname) && !isNoHeaderPopup(pathname);
const isSessionLocked = getIsSessionLocked(pathname);
+ // TODO: Refactor? This is very hard to manage with dynamic routes. Temporarily
+ // added a fix to catch the swap route: '/swap/:base/:quote?'
function getOnGoBackLocation(pathname: RouteUrls) {
+ if (pathname.includes('/swap')) return navigate(RouteUrls.Home);
switch (pathname) {
- case RouteUrls.Swap:
case RouteUrls.Fund.replace(':currency', 'STX'):
case RouteUrls.Fund.replace(':currency', 'BTC'):
case RouteUrls.SendCryptoAssetForm.replace(':symbol', 'stx'):
diff --git a/src/app/pages/home/components/account-actions.tsx b/src/app/pages/home/components/account-actions.tsx
index e672502ca1b..9fbc32d8e0c 100644
--- a/src/app/pages/home/components/account-actions.tsx
+++ b/src/app/pages/home/components/account-actions.tsx
@@ -53,7 +53,7 @@ export function AccountActions() {
data-testid={HomePageSelectors.SwapBtn}
icon={}
label="Swap"
- onClick={() => navigate(RouteUrls.Swap)}
+ onClick={() => navigate(RouteUrls.Swap.replace(':base', 'STX').replace(':quote', ''))}
/>
),
[ChainID.Testnet]: null,
diff --git a/src/app/pages/swap/alex-swap-container.tsx b/src/app/pages/swap/alex-swap-container.tsx
index 0107298857c..0b19faf9676 100644
--- a/src/app/pages/swap/alex-swap-container.tsx
+++ b/src/app/pages/swap/alex-swap-container.tsx
@@ -1,5 +1,5 @@
import { useMemo, useState } from 'react';
-import { Outlet, useNavigate } from 'react-router-dom';
+import { Outlet } from 'react-router-dom';
import { bytesToHex } from '@stacks/common';
import { ContractCallPayload, TransactionTypes } from '@stacks/connect';
@@ -30,6 +30,7 @@ import { useAlexBroadcastSwap } from './hooks/use-alex-broadcast-swap';
import { oneHundredMillion, useAlexSwap } from './hooks/use-alex-swap';
import { useStacksBroadcastSwap } from './hooks/use-stacks-broadcast-swap';
import { SwapAsset, SwapFormValues } from './hooks/use-swap-form';
+import { useSwapNavigate } from './hooks/use-swap-navigate';
import { SwapContext, SwapProvider } from './swap.context';
import {
defaultSwapFee,
@@ -41,7 +42,7 @@ export const alexSwapRoutes = generateSwapRoutes();
function AlexSwapContainer() {
const [isSendingMax, setIsSendingMax] = useState(false);
- const navigate = useNavigate();
+ const navigate = useSwapNavigate();
const { setIsLoading } = useLoading(LoadingKeys.SUBMIT_SWAP_TRANSACTION);
const currentAccount = useCurrentStacksAccount();
const generateUnsignedTx = useGenerateStacksContractCallUnsignedTx();
@@ -78,14 +79,14 @@ function AlexSwapContainer() {
);
async function onSubmitSwapForReview(values: SwapFormValues) {
- if (isUndefined(values.swapAssetFrom) || isUndefined(values.swapAssetTo)) {
+ if (isUndefined(values.swapAssetBase) || isUndefined(values.swapAssetQuote)) {
logger.error('Error submitting swap for review');
return;
}
const [router, lpFee] = await Promise.all([
- alex.getRouter(values.swapAssetFrom.currency, values.swapAssetTo.currency),
- alex.getFeeRate(values.swapAssetFrom.currency, values.swapAssetTo.currency),
+ alex.getRouter(values.swapAssetBase.currency, values.swapAssetQuote.currency),
+ alex.getFeeRate(values.swapAssetBase.currency, values.swapAssetQuote.currency),
]);
onSetSwapSubmissionData({
@@ -100,10 +101,10 @@ function AlexSwapContainer() {
.filter(isDefined),
slippage,
sponsored: isSponsoredByAlex,
- swapAmountFrom: values.swapAmountFrom,
- swapAmountTo: values.swapAmountTo,
- swapAssetFrom: values.swapAssetFrom,
- swapAssetTo: values.swapAssetTo,
+ swapAmountBase: values.swapAmountBase,
+ swapAmountQuote: values.swapAmountQuote,
+ swapAssetBase: values.swapAssetBase,
+ swapAssetQuote: values.swapAssetQuote,
timestamp: new Date().toISOString(),
});
@@ -117,8 +118,8 @@ function AlexSwapContainer() {
}
if (
- isUndefined(swapSubmissionData.swapAssetFrom) ||
- isUndefined(swapSubmissionData.swapAssetTo)
+ isUndefined(swapSubmissionData.swapAssetBase) ||
+ isUndefined(swapSubmissionData.swapAssetQuote)
) {
logger.error('No assets selected to perform swap');
return;
@@ -127,14 +128,14 @@ function AlexSwapContainer() {
setIsLoading();
const fromAmount = BigInt(
- new BigNumber(swapSubmissionData.swapAmountFrom)
+ new BigNumber(swapSubmissionData.swapAmountBase)
.multipliedBy(oneHundredMillion)
.dp(0)
.toString()
);
const minToAmount = BigInt(
- new BigNumber(swapSubmissionData.swapAmountTo)
+ new BigNumber(swapSubmissionData.swapAmountQuote)
.multipliedBy(oneHundredMillion)
.multipliedBy(new BigNumber(1).minus(slippage))
.dp(0)
@@ -143,8 +144,8 @@ function AlexSwapContainer() {
const tx = alex.runSwap(
currentAccount?.address,
- swapSubmissionData.swapAssetFrom.currency,
- swapSubmissionData.swapAssetTo.currency,
+ swapSubmissionData.swapAssetBase.currency,
+ swapSubmissionData.swapAssetQuote.currency,
fromAmount,
minToAmount,
swapSubmissionData.router.map(x => x.currency)
@@ -197,8 +198,8 @@ function AlexSwapContainer() {
onSetIsSendingMax: value => setIsSendingMax(value),
onSubmitSwapForReview,
onSubmitSwap,
- swappableAssetsFrom: migratePositiveBalancesToTop(swappableAssets),
- swappableAssetsTo: swappableAssets,
+ swappableAssetsBase: migratePositiveBalancesToTop(swappableAssets),
+ swappableAssetsQuote: swappableAssets,
swapSubmissionData,
};
diff --git a/src/app/pages/swap/components/swap-choose-asset/components/swap-asset-item.tsx b/src/app/pages/swap/components/swap-asset-dialog/components/swap-asset-item.tsx
similarity index 94%
rename from src/app/pages/swap/components/swap-choose-asset/components/swap-asset-item.tsx
rename to src/app/pages/swap/components/swap-asset-dialog/components/swap-asset-item.tsx
index 8e56372da2b..951e4b7c7ab 100644
--- a/src/app/pages/swap/components/swap-choose-asset/components/swap-asset-item.tsx
+++ b/src/app/pages/swap/components/swap-asset-dialog/components/swap-asset-item.tsx
@@ -22,7 +22,7 @@ export function SwapAssetItem({ asset, onClick }: SwapAssetItemProps) {
const fallback = getAvatarFallback(asset.name);
return (
-
+
diff --git a/src/app/pages/swap/components/swap-choose-asset/components/swap-asset-list.tsx b/src/app/pages/swap/components/swap-asset-dialog/components/swap-asset-list.tsx
similarity index 56%
rename from src/app/pages/swap/components/swap-choose-asset/components/swap-asset-list.tsx
rename to src/app/pages/swap/components/swap-asset-dialog/components/swap-asset-list.tsx
index c7870c93e52..736c2152b17 100644
--- a/src/app/pages/swap/components/swap-choose-asset/components/swap-asset-list.tsx
+++ b/src/app/pages/swap/components/swap-asset-dialog/components/swap-asset-list.tsx
@@ -1,4 +1,4 @@
-import { useNavigate } from 'react-router-dom';
+import { useNavigate, useParams } from 'react-router-dom';
import { SwapSelectors } from '@tests/selectors/swap.selectors';
import BigNumber from 'bignumber.js';
@@ -6,6 +6,7 @@ import { useFormikContext } from 'formik';
import { Stack } from 'leather-styles/jsx';
import { createMoney } from '@shared/models/money.model';
+import { RouteUrls } from '@shared/route-urls';
import { isUndefined } from '@shared/utils';
import { convertAmountToFractionalUnit } from '@app/common/money/calculate-money';
@@ -13,46 +14,46 @@ import { formatMoneyWithoutSymbol } from '@app/common/money/format-money';
import { useSwapContext } from '@app/pages/swap/swap.context';
import { SwapAsset, SwapFormValues } from '../../../hooks/use-swap-form';
-import { useSwapChooseAssetState } from '../swap-choose-asset';
import { SwapAssetItem } from './swap-asset-item';
interface SwapAssetList {
assets: SwapAsset[];
+ type: string;
}
-export function SwapAssetList({ assets }: SwapAssetList) {
+export function SwapAssetList({ assets, type }: SwapAssetList) {
const { fetchToAmount } = useSwapContext();
- const { swapListType } = useSwapChooseAssetState();
const { setFieldError, setFieldValue, values } = useFormikContext();
const navigate = useNavigate();
-
- const isFromList = swapListType === 'from';
- const isToList = swapListType === 'to';
+ const { base, quote } = useParams();
+ const isBaseList = type === 'base';
+ const isQuoteList = type === 'quote';
const selectableAssets = assets.filter(
asset =>
- (isFromList && asset.name !== values.swapAssetTo?.name) ||
- (isToList && asset.name !== values.swapAssetFrom?.name)
+ (isBaseList && asset.name !== values.swapAssetQuote?.name) ||
+ (isQuoteList && asset.name !== values.swapAssetBase?.name)
);
- async function onChooseAsset(asset: SwapAsset) {
+ async function onSelectAsset(asset: SwapAsset) {
let from: SwapAsset | undefined;
let to: SwapAsset | undefined;
- if (isFromList) {
+ if (isBaseList) {
from = asset;
- to = values.swapAssetTo;
- await setFieldValue('swapAssetFrom', asset);
- } else if (isToList) {
- from = values.swapAssetFrom;
+ to = values.swapAssetQuote;
+ await setFieldValue('swapAssetBase', asset);
+ navigate(RouteUrls.Swap.replace(':base', from.name).replace(':quote', quote ?? ''));
+ } else if (isQuoteList) {
+ from = values.swapAssetBase;
to = asset;
- await setFieldValue('swapAssetTo', asset);
- setFieldError('swapAssetTo', undefined);
+ await setFieldValue('swapAssetQuote', asset);
+ setFieldError('swapAssetQuote', undefined);
+ navigate(RouteUrls.Swap.replace(':base', base ?? '').replace(':quote', to.name));
}
- navigate(-1);
- if (from && to && values.swapAmountFrom) {
- const toAmount = await fetchToAmount(from, to, values.swapAmountFrom);
+ if (from && to && values.swapAmountBase) {
+ const toAmount = await fetchToAmount(from, to, values.swapAmountBase);
if (isUndefined(toAmount)) {
- await setFieldValue('swapAmountTo', '');
+ await setFieldValue('swapAmountQuote', '');
return;
}
const toAmountAsMoney = createMoney(
@@ -60,18 +61,18 @@ export function SwapAssetList({ assets }: SwapAssetList) {
to?.balance.symbol ?? '',
to?.balance.decimals
);
- await setFieldValue('swapAmountTo', formatMoneyWithoutSymbol(toAmountAsMoney));
- setFieldError('swapAmountTo', undefined);
+ await setFieldValue('swapAmountQuote', formatMoneyWithoutSymbol(toAmountAsMoney));
+ setFieldError('swapAmountQuote', undefined);
}
}
return (
-
+
{selectableAssets.map(asset => (
onChooseAsset(asset)}
+ onClick={() => onSelectAsset(asset)}
/>
))}
diff --git a/src/app/pages/swap/components/swap-asset-dialog/swap-asset-dialog-base.tsx b/src/app/pages/swap/components/swap-asset-dialog/swap-asset-dialog-base.tsx
new file mode 100644
index 00000000000..2db2e43070e
--- /dev/null
+++ b/src/app/pages/swap/components/swap-asset-dialog/swap-asset-dialog-base.tsx
@@ -0,0 +1,33 @@
+import { RouteUrls } from '@shared/route-urls';
+
+import { Dialog } from '@app/ui/components/containers/dialog/dialog';
+import { Header } from '@app/ui/components/containers/headers/header';
+
+import { useSwapNavigate } from '../../hooks/use-swap-navigate';
+import { useSwapContext } from '../../swap.context';
+import { SwapAssetList } from './components/swap-asset-list';
+
+export function SwapAssetDialogBase() {
+ const { swappableAssetsBase } = useSwapContext();
+ const navigate = useSwapNavigate();
+
+ return (
+
+ );
+}
diff --git a/src/app/pages/swap/components/swap-asset-dialog/swap-asset-dialog-quote.tsx b/src/app/pages/swap/components/swap-asset-dialog/swap-asset-dialog-quote.tsx
new file mode 100644
index 00000000000..dffce78d4a0
--- /dev/null
+++ b/src/app/pages/swap/components/swap-asset-dialog/swap-asset-dialog-quote.tsx
@@ -0,0 +1,33 @@
+import { RouteUrls } from '@shared/route-urls';
+
+import { Dialog } from '@app/ui/components/containers/dialog/dialog';
+import { Header } from '@app/ui/components/containers/headers/header';
+
+import { useSwapNavigate } from '../../hooks/use-swap-navigate';
+import { useSwapContext } from '../../swap.context';
+import { SwapAssetList } from './components/swap-asset-list';
+
+export function SwapAssetDialogQuote() {
+ const { swappableAssetsQuote } = useSwapContext();
+ const navigate = useSwapNavigate();
+
+ return (
+
+ );
+}
diff --git a/src/app/pages/swap/components/select-asset-trigger-button.tsx b/src/app/pages/swap/components/swap-asset-select/components/select-asset-trigger-button.tsx
similarity index 94%
rename from src/app/pages/swap/components/select-asset-trigger-button.tsx
rename to src/app/pages/swap/components/swap-asset-select/components/select-asset-trigger-button.tsx
index d51a9747d3a..c76294f5e38 100644
--- a/src/app/pages/swap/components/select-asset-trigger-button.tsx
+++ b/src/app/pages/swap/components/swap-asset-select/components/select-asset-trigger-button.tsx
@@ -9,13 +9,13 @@ import { ChevronDownIcon } from '@app/ui/icons/chevron-down-icon';
interface SelectAssetTriggerButtonProps {
icon?: string;
name: string;
- onChooseAsset(): void;
+ onSelectAsset(): void;
symbol: string;
}
export function SelectAssetTriggerButton({
icon,
name,
- onChooseAsset,
+ onSelectAsset,
symbol,
}: SelectAssetTriggerButtonProps) {
const [field] = useField(name);
@@ -24,7 +24,7 @@ export function SelectAssetTriggerButton({
return (