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: 30 seconds recaptcha #948

Merged
merged 1 commit into from
Dec 10, 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
2 changes: 1 addition & 1 deletion src/common/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const routes: Readonly<RouteRecordRaw[]> = [
path: '/pegin/:wallet/create',
name: 'Create',
component: () => import(/* webpackChunkName: "pegin-create" */ '../../pegin/views/Create.vue'),
beforeEnter: checkAcceptedTerms,
beforeEnter: [checkAcceptedTerms, checkFromRoute],
},
{
path: '/:type/success/tx/:txId/:amount/:confirmations',
Expand Down
7 changes: 7 additions & 0 deletions src/common/store/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ export const SESSION_ADD_TERMS_AND_CONDITIONS_ENABLED = 'SESSION_ADD_TERMS_AND_C
export const SESSION_SWITCH_LOCALE = 'SESSION_SWITCH_LOCALE';
export const SESSION_ADD_FEATURES = 'SESSION_ADD_FEATURES';
export const SESSION_ADD_API_VERSION = 'SESSION_ADD_API_VERSION';
export const SESSION_COUNTDOWN_GRECAPTCHA_TIME = 'SESSION_COUNTDOWN_GRECAPTCHA_TIME';
export const SESSION_CLEAR_GRECAPTCHA_INTERVAL = 'SESSION_CLEAR_GRECAPTCHA_INTERVAL';

// Pegin tx Mutations
export const PEGIN_TX_SET_ADDRESS_LIST = 'PEGIN_TX_SET_ADDRESS_LIST';
Expand Down Expand Up @@ -194,6 +196,9 @@ export const SESSION_SET_FEATURES = 'SESSION_SET_FEATURES';
export const SESSION_GET_RBTC_GAS_FEE = 'SESSION_GET_RBTC_GAS_FEE';
export const SESSION_SET_API_VERSION = 'SESSION_SET_API_VERSION';
export const SESSION_SETUP_EVENTS = 'SESSION_SETUP_EVENTS';
export const SESSION_SET_DECREMENT_GRECAPTCHA_COUNTDOWN = 'SESSION_SET_GRECAPTCHA_COUNTDOWN';
export const SESSION_SET_GRECAPTCHA_INTERVAL = 'SESSION_SET_GRECAPTCHA_INTERVAL';
export const SESSION_RESET_GRECAPTCHA_COUNTDOWN = 'SESSION_RESET_GRECAPTCHA_COUNTDOWN';

// Pegin tx getters
export const WALLET_NAME = 'WALLET_NAME';
Expand Down Expand Up @@ -383,3 +388,5 @@ export enum RejectedPegoutReasons {
CALLER_CONTRACT = 'CALLER_CONTRACT',
FEE_ABOVE_VALUE = 'FEE_ABOVE_VALUE',
}

export const RECAPTCHA_NEW_TOKEN_TIME = 30;
17 changes: 17 additions & 0 deletions src/common/store/session/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,21 @@ export const actions: ActionTree<SessionState, RootState> = {
dispatch(constants.WEB3_SESSION_GET_ACCOUNT);
});
},
[constants.SESSION_COUNTDOWN_GRECAPTCHA_TIME]: ({ state, commit, dispatch }) => {
const intervalId = setInterval(() => {
if (state.grecaptchaCountdown > 0) {
commit(constants.SESSION_SET_DECREMENT_GRECAPTCHA_COUNTDOWN);
} else {
dispatch(constants.SESSION_CLEAR_GRECAPTCHA_INTERVAL);
}
}, 1000);
commit(constants.SESSION_SET_GRECAPTCHA_INTERVAL, intervalId);
},
[constants.SESSION_CLEAR_GRECAPTCHA_INTERVAL]: ({ state, commit }) => {
const { grecaptchaIntervalId } = state;
if (grecaptchaIntervalId) {
clearInterval(grecaptchaIntervalId);
commit(constants.SESSION_RESET_GRECAPTCHA_COUNTDOWN);
}
},
};
11 changes: 11 additions & 0 deletions src/common/store/session/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,15 @@ export const mutations: MutationTree<SessionState> = {
[constants.SESSION_SET_API_VERSION]: (state, apiVersion: string) => {
state.apiVersion = apiVersion;
},
[constants.SESSION_RESET_GRECAPTCHA_COUNTDOWN]: (state) => {
state.grecaptchaCountdown = constants.RECAPTCHA_NEW_TOKEN_TIME;
},
[constants.SESSION_SET_DECREMENT_GRECAPTCHA_COUNTDOWN]: (state) => {
if (state.grecaptchaCountdown > 0) {
state.grecaptchaCountdown -= 1;
}
},
[constants.SESSION_SET_GRECAPTCHA_INTERVAL]: (state, intervalId: number) => {
state.grecaptchaIntervalId = intervalId;
},
};
2 changes: 2 additions & 0 deletions src/common/types/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ export interface SessionState {
acceptedTerms?: boolean;
features: Array<Feature>;
apiVersion: string;
grecaptchaCountdown: number;
grecaptchaIntervalId: number | undefined;
}
2 changes: 2 additions & 0 deletions src/common/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ export const getClearSessionState = ():SessionState => (
bitcoinPrice: 0,
features: [],
apiVersion: '',
grecaptchaCountdown: constants.RECAPTCHA_NEW_TOKEN_TIME,
grecaptchaIntervalId: undefined,
}
);

