Skip to content

Commit

Permalink
fix: disable ledger btc swap
Browse files Browse the repository at this point in the history
  • Loading branch information
fbwoolf committed Dec 18, 2024
1 parent d0c2efc commit cff46da
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 25 deletions.
19 changes: 15 additions & 4 deletions src/app/pages/swap/bitflow-swap-container.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useCallback, useState } from 'react';
import { Outlet, useNavigate } from 'react-router-dom';

import type { P2Ret } from '@scure/btc-signer/payment';
import { bytesToHex } from '@stacks/common';
import { type ContractCallPayload, TransactionTypes } from '@stacks/connect';
import {
Expand All @@ -19,11 +20,13 @@ import { bitflow } from '@shared/utils/bitflow-sdk';

import { LoadingKeys, useLoading } from '@app/common/hooks/use-loading';
import { Content, Page } from '@app/components/layout';
import { BitcoinNativeSegwitAccountLoader } from '@app/components/loaders/bitcoin-account-loader';
import { PageHeader } from '@app/features/container/headers/page.header';
import type {
SbtcSponsorshipEligibility,
TransactionBase,
} from '@app/query/sbtc/sponsored-transactions.query';
import type { Signer } from '@app/store/accounts/blockchain/bitcoin/bitcoin-signer';
import { useCurrentStacksAccount } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks';
import { useGenerateStacksContractCallUnsignedTx } from '@app/store/transactions/contract-call.hooks';
import { useSignStacksTransaction } from '@app/store/transactions/transaction.hooks';
Expand All @@ -38,9 +41,17 @@ import { useStacksBroadcastSwap } from './hooks/use-stacks-broadcast-swap';
import { useSwapNavigate } from './hooks/use-swap-navigate';
import { SwapContext, SwapProvider } from './swap.context';

export const bitflowSwapRoutes = generateSwapRoutes(<BitflowSwapContainer />);
// TODO: Refactor coupled Bitflow and Bitcoin swap containers, they should be separate
export const bitflowSwapRoutes = generateSwapRoutes(
<BitcoinNativeSegwitAccountLoader current fallback={<BitflowSwapContainer />}>
{signer => <BitflowSwapContainer btcSigner={signer} />}
</BitcoinNativeSegwitAccountLoader>
);

function BitflowSwapContainer() {
interface BitflowSwapContainerProps {
btcSigner?: Signer<P2Ret>;
}
function BitflowSwapContainer({ btcSigner }: BitflowSwapContainerProps) {
const [unsignedTx, setUnsignedTx] = useState<TransactionBase | undefined>();
const [isSendingMax, setIsSendingMax] = useState(false);
const [isPreparingSwapReview, setIsPreparingSwapReview] = useState(false);
Expand All @@ -51,7 +62,7 @@ function BitflowSwapContainer() {
const generateUnsignedTx = useGenerateStacksContractCallUnsignedTx();
const signTx = useSignStacksTransaction();
const broadcastStacksSwap = useStacksBroadcastSwap();
const { onDepositSbtc, onReviewDepositSbtc } = useSbtcDepositTransaction();
const { onDepositSbtc, onReviewDepositSbtc } = useSbtcDepositTransaction(btcSigner);

const [sponsorshipEligibility, setSponsorshipEligibility] = useState<
SbtcSponsorshipEligibility | undefined
Expand All @@ -72,7 +83,7 @@ function BitflowSwapContainer() {
swappableAssetsBase,
swappableAssetsQuote,
swapSubmissionData,
} = useBitflowSwap();
} = useBitflowSwap(btcSigner);

const onSubmitSwapForReview = useCallback(
async (values: SwapFormValues) => {
Expand Down
2 changes: 2 additions & 0 deletions src/app/pages/swap/generate-swap-routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Route } from 'react-router-dom';

import { RouteUrls } from '@shared/route-urls';

import { ledgerBitcoinTxSigningRoutes } from '@app/features/ledger/flows/bitcoin-tx-signing/ledger-bitcoin-sign-tx-container';
import { ledgerStacksTxSigningRoutes } from '@app/features/ledger/flows/stacks-tx-signing/ledger-sign-stacks-tx-container';
import { AccountGate } from '@app/routes/account-gate';

Expand All @@ -20,6 +21,7 @@ export function generateSwapRoutes(container: React.ReactNode) {
</Route>
<Route path={RouteUrls.SwapError} element={<SwapError />} />
<Route path={RouteUrls.SwapReview} element={<SwapReview />}>
{ledgerBitcoinTxSigningRoutes}
{ledgerStacksTxSigningRoutes}
</Route>
</Route>
Expand Down
13 changes: 9 additions & 4 deletions src/app/pages/swap/hooks/use-bitflow-swap.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useCallback, useMemo, useState } from 'react';

import type { P2Ret } from '@scure/btc-signer/payment';
import type { RouteQuote } from 'bitflow-sdk';

import { type SwapAsset } from '@leather.io/query';
Expand All @@ -9,7 +10,9 @@ import { logger } from '@shared/logger';
import { bitflow } from '@shared/utils/bitflow-sdk';

import { useConfigSbtc } from '@app/query/common/remote-config/remote-config.query';
import type { Signer } from '@app/store/accounts/blockchain/bitcoin/bitcoin-signer';
import { useCurrentStacksAccountAddress } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks';
import { useHasLedgerKeys } from '@app/store/ledger/ledger.selectors';

import { SwapSubmissionData } from '../swap.context';
import { useBitflowSwappableAssets } from './use-bitflow-swappable-assets';
Expand All @@ -26,22 +29,24 @@ function getBitflowSwappableAssetsWithSbtcAtTop(assets: SwapAsset[]) {
].filter(isDefined);
}

export function useBitflowSwap() {
export function useBitflowSwap(btcSigner?: Signer<P2Ret>) {
const [isCrossChainSwap, setIsCrossChainSwap] = useState(false);
const [swapSubmissionData, setSwapSubmissionData] = useState<SwapSubmissionData>();
const [slippage, _setSlippage] = useState(0.04);
const [isFetchingExchangeRate, setIsFetchingExchangeRate] = useState(false);
const address = useCurrentStacksAccountAddress();
const { data: bitflowSwapAssets = [] } = useBitflowSwappableAssets(address);
const { isSbtcEnabled } = useConfigSbtc();
const isLedger = useHasLedgerKeys();

const createBtcAsset = useBtcSwapAsset();
const createBtcAsset = useBtcSwapAsset(btcSigner);
const btcAsset = createBtcAsset();

const swappableAssetsBase = useMemo(() => {
if (!isSbtcEnabled) return migratePositiveAssetBalancesToTop(bitflowSwapAssets);
if (!isSbtcEnabled || !btcSigner || isLedger)
return migratePositiveAssetBalancesToTop(bitflowSwapAssets);
return [btcAsset, ...getBitflowSwappableAssetsWithSbtcAtTop(bitflowSwapAssets)];
}, [bitflowSwapAssets, btcAsset, isSbtcEnabled]);
}, [bitflowSwapAssets, btcAsset, btcSigner, isLedger, isSbtcEnabled]);

const swappableAssetsQuote = useMemo(() => {
if (!isSbtcEnabled) return bitflowSwapAssets;
Expand Down
8 changes: 4 additions & 4 deletions src/app/pages/swap/hooks/use-btc-bridge-asset.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { useCallback } from 'react';

import BtcAvatarIconSrc from '@assets/avatars/btc-avatar-icon.png';
import type { P2Ret } from '@scure/btc-signer/payment';

import { type SwapAsset, useCryptoCurrencyMarketDataMeanAverage } from '@leather.io/query';

import { useBtcCryptoAssetBalanceNativeSegwit } from '@app/query/bitcoin/balance/btc-balance-native-segwit.hooks';
import { useCurrentAccountNativeSegwitIndexZeroSigner } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
import type { Signer } from '@app/store/accounts/blockchain/bitcoin/bitcoin-signer';

export function useBtcSwapAsset() {
const nativeSegwitSigner = useCurrentAccountNativeSegwitIndexZeroSigner();
const currentBitcoinAddress = nativeSegwitSigner.address;
export function useBtcSwapAsset(btcSigner?: Signer<P2Ret>) {
const currentBitcoinAddress = btcSigner?.address ?? '';
const { balance } = useBtcCryptoAssetBalanceNativeSegwit(currentBitcoinAddress);
const bitcoinMarketData = useCryptoCurrencyMarketDataMeanAverage('BTC');

Expand Down
25 changes: 15 additions & 10 deletions src/app/pages/swap/hooks/use-sbtc-deposit-transaction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom';

import { bytesToHex } from '@noble/hashes/utils';
import * as btc from '@scure/btc-signer';
import type { P2TROut } from '@scure/btc-signer/payment';
import type { P2Ret, P2TROut } from '@scure/btc-signer/payment';
import {
MAINNET,
REGTEST,
Expand All @@ -29,7 +29,7 @@ import { useToast } from '@app/features/toasts/use-toast';
import { useCurrentNativeSegwitUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
import { useBreakOnNonCompliantEntity } from '@app/query/common/compliance-checker/compliance-checker.query';
import { useBitcoinScureLibNetworkConfig } from '@app/store/accounts/blockchain/bitcoin/bitcoin-keychain';
import { useCurrentAccountNativeSegwitIndexZeroSigner } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
import type { Signer } from '@app/store/accounts/blockchain/bitcoin/bitcoin-signer';
import { useCurrentStacksAccount } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks';
import { useCurrentNetwork } from '@app/store/networks/networks.selectors';

Expand Down Expand Up @@ -61,16 +61,17 @@ function getSbtcNetworkConfig(network: BitcoinNetworkModes) {
const clientMainnet = new SbtcApiClientMainnet();
const clientTestnet = new SbtcApiClientTestnet();

export function useSbtcDepositTransaction() {
export function useSbtcDepositTransaction(btcSigner?: Signer<P2Ret>) {
const toast = useToast();
const { setIsIdle } = useLoading(LoadingKeys.SUBMIT_SWAP_TRANSACTION);
const stacksAccount = useCurrentStacksAccount();
const { data: utxos } = useCurrentNativeSegwitUtxos();
const { data: feeRates } = useAverageBitcoinFeeRates();
const signer = useCurrentAccountNativeSegwitIndexZeroSigner();
const networkMode = useBitcoinScureLibNetworkConfig();
const navigate = useNavigate();
const network = useCurrentNetwork();
// TODO: Use with Ledger integration
// const sign = useSignBitcoinTx();

const client = useMemo(
() => (network.chain.bitcoin.mode === 'mainnet' ? clientMainnet : clientTestnet),
Expand All @@ -82,7 +83,7 @@ export function useSbtcDepositTransaction() {

return {
async onReviewDepositSbtc(swapData: SwapSubmissionData, isSendingMax: boolean) {
if (!stacksAccount || !utxos) return;
if (!stacksAccount || !utxos || !btcSigner) return;

try {
const deposit: SbtcDeposit = buildSbtcDepositTx({
Expand All @@ -92,7 +93,7 @@ export function useSbtcDepositTransaction() {
signersPublicKey: await client.fetchSignersPublicKey(),
maxSignerFee,
reclaimLockTime,
reclaimPublicKey: bytesToHex(signer.publicKey).slice(2),
reclaimPublicKey: bytesToHex(btcSigner.publicKey).slice(2),
});

const determineUtxosArgs = {
Expand All @@ -110,7 +111,7 @@ export function useSbtcDepositTransaction() {
? determineUtxosForSpendAll(determineUtxosArgs)
: determineUtxosForSpend(determineUtxosArgs);

const p2wpkh = btc.p2wpkh(signer.publicKey, networkMode);
const p2wpkh = btc.p2wpkh(btcSigner.publicKey, networkMode);

for (const input of inputs) {
deposit.transaction.addInput({
Expand All @@ -128,7 +129,11 @@ export function useSbtcDepositTransaction() {
outputs.forEach(output => {
// Add change output
if (!output.address) {
deposit.transaction.addOutputAddress(signer.address, BigInt(output.value), networkMode);
deposit.transaction.addOutputAddress(
btcSigner.address,
BigInt(output.value),
networkMode
);
return;
}
});
Expand All @@ -140,11 +145,11 @@ export function useSbtcDepositTransaction() {
}
},
async onDepositSbtc(swapSubmissionData: SwapSubmissionData) {
if (!stacksAccount) return;
if (!stacksAccount || !btcSigner) return;
const sBtcDeposit = swapSubmissionData.txData?.deposit as SbtcDeposit;

try {
signer.sign(sBtcDeposit.transaction);
btcSigner.sign(sBtcDeposit.transaction);
sBtcDeposit.transaction.finalize();
logger.info('Deposit', { deposit: sBtcDeposit });

Expand Down
6 changes: 3 additions & 3 deletions src/app/query/bitcoin/address/utxos-by-address.hooks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useNativeSegwitUtxosByAddress } from '@leather.io/query';

import { useCurrentAccountNativeSegwitIndexZeroSigner } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
import { useCurrentAccountNativeSegwitIndexZeroSignerNullable } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';

const defaultArgs = {
filterInscriptionUtxos: true,
Expand All @@ -15,8 +15,8 @@ const defaultArgs = {
export function useCurrentNativeSegwitUtxos(args = defaultArgs) {
const { filterInscriptionUtxos, filterPendingTxsUtxos, filterRunesUtxos } = args;

const nativeSegwitSigner = useCurrentAccountNativeSegwitIndexZeroSigner();
const address = nativeSegwitSigner.address;
const nativeSegwitSigner = useCurrentAccountNativeSegwitIndexZeroSignerNullable();
const address = nativeSegwitSigner?.address ?? '';

return useNativeSegwitUtxosByAddress({
address,
Expand Down

0 comments on commit cff46da

Please sign in to comment.