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(bridge-ui-v2): bugfixes #15400

Merged
merged 5 commits into from
Dec 21, 2023
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
39 changes: 36 additions & 3 deletions packages/bridge-ui-v2/src/components/Bridge/Actions.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<script lang="ts">
import { t } from 'svelte-i18n';

import { routingContractsMap } from '$bridgeConfig';
import ActionButton from '$components/Button/ActionButton.svelte';
import { Icon } from '$components/Icon';
import { bridges, ContractType, type RequireApprovalArgs } from '$libs/bridge';
import type { ERC20Bridge } from '$libs/bridge/ERC20Bridge';
import type { ERC721Bridge } from '$libs/bridge/ERC721Bridge';
import type { ERC1155Bridge } from '$libs/bridge/ERC1155Bridge';
import { getContractAddressByType } from '$libs/bridge/getContractAddressByType';
Expand Down Expand Up @@ -62,6 +64,34 @@
if (paused) throw new BridgePausedError('Bridge is paused');
});
$validatingAmount = true;

if ($selectedToken?.type === TokenType.ERC20) {
if ($account?.address && $network?.id && $destNetwork?.id) {
const currentChainId = $network?.id;
const destinationChainId = $destNetwork?.id;
const tokenVaultAddress = routingContractsMap[currentChainId][destinationChainId].erc20VaultAddress;

const bridge = bridges[$selectedToken.type] as ERC20Bridge;

try {
const requiresApproval = await bridge.requireAllowance({
amount: $enteredAmount,
tokenAddress: $selectedToken.addresses[currentChainId],
ownerAddress: $account.address,
spenderAddress: tokenVaultAddress,
});
$insufficientAllowance = false;
$validatingAmount = false;
return !requiresApproval;
} catch (error) {
console.error('isApprovedForAll error');
$validatingAmount = false;
return false;
}
}
$validatingAmount = false;
return false;
}
if ($selectedToken?.type === TokenType.ERC721 || $selectedToken?.type === TokenType.ERC1155) {
if ($account?.address && $network?.id && $destNetwork?.id) {
const currentChainId = $network?.id;
Expand Down Expand Up @@ -181,9 +211,12 @@
!paused;

$: erc20ConditionsSatisfied =
!canDoNothing && !$insufficientAllowance && commonConditions && $tokenBalance && $enteredAmount;
$: erc721ConditionsSatisfied = allTokensApproved && commonConditions;
$: erc1155ConditionsSatisfied = allTokensApproved && $enteredAmount && $enteredAmount > 0 && commonConditions;
commonConditions && !canDoNothing && !$insufficientAllowance && $tokenBalance && $enteredAmount;

$: erc721ConditionsSatisfied = commonConditions && allTokensApproved;

$: erc1155ConditionsSatisfied = commonConditions && allTokensApproved && $enteredAmount && $enteredAmount > 0;

$: ethConditionsSatisfied = commonConditions && $enteredAmount && $enteredAmount > 0;

$: disableBridge = isERC20
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import { isAddress } from 'ethereum-address';
import { createEventDispatcher } from 'svelte';
import { createEventDispatcher, onDestroy } from 'svelte';
import { t } from 'svelte-i18n';
import type { Address } from 'viem';

Expand Down Expand Up @@ -68,6 +68,10 @@
$: borderState = validState ? 'success' : invalidState ? 'error' : defaultBorder;

$: classes = classNames($$props.class, borderState);

onDestroy(() => {
clearAddress();
});
</script>

<div class="f-col space-y-2">
Expand Down
1 change: 0 additions & 1 deletion packages/bridge-ui-v2/src/components/Bridge/Amount.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@
invalidInput = true;
break;
}
console.error('Error validating amount: ', err);
} finally {
$validatingAmount = false;
}
Expand Down
10 changes: 5 additions & 5 deletions packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@