Expand Down
24 changes: 20 additions & 4 deletions src/pegin/components/create/PegInForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,20 @@
<div v-if="showOptions" class="d-flex flex-column ga-2">
<span class="font-weight-bold">Select mode</span>
<v-row no-gutters class="ga-4 ga-lg-8">
<v-col v-if="peginQuotes.length === 0">
<v-col v-if="!flyoverIsEnabled">
<pegin-option-card :option-type="peginType.FLYOVER" flyover-not-available>
<template v-slot>
<h4><span class="text-orange">Fast Mode</span> is unavailable at this time.</h4>
<h4 v-if="countdown === recaptchanNewTokenTime">
<span class="text-orange">Fast Mode</span> is unavailable at this time.
</h4>
<h4 v-else>
Fast mode will be <br> available in
<span class="text-orange">{{ countdown }} seconds.</span>
</h4>
</template>
</pegin-option-card>
</v-col>
<v-col v-for="(quote, index) in peginQuotes" :key="index">
<v-col v-else v-for="(quote, index) in peginQuotes" :key="index">
<pegin-option-card
:option-type="peginType.FLYOVER"
@selected-option="changeSelectedOption"
Expand Down Expand Up @@ -144,6 +150,8 @@ export default defineComponent({
const selectedFee = useGetter<SatoshiBig>('pegInTx', constants.PEGIN_TX_GET_SAFE_TX_FEE);
const selectedAccountBalance = useGetter<SatoshiBig>('pegInTx', constants.PEGIN_TX_GET_SELECTED_BALANCE);
const loadingFee = useStateAttribute<boolean>('pegInTx', 'loadingFee');
const startCountdown = useAction('web3Session', constants.SESSION_COUNTDOWN_GRECAPTCHA_TIME);
const countdown = useStateAttribute<number>('web3Session', 'grecaptchaCountdown');

const enoughAmountFlyover = computed(() => {
if (!selectedQuote.value) {
Expand All @@ -166,6 +174,9 @@ export default defineComponent({
return quoteList;
});

const flyoverIsEnabled = computed(() => props.isFlyoverAvailable
&& countdown.value === constants.RECAPTCHA_NEW_TOKEN_TIME);

function back() {
pegInFormState.value.send('loading');
clearQuotes();
Expand Down Expand Up @@ -193,6 +204,7 @@ export default defineComponent({
peginType: constants.peginType.POWPEG,
});
} else {
startCountdown();
acceptQuote()
.then((acceptedQuote) => {
context.emit('createTx', {
Expand Down Expand Up @@ -288,7 +300,8 @@ export default defineComponent({
return enoughAmountFlyover.value
&& !!flyoverPeginState.value.selectedQuoteHash
&& !!flyoverPeginState.value.rootstockRecipientAddress
&& flyoverPeginState.value.rootstockRecipientAddress !== '0x';
&& flyoverPeginState.value.rootstockRecipientAddress !== '0x'
&& countdown.value === constants.RECAPTCHA_NEW_TOKEN_TIME;
}

return false;
Expand Down Expand Up @@ -344,6 +357,9 @@ export default defineComponent({
validAmount,
validAddress,
sendTx,
flyoverIsEnabled,
countdown,
recaptchanNewTokenTime: constants.RECAPTCHA_NEW_TOKEN_TIME,
};
},
});
Expand Down
88 changes: 50 additions & 38 deletions src/pegout/components/PegoutForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,43 @@
">Select Mode</span>
</v-row>
<v-row>
<v-col cols="6" v-if="!flyoverResponded" >
<pegout-option class="mr-2" flyover-not-available
:option-type="pegoutType.FLYOVER">
<template v-slot>
<h4>
<span class="text-orange">Fast Mode</span> is unavailable at this time.
</h4>
</template>
</pegout-option>
</v-col>
<v-col cols="6" v-for="(quote, index) in pegoutQuotes" :key="index" >
<pegout-option
:option-type="pegoutType.FLYOVER"
:class="index === 0 ? 'mr-2' : 'ml-2'"
:quote="quote"
:isWalletAuthorizedToSign="isWalletAuthorizedToSign"
@openAddressDialog="showAddressDialog = true"
@changeSelectedOption="changeSelectedOption"
:selectedOption="selectedOption === quote.quoteHash"
:quote-difference="quoteDifference"
/>
</v-col>
<v-col cols="6">
<pegout-option class="ml-2"
:option-type="pegoutType.POWPEG"
:quote="nativeQuote"
:isWalletAuthorizedToSign="isWalletAuthorizedToSign"
@openAddressDialog="showAddressDialog = true"
@changeSelectedOption="changeSelectedOption"
:selectedOption="selectedOption === ''"
:quote-differences="quoteDifference"
/>
</v-col>
<v-col cols="6" v-if="!flyoverIsEnabled" >
<pegout-option class="mr-2" flyover-not-available
:option-type="pegoutType.FLYOVER">
<template v-slot>
<h4 v-if="countdown === recaptchanNewTokenTime">
<span class="text-orange">Fast Mode</span> is unavailable at this time.
</h4>
<h4 v-else>
Fast mode will be <br> available in
<span class="text-orange">{{ countdown }} seconds.</span>
</h4>
</template>
</pegout-option>
</v-col>
<v-col cols="6" v-else v-for="(quote, index) in pegoutQuotes" :key="index" >
<pegout-option
:option-type="pegoutType.FLYOVER"
:class="index === 0 ? 'mr-2' : 'ml-2'"
:quote="quote"
:isWalletAuthorizedToSign="isWalletAuthorizedToSign"
@openAddressDialog="showAddressDialog = true"
@changeSelectedOption="changeSelectedOption"
:selectedOption="selectedOption === quote.quoteHash"
:quote-difference="quoteDifference"
/>
</v-col>
<v-col cols="6">
<pegout-option class="ml-2"
:option-type="pegoutType.POWPEG"
:quote="nativeQuote"
:isWalletAuthorizedToSign="isWalletAuthorizedToSign"
@openAddressDialog="showAddressDialog = true"
@changeSelectedOption="changeSelectedOption"
:selectedOption="selectedOption === ''"
:quote-differences="quoteDifference"
/>
</v-col>
</v-row>
</template>
<v-row v-else-if="loadingQuotes" class="pt-4 justify-center">
Expand Down Expand Up @@ -207,6 +211,8 @@ export default defineComponent({
const clearQuotes = useAction('flyoverPegout', constants.FLYOVER_PEGOUT_CLEAR_QUOTES);
const amountToTransfer = useStateAttribute<WeiBig>('flyoverPegout', 'amountToTransfer');
const liquidityProviders = useStateAttribute<LiquidityProvider2WP[]>('flyoverPegout', 'liquidityProviders');
const startCountdown = useAction('web3Session', constants.SESSION_COUNTDOWN_GRECAPTCHA_TIME);
const countdown = useStateAttribute<number>('web3Session', 'grecaptchaCountdown');

const pegoutQuotes = computed(() => {
const quoteList: QuotePegOut2WP[] = [];
Expand Down Expand Up @@ -297,10 +303,12 @@ export default defineComponent({

const isValid = computed(() => {
if (selectedQuote.value === undefined) return !loadingQuotes.value && isReadyToCreate.value;
return !loadingQuotes.value && isFlyoverReady.value;
return !loadingQuotes.value && isFlyoverReady.value
&& countdown.value === constants.RECAPTCHA_NEW_TOKEN_TIME;
});

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

function handlePegoutError(error: ServiceError) {
txError.value = error;
Expand Down Expand Up @@ -407,8 +415,10 @@ export default defineComponent({
: TxStatusType.PEGOUT.toLowerCase();
pegOutFormState.value.send('loading');
try {
if (quoteHash) await sendFlyoverTx(quoteHash);
else await sendTx();
if (quoteHash) {
startCountdown();
await sendFlyoverTx(quoteHash);
} else await sendTx();
ApiService.registerTx(quoteHash ? registerFlyover.value : registerPegout.value);
changePage(type);
} catch (e) {
Expand Down Expand Up @@ -554,10 +564,12 @@ export default defineComponent({
nativeQuote,
pegoutType: constants.pegoutType,
isValid,
flyoverResponded,
flyoverIsEnabled,
clearForError,
clearAmount,
checkValidAmount,
countdown,
recaptchanNewTokenTime: constants.RECAPTCHA_NEW_TOKEN_TIME,
};
},
});
Expand Down
Loading