Skip to content

Commit

Permalink
refactor: swap sbtc for sip10 tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
fbwoolf committed Dec 11, 2024
1 parent 9d96828 commit 9b04dc2
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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 ?? ''));
Expand All @@ -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;
}
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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 ? (
<LoadingSpinner justifyContent="flex-end" size="sm" />
Expand Down
28 changes: 20 additions & 8 deletions src/app/pages/swap/hooks/use-bitflow-swap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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(
Expand All @@ -42,10 +44,20 @@ export function useBitflowSwap() {
baseAmount: string
): Promise<RouteQuote | undefined> => {
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) {
Expand Down

0 comments on commit 9b04dc2

Please sign in to comment.