Skip to content

Commit

Permalink
feat: btc to sbtc swap
Browse files Browse the repository at this point in the history
  • Loading branch information
fbwoolf committed Dec 4, 2024
1 parent dff2e4f commit e66dc21
Show file tree
Hide file tree
Showing 21 changed files with 351 additions and 138 deletions.
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,11 @@
"@leather.io/constants": "0.13.5",
"@leather.io/crypto": "1.6.14",
"@leather.io/models": "0.22.0",
"@leather.io/query": "2.23.3",
"@leather.io/query": "2.26.1",
"@leather.io/stacks": "1.4.0",
"@leather.io/tokens": "0.12.1",
"@leather.io/ui": "1.39.0",
"@leather.io/utils": "0.20.0",
"@leather.io/utils": "0.21.1",
"@ledgerhq/hw-transport-webusb": "6.27.19",
"@noble/hashes": "1.5.0",
"@noble/secp256k1": "2.1.0",
Expand Down Expand Up @@ -193,7 +193,6 @@
"@types/lodash.uniqby": "4.7.7",
"@typescript-eslint/eslint-plugin": "7.5.0",
"@zondax/ledger-stacks": "1.0.4",
"alex-sdk": "2.1.4",
"are-passive-events-supported": "1.1.1",
"argon2-browser": "1.18.0",
"assert": "2.1.0",
Expand Down
99 changes: 84 additions & 15 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 0 additions & 6 deletions src/app/common/asset-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@ import {
isMoneyGreaterThanZero,
} from '@leather.io/utils';

export function migratePositiveAssetBalancesToTop<T extends { balance: Money }[]>(assets: T) {
const assetsWithPositiveBalance = assets.filter(asset => asset.balance.amount.isGreaterThan(0));
const assetsWithZeroBalance = assets.filter(asset => asset.balance.amount.isEqualTo(0));
return [...assetsWithPositiveBalance, ...assetsWithZeroBalance] as T;
}

export function convertAssetBalanceToFiat<
T extends { balance: Money | null; marketData: MarketData | null },
>(asset: T) {
Expand Down
2 changes: 1 addition & 1 deletion src/app/common/hooks/use-calculate-sip10-fiat-value.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { useConfigSbtc } from '@app/query/common/remote-config/remote-config.que

import { getPrincipalFromContractId } from '../utils';

function castBitcoinMarketDataToSbtcMarketData(bitcoinMarketData: MarketData) {
export function castBitcoinMarketDataToSbtcMarketData(bitcoinMarketData: MarketData) {
return createMarketData(
createMarketPair('sBTC', 'USD'),
createMoney(bitcoinMarketData.price.amount.toNumber(), 'USD')
Expand Down
11 changes: 10 additions & 1 deletion src/app/pages/home/components/account-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,16 @@ export function AccountActions() {
</Box>
</BasicTooltip>
),
[ChainID.Testnet]: null,
// Temporary for sBTC testing
[ChainID.Testnet]: (
<IconButton
data-testid={HomePageSelectors.SwapBtn}
disabled={swapsBtnDisabled}
icon={<ArrowsRepeatLeftRightIcon />}
label="Swap"
onClick={() => navigate(RouteUrls.Swap.replace(':base', 'STX').replace(':quote', ''))}
/>
),
})}
</Flex>
);
Expand Down
2 changes: 1 addition & 1 deletion src/app/pages/receive/components/receive-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { truncateMiddle } from '@leather.io/utils';
interface ReceiveItemProps {
address?: string;
dataTestId?: string;
icon: React.JSX.Element;
icon: React.ReactNode;
onCopyAddress(): void;
onClickQrCode?(): void;
title: string;
Expand Down
13 changes: 9 additions & 4 deletions src/app/pages/receive/components/receive-tokens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
StxAvatarIcon,
defaultFallbackDelay,
} from '@leather.io/ui';
import { isString } from '@leather.io/utils';

