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

feat(bridge-ui): more informative processing fee #13488

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
dfe1e6d
ProcessingFee refactoring
jscriptcoder Mar 28, 2023
fa5a504
Store value in localStorage
jscriptcoder Mar 28, 2023
764b008
Fix storing opt-in/out
jscriptcoder Mar 28, 2023
a429c5e
Add Button component
jscriptcoder Mar 28, 2023
2f79c3b
Minor change
jscriptcoder Mar 28, 2023
957d587
wip
jscriptcoder Mar 28, 2023
1345e67
Transaction refactoring
jscriptcoder Mar 28, 2023
d424408
OptInOutTooltip component
jscriptcoder Mar 28, 2023
a64c233
Add opt in/out to claim
jscriptcoder Mar 28, 2023
2faaafd
Minor fix
jscriptcoder Mar 28, 2023
7228cb2
Merge branch 'main' into 13476-featbridge-ui-uiux-suggestion-to-bette…
jscriptcoder Mar 29, 2023
f28032a
Add some comments
jscriptcoder Mar 29, 2023
c4ca359
Improve types
jscriptcoder Mar 29, 2023
8a18590
Correct notice message
jscriptcoder Mar 29, 2023
b17d23a
Rename component
jscriptcoder Mar 29, 2023
f5727b9
Minor changes
jscriptcoder Mar 29, 2023
c9fd206
Revert change on TooltipModal
jscriptcoder Mar 29, 2023
ef02d79
Rename Notice modal
jscriptcoder Mar 29, 2023
a2c901d
Typo
jscriptcoder Mar 29, 2023
4400758
Minor change
jscriptcoder Mar 29, 2023
7404a31
Fix label association
jscriptcoder Mar 29, 2023
a13d16a
Merge branch 'main' into 13476-featbridge-ui-uiux-suggestion-to-bette…
jscriptcoder Mar 29, 2023
8b49ac4
Typo
jscriptcoder Mar 30, 2023
fd94471
Merge branch 'main' into 13476-featbridge-ui-uiux-suggestion-to-bette…
jscriptcoder Mar 30, 2023
e7db765
Fix wrong constant
jscriptcoder Mar 30, 2023
f255e72
Add TODO
jscriptcoder Mar 30, 2023
2ba7871
Fix some eslint warnigs
jscriptcoder Mar 30, 2023
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
23 changes: 9 additions & 14 deletions packages/bridge-ui/src/components/form/BridgeForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
import { LottiePlayer } from '@lottiefiles/svelte-lottie-player';

import { token } from '../../store/token';
import { processingFee } from '../../store/fee';
import { fromChain, toChain } from '../../store/chain';
import { activeBridge, bridgeType } from '../../store/bridge';
import { signer } from '../../store/signer';
import { BigNumber, Contract, ethers, Signer } from 'ethers';
import ProcessingFee from './ProcessingFee.svelte';
import ProcessingFee from './ProcessingFee';
import SelectToken from '../buttons/SelectToken.svelte';

import type { Token } from '../../domain/token';
Expand All @@ -21,7 +20,6 @@
transactioner,
transactions as transactionsStore,
} from '../../store/transactions';
import { ProcessingFeeMethod } from '../../domain/fee';
import Memo from './Memo.svelte';
import ERC20_ABI from '../../constants/abi/ERC20';
import TokenVaultABI from '../../constants/abi/TokenVault';
Expand All @@ -39,20 +37,21 @@
import { providers } from '../../provider/providers';
import { tokenVaults } from '../../vault/tokenVaults';
import { isOnCorrectChain } from '../../utils/isOnCorrectChain';
import { ProcessingFeeMethod } from '../../domain/fee';

let amount: string;
let amountInput: HTMLInputElement;
let requiresAllowance: boolean = false;
let btnDisabled: boolean = true;
let tokenBalance: string;
let customFee: string = '0';
let recommendedFee: string = '0';
let memo: string = '';
let loading: boolean = false;
let isFaucetModalOpen: boolean = false;
let memoError: string;
let to: string = '';
let showTo: boolean = false;
let feeMethod: ProcessingFeeMethod = ProcessingFeeMethod.RECOMMENDED;
let feeAmount: string = '0';

// TODO: too much going on here. We need to extract
// logic and unit test the hell out of all this.
Expand Down Expand Up @@ -333,10 +332,12 @@
memo: memo,
to: showTo && to ? to : await $signer.getAddress(),
});

const requiredGas = gasEstimate.mul(feeData.gasPrice);
const userBalance = await $signer.getBalance('latest');
const processingFee = getProcessingFee();
let balanceAvailableForTx = userBalance.sub(requiredGas);

if (processingFee) {
balanceAvailableForTx = balanceAvailableForTx.sub(processingFee);
}
Expand All @@ -362,17 +363,11 @@
}

