Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: do not show countdown while a transaction is being processed #979

Merged
merged 2 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .env.local.test
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ VUE_APP_LBC_ADDRESS='0xc2A630c053D12D63d32b025082f6Ba268db18300'
VUE_APP_DEBUG_MODE='true'

NODE_ENV=test
VUE_APP_FLYOVER_PEGOUT_QUOTE_DIFF_PERCENTAGE=2 # 2%
VUE_APP_FLYOVER_PEGOUT_QUOTE_DIFF_PERCENTAGE=2
VUE_APP_RECAPTCHA_NEW_TOKEN_TIME=30

1 change: 1 addition & 0 deletions .github/workflows/deploy_MainNet_UI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ jobs:
VUE_APP_SLOW_MINING_BLOCK=5
VUE_APP_LBC_ADDRESS='0xAA9cAf1e3967600578727F975F283446A3Da6612'
VUE_APP_FLYOVER_PEGOUT_QUOTE_DIFF_PERCENTAGE=2
VUE_APP_RECAPTCHA_NEW_TOKEN_TIME=30
npm run-script build

- name: Configure AWS credentials
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/deploy_TestNet_UI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ jobs:
VUE_APP_SLOW_MINING_BLOCK=5
VUE_APP_LBC_ADDRESS='0xc2A630c053D12D63d32b025082f6Ba268db18300'
VUE_APP_FLYOVER_PEGOUT_QUOTE_DIFF_PERCENTAGE=2
VUE_APP_RECAPTCHA_NEW_TOKEN_TIME=30
npm run-script build

- name: Configure AWS credentials
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/deploy_staging_MainNet_UI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ jobs:
VUE_APP_SLOW_MINING_BLOCK=5
VUE_APP_LBC_ADDRESS='0xAA9cAf1e3967600578727F975F283446A3Da6612'
VUE_APP_FLYOVER_PEGOUT_QUOTE_DIFF_PERCENTAGE=2
VUE_APP_RECAPTCHA_NEW_TOKEN_TIME=30
npm run-script build

- name: Configure AWS credentials
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/deploy_staging_TestNet_UI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ jobs:
VUE_APP_SLOW_MINING_BLOCK=5
VUE_APP_LBC_ADDRESS='0xc2A630c053D12D63d32b025082f6Ba268db18300'
VUE_APP_FLYOVER_PEGOUT_QUOTE_DIFF_PERCENTAGE=20
VUE_APP_RECAPTCHA_NEW_TOKEN_TIME=30
npm run-script build

- name: Configure AWS credentials
Expand Down
1 change: 1 addition & 0 deletions ENV_VARIABLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The value of these variables are used in **environment-variables.ts** file.
|VUE_APP_LBC_ADDRESS | `0xc2A630c053D12D63d32b025082f6Ba268db18300` | Liquidity bridge contract address on the flyover protocol |
|VUE_APP_DEBUG_MODE | `false` | enable developer messages for debuging |
|VUE_APP_FLYOVER_PEGOUT_QUOTE_DIFF_PERCENTAGE | `2` | Defines quote difference percentage to 2% so it requieres the user to review condition only for a difference bigger that this percentage |
|VUE_APP_RECAPTCHA_NEW_TOKEN_TIME | `30` | Specifies the time (in seconds) to temporarily disable the flyover between new transactions. This accounts for the time required by Google reCAPTCHA to regenerate a challenge token |

## Example for .env.local.test file

Expand Down
1 change: 1 addition & 0 deletions src/common/store/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
4 changes: 3 additions & 1 deletion src/common/store/session/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { TransactionType, SessionState } from '@/common/types/session';
import { getClearSessionState } from '@/common/utils';
import { providers } from 'ethers';
import i18n from '@/i18n';
import { EnvironmentAccessorService } from '@/common/services/enviroment-accessor.service';

