Skip to content

Commit

Permalink
Merge pull request #4878 from leather-wallet/release/monday
Browse files Browse the repository at this point in the history
Release/monday
  • Loading branch information
kyranjamie authored Jan 29, 2024
2 parents d556f70 + 68c557f commit 0c5d34b
Show file tree
Hide file tree
Showing 19 changed files with 149 additions and 123 deletions.
2 changes: 1 addition & 1 deletion config/wallet-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
},
"activeFiatProviders": {
"coinbase": {
"availableRegions": "inside-usa-only",
"availableRegions": "global",
"enabled": true,
"hasFastCheckoutProcess": true,
"hasTradingFees": true,
Expand Down
8 changes: 8 additions & 0 deletions src/app/common/api/fetch-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { analytics } from '@shared/utils/analytics';

const leatherHeaders: HeadersInit = {
'x-leather-version': VERSION,
'x-hiro-product': 'leather',
};

function isErrorCode(statusCode: number) {
Expand All @@ -30,6 +31,13 @@ export async function wrappedFetch(input: RequestInfo, init: RequestInit = {}) {
return resp;
}

axios.interceptors.request.use(request => {
if (request.url?.includes('hiro.so'))
Object.entries(leatherHeaders).forEach(([key, value]) => request.headers.set(key, value));

return request;
});

axios.interceptors.response.use(response => {
if (isErrorCode(response.status)) trackApiError(response.config.url ?? '', response.status);
return response;
Expand Down
20 changes: 6 additions & 14 deletions src/app/common/hooks/balance/btc/use-btc-balance.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,14 @@
import { useMemo } from 'react';

import BigNumber from 'bignumber.js';

import { createMoney } from '@shared/models/money.model';

import { baseCurrencyAmountInQuote, subtractMoney } from '@app/common/money/calculate-money';
import { baseCurrencyAmountInQuote } from '@app/common/money/calculate-money';
import { i18nFormatCurrency } from '@app/common/money/format-money';
import { createBitcoinCryptoCurrencyAssetTypeWrapper } from '@app/query/bitcoin/address/address.utils';
import { useBitcoinPendingTransactionsBalance } from '@app/query/bitcoin/address/transactions-by-address.hooks';
import { useNativeSegwitBalance } from '@app/query/bitcoin/balance/btc-native-segwit-balance.hooks';
import { useCryptoCurrencyMarketData } from '@app/query/common/market-data/market-data.hooks';

export function useBtcAssetBalance(btcAddress: string) {
const btcMarketData = useCryptoCurrencyMarketData('BTC');
const btcAssetBalance = useNativeSegwitBalance(btcAddress);
const { data: pendingBalance } = useBitcoinPendingTransactionsBalance(btcAddress);
const availableBalance = subtractMoney(
btcAssetBalance.balance,
pendingBalance ?? createMoney(new BigNumber(0), 'BTC')
);

return useMemo(
() => ({
Expand All @@ -27,11 +17,13 @@ export function useBtcAssetBalance(btcAddress: string) {
btcUsdBalance: i18nFormatCurrency(
baseCurrencyAmountInQuote(btcAssetBalance.balance, btcMarketData)
),
btcAvailableAssetBalance: createBitcoinCryptoCurrencyAssetTypeWrapper(availableBalance),
btcAvailableAssetBalance: createBitcoinCryptoCurrencyAssetTypeWrapper(
btcAssetBalance.balance
),
btcAvailableUsdBalance: i18nFormatCurrency(
baseCurrencyAmountInQuote(availableBalance, btcMarketData)
baseCurrencyAmountInQuote(btcAssetBalance.balance, btcMarketData)
),
}),
[btcAddress, btcAssetBalance, btcMarketData, availableBalance]
[btcAddress, btcAssetBalance, btcMarketData]
);
}
8 changes: 2 additions & 6 deletions src/app/common/hooks/use-transferable-asset-balances.hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,14 @@ import { useMemo } from 'react';

import type { AllTransferableCryptoAssetBalances } from '@shared/models/crypto-asset-balance.model';

import { useNativeSegwitBalance } from '@app/query/bitcoin/balance/btc-native-segwit-balance.hooks';
import { useTransferableStacksFungibleTokenAssetBalances } from '@app/query/stacks/balance/stacks-ft-balances.hooks';
import { createStacksCryptoCurrencyAssetTypeWrapper } from '@app/query/stacks/balance/stacks-ft-balances.utils';
import { useCurrentAccountNativeSegwitAddressIndexZero } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
import { useCurrentStacksAccount } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks';

import { useStxBalance } from './balance/stx/use-stx-balance';

export function useAllTransferableCryptoAssetBalances(): AllTransferableCryptoAssetBalances[] {
const account = useCurrentStacksAccount();
const currentBtcAddress = useCurrentAccountNativeSegwitAddressIndexZero();
const btcCryptoCurrencyAssetBalance = useNativeSegwitBalance(currentBtcAddress);

const { availableBalance: availableStxBalance } = useStxBalance();
const stxCryptoCurrencyAssetBalance = createStacksCryptoCurrencyAssetTypeWrapper(
Expand All @@ -24,6 +20,6 @@ export function useAllTransferableCryptoAssetBalances(): AllTransferableCryptoAs
);

return useMemo(() => {
return [btcCryptoCurrencyAssetBalance, stxCryptoCurrencyAssetBalance, ...stacksFtAssetBalances];
}, [btcCryptoCurrencyAssetBalance, stacksFtAssetBalances, stxCryptoCurrencyAssetBalance]);
return [stxCryptoCurrencyAssetBalance, ...stacksFtAssetBalances];
}, [stacksFtAssetBalances, stxCryptoCurrencyAssetBalance]);
}
13 changes: 13 additions & 0 deletions src/app/components/balance/bitcoin-balance-loader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { BitcoinCryptoCurrencyAssetBalance } from '@shared/models/crypto-asset-balance.model';

import { useNativeSegwitBalance } from '@app/query/bitcoin/balance/btc-native-segwit-balance.hooks';

interface BitcoinBalanceLoaderProps {
address: string;
children(balance: BitcoinCryptoCurrencyAssetBalance): React.ReactNode;
}

export function BitcoinBalanceLoader({ address, children }: BitcoinBalanceLoaderProps) {
const btcCryptoCurrencyAssetBalance = useNativeSegwitBalance(address);
return children(btcCryptoCurrencyAssetBalance);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
determineUtxosForSpend,
determineUtxosForSpendAll,
} from '@app/common/transactions/bitcoin/coinselect/local-coin-selection';
import { useCurrentNativeSegwitAccountSpendableUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
import { useCurrentNativeSegwitUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
import { useCurrentNativeSegwitAddressBalance } from '@app/query/bitcoin/balance/btc-native-segwit-balance.hooks';
import { useCryptoCurrencyMarketData } from '@app/query/common/market-data/market-data.hooks';

Expand All @@ -21,7 +21,7 @@ interface UseBitcoinCustomFeeArgs {
}
export function useBitcoinCustomFee({ amount, isSendingMax, recipient }: UseBitcoinCustomFeeArgs) {
const balance = useCurrentNativeSegwitAddressBalance();
const { data: utxos = [] } = useCurrentNativeSegwitAccountSpendableUtxos();
const { data: utxos = [] } = useCurrentNativeSegwitUtxos();
const btcMarketData = useCryptoCurrencyMarketData('BTC');

return useCallback(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,39 @@ import type { AllTransferableCryptoAssetBalances } from '@shared/models/crypto-a
import { StacksFungibleTokenAsset } from '@shared/models/crypto-asset.model';

import { useWalletType } from '@app/common/use-wallet-type';
import { BitcoinNativeSegwitAccountLoader } from '@app/components/account/bitcoin-account-loader';
import { BitcoinBalanceLoader } from '@app/components/balance/bitcoin-balance-loader';
import { Brc20TokensLoader } from '@app/components/brc20-tokens-loader';
import { Brc20TokenAssetList } from '@app/components/crypto-assets/bitcoin/brc20-token-asset-list/brc20-token-asset-list';
import { Brc20Token } from '@app/query/bitcoin/ordinals/brc20/brc20-tokens.query';
import { BtcIcon } from '@app/ui/components/icons/btc-icon';

import { CryptoCurrencyAssetItem } from '../crypto-currency-asset/crypto-currency-asset-item';
import { CryptoAssetListItem } from './crypto-asset-list-item';
import { CryptoAssetListLayout } from './crypto-asset-list.layout';

interface CryptoAssetListProps {
cryptoAssetBalances: AllTransferableCryptoAssetBalances[];
onItemClick(cryptoAssetBalance: AllTransferableCryptoAssetBalances): void;
brc20Tokens?: Brc20Token[];
}
export function CryptoAssetList({
cryptoAssetBalances,
onItemClick,
brc20Tokens,
}: CryptoAssetListProps) {
export function CryptoAssetList({ cryptoAssetBalances, onItemClick }: CryptoAssetListProps) {
const { whenWallet } = useWalletType();

return (
<CryptoAssetListLayout>
<BitcoinNativeSegwitAccountLoader current>
{signer => (
<BitcoinBalanceLoader address={signer.address}>
{balance => (
<CryptoCurrencyAssetItem
assetBalance={balance}
icon={<BtcIcon />}
onClick={() => onItemClick(balance)}
isPressable
/>
)}
</BitcoinBalanceLoader>
)}
</BitcoinNativeSegwitAccountLoader>
{cryptoAssetBalances.map(cryptoAssetBalance => (
<CryptoAssetListItem
onClick={() => onItemClick(cryptoAssetBalance)}
Expand All @@ -32,12 +45,18 @@ export function CryptoAssetList({
}
/>
))}
{brc20Tokens
? whenWallet({
software: <Brc20TokenAssetList brc20Tokens={brc20Tokens} />,
ledger: null,
})
: null}
{whenWallet({
software: (
<BitcoinNativeSegwitAccountLoader current>
{() => (
<Brc20TokensLoader>
{brc20Tokens => <Brc20TokenAssetList brc20Tokens={brc20Tokens} />}
</Brc20TokensLoader>
)}
</BitcoinNativeSegwitAccountLoader>
),
ledger: null,
})}
</CryptoAssetListLayout>
);
}
11 changes: 2 additions & 9 deletions src/app/pages/fund/choose-asset-to-fund/choose-asset-to-fund.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { AllTransferableCryptoAssetBalances } from '@shared/models/crypto-asset-
import { RouteUrls } from '@shared/route-urls';
import { isDefined } from '@shared/utils';

import { useBtcCryptoCurrencyAssetBalance } from '@app/common/hooks/balance/btc/use-btc-crypto-currency-asset-balance';
import { useStxCryptoCurrencyAssetBalance } from '@app/common/hooks/balance/stx/use-stx-crypto-currency-asset-balance';
import { useRouteHeader } from '@app/common/hooks/use-route-header';
import { useWalletType } from '@app/common/use-wallet-type';
Expand All @@ -16,28 +15,22 @@ import { ModalHeader } from '@app/components/modal-header';
import { useCheckLedgerBlockchainAvailable } from '@app/store/accounts/blockchain/utils';

export function ChooseCryptoAssetToFund() {
const btcCryptoCurrencyAssetBalance = useBtcCryptoCurrencyAssetBalance();
const stxCryptoCurrencyAssetBalance = useStxCryptoCurrencyAssetBalance();

const cryptoCurrencyAssetBalances = useMemo(
() => [btcCryptoCurrencyAssetBalance, stxCryptoCurrencyAssetBalance],
[btcCryptoCurrencyAssetBalance, stxCryptoCurrencyAssetBalance]
);

const { whenWallet } = useWalletType();
const navigate = useNavigate();

const checkBlockchainAvailable = useCheckLedgerBlockchainAvailable();

const filteredCryptoAssetBalances = useMemo(
() =>
cryptoCurrencyAssetBalances.filter(isDefined).filter(assetBalance =>
[stxCryptoCurrencyAssetBalance].filter(isDefined).filter(assetBalance =>
whenWallet({
ledger: checkBlockchainAvailable(assetBalance?.blockchain),
software: true,
})
),
[cryptoCurrencyAssetBalances, checkBlockchainAvailable, whenWallet]
[stxCryptoCurrencyAssetBalance, checkBlockchainAvailable, whenWallet]
);

useRouteHeader(<ModalHeader hideActions onGoBack={() => navigate(RouteUrls.Home)} title=" " />);
Expand Down
4 changes: 2 additions & 2 deletions src/app/pages/rpc-send-transfer/use-rpc-send-transfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { RouteUrls } from '@shared/route-urls';
import { useDefaultRequestParams } from '@app/common/hooks/use-default-request-search-params';
import { useOnMount } from '@app/common/hooks/use-on-mount';
import { initialSearchParams } from '@app/common/initial-search-params';
import { useCurrentNativeSegwitAccountSpendableUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
import { useCurrentNativeSegwitUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';

export function useRpcSendTransferRequestParams() {
const defaultParams = useDefaultRequestParams();
Expand All @@ -24,7 +24,7 @@ export function useRpcSendTransferRequestParams() {
export function useRpcSendTransfer() {
const navigate = useNavigate();
const { address, amount, origin } = useRpcSendTransferRequestParams();
const { data: utxos = [], refetch } = useCurrentNativeSegwitAccountSpendableUtxos();
const { data: utxos = [], refetch } = useCurrentNativeSegwitUtxos();

// Forcing a refetch to ensure UTXOs are fresh
useOnMount(() => refetch());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { useNavigate } from 'react-router-dom';
import { AllTransferableCryptoAssetBalances } from '@shared/models/crypto-asset-balance.model';
import { RouteUrls } from '@shared/route-urls';

import { useBrc20Tokens } from '@app/common/hooks/use-brc20-tokens';
import { useRouteHeader } from '@app/common/hooks/use-route-header';
import { useAllTransferableCryptoAssetBalances } from '@app/common/hooks/use-transferable-asset-balances.hooks';
import { useWalletType } from '@app/common/use-wallet-type';
Expand All @@ -16,7 +15,6 @@ import { useCheckLedgerBlockchainAvailable } from '@app/store/accounts/blockchai

export function ChooseCryptoAsset() {
const allTransferableCryptoAssetBalances = useAllTransferableCryptoAssetBalances();
const brc20Tokens = useBrc20Tokens();

const { whenWallet } = useWalletType();
const navigate = useNavigate();
Expand Down Expand Up @@ -49,7 +47,6 @@ export function ChooseCryptoAsset() {
<ChooseCryptoAssetLayout title="choose asset to send">
<CryptoAssetList
onItemClick={cryptoAssetBalance => navigateToSendForm(cryptoAssetBalance)}
brc20Tokens={brc20Tokens}
cryptoAssetBalances={allTransferableCryptoAssetBalances.filter(asset =>
whenWallet({
ledger: checkBlockchainAvailable(asset.blockchain),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { OrdinalSendFormValues } from '@shared/models/form.model';

import { determineUtxosForSpend } from '@app/common/transactions/bitcoin/coinselect/local-coin-selection';
import { createCounter } from '@app/common/utils/counter';
import { useCurrentNativeSegwitAccountSpendableUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
import { useCurrentNativeSegwitUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
import { UtxoWithDerivationPath } from '@app/query/bitcoin/bitcoin-client';
import { useBitcoinScureLibNetworkConfig } from '@app/store/accounts/blockchain/bitcoin/bitcoin-keychain';
import { useCurrentAccountNativeSegwitSigner } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
Expand All @@ -20,7 +20,7 @@ export function useGenerateUnsignedOrdinalTx(inscriptionInput: UtxoWithDerivatio
const createTaprootSigner = useCurrentAccountTaprootSigner();
const createNativeSegwitSigner = useCurrentAccountNativeSegwitSigner();
const networkMode = useBitcoinScureLibNetworkConfig();
const { data: nativeSegwitUtxos } = useCurrentNativeSegwitAccountSpendableUtxos();
const { data: nativeSegwitUtxos } = useCurrentNativeSegwitUtxos();

function coverFeeFromAdditionalUtxos(values: OrdinalSendFormValues) {
if (getAddressInfo(values.inscription.address).type === AddressType.p2wpkh) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
import { tokenAmountValidator } from '@app/common/validation/forms/amount-validators';
import { currencyAmountValidator } from '@app/common/validation/forms/currency-validators';
import { useUpdatePersistedSendFormValues } from '@app/features/popup-send-form-restoration/use-update-persisted-send-form-values';
import { useCurrentNativeSegwitAccountSpendableUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
import { useCurrentNativeSegwitUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
import { useCurrentAccountNativeSegwitIndexZeroSigner } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
import { useCurrentNetwork } from '@app/store/networks/networks.selectors';

Expand All @@ -44,7 +44,7 @@ export function useBrc20SendForm({ balance, tick, decimals }: UseBrc20SendFormAr
const navigate = useNavigate();
const currentNetwork = useCurrentNetwork();
const nativeSegwitSigner = useCurrentAccountNativeSegwitIndexZeroSigner();
const { data: utxos = [], refetch } = useCurrentNativeSegwitAccountSpendableUtxos();
const { data: utxos = [], refetch } = useCurrentNativeSegwitUtxos();

// Forcing a refetch to ensure UTXOs are fresh
useOnMount(() => refetch());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
currencyAmountValidator,
} from '@app/common/validation/forms/currency-validators';
import { useUpdatePersistedSendFormValues } from '@app/features/popup-send-form-restoration/use-update-persisted-send-form-values';
import { useCurrentNativeSegwitAccountSpendableUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
import { useCurrentNativeSegwitUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
import { useNativeSegwitBalance } from '@app/query/bitcoin/balance/btc-native-segwit-balance.hooks';
import { useCurrentAccountNativeSegwitIndexZeroSigner } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
import { useCurrentNetwork } from '@app/store/networks/networks.selectors';
Expand All @@ -34,7 +34,7 @@ export function useBtcSendForm() {
const formRef = useRef<FormikProps<BitcoinSendFormValues>>(null);
const currentNetwork = useCurrentNetwork();
const nativeSegwitSigner = useCurrentAccountNativeSegwitIndexZeroSigner();
const { data: utxos = [], refetch } = useCurrentNativeSegwitAccountSpendableUtxos();
const { data: utxos = [], refetch } = useCurrentNativeSegwitUtxos();
const btcCryptoCurrencyAssetBalance = useNativeSegwitBalance(nativeSegwitSigner.address);
const sendFormNavigate = useSendFormNavigate();
const calcMaxSpend = useCalculateMaxBitcoinSpend();
Expand Down
32 changes: 0 additions & 32 deletions src/app/query/bitcoin/address/transactions-by-address.hooks.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import { useCallback } from 'react';

import { createMoney } from '@shared/models/money.model';
import { BitcoinTx } from '@shared/models/transactions/bitcoin-transaction.model';

import { sumNumbers } from '@app/common/math/helpers';

import { UtxoResponseItem } from '../bitcoin-client';
import {
useGetBitcoinTransactionsByAddressQuery,
useGetBitcoinTransactionsByAddressesQuery,
} from './transactions-by-address.query';
import { useAllSpendableUtxosByAddress } from './utxos-by-address.hooks';

function useFilterAddressPendingTransactions() {
return useCallback((txs: BitcoinTx[]) => {
Expand Down Expand Up @@ -53,32 +50,3 @@ export function calculateOutboundPendingTxsValue(pendingTxs: BitcoinTx[], addres

return sumInputs.minus(sumOutputs).toNumber();
}

// filter out pending txs that have inputs that are not in the utxos list to prevent double extraction
function filterMissingUtxosPendingTxs(
pendingTxs: BitcoinTx[],
utxos: UtxoResponseItem[],
address: string
) {
return pendingTxs.filter(tx => {
return tx.vin.every(input => {
return (
utxos.some(utxo => utxo.txid === input.txid) &&
address === input.prevout.scriptpubkey_address
);
});
});
}

export function useBitcoinPendingTransactionsBalance(address: string) {
const filterPendingTransactions = useFilterAddressPendingTransactions();
const { data: utxos } = useAllSpendableUtxosByAddress(address);

return useGetBitcoinTransactionsByAddressQuery(address, {
select(txs) {
const pendingTxs = filterPendingTransactions(txs);
const filteredTxs = filterMissingUtxosPendingTxs(pendingTxs, utxos || [], address);
return createMoney(calculateOutboundPendingTxsValue(filteredTxs, address), 'BTC');
},
});
}
Loading

0 comments on commit 0c5d34b

Please sign in to comment.