function onNetworkChange(newNetwork: Network, oldNetwork: Network) {
resetForm();
$selectedToken = ETHToken;

if (newNetwork) {
const destChainId = $destinationChain?.id;
Expand Down Expand Up @@ -216,8 +217,11 @@
// Reset the form
resetForm();

// Refresh user's balance
// Refresh user's ETH balance
refreshUserBalance();

// Update amount balance after bridging
if (amountComponent) amountComponent.updateBalance();
} catch (err) {
console.error(err);
handleBridgeError(err as Error);
Expand All @@ -230,10 +234,6 @@
if (recipientComponent) recipientComponent.clearRecipient();
if (processingFeeComponent) processingFeeComponent.resetProcessingFee();

// Update balance after bridging
if (amountComponent) amountComponent.updateBalance();

$selectedToken = ETHToken;
bridging = false;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
import { createEventDispatcher, onDestroy } from 'svelte';
import { t } from 'svelte-i18n';

import { Icon } from '$components/Icon';
Expand Down Expand Up @@ -43,6 +43,10 @@
state = State.VALID;
dispatch('inputValidation');
}

onDestroy(() => {
clearIds();
});
</script>

<div class="f-col space-y-2">
Expand Down
7 changes: 4 additions & 3 deletions packages/bridge-ui-v2/src/components/Bridge/NFTBridge.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@

$recipientAddress = $account?.address || null;
bridgingStatus = 'pending';

$selectedToken = ETHToken;
importMethod === null;
scanned = false;
Expand All @@ -126,7 +125,9 @@
let activeStep: NFTSteps = NFTSteps.IMPORT;

const nextStep = () => (activeStep = Math.min(activeStep + 1, NFTSteps.CONFIRM));
const previousStep = () => (activeStep = Math.max(activeStep - 1, NFTSteps.IMPORT));
const previousStep = () => {
activeStep = Math.max(activeStep - 1, NFTSteps.IMPORT);
};

let nftStepTitle: string;
let nftStepDescription: string;
Expand Down Expand Up @@ -316,7 +317,7 @@
><span class="body-bold">{$t('bridge.nft.step.confirm.button.back')}</span>
</ActionButton>
{:else}
<button on:click={resetForm} class="flex justify-center py-3 link">
<button on:click={() => (activeStep = NFTSteps.REVIEW)} class="flex justify-center py-3 link">
{$t('common.back')}
</button>
{/if}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
import type { ERC1155Bridge } from '$libs/bridge/ERC1155Bridge';
import { getBridgeArgs } from '$libs/bridge/getBridgeArgs';
import { handleBridgeError } from '$libs/bridge/handleBridgeErrors';
import { BridgePausedError } from '$libs/error';
import { bridgeTxService } from '$libs/storage';
import { TokenType } from '$libs/token';
import { getCrossChainAddress } from '$libs/token/getCrossChainAddress';
import { isBridgePaused } from '$libs/util/checkForPausedContracts';
import { getConnectedWallet } from '$libs/util/getConnectedWallet';
import { account } from '$stores/account';
import { network } from '$stores/network';
Expand Down Expand Up @@ -86,6 +88,10 @@
};

