Skip to content

Commit 0dcf930

Browse files
committed
feat: split btc balances by address type
1 parent 79cb453 commit 0dcf930

File tree

7 files changed

+97
-39
lines changed

7 files changed

+97
-39
lines changed

apps/mobile/src/features/send/hooks/use-preload-btc-data.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ export function usePreloadBtcData(account: Account | null) {
1616
useQuery({
1717
queryKey: ['utxos-service-get-account-utxos', accountAddresses],
1818
queryFn: ({ signal }: QueryFunctionContext) =>
19-
getUtxosService().getAccountUtxos(accountAddresses, [], signal),
19+
getUtxosService().getAccountUtxos(
20+
{ account: accountAddresses, unprotectedUtxos: [] },
21+
signal
22+
),
2023
refetchOnReconnect: false,
2124
refetchOnWindowFocus: false,
2225
refetchOnMount: true,

apps/mobile/src/queries/balance/btc-balance.query.ts

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,74 @@ import { useAccountAddresses, useTotalAccountAddresses } from '@/hooks/use-accou
33
import { useSettings } from '@/store/settings/settings';
44
import { QueryFunctionContext, useQuery } from '@tanstack/react-query';
55

6-
import { AccountAddresses } from '@leather.io/models';
7-
import { getBtcBalancesService } from '@leather.io/services';
6+
import { BtcAccountRequest, getBtcBalancesService } from '@leather.io/services';
87

98
export function useBtcTotalBalance() {
109
const accounts = useTotalAccountAddresses();
11-
return toFetchState(useBtcAggregateBalanceQuery(accounts));
10+
return toFetchState(
11+
useBtcAggregateBalanceQuery(accounts.map(account => ({ account, unprotectedUtxos: [] })))
12+
);
13+
}
14+
15+
export function useBtcTotalNativeSegwitBalance() {
16+
const accounts = useTotalAccountAddresses();
17+
return toFetchState(
18+
useBtcAggregateBalanceQuery(
19+
accounts.map(account => ({
20+
account,
21+
unprotectedUtxos: [],
22+
exclude: { taprootAddresses: true },
23+
}))
24+
)
25+
);
26+
}
27+
28+
export function useBtcTotalTaprootBalance() {
29+
const accounts = useTotalAccountAddresses();
30+
return toFetchState(
31+
useBtcAggregateBalanceQuery(
32+
accounts.map(account => ({
33+
account,
34+
unprotectedUtxos: [],
35+
exclude: { nativeSegwitAddresses: true },
36+
}))
37+
)
38+
);
1239
}
1340

1441
export function useBtcAccountBalance(fingerprint: string, accountIndex: number) {
1542
const account = useAccountAddresses(fingerprint, accountIndex);
16-
return toFetchState(useBtcAccountBalanceQuery(account));
43+
return toFetchState(useBtcAccountBalanceQuery({ account, unprotectedUtxos: [] }));
44+
}
45+
46+
export function useBtcAccountNativeSegwitBalance(fingerprint: string, accountIndex: number) {
47+
const account = useAccountAddresses(fingerprint, accountIndex);
48+
return toFetchState(
49+
useBtcAccountBalanceQuery({
50+
account,
51+
unprotectedUtxos: [],
52+
exclude: { taprootAddresses: true },
53+
})
54+
);
55+
}
56+
57+
export function useBtcAccountTaprootBalance(fingerprint: string, accountIndex: number) {
58+
const account = useAccountAddresses(fingerprint, accountIndex);
59+
return toFetchState(
60+
useBtcAccountBalanceQuery({
61+
account,
62+
unprotectedUtxos: [],
63+
exclude: { nativeSegwitAddresses: true },
64+
})
65+
);
1766
}
1867

19-
function useBtcAccountBalanceQuery(account: AccountAddresses) {
68+
function useBtcAccountBalanceQuery(request: BtcAccountRequest) {
2069
const { fiatCurrencyPreference } = useSettings();
2170
return useQuery({
22-
queryKey: ['btc-balance-service-get-btc-account-balance', account, fiatCurrencyPreference],
71+
queryKey: ['btc-balance-service-get-btc-account-balance', request, fiatCurrencyPreference],
2372
queryFn: ({ signal }: QueryFunctionContext) =>
24-
getBtcBalancesService().getBtcAccountBalance({ account, unprotectedUtxos: [] }, signal),
73+
getBtcBalancesService().getBtcAccountBalance(request, signal),
2574
refetchOnReconnect: false,
2675
refetchOnWindowFocus: false,
2776
refetchOnMount: true,
@@ -31,18 +80,12 @@ function useBtcAccountBalanceQuery(account: AccountAddresses) {
3180
});
3281
}
3382

34-
function useBtcAggregateBalanceQuery(accounts: AccountAddresses[]) {
83+
function useBtcAggregateBalanceQuery(requests: BtcAccountRequest[]) {
3584
const { fiatCurrencyPreference } = useSettings();
3685
return useQuery({
37-
queryKey: ['btc-balance-service-get-btc-aggregate-balance', accounts, fiatCurrencyPreference],
86+
queryKey: ['btc-balance-service-get-btc-aggregate-balance', requests, fiatCurrencyPreference],
3887
queryFn: ({ signal }: QueryFunctionContext) =>
39-
getBtcBalancesService().getBtcAggregateBalance(
40-
accounts.map(account => ({
41-
account,
42-
unprotectedUtxos: [],
43-
})),
44-
signal
45-
),
88+
getBtcBalancesService().getBtcAggregateBalance(requests, signal),
4689
refetchOnReconnect: false,
4790
refetchOnWindowFocus: false,
4891
refetchOnMount: true,

apps/mobile/src/queries/utxos/utxos.query.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ function useAccountUtxosQuery(account: AccountAddresses) {
1414
return useQuery({
1515
queryKey: ['utxos-service-get-account-utxos', account],
1616
queryFn: ({ signal }: QueryFunctionContext) =>
17-
getUtxosService().getAccountUtxos(account, [], signal),
17+
getUtxosService().getAccountUtxos({ account, unprotectedUtxos: [] }, signal),
1818
refetchOnReconnect: false,
1919
refetchOnWindowFocus: false,
2020
refetchOnMount: true,

packages/services/src/balances/btc-balances.service.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
import type { SettingsService } from '../infrastructure/settings/settings.service';
1313
import { Types } from '../inversify.types';
1414
import { MarketDataService } from '../market-data/market-data.service';
15+
import { BtcAccountRequest } from '../types/btc.types';
1516
import { UtxosService } from '../utxos/utxos.service';
1617
import { sumUtxoValues } from '../utxos/utxos.utils';
1718

@@ -73,14 +74,10 @@ export class BtcBalancesService {
7374
* A list of selectively unprotected UTXOs provided on the request will move the UTXO values from protected to available balance.
7475
*/
7576
public async getBtcAccountBalance(
76-
request: BtcAccountBalanceRequest,
77+
request: BtcAccountRequest,
7778
signal?: AbortSignal
7879
): Promise<AccountQuotedBtcBalance> {
79-
const utxos = await this.utxosService.getAccountUtxos(
80-
request.account,
81-
request.unprotectedUtxos,
82-
signal
83-
);
80+
const utxos = await this.utxosService.getAccountUtxos(request, signal);
8481

8582
const totalBalance = createMoney(sumUtxoValues(utxos.confirmed), 'BTC');
8683
const inboundBalance = createMoney(sumUtxoValues(utxos.inbound), 'BTC');
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { AccountAddresses, UtxoId } from '@leather.io/models';
2+
3+
export interface BtcAccountRequest {
4+
account: AccountAddresses;
5+
unprotectedUtxos: UtxoId[];
6+
exclude?: {
7+
nativeSegwitAddresses?: boolean;
8+
taprootAddresses?: boolean;
9+
};
10+
}

packages/services/src/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from './asset.types';
2+
export * from './btc.types';

packages/services/src/utxos/utxos.service.ts

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { injectable } from 'inversify';
22

3-
import { AccountAddresses, OwnedUtxo, UtxoId } from '@leather.io/models';
3+
import { OwnedUtxo, UtxoId } from '@leather.io/models';
44
import { hasBitcoinAddress, isDefined } from '@leather.io/utils';
55

66
import { BestInSlotApiClient } from '../infrastructure/api/best-in-slot/best-in-slot-api.client';
77
import { LeatherApiClient } from '../infrastructure/api/leather/leather-api.client';
88
import { BitcoinTransactionsService } from '../transactions/bitcoin-transactions.service';
9+
import { BtcAccountRequest } from '../types/btc.types';
910
import {
1011
filterMatchesAnyUtxoId,
1112
filterOutMatchesAnyUtxoId,
@@ -51,25 +52,28 @@ export class UtxosService {
5152
* An optional list of unprotected UTXOs can be provided on request to selectively move UTXO values from protected to available.
5253
*/
5354
public async getAccountUtxos(
54-
account: AccountAddresses,
55-
unprotectedUtxos: UtxoId[],
55+
{ account, unprotectedUtxos, exclude }: BtcAccountRequest,
5656
signal?: AbortSignal
5757
): Promise<UtxoTotals> {
5858
if (!hasBitcoinAddress(account)) return emptyUtxos;
5959

6060
const [nativeSegwitUtxos, taprootUtxos] = await Promise.all([
61-
this.getDescriptorUtxos(
62-
account.id.fingerprint,
63-
account.bitcoin.nativeSegwitDescriptor,
64-
[],
65-
signal
66-
),
67-
this.getDescriptorUtxos(
68-
account.id.fingerprint,
69-
account.bitcoin.taprootDescriptor,
70-
unprotectedUtxos,
71-
signal
72-
),
61+
!exclude?.nativeSegwitAddresses
62+
? this.getDescriptorUtxos(
63+
account.id.fingerprint,
64+
account.bitcoin.nativeSegwitDescriptor,
65+
[],
66+
signal
67+
)
68+
: Promise.resolve(emptyUtxos),
69+
!exclude?.taprootAddresses
70+
? this.getDescriptorUtxos(
71+
account.id.fingerprint,
72+
account.bitcoin.taprootDescriptor,
73+
unprotectedUtxos,
74+
signal
75+
)
76+
: Promise.resolve(emptyUtxos),
7377
]);
7478
return {
7579
confirmed: [...nativeSegwitUtxos.confirmed, ...taprootUtxos.confirmed],

0 commit comments

Comments
 (0)