Skip to content

Commit a3ca5db

Browse files
authored
fix(lightning): calculate blocktank limits (#1030)
* fix(lightning): calculate blocktank limits * fix(lightning): fix calculate blocktank limits
1 parent cef819f commit a3ca5db

File tree

4 files changed

+79
-27
lines changed

4 files changed

+79
-27
lines changed

src/screens/Lightning/CustomSetup.tsx

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -190,24 +190,40 @@ const CustomSetup = ({
190190
satoshis: satoshisCapped,
191191
};
192192
} else {
193-
const convertedAmount = convertCurrency({
193+
const amount = convertCurrency({
194194
amount: blocktankService.max_chan_receiving_usd,
195195
from: 'USD',
196196
to: selectedCurrency,
197197
});
198-
const satoshis = convertToSats(
199-
convertedAmount.fiatValue,
198+
const amountSatoshis = convertToSats(
199+
amount.fiatValue,
200200
EBalanceUnit.fiat,
201201
);
202-
// Ensure the conversion still puts us below the max_chan_receiving
203-
const satoshisCapped = Math.min(
204-
satoshis,
202+
// subtract a buffer to ensure we don't land right on the max channel size
203+
// also avoids exchange rate deltas with Blocktank
204+
const buffer = convertCurrency({
205+
amount: 10,
206+
from: 'USD',
207+
to: selectedCurrency,
208+
});
209+
const bufferSatoshis = convertToSats(
210+
buffer.fiatValue,
211+
EBalanceUnit.fiat,
212+
);
213+
214+
// Ensure the amount is below the max channel size
215+
const receiveLimit = amountSatoshis - spendingAmount! - bufferSatoshis;
216+
let satoshisCapped = Math.min(amountSatoshis, receiveLimit);
217+
218+
// Ensure the amount is below max_chan_receiving
219+
satoshisCapped = Math.min(
220+
satoshisCapped,
205221
blocktankService.max_chan_receiving,
206222
);
207223

208224
return {
209225
...p,
210-
fiatAmount: convertedAmount.fiatValue,
226+
fiatAmount: amount.fiatValue,
211227
satoshis: satoshisCapped,
212228
};
213229
}
@@ -218,6 +234,7 @@ const CustomSetup = ({
218234
blocktankService.max_chan_receiving,
219235
blocktankService.max_chan_receiving_usd,
220236
selectedCurrency,
237+
spendingAmount,
221238
]);
222239

223240
// set initial spending/receiving amount
@@ -247,7 +264,7 @@ const CustomSetup = ({
247264
? blocktankService.min_channel_size
248265
: 0;
249266

250-
const result = getNumberPadText(amount, unit, true);
267+
const result = getNumberPadText(amount, unit);
251268
setTextFieldValue(result);
252269
}
253270
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -272,7 +289,7 @@ const CustomSetup = ({
272289
// fetch approximate channel open cost on ReceiveAmount screen
273290
useEffect(() => {
274291
if (!spending && receivingPackages.length) {
275-
const defaultPackage = receivingPackages.find((p) => p.id === 'medium')!;
292+
const defaultPackage = receivingPackages.find((p) => p.id === 'big')!;
276293
const getChannelOpenCost = async (): Promise<void> => {
277294
const response = await startChannelPurchase({
278295
productId,

src/screens/Lightning/QuickSetup.tsx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
startChannelPurchase,
3131
} from '../../store/actions/blocktank';
3232
import { showErrorNotification } from '../../utils/notifications';
33-
import { convertToSats } from '../../utils/exchange-rate';
33+
import { convertToSats, getFiatDisplayValues } from '../../utils/exchange-rate';
3434
import { SPENDING_LIMIT_RATIO } from '../../utils/wallet/constants';
3535
import type { LightningScreenProps } from '../../navigation/types';
3636
import {
@@ -78,7 +78,11 @@ const QuickSetup = ({
7878
return convertToSats(textFieldValue, unit);
7979
}, [textFieldValue, unit]);
8080

81-
const blocktankSpendingLimit = blocktankService.max_chan_spending;
81+
const diff = 0.01;
82+
const btSpendingLimit = blocktankService.max_chan_spending;
83+
const btSpendingLimitBalanced = Math.round(
84+
btSpendingLimit / 2 - btSpendingLimit * diff,
85+
);
8286
const spendableBalance = Math.round(onchainBalance * SPENDING_LIMIT_RATIO);
8387
const savingsAmount = onchainBalance - spendingAmount;
8488
const savingsPercentage = Math.round((savingsAmount / onchainBalance) * 100);
@@ -87,8 +91,17 @@ const QuickSetup = ({
8791
);
8892

8993
const spendingLimit = useMemo(() => {
90-
return Math.min(spendableBalance, blocktankSpendingLimit);
91-
}, [spendableBalance, blocktankSpendingLimit]);
94+
return Math.min(spendableBalance, btSpendingLimitBalanced);
95+
}, [spendableBalance, btSpendingLimitBalanced]);
96+
97+
const btSpendingLimitBalancedUsd = useMemo((): string => {
98+
const { fiatWhole } = getFiatDisplayValues({
99+
satoshis: btSpendingLimitBalanced,
100+
currency: 'USD',
101+
});
102+
103+
return fiatWhole;
104+
}, [btSpendingLimitBalanced]);
92105

93106
// BTC -> satoshi -> fiat
94107
const nextUnit = useMemo(() => {
@@ -135,7 +148,7 @@ const QuickSetup = ({
135148

136149
// Ensure local balance is bigger than remote balance
137150
const localBalance = Math.max(
138-
Math.round(spendingAmount * 1.1),
151+
Math.round(spendingAmount + spendingAmount * diff),
139152
blocktankService.min_channel_size,
140153
);
141154
const purchaseResponse = await startChannelPurchase({
@@ -211,13 +224,17 @@ const QuickSetup = ({
211224
</View>
212225
</AnimatedView>
213226

214-
{spendingAmount === Math.round(blocktankSpendingLimit) && (
227+
{spendingAmount === Math.round(btSpendingLimitBalanced) && (
215228
<AnimatedView
216229
style={styles.note}
217230
entering={FadeIn}
218231
exiting={FadeOut}
219232
testID="QuickSetupBlocktankNote">
220-
<Text02S color="gray1">{t('note_blocktank_limit')}</Text02S>
233+
<Text02S color="gray1">
234+
{t('note_blocktank_limit', {
235+
usdValue: btSpendingLimitBalancedUsd,
236+
})}
237+
</Text02S>
221238
</AnimatedView>
222239
)}
223240

src/screens/Transfer/Setup.tsx

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
} from '../../store/actions/blocktank';
2929
import { useSelector } from 'react-redux';
3030
import { SPENDING_LIMIT_RATIO } from '../../utils/wallet/constants';
31-
import { convertToSats } from '../../utils/exchange-rate';
31+
import { convertToSats, getFiatDisplayValues } from '../../utils/exchange-rate';
3232
import {
3333
resetOnChainTransaction,
3434
setupOnChainTransaction,
@@ -72,8 +72,12 @@ const Setup = ({ navigation }: TransferScreenProps<'Setup'>): ReactElement => {
7272
return convertToSats(textFieldValue, unit);
7373
}, [textFieldValue, unit]);
7474

75+
const diff = 0.01;
76+
const btSpendingLimit = blocktankService.max_chan_spending;
77+
const btSpendingLimitBalanced = Math.round(
78+
btSpendingLimit / 2 - btSpendingLimit * diff,
79+
);
7580
const totalBalance = onchainBalance + lightningBalance;
76-
const blocktankSpendingLimit = blocktankService.max_chan_spending;
7781
const spendableBalance = Math.round(totalBalance * SPENDING_LIMIT_RATIO);
7882
const savingsAmount = totalBalance - spendingAmount;
7983
const spendingPercentage = Math.round((spendingAmount / totalBalance) * 100);
@@ -82,9 +86,18 @@ const Setup = ({ navigation }: TransferScreenProps<'Setup'>): ReactElement => {
8286
const isButtonDisabled = spendingAmount === lightningBalance;
8387

8488
const spendingLimit = useMemo(() => {
85-
const min = Math.min(spendableBalance, blocktankSpendingLimit);
89+
const min = Math.min(spendableBalance, btSpendingLimitBalanced);
8690
return min < lightningBalance ? lightningBalance : min;
87-
}, [spendableBalance, blocktankSpendingLimit, lightningBalance]);
91+
}, [spendableBalance, btSpendingLimitBalanced, lightningBalance]);
92+
93+
const btSpendingLimitBalancedUsd = useMemo((): string => {
94+
const { fiatWhole } = getFiatDisplayValues({
95+
satoshis: btSpendingLimitBalanced,
96+
currency: 'USD',
97+
});
98+
99+
return fiatWhole;
100+
}, [btSpendingLimitBalanced]);
88101

89102
// set initial value
90103
useEffect(() => {
@@ -144,10 +157,11 @@ const Setup = ({ navigation }: TransferScreenProps<'Setup'>): ReactElement => {
144157
// buy an additional channel from Blocktank with the difference
145158
setLoading(true);
146159
const remoteBalance = spendingAmount - lightningBalance;
147-
const localBalance =
148-
Math.round(remoteBalance * 1.1) > blocktankService.min_channel_size
149-
? Math.round(remoteBalance * 1.1)
150-
: blocktankService.min_channel_size;
160+
// Ensure local balance is bigger than remote balance
161+
const localBalance = Math.max(
162+
Math.round(remoteBalance + remoteBalance * diff),
163+
blocktankService.min_channel_size,
164+
);
151165

152166
const purchaseResponse = await startChannelPurchase({
153167
selectedNetwork,
@@ -231,12 +245,16 @@ const Setup = ({ navigation }: TransferScreenProps<'Setup'>): ReactElement => {
231245
</View>
232246
</AnimatedView>
233247

234-
{spendingAmount === Math.round(blocktankSpendingLimit) && (
248+
{spendingAmount === Math.round(btSpendingLimitBalanced) && (
235249
<AnimatedView
236250
style={styles.note}
237251
entering={FadeIn}
238252
exiting={FadeOut}>
239-
<Text02S color="gray1">{t('note_blocktank_limit')}</Text02S>
253+
<Text02S color="gray1">
254+
{t('note_blocktank_limit', {
255+
usdValue: btSpendingLimitBalancedUsd,
256+
})}
257+
</Text02S>
240258
</AnimatedView>
241259
)}
242260

src/utils/i18n/locales/en/lightning.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"savings": "Savings",
1717
"spending_label": "Spending balance",
1818
"receiving_label": "Receiving capacity",
19-
"note_blocktank_limit": "The amount you can transfer to your spending balance is currently limited to $999.",
19+
"note_blocktank_limit": "The amount you can transfer to your spending balance is currently limited to ${{usdValue}}.",
2020
"note_reserve_limit": "The amount you can transfer to your spending balance is limited to 80%. You need to keep funds in reserve to move this bitcoin back to savings.",
2121
"quick_confirm_header": "Please\nConfirm.",
2222
"quick_confirm_cost": "It costs <white>{{amount}}</white> to connect you to Lightning and set up your spending balance.",

0 commit comments

Comments
 (0)