diff --git a/src/app/pages/swap/components/swap-asset-dialog/components/use-swap-asset-list.tsx b/src/app/pages/swap/components/swap-asset-dialog/components/use-swap-asset-list.tsx
index 0d226e2c14..e648025b7e 100644
--- a/src/app/pages/swap/components/swap-asset-dialog/components/use-swap-asset-list.tsx
+++ b/src/app/pages/swap/components/swap-asset-dialog/components/use-swap-asset-list.tsx
@@ -15,6 +15,7 @@ import {
import type { SwapFormValues } from '@shared/models/form.model';
import { RouteUrls } from '@shared/route-urls';
+// import { bitflow } from '@shared/utils/bitflow-sdk';
import { useSwapContext } from '@app/pages/swap/swap.context';
import type { SwapAssetListProps } from './swap-asset-list';
@@ -28,24 +29,36 @@ export function useSwapAssetList({ assets, type }: SwapAssetListProps) {
const isBaseList = type === 'base';
const isQuoteList = type === 'quote';
- const selectableAssets = assets.filter(
- asset =>
- (isBaseList && asset.name !== values.swapAssetQuote?.name) ||
- (isQuoteList && asset.name !== values.swapAssetBase?.name)
- );
+ // async function getBtcToken() {
+ // // const tokens = await bitflow.getAvailableTokens();
+ // // console.log(tokens.filter(token => token.tokenId === 'token-xbtc'));
+ // const result = await bitflow.getQuoteForRoute('token-stx', 'token-xbtc', 1);
+ // console.log(result);
+ // }
+
+ // Filter out selected asset from selectable assets
+ const selectableAssets = assets
+ .filter(
+ asset =>
+ (isBaseList && asset.name !== values.swapAssetQuote?.name) ||
+ (isQuoteList && asset.name !== values.swapAssetBase?.name)
+ )
+ // Only show sBTC as quote option if BTC is selected as base
+ .filter(
+ asset =>
+ isBaseList ||
+ (isQuoteList && values.swapAssetBase?.name !== 'BTC') ||
+ (isQuoteList && values.swapAssetBase?.name === 'BTC' && asset.name === 'sBTC')
+ );
const onSelectBaseAsset = useCallback(
- (baseAsset: SwapAsset, quoteAsset?: SwapAsset) => {
+ (baseAsset: SwapAsset) => {
void setFieldValue('swapAssetBase', baseAsset);
// Handle bridge assets
if (baseAsset.name === 'BTC') {
onSetIsCrossChainSwap(true);
return navigate(RouteUrls.Swap.replace(':base', baseAsset.name).replace(':quote', 'sBTC'));
}
- if (quoteAsset?.name === 'sBTC') {
- void setFieldValue('swapAssetQuote', undefined);
- return navigate(RouteUrls.Swap.replace(':base', baseAsset.name).replace(':quote', ''));
- }
// Handle swap assets
onSetIsCrossChainSwap(false);
navigate(RouteUrls.Swap.replace(':base', baseAsset.name).replace(':quote', quote ?? ''));
@@ -54,29 +67,20 @@ export function useSwapAssetList({ assets, type }: SwapAssetListProps) {
);
const onSelectQuoteAsset = useCallback(
- (quoteAsset: SwapAsset, baseAsset?: SwapAsset) => {
+ (quoteAsset: SwapAsset) => {
void setFieldValue('swapAssetQuote', quoteAsset);
setFieldError('swapAssetQuote', undefined);
- // Handle bridge assets
- if (isQuoteList && quoteAsset.name === 'sBTC') {
- onSetIsCrossChainSwap(true);
- return navigate(RouteUrls.Swap.replace(':base', 'BTC').replace(':quote', quoteAsset.name));
- }
- if (isQuoteList && baseAsset?.name === 'BTC') {
- return navigate(RouteUrls.Swap.replace(':base', 'STX').replace(':quote', quoteAsset.name));
- }
- // Handle swap assets
- onSetIsCrossChainSwap(false);
navigate(RouteUrls.Swap.replace(':base', base ?? '').replace(':quote', quoteAsset.name));
},
- [base, isQuoteList, navigate, onSetIsCrossChainSwap, setFieldError, setFieldValue]
+ [base, navigate, setFieldError, setFieldValue]
);
const onFetchQuoteAmount = useCallback(
async (baseAsset: SwapAsset, quoteAsset: SwapAsset) => {
+ // await getBtcToken();
const quoteAmount = await fetchQuoteAmount(baseAsset, quoteAsset, values.swapAmountBase);
- // Handle race condition; make sure quote amount is 1:1
- if (baseAsset.name === 'BTC' || quoteAsset.name === 'sBTC') {
+ // Handle race condition; make sure quote amount is 1:1 for BTC swap
+ if (baseAsset.name === 'BTC') {
void setFieldValue('swapAmountQuote', values.swapAmountBase);
return;
}
@@ -103,12 +107,12 @@ export function useSwapAssetList({ assets, type }: SwapAssetListProps) {
if (isBaseList) {
baseAsset = asset;
quoteAsset = values.swapAssetQuote;
- onSelectBaseAsset(baseAsset, quoteAsset);
+ onSelectBaseAsset(baseAsset);
}
if (isQuoteList) {
baseAsset = values.swapAssetBase;
quoteAsset = asset;
- onSelectQuoteAsset(quoteAsset, baseAsset);
+ onSelectQuoteAsset(quoteAsset);
}
if (baseAsset && quoteAsset && values.swapAmountBase) {
await onFetchQuoteAmount(baseAsset, quoteAsset);
diff --git a/src/app/pages/swap/components/swap-asset-select/swap-asset-select-quote.tsx b/src/app/pages/swap/components/swap-asset-select/swap-asset-select-quote.tsx
index f5a8b27683..d9cda93070 100644
--- a/src/app/pages/swap/components/swap-asset-select/swap-asset-select-quote.tsx
+++ b/src/app/pages/swap/components/swap-asset-select/swap-asset-select-quote.tsx
@@ -18,7 +18,7 @@ import { SwapAmountField } from './components/swap-amount-field';
import { SwapAssetSelectLayout } from './components/swap-asset-select.layout';
export function SwapAssetSelectQuote() {
- const { isFetchingExchangeRate } = useSwapContext();
+ const { isCrossChainSwap, isFetchingExchangeRate } = useSwapContext();
const [amountField] = useField('swapAmountQuote');
const [assetField] = useField('swapAssetQuote');
const navigate = useSwapNavigate();
@@ -37,7 +37,7 @@ export function SwapAssetSelectQuote() {
icon={assetField.value?.icon}
name="swapAmountQuote"
onSelectAsset={() => navigate(RouteUrls.SwapAssetSelectQuote)}
- showToggle={assetField.value?.name !== 'sBTC'}
+ showToggle={!isCrossChainSwap}
swapAmountInput={
isFetchingExchangeRate ? (
diff --git a/src/app/pages/swap/hooks/use-bitflow-swap.tsx b/src/app/pages/swap/hooks/use-bitflow-swap.tsx
index 4e2185ad92..8aced38615 100644
--- a/src/app/pages/swap/hooks/use-bitflow-swap.tsx
+++ b/src/app/pages/swap/hooks/use-bitflow-swap.tsx
@@ -2,7 +2,7 @@ import { useCallback, useMemo, useState } from 'react';
import type { RouteQuote } from 'bitflow-sdk';
-import type { SwapAsset } from '@leather.io/query';
+import { type SwapAsset } from '@leather.io/query';
import { migratePositiveAssetBalancesToTop } from '@leather.io/utils';
import { logger } from '@shared/logger';
@@ -22,17 +22,19 @@ export function useBitflowSwap() {
const address = useCurrentStacksAccountAddress();
const { data: bitflowSwapAssets = [] } = useBitflowSwappableAssets(address);
- // Bridge assets
+ // Bridge assets; to remove once supported by Bitflow api
const createBtcAsset = useBtcSwapAsset();
const createSbtcAsset = useSbtcSwapAsset();
+ const btcAsset = createBtcAsset();
+ const sbtcAsset = createSbtcAsset();
const swappableAssetsBase = useMemo(
- () => [createBtcAsset(), ...migratePositiveAssetBalancesToTop(bitflowSwapAssets)],
- [bitflowSwapAssets, createBtcAsset]
+ () => [btcAsset, sbtcAsset, ...migratePositiveAssetBalancesToTop(bitflowSwapAssets)],
+ [bitflowSwapAssets, btcAsset, sbtcAsset]
);
const swappableAssetsQuote = useMemo(
- () => [createSbtcAsset(), ...bitflowSwapAssets],
- [bitflowSwapAssets, createSbtcAsset]
+ () => [sbtcAsset, ...bitflowSwapAssets],
+ [bitflowSwapAssets, sbtcAsset]
);
const fetchRouteQuote = useCallback(
@@ -42,10 +44,20 @@ export function useBitflowSwap() {
baseAmount: string
): Promise => {
if (!baseAmount || !base || !quote || isCrossChainSwap) return;
+ let baseTokenId = base.tokenId;
+ let quoteTokenId = quote.tokenId;
+ // Temporarily handle sBTC exchange rate; force as BTC
+ // TODO: Remove once Bitflow supports sBTC exchange rate
+ if (base.tokenId === 'token-sbtc') {
+ baseTokenId = 'token-xbtc';
+ }
+ if (quote.tokenId === 'token-sbtc') {
+ quoteTokenId = 'token-xbtc';
+ }
try {
const result = await bitflow.getQuoteForRoute(
- base.tokenId,
- quote.tokenId,
+ baseTokenId,
+ quoteTokenId,
Number(baseAmount)
);
if (!result.bestRoute) {