function getProcessingFee() {
if ($processingFee === ProcessingFeeMethod.NONE) {
if (feeMethod === ProcessingFeeMethod.NONE) {
return undefined;
}

if ($processingFee === ProcessingFeeMethod.CUSTOM) {
return BigNumber.from(ethers.utils.parseEther(customFee));
}

if ($processingFee === ProcessingFeeMethod.RECOMMENDED) {
return BigNumber.from(ethers.utils.parseEther(recommendedFee));
}
return BigNumber.from(ethers.utils.parseEther(feeAmount));
}

$: getUserBalance($signer, $token, $fromChain);
Expand Down Expand Up @@ -458,7 +453,7 @@

<To bind:showTo bind:to />

<ProcessingFee bind:customFee bind:recommendedFee />
<ProcessingFee bind:method={feeMethod} bind:amount={feeAmount} />

<Memo bind:memo bind:memoError />

Expand Down
108 changes: 0 additions & 108 deletions packages/bridge-ui/src/components/form/ProcessingFee.svelte

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<script>
import { onMount } from 'svelte';
import { localStoragePrefix } from '../../../config';
import TooltipModal from '../../modals/TooltipModal.svelte';

export let show = false;

let noShowAgainLocalStorageKey = `${localStoragePrefix}_NoneFeeTooltip_noShowAgain`;
let noShowAgainStorage = false;
let noShowAgainCheckbox = false;

onMount(() => {
// Has the user opted out of seeing this message?
noShowAgainStorage = Boolean(
localStorage.getItem(noShowAgainLocalStorageKey),
);
noShowAgainCheckbox = noShowAgainStorage;
});

function onConfirmNotice() {
if (noShowAgainCheckbox) {
// If checkbox is checked, store it in localStorage so
// the user doesn't see the message again.
localStorage.setItem(noShowAgainLocalStorageKey, 'true');
noShowAgainStorage = true;
}

show = false;
}
</script>

<!--
TODO: we might want noShowAgainStorage to be dynamic, otherwise
the user will have to refresh the page to see the message again
if they delete the localStorage entry.
-->
<TooltipModal title="Notice" isOpen={show && !noShowAgainStorage}>
<div slot="body" class="space-y-6">
<!-- TODO: translations? -->
<div class="text-center">
Selecting <strong>None</strong> means that you'll require ETH on the receiving
chain in otder to claim the bridged token. Pleas, come back later to manually
claim.
</div>

<div class="text-left flex items-center">
<input
style:border-radius="0.5rem"
type="checkbox"
id="noShowAgain"
bind:checked={noShowAgainCheckbox}
class="checkbox checkbox-secundary mr-2" />
<label for="noShowAgain">Do not show this message again</label>
</div>

<div class="flex justify-center">
<button
class="confirm btn btn-accent btn-md btn-wide"
on:click={onConfirmNotice}>
Confirm
</button>
</div>
</div>
</TooltipModal>

<style>
.confirm {
/* TODO: design needed for buttons */
height: 54px;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<script lang="ts">
import { _ } from 'svelte-i18n';
import { ProcessingFeeMethod } from '../../../domain/fee';
import { toChain, fromChain } from '../../../store/chain';
import { token } from '../../../store/token';
import { signer } from '../../../store/signer';
import { recommendProcessingFee } from '../../../utils/recommendProcessingFee';
import ButtonWithTooltip from '../../ButtonWithTooltip.svelte';
import { processingFees } from '../../../fee/processingFees';
import GeneralTooltip from './ProcessingFeeTooltip.svelte';
import NoneFeeTooltip from './NoneFeeTooltip.svelte';

export let method: ProcessingFeeMethod = ProcessingFeeMethod.RECOMMENDED;
export let amount: string = '0';

let showProcessingFeeTooltip: boolean = false;
let showNoneFeeTooltip: boolean = false;

$: recommendProcessingFee($toChain, $fromChain, method, $token, $signer)
.then((recommendedFee) => (amount = recommendedFee))
.catch((e) => console.error(e));

function updateAmount(event: Event) {
const target = event.target as HTMLInputElement;
amount = target.value.toString();
}

function focus(input: HTMLInputElement) {
input.select();
}

function selectFee(selectedMethod: ProcessingFeeMethod) {
return () => {
method = selectedMethod;
if (selectedMethod === ProcessingFeeMethod.NONE) {
showNoneFeeTooltip = true;
}
};
}
</script>

<div class="my-10">
<div class="flex flex-row justify-between">
<ButtonWithTooltip onClick={() => (showProcessingFeeTooltip = true)}>
<span slot="buttonText">{$_('bridgeForm.processingFeeLabel')}</span>
</ButtonWithTooltip>
</div>

<!--
TODO: how about showing recommended also in a readonly input
and when clicking on Custom it becomes editable?

TODO: transition between options
-->
{#if method === ProcessingFeeMethod.CUSTOM}
<label class="mt-2 input-group relative">
<input
use:focus
type="number"
step="0.01"
placeholder="0.01"
min="0"
on:input={updateAmount}
class="input input-primary bg-dark-2 border-dark-2 input-md md:input-lg w-full focus:ring-0 !rounded-r-none"
name="amount" />
<span class="!rounded-r-lg bg-dark-2">ETH</span>
</label>
{:else if method === ProcessingFeeMethod.RECOMMENDED}
<div class="flex flex-row">
<span class="mt-2 text-sm">{amount} ETH</span>
</div>
{/if}

<div class="flex mt-2 space-x-2">
{#each Array.from(processingFees) as fee}
{@const [feeMethod, { displayText }] = fee}
{@const selected = method === feeMethod}

<button
class="{selected
? 'border-accent hover:border-accent'
: ''} btn btn-md text-xs font-semibold md:w-32 dark:bg-dark-5"
on:click={selectFee(feeMethod)}>{displayText}</button>
{/each}
</div>
</div>

<GeneralTooltip bind:show={showProcessingFeeTooltip} />
<NoneFeeTooltip bind:show={showNoneFeeTooltip} />

<style>
/* hide number input arrows */
input[type='number']::-webkit-outer-spin-button,
input[type='number']::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
-moz-appearance: textfield !important;
}
</style>
Loading