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-v2): destination token bridged #14448

Merged
merged 86 commits into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
8742a9b
feat(nft-bridge): initial UI setup for NFT bridge, fetching images, u…
KorbinianK Jul 24, 2023
a97acd3
Merge remote-tracking branch 'origin/main' into feat/activities
KorbinianK Jul 25, 2023
fe03cc0
feat(bridge-ui-v2): add relayer api, initial activities page
KorbinianK Jul 26, 2023
e5731af
chore(bridge-ui-v2): remove bg asset
KorbinianK Jul 26, 2023
b9554f3
feat(bridge-ui-v2): update bg
KorbinianK Jul 26, 2023
911f3d2
types
jscriptcoder Jul 26, 2023
eed4ee3
types
jscriptcoder Jul 26, 2023
8c58d26
Merge remote-tracking branch 'origin/main' into feat/activities
KorbinianK Jul 26, 2023
44ebb89
bridgetx storage
jscriptcoder Jul 26, 2023
cc2eacf
bridge tx service
jscriptcoder Jul 26, 2023
beea5ad
minor changes in the styling
jscriptcoder Jul 26, 2023
bb6ef3d
minor change
jscriptcoder Jul 26, 2023
613c55c
chore(bridge-ui-v2): types, additional vault configs
KorbinianK Jul 26, 2023
d79bcc6
Merge remote-tracking branch 'origin/feat/bridgetx_storage' into feat…
KorbinianK Jul 26, 2023
2336a19
feat(bridge-ui-v2): BridgeTx storage (#14284)
jscriptcoder Jul 26, 2023
116b4e3
feat(bridge-ui-v2): wip on activities page, checking for connection s…
KorbinianK Jul 26, 2023
526680a
Merge branch 'feat/activities' of https://github.com/taikoxyz/taiko-m…
KorbinianK Jul 26, 2023
38102ca
Merge branch 'main' into feat/activities
KorbinianK Jul 26, 2023
3fb8ffd
feat(bridge-ui-v2): transaction component, update types
KorbinianK Jul 27, 2023
209789b
feat(bridge-ui-v2): removed polling from relayer, fixed receipt fetching
KorbinianK Jul 27, 2023
1b1c46a
fix(bridge-ui-v2): fix i18n links
KorbinianK Jul 28, 2023
bf929af
fix(bridge-ui-v2): added return to _enhance in storage service
KorbinianK Jul 28, 2023
9be854e
feat(bridge-ui-v2): optimize releayeApi filter conditions
KorbinianK Jul 28, 2023
25f64c7
feat(bridge-ui-v2): merging local-storage and relayer tx
KorbinianK Jul 28, 2023
3c399e6
chore(bridge-ui-v2): moved mergeTx function to util
KorbinianK Jul 28, 2023
580caf8
feat(bridge-ui-v2): transaction logic (#14295)
jscriptcoder Jul 28, 2023
563bf3f
feat(bridge-ui-v2): updated styling
KorbinianK Jul 28, 2023
f08092a
Merge branch 'feat/activities' of https://github.com/taikoxyz/taiko-m…
KorbinianK Jul 28, 2023
1a87dcb
feat(bridge-ui-v2): added mobile view
KorbinianK Jul 28, 2023
4097dc4
fix(bridge-ui-v2): i18n fixes
KorbinianK Jul 31, 2023
fcf4b42
fix(bridge-ui-v2): fix i18n
KorbinianK Jul 31, 2023
026583e
feat(bridge-ui-v2): moved dynamic blur to appconfig
KorbinianK Aug 1, 2023
9de45bd
feat(bridge-ui-v2): mobile view
KorbinianK Aug 1, 2023
c2d4b26
feat(bridge-ui-v2): small cleanup, style adjustments for mobile card
KorbinianK Aug 2, 2023
7b8066d
feat(bridge-ui-v2): use component for mobile detection
KorbinianK Aug 2, 2023
09a5cb6
chore
KorbinianK Aug 2, 2023
4744c24
feat(bridge-ui-v2): add todos and fix i18n
KorbinianK Aug 2, 2023
ee458fa
feat(bridge-ui-v2): use responsive tailwind tags
KorbinianK Aug 3, 2023
8467e41
feat(bridge-ui-v2): added chainselector, status details dialog
KorbinianK Aug 3, 2023
18d1180
feat(bridge-ui-v2): Status component (#14312)
jscriptcoder Aug 3, 2023
02afb20
fix(bridge-ui-v2): complying with design (#14376)
jscriptcoder Aug 4, 2023
4e1b370
fix small issue when tx fails
jscriptcoder Aug 4, 2023
4804735
fix(bridge-ui-v2): validating amount (#14380)
jscriptcoder Aug 4, 2023
a795d60
merge main and resolve conflicts
jscriptcoder Aug 7, 2023
12ce9f8
revert change in eventindexer.yml
jscriptcoder Aug 7, 2023
dbb681d
fix pnpm-lock
jscriptcoder Aug 7, 2023
7e2ff25
Merge branch 'feat/activities' of https://github.com/taikoxyz/taiko-m…
jscriptcoder Aug 7, 2023
e253e8b
Revert eventindexer.yml
jscriptcoder Aug 7, 2023
e2a4a9f
revert change
jscriptcoder Aug 7, 2023
02ec5bd
minor fix
jscriptcoder Aug 7, 2023
dd4d403
minor fix
jscriptcoder Aug 7, 2023
463187f
Revert README.md
jscriptcoder Aug 7, 2023
863016d
Revert tokenomics_batch_auction.md
jscriptcoder Aug 7, 2023
908c1f8
Revert eventindexer.yml
jscriptcoder Aug 7, 2023
c63d43d
chore(bridge-ui-v2): update .env-example
KorbinianK Aug 7, 2023
a853f65
chore(bridge-ui-v2): linting
KorbinianK Aug 7, 2023
d908d8c
feat(bridge-ui-v2): decode of base64 without buffer
KorbinianK Aug 7, 2023
d091d3b
fix(bridge-ui-v2): i18n for claim reject
KorbinianK Aug 7, 2023
499a27a
fix(bridge-ui-v2): Buffer missing (#14407)
jscriptcoder Aug 8, 2023
834dc72
chore(bridge-ui-v2): cleanup and i18n
KorbinianK Aug 8, 2023
9f1a0f3
feat(bridge-ui-v2): catch empty receipts
KorbinianK Aug 8, 2023
4dd18b7
feat(bridge-ui-v2): clearing local transaction if relayer tx found,
KorbinianK Aug 8, 2023
4669106
feat(bridge-ui-v2): Light mode (#14420)
jscriptcoder Aug 9, 2023
4b89652
add custom
jscriptcoder Aug 9, 2023
74c70fa
feat(bridge-ui-v2): updated and fixed unit test, linting
KorbinianK Aug 9, 2023
18e5ff8
feat(bridge-ui-v2): processing fee dialog UX
KorbinianK Aug 10, 2023
05ce8b3
Merge branch 'feat/activities' of https://github.com/taikoxyz/taiko-m…
jscriptcoder Aug 10, 2023
8ce51be
fix(bridge-ui-v2): Fix token dropdown (#14436)
jscriptcoder Aug 10, 2023
0095ba7
feat(bridge-ui-v2): style adjustments, feature flag for nft tabs
KorbinianK Aug 10, 2023
d969657
feat(bridge-ui-v2): styling adjustments
KorbinianK Aug 10, 2023
51a61e5
center text in chainselector
KorbinianK Aug 10, 2023
9475ffd
feat(bridge-ui-v2): disable nft bridge in routes if flag set
KorbinianK Aug 10, 2023
5f9f3ac
Merge branch 'feat/activities' of https://github.com/taikoxyz/taiko-m…
jscriptcoder Aug 10, 2023
6f72ce8
fix import
jscriptcoder Aug 10, 2023
a4b3c43
fix amount alert messages
jscriptcoder Aug 10, 2023
de628cd
update .env.example
KorbinianK Aug 10, 2023
01db9d3
feat(bridge-ui-v2): check if dest token is already bridged
KorbinianK Aug 10, 2023
d3cce55
feat(bridge-ui-v2): rework getting cross chain Address
KorbinianK Aug 14, 2023
7185eca
linting
KorbinianK Aug 14, 2023
464d6a4
Update getCrossChainAddress.test.ts
KorbinianK Aug 14, 2023
8100be9
fix processingfee and balance
KorbinianK Aug 14, 2023
658cfcb
catch pre-configured addresses and avoid uneccessary calls
KorbinianK Aug 14, 2023
ff3b883
chore(bridge-ui-v2): cleanup
KorbinianK Aug 15, 2023
9021162
feat(bridge-ui-v2): update custom tokens
KorbinianK Aug 15, 2023
f85d870
feat(bridge-ui-v2): add logging
KorbinianK Aug 15, 2023
cb200b5
Merge remote-tracking branch 'origin/main' into feat/destination-bridged
KorbinianK Aug 15, 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
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import { Spinner } from '$components/Spinner';
import { activitiesConfig } from '$config';
import { type BridgeTransaction, fetchTransactions } from '$libs/bridge';
import { web3modal } from '$libs/connect';
import { bridgeTxService } from '$libs/storage';
import { account, network } from '$stores';
import type { Account } from '$stores/account';
Expand Down Expand Up @@ -51,8 +50,6 @@
return bridgeTx.slice(start, end);
};

const onWalletConnect = () => web3modal.openModal();

const onAccountChange = async (newAccount: Account, oldAccount?: Account) => {
// We want to make sure that we are connected and only
// fetch if the account has changed
Expand Down
17 changes: 2 additions & 15 deletions packages/bridge-ui-v2/src/components/Activities/Transaction.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
import { t } from 'svelte-i18n';
import { formatEther } from 'viem';

import type { BridgeTransaction, MessageStatus } from '$libs/bridge';
import type { BridgeTransaction } from '$libs/bridge';
import { chainUrlMap } from '$libs/chain';

export let item: BridgeTransaction;

import { createEventDispatcher, onDestroy } from 'svelte';
import { createEventDispatcher } from 'svelte';

import { DesktopOrLarger } from '$components/DesktopOrLarger';
import { Icon } from '$components/Icon';
Expand All @@ -23,19 +23,6 @@

const handlePress = () => dispatch('press');

const mapStatusToText = (status: MessageStatus) => {
switch (status) {
case 1:
return 'Pending';
case 2:
return 'Claimed';
case 3:
return 'Failed';
default:
return 'Unknown';
}
};

let attrs = isDesktopOrLarger ? {} : { role: 'button' };
</script>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import { InputBox } from '$components/InputBox';
import { LoadingText } from '$components/LoadingText';
import { Tooltip } from '$components/Tooltip';
import { processingFeeComponent } from '$config';
import { ProcessingFeeMethod } from '$libs/fee';
import { parseToWei } from '$libs/util/parseToWei';
import { uid } from '$libs/util/uid';
Expand Down Expand Up @@ -63,12 +62,6 @@
closeModal();
}

function closeModalWithDelay() {
// By adding delay there is enough time to see the selected option
// before closing the modal. Better experience for the user.
setTimeout(closeModal, processingFeeComponent.closingDelayOptionClick);
}

function focusInputBox() {
inputBox.focus();
}
Expand Down
2 changes: 0 additions & 2 deletions packages/bridge-ui-v2/src/components/InputBox/InputBox.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
<script lang="ts">
import { onMount } from 'svelte';

import { classNames } from '$libs/util/classNames';

export let error = false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { erc20ABI, getNetwork,readContract } from '@wagmi/core';
import { erc20ABI, getNetwork, readContract } from '@wagmi/core';
import { fetchToken } from '@wagmi/core';
import { createEventDispatcher } from 'svelte';
import { t } from 'svelte-i18n';
import type { Address } from 'viem';
import { formatUnits } from 'viem';
Expand All @@ -12,11 +13,16 @@
import Erc20 from '$components/Icon/ERC20.svelte';
import { Spinner } from '$components/Spinner';
import { tokenService } from '$libs/storage/services';
import { type Token, type TokenEnv,TokenType } from '$libs/token';
import { type GetCrossChainAddressArgs, type Token, type TokenEnv, TokenType } from '$libs/token';
import { getCrossChainAddress } from '$libs/token/getCrossChainAddress';
import { getLogger } from '$libs/util/logger';
import { uid } from '$libs/util/uid';
import { account } from '$stores/account';

import { destNetwork } from '../Bridge/state';

const dispatch = createEventDispatcher();

const log = getLogger('component:AddCustomERC20');
const dialogId = `dialog-${uid()}`;

Expand All @@ -32,10 +38,29 @@
let disabled = true;
let isValidEthereumAddress = false;

const addCustomErc20Token = () => {
const addCustomErc20Token = async () => {
if (customToken) {
tokenService.storeToken(customToken, $account?.address as Address);
customTokens = tokenService.getTokens($account?.address as Address);

const { chain: srcChain } = getNetwork();
const destChain = $destNetwork;

if (!srcChain || !destChain) return;

// let's check if this token has already been bridged
const bridgedAddress = await getCrossChainAddress({
token: customToken,
srcChainId: srcChain.id,
destChainId: destChain.id,
} as GetCrossChainAddressArgs);

// only update the token if we actually have a bridged address
if (bridgedAddress && bridgedAddress !== customToken.addresses[destChain.id]) {
customToken.addresses[destChain.id] = bridgedAddress as Address;

tokenService.updateToken(customToken, $account?.address as Address);
}
}
tokenAddress = '';
tokenDetails = null;
Expand All @@ -58,6 +83,7 @@
const address = $account.address;
tokenService.removeToken(token, address as Address);
customTokens = tokenService.getTokens(address as Address);
dispatch('tokenRemoved', { token });
};

const onAddressValidation = async (event: { detail: { isValidEthereumAddress: boolean } }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
</div>
</dialog>

<AddCustomErc20 bind:modalOpen />
<AddCustomErc20 bind:modalOpen on:tokenRemoved />

<!-- <OnNetwork change={onNetworkChange} /> -->
<OnAccount change={onAccountChange} />
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,6 @@
</li>
</ul>

<AddCustomErc20 bind:modalOpen={addArc20ModalOpen} />
<AddCustomErc20 bind:modalOpen={addArc20ModalOpen} on:tokenRemoved />

<OnAccount change={onAccountChange} />
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Erc20 from '$components/Icon/ERC20.svelte';
import { warningToast } from '$components/NotificationToast';
import { tokenService } from '$libs/storage/services';
import type { Token } from '$libs/token';
import { ETHToken, type Token } from '$libs/token';
import { getCrossChainAddress } from '$libs/token/getCrossChainAddress';
import { uid } from '$libs/util/uid';
import { account } from '$stores/account';
Expand Down Expand Up @@ -69,15 +69,26 @@
srcChainId: chain.id,
destChainId: destChain.id,
});
token.addresses[destChain.id] = bridgedAddress as Address;

tokenService.updateToken(token, $account?.address as Address);
// only update the token if we actually have a new bridged address
if (bridgedAddress && bridgedAddress !== token.addresses[destChain.id]) {
token.addresses[destChain.id] = bridgedAddress as Address;

tokenService.updateToken(token, $account?.address as Address);
}
}
value = token;

closeMenu();
};

const handleTokenRemoved = (event: { detail: { token: Token } }) => {
// if the selected token is the one that was removed by the user, remove it
if (event.detail.token === value) {
value = ETHToken;
}
};

onDestroy(() => closeMenu());
</script>

Expand Down Expand Up @@ -114,7 +125,7 @@
</button>

{#if isDesktopOrLarger}
<DropdownView {id} {menuOpen} {tokens} {value} {selectToken} />
<DropdownView {id} {menuOpen} {tokens} {value} {selectToken} on:tokenRemoved={handleTokenRemoved} />
{:else}
<DialogView {id} {menuOpen} {tokens} {value} {selectToken} {closeMenu} />
{/if}
Expand Down
4 changes: 2 additions & 2 deletions packages/bridge-ui-v2/src/libs/bridge/checkBalanceToBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ export async function checkBalanceToBridge({

const isTokenAlreadyDeployed = await isDeployedCrossChain({
token,
srcChainId: destChainId,
destChainId: srcChainId,
srcChainId,
destChainId,
});

try {
Expand Down
24 changes: 16 additions & 8 deletions packages/bridge-ui-v2/src/libs/fee/recommendProcessingFee.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { getPublicClient } from '@wagmi/core';
import { zeroAddress } from 'viem';

import { recommentProcessingFee } from '$config';
import { getAddress, type Token, TokenType } from '$libs/token';
import { isDeployedCrossChain, type Token, TokenType } from '$libs/token';
import { getLogger } from '$libs/util/logger';

const log = getLogger('libs:recommendedProcessingFee');

type RecommendProcessingFeeArgs = {
token: Token;
Expand All @@ -25,16 +27,22 @@ export async function recommendProcessingFee({ token, destChainId, srcChainId }:
throw Error('missing required source chain for ERC20 token');
}

const tokenAddress = await getAddress({ token, srcChainId, destChainId });
const isTokenAlreadyDeployed = await isDeployedCrossChain({
token,
srcChainId,
destChainId,
});

if (!tokenAddress || tokenAddress === zeroAddress) {
// Gas limit for erc20 if not deployed on the destination chain
// already is about ~2.9m, so we add some to make it enticing
gasLimit = erc20NotDeployedGasLimit;
} else {
if (isTokenAlreadyDeployed) {
// Gas limit for erc20 if already deployed on the destination chain is
// about ~1m, so again, add some to ensure processing
gasLimit = erc20DeployedGasLimit;
log(`token ${token.symbol} is already deployed on chain ${destChainId}`);
} else {
// Gas limit for erc20 if not deployed on the destination chain
// already is about ~2.9m, so we add some to make it enticing
gasLimit = erc20NotDeployedGasLimit;
log(`token ${token.symbol} is not deployed on chain ${destChainId}`);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class CustomTokenService implements TokenService {

// Filter out zero addresses from the new token's addresses
const filteredAddresses = Object.fromEntries(
Object.entries(token.addresses).filter(([key, value]) => value !== zeroAddress),
Object.entries(token.addresses).filter(([, value]) => value !== zeroAddress),
);

// Find the stored token to update
Expand Down
51 changes: 18 additions & 33 deletions packages/bridge-ui-v2/src/libs/token/getAddress.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { getContract, type GetContractResult } from '@wagmi/core';
import { type Address, getContract, type GetContractResult } from '@wagmi/core';

Check warning on line 1 in packages/bridge-ui-v2/src/libs/token/getAddress.test.ts

View workflow job for this annotation

GitHub Actions / build

'Address' is defined but never used

import { tokenVaultABI } from '$abi';
import { PUBLIC_L1_CHAIN_ID, PUBLIC_L2_CHAIN_ID } from '$env/static/public';
import { chainContractsMap } from '$libs/chain';

import { getAddress } from './getAddress';
import { ETHToken, testERC20Tokens } from './tokens';
Expand All @@ -16,46 +14,33 @@
const mockTokenContract = {
read: {
canonicalToBridged: vi.fn(),
isBridgedToken: vi.fn(),
bridgedToCanonical: vi.fn(),
},
} as unknown as GetContractResult<readonly unknown[], unknown>;

describe('getAddress', () => {
beforeAll(() => {
vi.mocked(getContract).mockReturnValue(mockTokenContract);
});
beforeEach(() => {
vi.resetAllMocks();

it('should return undefined if ETH', async () => {
expect(await getAddress({ token: ETHToken, srcChainId: Number(PUBLIC_L1_CHAIN_ID) })).toBeUndefined();
vi.mocked(getContract).mockReturnValue(mockTokenContract);
});

it('should return the address if ERC20 and has address on the source chain', async () => {
expect(await getAddress({ token: HORSEToken, srcChainId: Number(PUBLIC_L1_CHAIN_ID) })).toEqual(
HORSEToken.addresses[PUBLIC_L1_CHAIN_ID],
);
describe('ETH Tests', () => {
it('should return undefined if ETH', async () => {
expect(await getAddress({ token: ETHToken, srcChainId: Number(PUBLIC_L1_CHAIN_ID) })).toBeUndefined();
});
});

it('should return undefined if ERC20 and has no address on the source chain and no destination chain is is passed in', async () => {
expect(await getAddress({ token: HORSEToken, srcChainId: Number(PUBLIC_L2_CHAIN_ID) })).toBeUndefined();
});
describe('ERC20 Tests', () => {
it('should return the address if ERC20 and has address on the source chain', async () => {
expect(await getAddress({ token: HORSEToken, srcChainId: Number(PUBLIC_L1_CHAIN_ID) })).toEqual(
HORSEToken.addresses[PUBLIC_L1_CHAIN_ID],
);
});

it('should return the address of deployed ERC20 token', async () => {
vi.mocked(mockTokenContract.read.canonicalToBridged).mockResolvedValue('0x456789');

expect(
await getAddress({
token: HORSEToken,
srcChainId: Number(PUBLIC_L2_CHAIN_ID),
destChainId: Number(PUBLIC_L1_CHAIN_ID),
}),
).toEqual('0x456789');
expect(mockTokenContract.read.canonicalToBridged).toHaveBeenCalledWith([
BigInt(1),
HORSEToken.addresses[PUBLIC_L1_CHAIN_ID],
]);
expect(getContract).toHaveBeenCalledWith({
abi: tokenVaultABI,
address: chainContractsMap[PUBLIC_L2_CHAIN_ID].tokenVaultAddress,
chainId: Number(PUBLIC_L2_CHAIN_ID),
it('should return undefined if ERC20 and has no address on the source chain and no destination chain is is passed in', async () => {
expect(await getAddress({ token: HORSEToken, srcChainId: Number(PUBLIC_L2_CHAIN_ID) })).toBeUndefined();
});
});
});
Loading
Loading