Skip to content

Commit

Permalink
feat(bridge-ui-v2): Processing Fee (#14170)
Browse files Browse the repository at this point in the history
Co-authored-by: Korbinian <KorbinianK@users.noreply.github.com>
  • Loading branch information
jscriptcoder and KorbinianK committed Jul 17, 2023
1 parent 4ce016a commit 13ebf1c
Show file tree
Hide file tree
Showing 38 changed files with 563 additions and 209 deletions.
10 changes: 10 additions & 0 deletions packages/bridge-ui-v2/src/app.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const recommentProcessingFee = {
ethGasLimit: BigInt(900000),
erc20NotDeployedGasLimit: BigInt(3100000),
erc20DeployedGasLimit: BigInt(1100000),
};

export const processingFeeComponent = {
closingDelayOptionClick: 300,
intervalComputeRecommendedFee: 20000,
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,21 @@
import { t } from 'svelte-i18n';
import { successToast, warningToast } from '$components/NotificationToast';
import { account } from '$stores/account';
let prevAccount = $account;
import { OnAccount } from '$components/OnAccount';
import type { Account } from '$stores/account';
// Listen to changes in the account state and notify the user
// when the account is connected or disconnected via toast
account.subscribe((_account) => {
if (_account?.isConnected) {
function onAccountChange(newAccount: Account, oldAccount?: Account) {
if (newAccount?.isConnected) {
successToast($t('messages.account.connected'));
} else if (prevAccount && _account?.isDisconnected) {
} else if (oldAccount && newAccount?.isDisconnected) {
// We check if there was previous account, if not
// the user just hit the app, and there is no need
// to show the message.
warningToast($t('messages.account.disconnected'));
}
prevAccount = _account;
});
}
</script>

<OnAccount change={onAccountChange} />
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
import { Card } from '$components/Card';
import { ChainSelector } from '$components/ChainSelector';
import { srcChain } from '$stores/network';
import { network } from '$stores/network';
import ListWithDetailsView from './ListWithDetailsView.svelte';
import TableView from './TableView.svelte';
</script>

<Card class="md:min-w-[524px]" title={$t('activities.title')} text={$t('activities.subtitle')}>
<div class="space-y-[35px]">
<ChainSelector label={$t('chain_selector.currently_on')} value={$srcChain} />
<ChainSelector label={$t('chain_selector.currently_on')} value={$network} />
<!-- Small size view -->
<div class="md:hidden">
<ListWithDetailsView />
Expand Down

This file was deleted.

1 change: 0 additions & 1 deletion packages/bridge-ui-v2/src/components/AmountInput/index.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script lang="ts">
import { t } from 'svelte-i18n';
import { InputBox } from '$components/InputBox';
import { uid } from '$libs/util/uid';
import Balance from './Balance.svelte';
let inputId = `input-${uid()}`;
</script>

<div class="AmountInput f-col space-y-2">
<div class="f-between-center text-secondary-content">
<label class="body-regular" for={inputId}>{$t('amount_input.label')}</label>
<Balance />
</div>
<div class="relative f-items-center">
<InputBox
id={inputId}
type="number"
placeholder="0.01"
min="0"
class="w-full input-box outline-none py-6 pr-16 px-[26px] title-subsection-bold placeholder:text-tertiary-content" />
<button class="absolute right-6 uppercase">{$t('amount_input.button.max')}</button>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<script lang="ts">
import type { FetchBalanceResult } from '@wagmi/core';
import { t } from 'svelte-i18n';
import LoadingText from '$components/LoadingText/LoadingText.svelte';
import { getBalance as getTokenBalance, type Token } from '$libs/token';
import { truncateString } from '$libs/util/truncateString';
import { type Account, account } from '$stores/account';
import { network } from '$stores/network';
import { destNetwork, selectedToken } from '../state';
let tokenBalance: Maybe<FetchBalanceResult>;
let computingTokenBalance = false;
let errorComputingTokenBalance = false;

Check warning on line 15 in packages/bridge-ui-v2/src/components/Bridge/AmountInput/Balance.svelte

View workflow job for this annotation

GitHub Actions / build

'errorComputingTokenBalance' is assigned a value but never used
async function updateTokenBalance(token: Maybe<Token>, account?: Account, srcChainId?: number, destChainId?: number) {
if (!token || !account || !account.address) return;
computingTokenBalance = true;
errorComputingTokenBalance = false;
try {
tokenBalance = await getTokenBalance({
token,
destChainId,
userAddress: account.address,
chainId: srcChainId,
});
} catch (error) {
console.error(error);
errorComputingTokenBalance = true;
} finally {
computingTokenBalance = false;
}
}
export function renderTokenBalance(balance: Maybe<FetchBalanceResult>) {
if (!balance) return '0.00';
return `${truncateString(balance.formatted, 6)} ${balance.symbol}`;
}
$: updateTokenBalance($selectedToken, $account, $network?.id, $destNetwork?.id);
</script>

<div class="body-small-regular">
<span>{$t('amount_input.balance')}:</span>
<span>
{#if computingTokenBalance}
<LoadingText mask="0.0000" />
<LoadingText mask="XXX" />
{:else}
{renderTokenBalance(tokenBalance)}
{/if}
</span>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as AmountInput } from './AmountInput.svelte';
54 changes: 39 additions & 15 deletions packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte
Original file line number Diff line number Diff line change
@@ -1,38 +1,58 @@
<script lang="ts">
import { t } from 'svelte-i18n';
import AmountInput from '$components/AmountInput';
import Button from '$components/Button/Button.svelte';
import { Button } from '$components/Button';
import { Card } from '$components/Card';
import { ChainSelector } from '$components/ChainSelector';
import Icon from '$components/Icon/Icon.svelte';
import { ProcessingFee } from '$components/ProcessingFee';
import { RecipientInput } from '$components/RecipientInput';
import { OnAccount } from '$components/OnAccount';
import { OnNetwork } from '$components/OnNetwork';
import { TokenDropdown } from '$components/TokenDropdown';
import { type Token, tokens } from '$libs/token';
import { destChain, srcChain } from '$stores/network';
import { chains } from '$libs/chain';
import { ETHToken, tokens } from '$libs/token';
import type { Account } from '$stores/account';
import { type Network, network } from '$stores/network';
let selectedToken: Token;
import { AmountInput } from './AmountInput';
import { ProcessingFee } from './ProcessingFee';
import { RecipientInput } from './RecipientInput';
import { destNetwork, selectedToken } from './state';
import SwitchChainsButton from './SwitchChainsButton.svelte';
function onNetworkChange(network: Network) {
if (network && chains.length === 2) {
// If there are only two chains, the destination chain will be the other one
const otherChain = chains.find((chain) => chain.id !== network.id);
if (otherChain) destNetwork.set(otherChain);
}
}
function onAccountChange(account: Account) {
if (account && account.isConnected && !$selectedToken) {
$selectedToken = ETHToken;
} else if (account && account.isDisconnected) {
$selectedToken = null;
$destNetwork = null;
}
}
</script>

<Card class="md:w-[524px]" title={$t('bridge.title')} text={$t('bridge.subtitle')}>
<div class="space-y-[35px]">
<div class="space-y-4">
<div class="space-y-2">
<ChainSelector label={$t('chain.from')} value={$srcChain} />
<TokenDropdown {tokens} bind:value={selectedToken} />
<ChainSelector label={$t('chain.from')} value={$network} switchWallet />
<TokenDropdown {tokens} bind:value={$selectedToken} />
</div>

<AmountInput token={selectedToken} />
<AmountInput />

<div class="f-justify-center">
<button class="f-center rounded-full bg-secondary-icon w-[30px] h-[30px]">
<Icon type="up-down" />
</button>
<SwitchChainsButton />
</div>

<div class="space-y-2">
<ChainSelector label={$t('chain.to')} value={$destChain} />
<ChainSelector label={$t('chain.to')} value={$destNetwork} readOnly />
<RecipientInput />
</div>
</div>
Expand All @@ -46,3 +66,7 @@
</Button>
</div>
</Card>

<OnNetwork change={onNetworkChange} />

<OnAccount change={onAccountChange} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<script lang="ts">
import type { Address } from 'abitype';
import { recommendProcessingFee } from '$libs/fee';
import { getBalance, type Token } from '$libs/token';
import { account, network } from '$stores';
import { destNetwork, selectedToken } from '../state';
export let enoughEth: boolean;
export let calculating = false;
export let error = false;
async function compute(token: Maybe<Token>, userAddress?: Address, srcChainId?: number, destChainId?: number) {
if (!token || !userAddress || !srcChainId || !destChainId) {
enoughEth = false;
return;
}
calculating = true;
error = false;
try {
// Get the balance of the user on the destination chain
const destBalance = await getBalance({
token,
userAddress,
chainId: destChainId,
});
// Calculate the recommended amount of ETH needed for processMessage call
const recommendedAmount = await recommendProcessingFee({
token,
destChainId,
srcChainId,
});
// Does the user have enough ETH to claim manually on the destination chain?
enoughEth = destBalance ? destBalance?.value >= recommendedAmount : false;
} catch (err) {
console.error(err);
error = true;
enoughEth = false;
} finally {
calculating = false;
}
}
$: compute($selectedToken, $account?.address, $network?.id, $destNetwork?.id);
</script>

0 comments on commit 13ebf1c

Please sign in to comment.