diff --git a/src/common/store/constants.ts b/src/common/store/constants.ts index c7ef40dc..67404a51 100644 --- a/src/common/store/constants.ts +++ b/src/common/store/constants.ts @@ -81,6 +81,7 @@ export const FLYOVER_PEGOUT_CLEAR_QUOTES = 'FLYOVER_PEGOUT_CLEAR_QUOTES'; export const FLYOVER_PEGOUT_SET_SELECTED_QUOTE_HASH = 'FLYOVER_PEGOUT_SET_SELECTED_QUOTE_HASH'; export const FLYOVER_PEGOUT_CLEAR_QUOTE_DIFFERENCES = 'FLYOVER_PEGOUT_CLEAR_QUOTE_DIFFERENCES'; export const FLYOVER_PEGOUT_GET_AVAILABLE_LIQUIDITY = 'FLYOVER_PEGOUT_GET_AVAILABLE_LIQUIDITY'; +export const FLYOVER_PEGOUT_ACCEPT_AND_SEND_QUOTE_WITH_CHANGED_CONDITIONS = 'FLYOVER_PEGOUT_ACCEPT_AND_SEND_QUOTE_WITH_CHANGED_CONDITIONS'; // Flyover PegIn actions export const FLYOVER_PEGIN_INIT = 'FLYOVER_PEGIN_INIT'; diff --git a/src/common/types/Common.ts b/src/common/types/Common.ts index c7d007e3..f6f1f19a 100644 --- a/src/common/types/Common.ts +++ b/src/common/types/Common.ts @@ -132,12 +132,6 @@ export interface NormalizedSummary { export type AddressType = 'BITCOIN_LEGACY_ADDRESS' | 'BITCOIN_SEGWIT_ADDRESS' | 'BITCOIN_NATIVE_SEGWIT_ADDRESS' | 'BITCOIN_MULTISIGNATURE_ADDRESS' | 'BITCOIN_UNKNOWN_ADDRESS_TYPE'; -export interface ObjectDifference { - key: string; - oldValue: unknown; - newValue: unknown; -} - export enum AppLocale { LOCALE_EN = 'en', LOCALE_ES = 'es', diff --git a/src/common/types/Flyover/FlyoverPegout.ts b/src/common/types/Flyover/FlyoverPegout.ts index 9b2e8db0..0fd84363 100644 --- a/src/common/types/Flyover/FlyoverPegout.ts +++ b/src/common/types/Flyover/FlyoverPegout.ts @@ -3,8 +3,20 @@ import { FlyoverService } from '../../services'; import SatoshiBig from '../SatoshiBig'; import WeiBig from '../WeiBig'; +export interface ReducedQuote { + gasFee: WeiBig; + callFee: WeiBig; + productFeeAmount: WeiBig; + value: WeiBig; +} +export interface ObjectDifference { + percentage: number; + previousQuote: ReducedQuote; + currentQuote: ReducedQuote; +} + export interface FlyoverPegoutState { - difference: number; + difference: ObjectDifference; amountToTransfer: WeiBig; validAmount: boolean; btcRecipientAddress: string; diff --git a/src/common/types/environment-variables.ts b/src/common/types/environment-variables.ts index 3b90cf31..62360ae2 100644 --- a/src/common/types/environment-variables.ts +++ b/src/common/types/environment-variables.ts @@ -97,7 +97,7 @@ export class EnvironmentVariables { this.flyoverGetProvidersTimeout = Number(process.env.VUE_APP_FLYOVER_GET_PROVIDERS_TIMEOUT) || defaultValues.flyoverGetProvidersTimeout; this.flyoverPegoutDiffPercentage = Number(process.env - .VUE_APP_FLYOVER_PEGOUT_QUOTE_DIFF_PERCENTAGE) || defaultValues.flyoverPegoutDiffPercentage; + .VUE_APP_FLYOVER_PEGOUT_QUOTE_DIFF_PERCENTAGE) ?? defaultValues.flyoverPegoutDiffPercentage; this.grecaptchaTime = Number(process.env.VUE_APP_RECAPTCHA_NEW_TOKEN_TIME) || defaultValues.grecaptchaTime; } diff --git a/src/common/utils/common.ts b/src/common/utils/common.ts index ef61e40d..5a9d150f 100644 --- a/src/common/utils/common.ts +++ b/src/common/utils/common.ts @@ -4,6 +4,7 @@ import { BITCOIN_AVERAGE_FEE_LEVEL } from '@/common/store/constants'; import { FlyoverPeginState, FlyoverPegoutState, ObjectDifference, PegOutTxState, + ReducedQuote, SessionState, WeiBig, } from '@/common/types'; import { FlyoverService } from '@/common/services'; @@ -103,6 +104,19 @@ export const getClearSessionState = (): SessionState => ( } ); +export const getClearReducedQuote = (): ReducedQuote => ({ + gasFee: new WeiBig(0, 'wei'), + callFee: new WeiBig(0, 'wei'), + productFeeAmount: new WeiBig(0, 'wei'), + value: new WeiBig(0, 'wei'), +}); + +export const getClearObjectDifference = (): ObjectDifference => ({ + percentage: 0, + previousQuote: getClearReducedQuote(), + currentQuote: getClearReducedQuote(), +}); + export const getClearFlyoverPegoutState = (): FlyoverPegoutState => ({ amountToTransfer: new WeiBig(0, 'wei'), validAmount: false, @@ -112,7 +126,7 @@ export const getClearFlyoverPegoutState = (): FlyoverPegoutState => ({ quotes: {}, flyoverService: markRaw(new FlyoverService()), selectedQuoteHash: '', - difference: 0, + difference: getClearObjectDifference(), }); export const getClearFlyoverPeginState = (): FlyoverPeginState => ({ @@ -126,31 +140,3 @@ export const getClearFlyoverPeginState = (): FlyoverPeginState => ({ selectedQuoteHash: '', acceptedQuoteSignature: '', }); - -export const compareObjects = ( - obj1: { [key: string]: unknown }, - obj2: { [key: string]: unknown }, -): Array => { - if (Object.getPrototypeOf(obj1) !== Object.getPrototypeOf(obj2)) { - throw new Error('Objects has different prototype'); - } - const differences: Array = []; - Object.keys(obj1).forEach((key) => { - if (obj1[key] instanceof WeiBig && obj2[key] instanceof WeiBig) { - if (!(obj1[key] as WeiBig).eq(obj2[key] as WeiBig)) { - differences.push({ - key, - oldValue: (obj1[key] as WeiBig).toRBTCString(), - newValue: (obj2[key] as WeiBig).toRBTCString(), - }); - } - } else if (obj1[key] !== obj2[key]) { - differences.push({ - key, - oldValue: obj1[key], - newValue: obj2[key], - }); - } - }); - return differences; -}; diff --git a/src/pegout/components/PegoutForm.vue b/src/pegout/components/PegoutForm.vue index 47c5777d..ff88a950 100644 --- a/src/pegout/components/PegoutForm.vue +++ b/src/pegout/components/PegoutForm.vue @@ -116,7 +116,7 @@ /> + :differences="quoteDifference" @continue="continueHandler" @cancel="clearForError" />
('web3Session', 'balance'); const sendTx = useAction('pegOutTx', constants.PEGOUT_TX_SEND); const sendFlyoverTx = useAction('flyoverPegout', constants.FLYOVER_PEGOUT_ACCEPT_AND_SEND_QUOTE); + const sendFlyoverTxWithConditionChanged = useAction('flyoverPegout', constants.FLYOVER_PEGOUT_ACCEPT_AND_SEND_QUOTE_WITH_CHANGED_CONDITIONS); const initFlyoverTx = useAction('flyoverPegout', constants.FLYOVER_PEGOUT_INIT); const initPegoutTx = useAction('pegOutTx', constants.PEGOUT_TX_INIT); const clearFlyoverState = useAction('flyoverPegout', constants.FLYOVER_PEGOUT_CLEAR_STATE); @@ -193,7 +195,7 @@ export default defineComponent({ const getPegoutQuotes = useAction('flyoverPegout', constants.FLYOVER_PEGOUT_GET_QUOTES); const ethersProvider = useStateAttribute('web3Session', 'ethersProvider'); const quotes = useStateAttribute>('flyoverPegout', 'quotes'); - const quoteDifference = useStateAttribute('flyoverPegout', 'difference'); + const quoteDifference = useStateAttribute('flyoverPegout', 'difference'); const selectedQuote = useGetter('flyoverPegout', constants.FLYOVER_PEGOUT_GET_SELECTED_QUOTE); const estimatedBtcToReceive = useGetter('pegOutTx', constants.PEGOUT_TX_GET_ESTIMATED_BTC_TO_RECEIVE); const isEnoughBalance = useGetter('pegOutTx', constants.PEGOUT_TX_IS_ENOUGH_BALANCE); @@ -241,7 +243,7 @@ export default defineComponent({ return ''; }); - const showQuoteDiff = computed(() => quoteDifference.value > quoteDiffPercentage + const showQuoteDiff = computed(() => quoteDifference.value.percentage > quoteDiffPercentage && diffShown.value); const validAmountToReceive = computed((): boolean => estimatedBtcToReceive.value.gt(0)); @@ -311,7 +313,7 @@ export default defineComponent({ }); const showCountdown = computed(() => { - if (sendingPegout.value) return true; + if (sendingPegout.value || diffShown.value) return true; return countdown.value === recaptchanNewTokenTime; }); @@ -512,13 +514,22 @@ export default defineComponent({ } } - function continueHandler() { - setSelectedQuoteHash(''); - selectedOption.value = ''; + async function continueHandler() { diffShown.value = false; + pegOutFormState.value.send('loading'); + try { + await sendFlyoverTxWithConditionChanged(); + } catch (e) { + if (e instanceof ServiceError) { + handlePegoutError(e); + } + } finally { + pegOutFormState.value.send('fill'); + } } function clearForError() { + diffShown.value = false; showTxErrorDialog.value = false; clearAmount.value = true; } diff --git a/src/pegout/components/QuoteDiffDialog.vue b/src/pegout/components/QuoteDiffDialog.vue index fb35522e..6abef12b 100644 --- a/src/pegout/components/QuoteDiffDialog.vue +++ b/src/pegout/components/QuoteDiffDialog.vue @@ -1,37 +1,59 @@