async function approve() {
isBridgePaused().then((paused) => {
if (paused) throw new BridgePausedError('Bridge is paused');
});

try {
if (!$selectedToken || !$network || !$destNetwork?.id) return;
const type: TokenType = $selectedToken.type;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import type { Address } from '@wagmi/core';
import { isAddress } from 'ethereum-address';
import { onMount } from 'svelte';
import { onDestroy } from 'svelte';
import { t } from 'svelte-i18n';

import { FlatAlert } from '$components/Alert';
Expand Down Expand Up @@ -177,7 +177,7 @@
validating = false;
};

onMount(() => {
onDestroy(() => {
reset();
});

Expand Down Expand Up @@ -226,6 +226,9 @@
$: isDisabled = idInputState !== IDInputState.VALID || addressInputState !== AddressInputState.VALID;

$: nothingFound = scanned && foundNFTs.length === 0;

$: displayOwnershipError =
contractAddress && enteredIds && !isOwnerOfAllToken && nftIdArray?.length > 0 && !validating;
</script>

<div class="f-between-center gap-[16px] mt-[30px]">
Expand All @@ -243,13 +246,10 @@ Manual NFT Input
class="bg-neutral-background border-0 h-[56px]"
on:addressvalidation={onAddressValidation}
labelText={$t('inputs.address_input.label.contract')} />
<!-- {#if addressInputState === AddressInputState.INVALID && invalidToken}
<FlatAlert type="error" forceColumnFlow message="todo: invalid token" />
{/if} -->

{#if !interfaceSupported}
<!-- {#if !interfaceSupported}
<Alert type="error">TODO: token interface is not supported (link to docs?)</Alert>
{/if}
{/if} -->
<div class="min-h-[20px] mt-[30px]">
<!-- TODO: add limit to config -->
<IdInput
Expand All @@ -262,8 +262,8 @@ Manual NFT Input
limit={1}
class="bg-neutral-background border-0 h-[56px]" />
<div class="min-h-[20px] !mt-3">
{#if !isOwnerOfAllToken && nftIdArray?.length > 0 && !validating}
<FlatAlert type="error" forceColumnFlow message="todo: must be owner of all token" />
{#if displayOwnershipError}
<FlatAlert type="error" forceColumnFlow message={$t('bridge.errors.not_the_owner_of_all')} />
{/if}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@
import { shortenAddress } from '$libs/util/shortenAddress';
import { network } from '$stores/network';

export let hasEnoughEth: boolean = false;

let recipientComponent: Recipient;
let processingFeeComponent: ProcessingFee;
export let hasEnoughEth: boolean = false;

const dispatch = createEventDispatcher();

$: nftsToDisplay = $selectedNFTs ? $selectedNFTs : [];

enum NFTView {
CARDS,
LIST,
}

let nftView: NFTView = NFTView.CARDS;

const changeNFTView = () => {
Expand All @@ -38,6 +38,8 @@
dispatch('editTransactionDetails');
};

$: nftsToDisplay = $selectedNFTs ? $selectedNFTs : [];

// check if any of the selected NFTs are ERC1155 tokens
$: isERC1155 = $selectedNFTs ? $selectedNFTs.some((nft) => nft.type === 'ERC1155') : false;
</script>
Expand Down
9 changes: 7 additions & 2 deletions packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import { TokenDropdown } from '$components/TokenDropdown';
import { chains } from '$libs/chain';
import { InsufficientBalanceError, MintError, TokenMintedError } from '$libs/error';
import { checkMintable, mint, testERC20Tokens, type Token } from '$libs/token';
import { checkMintable, mint, testERC20Tokens, testNFT, type Token } from '$libs/token';
import { account, network, pendingTransactions } from '$stores';

let minting = false;
Expand All @@ -26,6 +26,7 @@
let mintButtonEnabled = false;
let alertMessage = '';
let mintableTokens: Token[] = [];

const onlyMintable: boolean = true;

async function switchNetworkToL1() {
Expand Down Expand Up @@ -55,6 +56,7 @@

// Let's begin the minting process
minting = true;
mintButtonEnabled = false;

try {
const txHash = await mint(selectedToken, $network.id);
Expand Down Expand Up @@ -159,7 +161,10 @@

onMount(() => {
// Only show tokens in the dropdown that are mintable
mintableTokens = testERC20Tokens.filter((token) => token.mintable);
const testERC20 = testERC20Tokens.filter((token) => token.mintable);
const testNFTs = testNFT.filter((token) => token.mintable);

mintableTokens = [...testERC20, ...testNFTs];
});

$: connected = isUserConnected($account);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,17 @@
if (!tokenAddress) return;
loadingTokenDetails = true;
log('Fetching token details for address "%s"…', tokenAddress);
const type = await detectContractType(tokenAddress);

let type: TokenType;
try {
type = await detectContractType(tokenAddress);
} catch (error) {
log('Failed to detect contract type: ', error);
loadingTokenDetails = false;
state = AddressInputState.NOT_ERC20;
return;
}

if (type !== TokenType.ERC20) {
loadingTokenDetails = false;
state = AddressInputState.NOT_ERC20;
Expand Down Expand Up @@ -160,7 +170,6 @@
<dialog id={dialogId} class="modal modal-bottom md:modal-middle" class:modal-open={modalOpen}>
<div class="modal-box relative px-6 py-[35px] md:rounded-[20px] bg-dialog-background">
<CloseButton onClick={closeModal} />

<h3 class="title-body-bold mb-7">{$t('token_dropdown.custom_token.title')}</h3>

<p class="body-regular text-secondary-content mb-3">{$t('token_dropdown.custom_token.description')}</p>
Expand Down
1 change: 1 addition & 0 deletions packages/bridge-ui-v2/src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"title": "Allowance already set"
},
"no_decimals_allowed": "Decimals are not supported for this token",
"not_the_owner_of_all": "You must be the owner of all tokens",
"send_erc20_error": {
"message": "There was an issue attempting to send ERC20 token.",
"title": "Failed to send"
Expand Down
6 changes: 5 additions & 1 deletion packages/bridge-ui-v2/src/libs/token/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ export const ETHToken: Token = {
type: TokenType.ETH,
};

export const testERC20Tokens: Token[] = customToken;
export const testERC20Tokens: Token[] = customToken.filter((token) => token.type === TokenType.ERC20);

export const testNFT: Token[] = customToken.filter(
(token) => token.type === TokenType.ERC721 || token.type === TokenType.ERC1155,
);

export const tokens = [ETHToken, ...testERC20Tokens];
Loading