6
6
@close =" closeModal"
7
7
@close-overlay =" () => (p.addressListOpened = false)"
8
8
>
9
- <div v-if =" !p" >Loading fees</div >
9
+ <div v-if =" !p" class =" loading-wrapper" >
10
+ <div class =" loading-container" >
11
+ <CircleSpinner />
12
+ <p >
13
+ {{ $t("Loading...") }}
14
+ </p >
15
+ </div >
16
+ </div >
10
17
<div v-else class =" asset-transfer-input" >
11
18
<PageHeader >{{ p.modalTitle }}</PageHeader >
12
19
<PageBody class =" flex-column" >
55
62
</template >
56
63
</i18n >
57
64
</SwapFeesTooltip >
58
- {{p.limits}}
59
- current: {{p.currentLimitFiat}}
60
65
<Tooltip
61
66
:styles =" { width: '28.75rem' }"
62
67
preferredPosition =" bottom left"
69
74
v-if =" p.limits"
70
75
:amount =" p.currentLimitFiat"
71
76
:currency =" p.currencyFiatFallback.toLocaleLowerCase()"
72
- hideDecimals
77
+ hide-decimals
73
78
/>
74
79
<CircleSpinner v-else />
75
80
</div >
118
123
</section >
119
124
120
125
<DualCurrencyInput
121
- :fiatAmount.sync =" p. fiatAmount"
122
- :cryptoAmount.sync =" p. cryptoAmount"
126
+ :fiatAmount.sync =" fiatAmount"
127
+ :cryptoAmount.sync =" cryptoAmount"
123
128
:fiatCurrency =" p.currencyFiatFallback.toLocaleLowerCase()"
124
129
:cryptoCurrency =" p.currencyCrypto.toLocaleLowerCase()"
125
130
:fiatCurrencyDecimals =" p.decimalsFiat"
126
131
:cryptoCurrencyDecimals =" p.decimalsCrypto"
127
- :maxCrypto =" p.currentLimitCrypto"
128
- :maxFiat =" p.currentLimitFiat"
129
132
:exchangeRate =" p.exchangeRate"
130
133
:invalid-reason =" p.invalidReason"
131
134
@set-max =" setMax()"
147
150
{{ $t("Insufficient balance.") }}
148
151
<a @click =" () => setMax()" >{{ $t("Sell max") }}</a >
149
152
</template >
150
- <template v-else-if =" p . estimateError " >
151
- {{ p. estimateError }}
153
+ <template v-else-if =" estimateError " >
154
+ {{ estimateError }}
152
155
</template >
153
156
</MessageTransition >
154
157
</PageBody >
155
158
<PageFooter >
156
159
<button
157
160
class =" nq-button light-blue"
158
161
@mousedown.prevent
159
- :disabled =" !p.canSign || p.invalid || !p. fiatAmount || !p. cryptoAmount"
162
+ :disabled =" !p.canSign || p.invalid || !fiatAmount || !cryptoAmount"
160
163
@click =" p.sign()"
161
164
>
162
165
{{ $t("Confirm") }}
@@ -245,6 +248,7 @@ import {
245
248
defineComponent ,
246
249
onMounted ,
247
250
ref ,
251
+ watch ,
248
252
} from ' @vue/composition-api' ;
249
253
import {
250
254
AssetTransferMethod ,
@@ -264,9 +268,10 @@ import {
264
268
import { ENV_MAIN } from ' @/lib/Constants' ;
265
269
import { useAddressStore } from ' @/stores/Address' ;
266
270
import { useBtcAddressStore } from ' @/stores/BtcAddress' ;
267
- import { SwapState , useSwapsStore } from ' @/stores/Swaps' ;
271
+ import { isFiatAsset , SwapState , useSwapsStore } from ' @/stores/Swaps' ;
268
272
import { SwapAsset } from ' @nimiq/libswap' ;
269
273
import { useConfig } from ' @/composables/useConfig' ;
274
+ import { capDecimals , useSwapEstimate } from ' @/lib/swap/utils/CommonUtils' ;
270
275
import AddressList from ' ../AddressList.vue' ;
271
276
import DualCurrencyInput from ' ../DualCurrencyInput.vue' ;
272
277
import FiatConvertedAmount from ' ../FiatConvertedAmount.vue' ;
@@ -293,13 +298,50 @@ export default defineComponent({
293
298
},
294
299
setup(props , context ) {
295
300
const p /* params */ = ref <AssetTransferParams >(null );
296
- const cryptoAmount = computed (
297
- () => (p .value ?.cryptoAmount as unknown as number ) || 0 ,
298
- );
301
+
302
+ const { estimate } = useSwapEstimate ();
303
+
304
+ const _fiatAmount = ref (0 );
305
+ const fiatAmount = computed ({
306
+ get : () => {
307
+ if (_fiatAmount .value !== 0 ) return _fiatAmount .value ;
308
+ if (! estimate ?.value ) return 0 ;
309
+ if (! isFiatAsset (estimate .value .to .asset )) return 0 ;
310
+ return estimate .value .to .amount - estimate .value .to .fee ;
311
+ },
312
+ set : (value : number ) => {
313
+ _cryptoAmount .value = 0 ;
314
+ _fiatAmount .value = value ;
315
+ onInput (value );
316
+ },
317
+ });
318
+
319
+ const _cryptoAmount = ref (0 );
320
+ const cryptoAmount = computed ({
321
+ get : () => {
322
+ if (_cryptoAmount .value !== 0 ) return _cryptoAmount .value ;
323
+ if (! estimate .value || ! p .value ?.currencyCrypto ) return 0 ;
324
+ if (estimate .value .from .asset !== p .value .currencyCrypto ) return 0 ;
325
+ return capDecimals (estimate .value .from .amount + estimate .value .from .fee , estimate .value .from .asset );
326
+ },
327
+ set : (value : number ) => {
328
+ _fiatAmount .value = 0 ;
329
+ _cryptoAmount .value = value ;
330
+ onInput (value );
331
+ },
332
+ });
333
+
334
+ const fetchingEstimate = ref <boolean >(false );
299
335
300
336
onMounted (async () => {
301
337
const options: AssetTransferOptions = {
302
338
pair: props .pair ,
339
+ cryptoAmount ,
340
+ fiatAmount ,
341
+ estimate ,
342
+ updateEstimate ,
343
+ estimateError ,
344
+ fetchingEstimate ,
303
345
};
304
346
305
347
switch (props .method ) {
@@ -315,43 +357,81 @@ export default defineComponent({
315
357
}
316
358
});
317
359
360
+ let updateEstimateFn: (args : any ) => Promise <void >;
361
+ const estimateError = ref <string >(null );
362
+ let timeoutId: number | undefined ;
363
+
364
+ async function updateEstimate() {
365
+ if (! p .value ) return ;
366
+ clearTimeout (timeoutId );
367
+
368
+ fetchingEstimate .value = true ;
369
+
370
+ if (! updateEstimateFn ) {
371
+ updateEstimateFn = p .value ?.isSelling
372
+ ? (await import (' @/lib/swap/utils/SellUtils' )).updateSellEstimate
373
+ : (await import (' @/lib/swap/utils/BuyUtils' )).updateBuyEstimate ;
374
+ }
375
+
376
+ const args = _fiatAmount .value
377
+ ? { fiatAmount: fiatAmount .value , fiatAsset: p .value .currencyFiatFallback }
378
+ : { cryptoAmount: cryptoAmount .value , fiatAsset: p .value .currencyFiatFallback };
379
+ await updateEstimateFn (args ).then (() => {
380
+ estimateError .value = null ;
381
+ }).catch ((error ) => {
382
+ console .warn (error ); // eslint-disable-line no-console
383
+ estimateError .value = error .message ;
384
+ });
385
+
386
+ fetchingEstimate .value = false ;
387
+ }
388
+
389
+ function onInput(val : number ) {
390
+ clearTimeout (timeoutId );
391
+
392
+ if (! val ) {
393
+ estimate .value = null ;
394
+ estimateError .value = null ;
395
+ return ;
396
+ }
397
+
398
+ timeoutId = window .setTimeout (updateEstimate , 500 );
399
+ fetchingEstimate .value = true ;
400
+ }
401
+
318
402
const { activeAddressInfo } = useAddressStore ();
319
403
const { accountBalance : accountBtcBalance } = useBtcAddressStore ();
320
404
321
405
function setMax() {
322
406
if (! p .value ?.isSelling ) return ;
407
+ const currentLimitCrypto = p .value .currentLimitCrypto .value ;
323
408
324
409
switch (p .value .currencyCrypto ) {
325
410
case SwapAsset .NIM : {
326
- if (! p .value .currentLimitCrypto .value ) {
327
- p .value .updateCryptoAmount (activeAddressInfo .value ?.balance || 0 );
328
- } else if (
329
- p .value .currentLimitCrypto .value
330
- < (activeAddressInfo .value ?.balance || 0 )
331
- ) {
332
- p .value .updateCryptoAmount (p .value .currentLimitCrypto .value );
411
+ if (! currentLimitCrypto ) {
412
+ cryptoAmount .value = activeAddressInfo .value ?.balance || 0 ;
413
+ } else if (currentLimitCrypto < (activeAddressInfo .value ?.balance || 0 )) {
414
+ cryptoAmount .value = currentLimitCrypto ;
333
415
} else {
334
- p .value . updateCryptoAmount ( activeAddressInfo .value ?.balance || 0 ) ;
416
+ cryptoAmount .value = activeAddressInfo .value ?.balance || 0 ;
335
417
}
336
418
break ;
337
419
}
338
420
case SwapAsset .BTC : {
339
- if (! p .value .currentLimitCrypto .value ) {
340
- p .value .updateCryptoAmount (accountBtcBalance .value );
341
- } else if (
342
- p .value .currentLimitCrypto .value < accountBtcBalance .value
343
- ) {
344
- p .value .updateCryptoAmount (p .value .currentLimitCrypto .value );
421
+ if (! currentLimitCrypto ) {
422
+ cryptoAmount .value = accountBtcBalance .value ;
423
+ } else if (currentLimitCrypto < accountBtcBalance .value ) {
424
+ cryptoAmount .value = currentLimitCrypto ;
345
425
} else {
346
- p .value . updateCryptoAmount ( accountBtcBalance .value ) ;
426
+ cryptoAmount .value = accountBtcBalance .value ;
347
427
}
348
428
break ;
349
429
}
350
430
default :
351
431
throw new Error (' Invalid currency' );
352
432
}
353
433
354
- p .value . updateFiatAmount ( cryptoAmount .value * p .value .exchangeRate .value ) ;
434
+ fiatAmount .value = cryptoAmount .value * p .value .exchangeRate .value ;
355
435
}
356
436
357
437
function finishSwap() {
@@ -368,6 +448,13 @@ export default defineComponent({
368
448
}
369
449
}
370
450
451
+ const { activeSwap } = useSwapsStore ();
452
+ watch (activeSwap , () => {
453
+ if (activeSwap .value ) {
454
+ closeModal ();
455
+ }
456
+ });
457
+
371
458
const { config } = useConfig ();
372
459
const isMainnet = config .environment === ENV_MAIN ;
373
460
@@ -380,6 +467,9 @@ export default defineComponent({
380
467
SwapState ,
381
468
SwapAsset ,
382
469
activeAddressInfo ,
470
+ cryptoAmount ,
471
+ fiatAmount ,
472
+ estimateError ,
383
473
};
384
474
},
385
475
components: {
@@ -406,6 +496,19 @@ export default defineComponent({
406
496
407
497
<style scoped lang="scss">
408
498
.asset-transfer-modal {
499
+ .loading-wrapper {
500
+ display : grid ;
501
+ place-content : center ;
502
+ height : 100% ;
503
+
504
+ .loading-container {
505
+ display : flex ;
506
+ justify-content : center ;
507
+ align-items : center ;
508
+ gap : 2rem ;
509
+ }
510
+ }
511
+
409
512
.asset-transfer-input {
410
513
position : relative ;
411
514
height : 100% ;
0 commit comments