export const mutations: MutationTree<SessionState> = {
[constants.SESSION_SET_ACCOUNT]: (state, account: string) => {
Expand Down Expand Up @@ -58,7 +59,8 @@ export const mutations: MutationTree<SessionState> = {
state.apiVersion = apiVersion;
},
[constants.SESSION_RESET_GRECAPTCHA_COUNTDOWN]: (state) => {
state.grecaptchaCountdown = constants.RECAPTCHA_NEW_TOKEN_TIME;
state.grecaptchaCountdown = EnvironmentAccessorService.getEnvironmentVariables()
.grecaptchaTime;
},
[constants.SESSION_SET_DECREMENT_GRECAPTCHA_COUNTDOWN]: (state) => {
if (state.grecaptchaCountdown > 0) {
Expand Down
6 changes: 0 additions & 6 deletions src/common/types/Common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
15 changes: 14 additions & 1 deletion src/common/types/Flyover/FlyoverPegout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,21 @@ import { FlyoverService } from '../../services';
import SatoshiBig from '../SatoshiBig';
import WeiBig from '../WeiBig';

export interface ReducedQuote {
gasFee: WeiBig;
callFee: WeiBig;
productFeeAmount: WeiBig;
value: WeiBig;
quoteHash: string;
}
export interface ObjectDifference {
percentage: number;
previousQuote: ReducedQuote;
currentQuote: ReducedQuote;
}

export interface FlyoverPegoutState {
difference: number;
difference: ObjectDifference;
amountToTransfer: WeiBig;
validAmount: boolean;
btcRecipientAddress: string;
Expand Down
4 changes: 4 additions & 0 deletions src/common/types/environment-variables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export class EnvironmentVariables {

public flyoverPegoutDiffPercentage: number;

public grecaptchaTime: number;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor(defaultValues: any = {}) {
this.vueAppCoin = process.env.VUE_APP_COIN || defaultValues.vueAppCoin;
Expand Down Expand Up @@ -96,6 +98,8 @@ export class EnvironmentVariables {
|| defaultValues.flyoverGetProvidersTimeout;
this.flyoverPegoutDiffPercentage = Number(process.env
.VUE_APP_FLYOVER_PEGOUT_QUOTE_DIFF_PERCENTAGE) || defaultValues.flyoverPegoutDiffPercentage;
this.grecaptchaTime = Number(process.env.VUE_APP_RECAPTCHA_NEW_TOKEN_TIME)
|| defaultValues.grecaptchaTime;
}

public get chainId(): number {
Expand Down
51 changes: 20 additions & 31 deletions src/common/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ 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';
import { markRaw } from 'vue';
import * as constants from '@/common/store/constants';
import { EnvironmentAccessorService } from '@/common/services/enviroment-accessor.service';

export const getChunkedValue = (value: string, maxLength: number) => (value.length < maxLength ? value : `${value.substr(0, maxLength / 2)}...${value.substr(value.length - maxLength / 2, value.length)}`);

Expand Down Expand Up @@ -83,7 +85,7 @@ export const getClearPegoutTxState = (): PegOutTxState => ({
selectedFee: BITCOIN_AVERAGE_FEE_LEVEL,
});

export const getClearSessionState = ():SessionState => (
export const getClearSessionState = (): SessionState => (
{
account: undefined,
ethersProvider: undefined,
Expand All @@ -96,11 +98,26 @@ export const getClearSessionState = ():SessionState => (
bitcoinPrice: 0,
features: [],
apiVersion: '',
grecaptchaCountdown: constants.RECAPTCHA_NEW_TOKEN_TIME,
grecaptchaCountdown: EnvironmentAccessorService.getEnvironmentVariables().grecaptchaTime
?? constants.RECAPTCHA_NEW_TOKEN_TIME,
grecaptchaIntervalId: undefined,
}
);

export const getClearReducedQuote = (): ReducedQuote => ({
gasFee: new WeiBig(0, 'wei'),
callFee: new WeiBig(0, 'wei'),
productFeeAmount: new WeiBig(0, 'wei'),
value: new WeiBig(0, 'wei'),
quoteHash: '',
});

export const getClearObjectDifference = (): ObjectDifference => ({
percentage: 0,
previousQuote: getClearReducedQuote(),
currentQuote: getClearReducedQuote(),
});

export const getClearFlyoverPegoutState = (): FlyoverPegoutState => ({
amountToTransfer: new WeiBig(0, 'wei'),
validAmount: false,
Expand All @@ -110,7 +127,7 @@ export const getClearFlyoverPegoutState = (): FlyoverPegoutState => ({
quotes: {},
flyoverService: markRaw(new FlyoverService()),
selectedQuoteHash: '',
difference: 0,
difference: getClearObjectDifference(),
});

export const getClearFlyoverPeginState = (): FlyoverPeginState => ({
Expand All @@ -124,31 +141,3 @@ export const getClearFlyoverPeginState = (): FlyoverPeginState => ({
selectedQuoteHash: '',
acceptedQuoteSignature: '',
});

export const compareObjects = (
obj1: { [key: string]: unknown },
obj2: { [key: string]: unknown },
): Array<ObjectDifference> => {
if (Object.getPrototypeOf(obj1) !== Object.getPrototypeOf(obj2)) {
throw new Error('Objects has different prototype');
}
const differences: Array<ObjectDifference> = [];
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;
};
1 change: 1 addition & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const defaultEnvironmentVariables = {
burnDustValue: 2000,
flyoverGetProvidersTimeout: 5000,
flyoverPegoutDiffPercentage: 2,
grecaptchaTime: constants.RECAPTCHA_NEW_TOKEN_TIME,
};

EnvironmentAccessorService.initializeEnvironmentVariables(defaultEnvironmentVariables);
Expand Down
18 changes: 14 additions & 4 deletions src/pegin/components/create/PegInForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ import { FlyoverService } from '@/common/services';
import FullTxErrorDialog from '@/common/components/exchange/FullTxErrorDialog.vue';
import RskDestinationAddress from '@/pegin/components/create/RskDestinationAddress.vue';
import { AcceptedQuote } from '@rsksmart/flyover-sdk';
import { EnvironmentAccessorService } from '@/common/services/enviroment-accessor.service';

export default defineComponent({
name: 'PegInForm',
Expand Down Expand Up @@ -152,6 +153,8 @@ export default defineComponent({
const loadingFee = useStateAttribute<boolean>('pegInTx', 'loadingFee');
const startCountdown = useAction('web3Session', constants.SESSION_COUNTDOWN_GRECAPTCHA_TIME);
const countdown = useStateAttribute<number>('web3Session', 'grecaptchaCountdown');
const recaptchanNewTokenTime = EnvironmentAccessorService.getEnvironmentVariables()
.grecaptchaTime;

const enoughAmountFlyover = computed(() => {
if (!selectedQuote.value) {
Expand All @@ -161,6 +164,8 @@ export default defineComponent({
return selectedAccountBalance.value?.gte(fullAmount);
});

const sendingPegin = computed(():boolean => pegInFormState.value.matches(['loading']));

const peginQuotes = computed(() => {
if (!props.isFlyoverAvailable) {
return [];
Expand All @@ -174,8 +179,13 @@ export default defineComponent({
return quoteList;
});

const flyoverIsEnabled = computed(() => props.isFlyoverAvailable
&& countdown.value === constants.RECAPTCHA_NEW_TOKEN_TIME);
const flyoverIsEnabled = computed(() => {
if (props.isFlyoverAvailable) {
if (sendingPegin.value) return true;
return countdown.value === recaptchanNewTokenTime;
}
return false;
});

function back() {
pegInFormState.value.send('loading');
Expand Down Expand Up @@ -300,7 +310,7 @@ export default defineComponent({
&& !!flyoverPeginState.value.selectedQuoteHash
&& !!flyoverPeginState.value.rootstockRecipientAddress
&& flyoverPeginState.value.rootstockRecipientAddress !== '0x'
&& countdown.value === constants.RECAPTCHA_NEW_TOKEN_TIME;
&& countdown.value === recaptchanNewTokenTime;
}

return false;
Expand Down Expand Up @@ -358,7 +368,7 @@ export default defineComponent({
sendTx,
flyoverIsEnabled,
countdown,
recaptchanNewTokenTime: constants.RECAPTCHA_NEW_TOKEN_TIME,
recaptchanNewTokenTime,
};
},
});
Expand Down
40 changes: 30 additions & 10 deletions src/pegout/components/PegoutForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
/>
</template>
<quote-diff-dialog :show-dialog="showQuoteDiff"
:differences="quoteDifference" @continue="continueHandler"/>
:differences="quoteDifference" @continue="continueHandler" @cancel="clearForError" />
<div id="recaptcha" class="g-recaptcha"
:data-sitekey="flyoverService.siteKey"
data-callback="onRecaptchaSuccess"
Expand All @@ -139,7 +139,8 @@ import {
} from '@/common/store/helper';
import { mdiArrowLeft, mdiArrowRight } from '@mdi/js';
import {
FlyoverPegoutState, LiquidityProvider2WP, PegoutQuoteDbModel, PegOutTxState, QuotePegOut2WP,
FlyoverPegoutState, LiquidityProvider2WP, ObjectDifference,
PegoutQuoteDbModel, PegOutTxState, QuotePegOut2WP,
SatoshiBig, TxInfo, TxStatusType, WeiBig,
} from '@/common/types';
import {
Expand Down Expand Up @@ -186,14 +187,15 @@ export default defineComponent({
const balance = useStateAttribute<WeiBig>('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);
const clearPegoutTx = useAction('pegOutTx', constants.PEGOUT_TX_CLEAR);
const getPegoutQuotes = useAction('flyoverPegout', constants.FLYOVER_PEGOUT_GET_QUOTES);
const ethersProvider = useStateAttribute<providers.Web3Provider>('web3Session', 'ethersProvider');
const quotes = useStateAttribute<Record<number, QuotePegOut2WP[]>>('flyoverPegout', 'quotes');
const quoteDifference = useStateAttribute<number>('flyoverPegout', 'difference');
const quoteDifference = useStateAttribute<ObjectDifference>('flyoverPegout', 'difference');
const selectedQuote = useGetter<QuotePegOut2WP>('flyoverPegout', constants.FLYOVER_PEGOUT_GET_SELECTED_QUOTE);
const estimatedBtcToReceive = useGetter<SatoshiBig>('pegOutTx', constants.PEGOUT_TX_GET_ESTIMATED_BTC_TO_RECEIVE);
const isEnoughBalance = useGetter<boolean>('pegOutTx', constants.PEGOUT_TX_IS_ENOUGH_BALANCE);
Expand All @@ -213,6 +215,8 @@ export default defineComponent({
const liquidityProviders = useStateAttribute<LiquidityProvider2WP[]>('flyoverPegout', 'liquidityProviders');
const startCountdown = useAction('web3Session', constants.SESSION_COUNTDOWN_GRECAPTCHA_TIME);
const countdown = useStateAttribute<number>('web3Session', 'grecaptchaCountdown');
const recaptchanNewTokenTime = EnvironmentAccessorService.getEnvironmentVariables()
.grecaptchaTime;

const pegoutQuotes = computed(() => {
const quoteList: QuotePegOut2WP[] = [];
Expand All @@ -239,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));
Expand Down Expand Up @@ -305,11 +309,16 @@ export default defineComponent({
const isValid = computed(() => {
if (selectedQuote.value === undefined) return !loadingQuotes.value && isReadyToCreate.value;
return !loadingQuotes.value && isFlyoverReady.value
&& countdown.value === constants.RECAPTCHA_NEW_TOKEN_TIME;
&& countdown.value === recaptchanNewTokenTime;
});

const showCountdown = computed(() => {
if (sendingPegout.value || diffShown.value) return true;
return countdown.value === recaptchanNewTokenTime;
});

const flyoverIsEnabled = computed(() => pegoutQuotes.value.length > 0
&& props.flyoverEnabled && countdown.value === constants.RECAPTCHA_NEW_TOKEN_TIME);
&& props.flyoverEnabled && showCountdown.value);

function handlePegoutError(error: ServiceError) {
txError.value = error;
Expand Down Expand Up @@ -505,13 +514,24 @@ export default defineComponent({
}
}

function continueHandler() {
setSelectedQuoteHash('');
selectedOption.value = '';
async function continueHandler() {
diffShown.value = false;
pegOutFormState.value.send('loading');
try {
await sendFlyoverTxWithConditionChanged();
ApiService.registerTx(registerFlyover.value);
changePage(TxStatusType.FLYOVER_PEGOUT.toLowerCase());
} catch (e) {
if (e instanceof ServiceError) {
handlePegoutError(e);
}
} finally {
pegOutFormState.value.send('fill');
}
}

function clearForError() {
diffShown.value = false;
showTxErrorDialog.value = false;
clearAmount.value = true;
}
Expand Down Expand Up @@ -569,7 +589,7 @@ export default defineComponent({
clearAmount,
checkValidAmount,
countdown,
recaptchanNewTokenTime: constants.RECAPTCHA_NEW_TOKEN_TIME,
recaptchanNewTokenTime,
};
},
});
Expand Down
Loading
Loading