Skip to content

Commit 34e1eb7

Browse files
committed
fix: don't show error when opening transfer send modal with 0 btc balance
1 parent 7e7d575 commit 34e1eb7

File tree

2 files changed

+77
-95
lines changed

2 files changed

+77
-95
lines changed

src/popup/components/TransactionSpeedPicker.vue

+16-36
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22
<div class="transaction-speed-picker">
33
<div class="radio-wrapper">
44
<RadioButton
5-
v-for="(fee, index) in feeList"
6-
:key="fee"
7-
:value="selectedIndex === index"
5+
v-for="(feeItem, index) in feeList"
6+
:key="index"
7+
:value="modelValue === index"
88
@input="handleInput(index)"
99
>
10-
<p>
11-
{{ labels[index] }}
12-
</p>
10+
<p v-text="feeItem.label" />
1311
</RadioButton>
1412
</div>
1513
<p
@@ -18,30 +16,26 @@
1816
>
1917
{{
2018
$t('modals.send.transactionWillBeCompleted', {
21-
time: secondsToRelativeTime(feeList[selectedIndex].time, true)
19+
time: secondsToRelativeTime(feeList[modelValue].time, true)
2220
})
2321
}}
2422
</p>
2523
</div>
2624
</template>
2725

2826
<script lang="ts">
29-
import {
30-
defineComponent,
31-
PropType,
32-
ref,
33-
watch,
34-
} from 'vue';
35-
import { useI18n } from 'vue-i18n';
36-
import BigNumber from 'bignumber.js';
27+
import { defineComponent, PropType } from 'vue';
3728
38-
import RadioButton from '@/popup/components/RadioButton.vue';
29+
import type { BigNumberPublic } from '@/types';
3930
import { secondsToRelativeTime } from '@/utils';
4031
import { UNFINISHED_FEATURES } from '@/constants';
4132
42-
type FeeItem = {
43-
fee: BigNumber,
44-
time: number, // time in seconds
33+
import RadioButton from '@/popup/components/RadioButton.vue';
34+
35+
export type FeeItem = {
36+
fee: BigNumberPublic;
37+
time: number; // time in seconds
38+
label: string;
4539
}
4640
4741
export default defineComponent({
@@ -52,30 +46,16 @@ export default defineComponent({
5246
required: true,
5347
validate: (val: string[]) => val.length === 3,
5448
},
49+
modelValue: { type: Number, default: 1 },
5550
},
56-
emits: ['changeFee'],
51+
emits: ['update:modelValue'],
5752
setup(props, { emit }) {
58-
const { t } = useI18n();
59-
const selectedIndex = ref(1);
60-
const labels = [t('common.transferSpeed.slow'), t('common.transferSpeed.medium'), t('common.transferSpeed.fast')];
61-
6253
function handleInput(index: number) {
63-
selectedIndex.value = index;
64-
emit('changeFee', props.feeList[index].fee);
54+
emit('update:modelValue', index);
6555
}
6656
67-
watch(
68-
() => props.feeList,
69-
() => {
70-
emit('changeFee', props.feeList[selectedIndex.value].fee);
71-
},
72-
{ immediate: true },
73-
);
74-
7557
return {
7658
UNFINISHED_FEATURES,
77-
labels,
78-
selectedIndex,
7959
secondsToRelativeTime,
8060
handleInput,
8161
};

src/protocols/bitcoin/components/TransferSendForm.vue

+61-59
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@
6060
>
6161
<template #value>
6262
<TransactionSpeedPicker
63+
v-model="feeSelectedIndex"
6364
:fee-list="feeList"
64-
@changeFee="(value) => setFee(value)"
6565
/>
6666
</template>
6767
</DetailsItem>
@@ -82,34 +82,36 @@ import {
8282
watch,
8383
} from 'vue';
8484
import { useStore } from 'vuex';
85+
import { useI18n } from 'vue-i18n';
8586
import BigNumber from 'bignumber.js';
8687
import { toBitcoin } from 'satoshi-bitcoin';
8788
88-
import { useNetworks } from '@/composables/networks';
89+
import type { TransferFormModel } from '@/types';
8990
import {
9091
useAccounts,
9192
useBalances,
93+
useNetworks,
9294
} from '@/composables';
93-
import type { TransferFormModel } from '@/types';
94-
import {
95-
BTC_COIN_NAME,
96-
BTC_SYMBOL,
97-
DUST_AMOUNT,
98-
} from '@/protocols/bitcoin/config';
9995
import { useTransferSendForm } from '@/composables/transferSendForm';
10096
import { NETWORK_TYPE_TESTNET, PROTOCOL_BITCOIN } from '@/constants';
10197
import {
10298
executeAndSetInterval,
10399
fetchJson,
104100
} from '@/utils';
105-
106101
import { ProtocolAdapterFactory } from '@/lib/ProtocolAdapterFactory';
102+
import Logger from '@/lib/logger';
103+
import {
104+
BTC_COIN_NAME,
105+
BTC_SYMBOL,
106+
DUST_AMOUNT,
107+
} from '@/protocols/bitcoin/config';
108+
107109
import { INFO_BOX_TYPES } from '@/popup/components/InfoBox.vue';
108110
import DetailsItem from '@/popup/components/DetailsItem.vue';
109111
import TransferSendFormBase from '@/popup/components/TransferSendFormBase.vue';
110112
import TransferSendRecipient from '@/popup/components/TransferSend/TransferSendRecipient.vue';
111113
import TransferSendAmount from '@/popup/components/TransferSend/TransferSendAmount.vue';
112-
import TransactionSpeedPicker from '@/popup/components/TransactionSpeedPicker.vue';
114+
import TransactionSpeedPicker, { FeeItem } from '@/popup/components/TransactionSpeedPicker.vue';
113115
import BtnPlain from '@/popup/components/buttons/BtnPlain.vue';
114116
115117
import EditIcon from '@/icons/pencil.svg?vue-component';
@@ -134,7 +136,10 @@ export default defineComponent({
134136
},
135137
emits: ['update:transferData', 'success', 'error'],
136138
setup(props, { emit }) {
139+
const bitcoinAdapter = ProtocolAdapterFactory.getAdapter(PROTOCOL_BITCOIN);
140+
137141
const store = useStore();
142+
const { t } = useI18n();
138143
const { activeNetwork } = useNetworks();
139144
140145
const hasMultisigTokenWarning = ref(false);
@@ -159,20 +164,21 @@ export default defineComponent({
159164
protocol: PROTOCOL_BITCOIN,
160165
});
161166
162-
const fee = ref(new BigNumber(0));
163-
const feeList = ref([
164-
{ fee: new BigNumber(0.00002), time: 3540 },
165-
{ fee: new BigNumber(0.00004), time: 600 },
166-
{ fee: new BigNumber(0.00005), time: 25 },
167+
const feeSelectedIndex = ref(1);
168+
const feeSlow = ref(new BigNumber(0.00002));
169+
const feeMedium = ref(new BigNumber(0.00002));
170+
const feeHigh = ref(new BigNumber(0.00002));
171+
172+
const feeList = computed((): FeeItem[] => [
173+
{ fee: feeSlow.value, time: 3540, label: t('common.transferSpeed.slow') },
174+
{ fee: feeMedium.value, time: 600, label: t('common.transferSpeed.medium') },
175+
{ fee: feeHigh.value, time: 25, label: t('common.transferSpeed.fast') },
167176
]);
177+
const fee = computed(() => feeList.value[feeSelectedIndex.value].fee);
168178
169179
const numericFee = computed(() => +fee.value.toFixed());
170180
const max = computed(() => balance.value.minus(fee.value));
171181
172-
function setFee(value: BigNumber) {
173-
fee.value = value;
174-
}
175-
176182
function emitCurrentFormModelState() {
177183
const inputPayload: TransferFormModel = {
178184
...formModel.value,
@@ -198,46 +204,42 @@ export default defineComponent({
198204
}
199205
200206
async function updateFeeList() {
201-
const bitcoinAdapter = ProtocolAdapterFactory.getAdapter(PROTOCOL_BITCOIN);
202-
const byteSize = (await bitcoinAdapter.constructAndSignTx(
203-
// TODO: changed to 0 because balance.value can differs
204-
// from totalAmount from constructAndSignTx (balance is not being updated fast enough)
205-
// consider returning an actual amount in future
206-
0,
207-
formModel.value.address! || activeAccount.value.address,
208-
{
209-
fee: 0,
210-
...activeAccount.value,
211-
},
212-
)).virtualSize();
213-
const { nodeUrl } = activeNetwork.value.protocols.bitcoin;
214-
215-
const feeRate = (await fetchJson(`${nodeUrl}/fee-estimates`))['5'];
216-
const feeStepFactor = new BigNumber(0.5);
217-
const mediumFee = new BigNumber(Math.ceil(feeRate * byteSize));
218-
219-
feeList.value = [
220-
{
221-
fee: new BigNumber(toBitcoin(Math.ceil(mediumFee.minus(
222-
mediumFee.times(feeStepFactor),
223-
).toNumber()))),
224-
time: 3540,
225-
},
226-
{
227-
fee: new BigNumber(toBitcoin(
207+
try {
208+
const byteSize = (await bitcoinAdapter.constructAndSignTx(
209+
// TODO: changed to 0 because balance.value can differs
210+
// from totalAmount from constructAndSignTx (balance is not being updated fast enough)
211+
// consider returning an actual amount in future
212+
0,
213+
formModel.value.address || activeAccount.value.address,
214+
{
215+
fee: 0,
216+
...activeAccount.value,
217+
},
218+
)).virtualSize();
219+
const { nodeUrl } = activeNetwork.value.protocols.bitcoin;
220+
221+
const feeRate = (await fetchJson(`${nodeUrl}/fee-estimates`))['5'];
222+
const feeStepFactor = new BigNumber(0.5);
223+
const newFeeMedium = new BigNumber(Math.ceil(feeRate * byteSize));
224+
225+
feeSlow.value = new BigNumber(
226+
toBitcoin(Math.ceil(newFeeMedium.minus(newFeeMedium.times(feeStepFactor)).toNumber())),
227+
);
228+
229+
feeMedium.value = new BigNumber(
230+
toBitcoin(
228231
// Double the fee for the testnet to match relay fee.
229232
// TODO: Revisit this along with fee calculation
230-
mediumFee.toNumber() * (activeNetwork.value.type === NETWORK_TYPE_TESTNET ? 2.0 : 1.0),
231-
)),
232-
time: 600,
233-
},
234-
{
235-
fee: new BigNumber(toBitcoin(Math.ceil(mediumFee.plus(
236-
mediumFee.times(feeStepFactor),
237-
).toNumber()))),
238-
time: 25,
239-
},
240-
];
233+
newFeeMedium.toNumber() * (activeNetwork.value.type === NETWORK_TYPE_TESTNET ? 2 : 1),
234+
),
235+
);
236+
237+
feeHigh.value = new BigNumber(
238+
toBitcoin(Math.ceil(newFeeMedium.plus(newFeeMedium.times(feeStepFactor)).toNumber())),
239+
);
240+
} catch (error: any) {
241+
Logger.write(error);
242+
}
241243
}
242244
243245
let polling: NodeJS.Timer | null = null;
@@ -280,16 +282,16 @@ export default defineComponent({
280282
isUrlTippingEnabled,
281283
activeNetwork,
282284
fee,
285+
feeList,
286+
feeSelectedIndex,
283287
numericFee,
284288
activeAccount,
285-
feeList,
286289
errors,
287290
balance,
288291
max,
289292
clearPayload,
290293
openScanQrModal,
291294
handleAssetChange,
292-
setFee,
293295
EditIcon,
294296
DeleteIcon,
295297
PlusCircleIcon,

0 commit comments

Comments
 (0)