import { copyToClipboard } from '@app/common/utils/copy-to-clipboard';
import { useToast } from '@app/features/toasts/use-toast';
Expand Down Expand Up @@ -116,10 +117,14 @@ export function ReceiveTokens({
key={asset.name}
address={asset.address}
icon={
<Avatar.Root>
<Avatar.Image alt={asset.fallback} src={asset.icon} />
<Avatar.Fallback delayMs={defaultFallbackDelay}>{asset.fallback}</Avatar.Fallback>
</Avatar.Root>
isString(asset.icon) ? (
<Avatar.Root>
<Avatar.Image alt={asset.fallback} src={asset.icon} />
<Avatar.Fallback delayMs={defaultFallbackDelay}>{asset.fallback}</Avatar.Fallback>
</Avatar.Root>
) : (
asset.icon
)
}
// onClickQrCode={() => null}
onCopyAddress={async () => {
Expand Down
24 changes: 17 additions & 7 deletions src/app/pages/swap/bitflow-swap-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ import {
} from '@stacks/transactions';

import { defaultSwapFee } from '@leather.io/query';
import { isDefined, isError, isUndefined } from '@leather.io/utils';
import {
isDefined,
isError,
isUndefined,
migratePositiveAssetBalancesToTop,
} from '@leather.io/utils';

import { logger } from '@shared/logger';
import { RouteUrls } from '@shared/route-urls';
import { bitflow } from '@shared/utils/bitflow-sdk';

import { migratePositiveAssetBalancesToTop } from '@app/common/asset-utils';
import { LoadingKeys, useLoading } from '@app/common/hooks/use-loading';
import { Content, Page } from '@app/components/layout';
import { PageHeader } from '@app/features/container/headers/page.header';
Expand All @@ -29,6 +33,7 @@ import { estimateLiquidityFee, formatDexPathItem } from './bitflow-swap.utils';
import { SwapForm } from './components/swap-form';
import { generateSwapRoutes } from './generate-swap-routes';
import { useBitflowSwap } from './hooks/use-bitflow-swap';
import { useBtcSwapAsset, useSBtcSwapAsset } from './hooks/use-sbtc-bridge-assets';
import { useStacksBroadcastSwap } from './hooks/use-stacks-broadcast-swap';
import { SwapFormValues } from './hooks/use-swap-form';
import { useSwapNavigate } from './hooks/use-swap-navigate';
Expand All @@ -38,22 +43,27 @@ export const bitflowSwapRoutes = generateSwapRoutes(<BitflowSwapContainer />);

function BitflowSwapContainer() {
const [isSendingMax, setIsSendingMax] = useState(false);
const [isPreparingSwapReview, setIsPreparingSwapReview] = useState(false);
const navigate = useNavigate();
const swapNavigate = useSwapNavigate();
const { setIsLoading, setIsIdle, isLoading } = useLoading(LoadingKeys.SUBMIT_SWAP_TRANSACTION);
const currentAccount = useCurrentStacksAccount();
const generateUnsignedTx = useGenerateStacksContractCallUnsignedTx();
const signTx = useSignStacksTransaction();
const broadcastStacksSwap = useStacksBroadcastSwap();
const [isPreparingSwapReview, setIsPreparingSwapReview] = useState(false);

// Bridge assets
const btcAsset = useBtcSwapAsset();
const sBtcAsset = useSBtcSwapAsset();

const {
fetchRouteQuote,
fetchQuoteAmount,
isFetchingExchangeRate,
onSetIsFetchingExchangeRate,
onSetSwapSubmissionData,
slippage,
swapAssets,
bitflowSwapAssets,
swapSubmissionData,
} = useBitflowSwap();

Expand Down Expand Up @@ -81,7 +91,7 @@ function BitflowSwapContainer() {
protocol: 'Bitflow',
dexPath: routeQuote.route.dex_path.map(formatDexPathItem),
router: routeQuote.route.token_path
.map(x => swapAssets.find(asset => asset.currency === x))
.map(x => bitflowSwapAssets.find(asset => asset.tokenId === x))
.filter(isDefined),
slippage,
sponsored: false,
Expand Down Expand Up @@ -185,8 +195,8 @@ function BitflowSwapContainer() {
onSetIsSendingMax: value => setIsSendingMax(value),
onSubmitSwapForReview,
onSubmitSwap,
swappableAssetsBase: migratePositiveAssetBalancesToTop(swapAssets),
swappableAssetsQuote: swapAssets,
swappableAssetsBase: [...[btcAsset], ...migratePositiveAssetBalancesToTop(bitflowSwapAssets)],
swappableAssetsQuote: [...[sBtcAsset], ...bitflowSwapAssets],
swapSubmissionData,
};

Expand Down
Loading

0 comments on commit e66dc21

Please sign in to comment.