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): add custom ERC20 tokens support #13170

Merged
merged 25 commits into from
Feb 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f45d817
feat(bridge-ui): adapt frontend to backend changes
shadab-taiko Feb 14, 2023
11e9ac0
fix(bridge-ui): fix tests
shadab-taiko Feb 14, 2023
6cd1487
Merge branch 'main' into a2-prep
cyberhorsey Feb 15, 2023
9d95b30
fix(bridge-ui): refactor
shadab-taiko Feb 15, 2023
11d4f22
Merge branch 'a2-prep' of github.com-taiko:taikochain/taiko-mono into…
shadab-taiko Feb 15, 2023
e243673
feat(bridge-ui): add custom erc20 support
shadab-taiko Feb 16, 2023
a08044f
fix(bridge-ui): fix tests
shadab-taiko Feb 16, 2023
30b59c7
Merge branch 'main' into custom-erc20
shadab-taiko Feb 16, 2023
95521a6
chore(bridge-ui): add env to README
shadab-taiko Feb 17, 2023
a030a93
feat(bridge-ui): fetch token details on user input
shadab-taiko Feb 17, 2023
89dc030
fix(bridge-ui): rename TokenStore to TokenService
shadab-taiko Feb 17, 2023
d85ab22
fix(bridge-ui): define domain method return types
shadab-taiko Feb 17, 2023
a4177c6
Merge branch 'main' into custom-erc20
shadab-taiko Feb 17, 2023
a723804
Merge branch 'main' into custom-erc20
shadab-taiko Feb 18, 2023
86ada77
fix(bridge-ui): add both chains while adding custom tokens
shadab-taiko Feb 18, 2023
9e885fe
fix(bridge-ui): remove accidental commit
shadab-taiko Feb 18, 2023
0f9e5e3
feat(bridge-ui): check if bridged token contract is deployed
shadab-taiko Feb 18, 2023
651355d
fix(brige-ui): test
shadab-taiko Feb 18, 2023
26581d2
Merge branch 'main' into custom-erc20
shadab-taiko Feb 20, 2023
5509402
Merge branch 'main' into custom-erc20
shadab-taiko Feb 20, 2023
3fe86be
feat(bridge-ui): create helper
shadab-taiko Feb 22, 2023
85c2312
fix(bridge-ui): review comments
shadab-taiko Feb 22, 2023
6eb496a
Merge branch 'main' of github.com-taiko:taikochain/taiko-mono into cu…
shadab-taiko Feb 22, 2023
c1dede3
Merge branch 'main' into custom-erc20
dantaik Feb 23, 2023
87c1e0b
Merge branch 'main' into custom-erc20
davidtaikocha Feb 23, 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
26 changes: 15 additions & 11 deletions packages/bridge-ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,22 @@ You can use the following values in the `.env` file to spin up the Bridge UI loc

```
VITE_NODE_ENV=dev
VITE_L1_RPC_URL="https://l1rpc.a1.taiko.xyz/"
VITE_L2_RPC_URL="https://l2rpc.a1.taiko.xyz/"
VITE_RELAYER_URL="http://localhost:4102/"
VITE_TEST_ERC20_ADDRESS_MAINNET="0x3E3a3416DbCc5cb4448B6b171fF15f9Da35Ab72d"
VITE_MAINNET_CHAIN_ID=31338
VITE_TAIKO_CHAIN_ID=167003
VITE_MAINNET_CHAIN_NAME="Ethereum A1"
VITE_TAIKO_CHAIN_NAME="Taiko A1"
VITE_L1_RPC_URL="https://l1rpc.internal.taiko.xyz/"
VITE_L2_RPC_URL="https://l2rpc.internal.taiko.xyz/"
VITE_RELAYER_URL="https://relayer.internal.taiko.xyz/"
VITE_TEST_ERC20_ADDRESS_MAINNET="0x1B5Ccd66cc2408A0084047720167F6234Dc5498A"
VITE_TEST_ERC20_SYMBOL_MAINNET="BULL"
VITE_TEST_ERC20_NAME_MAINNET="Bull Token"
VITE_MAINNET_CHAIN_ID=31336
VITE_TAIKO_CHAIN_ID=167001
VITE_MAINNET_CHAIN_NAME="Ethereum A2"
VITE_TAIKO_CHAIN_NAME="Taiko A2"
VITE_MAINNET_TOKEN_VAULT_ADDRESS="0xAE4C9bD0f7AE5398Df05043079596E2BF0079CE9"
shadab-taiko marked this conversation as resolved.
Show resolved Hide resolved
VITE_TAIKO_TOKEN_VAULT_ADDRESS="0x0000777700000000000000000000000000000002"
VITE_MAINNET_TOKEN_VAULT_ADDRESS="0xD0dfd5baCf160B97C8eE3ecb463F18c08673160c"
VITE_MAINNET_HEADER_SYNC_ADDRESS="0xa6421A7f48498cee3aEb6428a8A2DD5fAA3AcE2f"
VITE_TAIKO_HEADER_SYNC_ADDRESS="0x0000777700000000000000000000000000000001"
VITE_MAINNET_HEADER_SYNC_ADDRESS="0x7B3AF414448ba906f02a1CA307C56c4ADFF27ce7"
VITE_MAINNET_BRIDGE_ADDRESS="0x3612E284D763f42f5E4CB72B1602b23DAEC3cA60"
VITE_MAINNET_BRIDGE_ADDRESS="0x0237443359aB0b11EcDC41A7aF1C90226a88c70f"
VITE_TAIKO_BRIDGE_ADDRESS="0x0000777700000000000000000000000000000004"
VITE_MAINNET_SIGNAL_SERVICE_ADDRESS="0x403cc7802725928652a3d116Bb1781005e2e76d3"
VITE_TAIKO_SIGNAL_SERVICE_ADDRESS="0x0000777700000000000000000000000000000007"
```
8 changes: 4 additions & 4 deletions packages/bridge-ui/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ export default {
],
coverageThreshold: {
global: {
statements: 96,
branches: 79,
functions: 91,
lines: 97,
statements: 95,
branches: 72,
functions: 89,
lines: 96,
},
},
modulePathIgnorePatterns: ["<rootDir>/public/build/"],
Expand Down
19 changes: 16 additions & 3 deletions packages/bridge-ui/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
import BridgeABI from "./constants/abi/Bridge";
import { providers } from "./store/providers";
import HeaderAnnouncement from "./components/HeaderAnnouncement.svelte";
import type { TokenService } from "./domain/token";
import { CustomTokenService } from "./storage/customTokenService";
import { userTokens, tokenService } from "./store/userToken";

const providerMap: Map<number, ethers.providers.JsonRpcProvider> = new Map<
number,
Expand Down Expand Up @@ -130,15 +133,25 @@
providerMap
);

const tokenStore: TokenService = new CustomTokenService(
window.localStorage,
);

tokenService.set(tokenStore);

transactioner.set(storageTransactioner);

signer.subscribe(async (store) => {
if (store) {
const userAddress = await store.getAddress();
const txs = await $transactioner.GetAllByAddress(
await store.getAddress()
userAddress
);

transactions.set(txs);

const tokens = await $tokenService.GetTokens(userAddress)
userTokens.set(tokens);
}
return store;
});
Expand Down Expand Up @@ -180,7 +193,7 @@
}

transactionToIntervalMap.set(tx.ethersTx.hash, interval);
if (!tx.signal) return;
if (!tx.msgHash) return;

const contract = new ethers.Contract(
chains[tx.toChainId].bridgeAddress,
Expand All @@ -189,7 +202,7 @@
);

const messageStatus: MessageStatus =
await contract.getMessageStatus(tx.signal);
await contract.getMessageStatus(tx.msgHash);

if (messageStatus === MessageStatus.Done) {
successToast("Bridge message processed successfully");
Expand Down
4 changes: 4 additions & 0 deletions packages/bridge-ui/src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@
border-radius: 0.5rem;
}

ul.token-dropdown li.cursor-pointer:last-child, ul.token-dropdown li.cursor-pointer:first-child {
border-radius: 0;
}

.taiko-banner {
background-image: url('assets/taiko-banner.svg');
background-repeat: no-repeat;
Expand Down
Binary file added packages/bridge-ui/src/assets/erc20.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 6 additions & 2 deletions packages/bridge-ui/src/components/MessageStatusTooltip.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@
<ul class="list-disc ml-4">
<li class="mb-2">
<strong>Pending</strong>: Your asset is not ready to be bridged. Taiko
A1 => Ethereum A1 bridging can take several hours before being ready.
Ethereum A1 => Taiko A1 should be available to claim within minutes.
A1 => {import.meta.env
? import.meta.env.VITE_MAINNET_CHAIN_NAME
: "Ethereum A2"} bridging can take several hours before being ready.
{import.meta.env
? import.meta.env.VITE_MAINNET_CHAIN_NAME
: "Ethereum A2"} => {import.meta.env ? import.meta.env.VITE_TAIKO_CHAIN_NAME : "Taiko A2"} should be available to claim within minutes.
</li>
<li class="mb-2">
<strong>Claimable</strong>: Your asset is ready to be claimed on the
Expand Down
5 changes: 2 additions & 3 deletions packages/bridge-ui/src/components/Transaction.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import HeaderSync from "../constants/abi/HeaderSync";
import { providers } from "../store/providers";
import { fetchSigner, switchNetwork } from "@wagmi/core";
import Tooltip from "./Tooltip.svelte";
import Bridge from "../constants/abi/Bridge";
import ButtonWithTooltip from "./ButtonWithTooltip.svelte";

Expand Down Expand Up @@ -64,7 +63,7 @@
.Claim({
signer: $signer,
message: bridgeTx.message,
signal: bridgeTx.signal,
msgHash: bridgeTx.msgHash,
destBridgeAddress:
chains[bridgeTx.message.destChainId.toNumber()].bridgeAddress,
srcBridgeAddress:
Expand Down Expand Up @@ -109,7 +108,7 @@
$providers.get(chains[transaction.message.destChainId.toNumber()].id)
);

transaction.status = await contract.getMessageStatus(transaction.signal);
transaction.status = await contract.getMessageStatus(transaction.msgHash);
transaction = transaction;
if (transaction.status === MessageStatus.Done) clearInterval(interval);
}, 20 * 1000);
Expand Down
102 changes: 97 additions & 5 deletions packages/bridge-ui/src/components/buttons/SelectToken.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
<script lang="ts">
import { getProvider } from '@wagmi/core'
import { token } from "../../store/token";
import { bridgeType } from "../../store/bridge";
import { ETH, tokens } from "../../domain/token";
import type { Token } from "../../domain/token";
import { BridgeType } from "../../domain/bridge";
import { ChevronDown } from "svelte-heros-v2";
import { successToast } from "../../utils/toast";
import { ChevronDown, PlusCircle } from "svelte-heros-v2";
import { errorToast, successToast } from "../../utils/toast";
import { ethers } from "ethers";
import ERC20 from "../../constants/abi/ERC20";
import { signer } from '../../store/signer';
import { userTokens, tokenService } from '../../store/userToken';
import { fromChain, toChain } from '../../store/chain';
import Erc20 from '../icons/ERC20.svelte';
import AddCustomErc20 from '../form/AddCustomERC20.svelte';

let dropdownElement: HTMLDivElement;

Expand All @@ -25,23 +33,85 @@
document.activeElement.blur();
}
}

let showAddressField = false;

let loading = false;

async function addERC20(event: SubmitEvent) {
try {
loading = true;
const eventTarget = event.target as HTMLFormElement;
const { customTokenAddress } = eventTarget;
const tokenAddress = customTokenAddress.value;
if(!ethers.utils.isAddress(tokenAddress)) {
throw new Error();
}
const provider = getProvider();
const contract = new ethers.Contract(tokenAddress, ERC20, provider);

const userAddress = await $signer.getAddress();
const erc20Check = await contract.balanceOf(userAddress);
const [tokenName, decimals, symbol] = await Promise.all([
contract.name(),
contract.decimals(),
contract.symbol(),
])

const token = {
name: tokenName,
addresses: [
{
chainId: $fromChain.id,
address: tokenAddress,
},
{
chainId: $toChain.id,
address: "0x00",
}
],
decimals: decimals,
symbol: symbol,
logoComponent: null,
}
const updateTokensList = await $tokenService.StoreToken(token, userAddress);
select(token);
userTokens.set(updateTokensList);
eventTarget.reset();
showAddressField = false;
} catch(error) {
errorToast("Not a valid ERC20 address");
console.error(error);
} finally {
loading = false;
}
}
let customTokens = [];
userTokens.subscribe(value => {
if(value)
customTokens = value;
})
</script>

<div class="dropdown dropdown-bottom" bind:this={dropdownElement}>
<label
tabindex="0"
class="flex items-center justify-center hover:cursor-pointer"
>
<svelte:component this={$token.logoComponent} />
{#if $token.logoComponent}
<svelte:component this={$token.logoComponent} />
{:else}
<Erc20 />
{/if}
<p class="px-2 text-sm">{$token.symbol.toUpperCase()}</p>
<ChevronDown size='20' />
</label>
<ul
tabindex="0"
class="dropdown-content menu my-2 shadow-xl bg-dark-2 rounded-box p-2"
class="token-dropdown dropdown-content menu my-2 shadow-xl bg-dark-2 rounded-box p-2"
>
{#each tokens as t}
<li class="cursor-pointer w-full hover:bg-dark-5 px-4 py-4">
<li class="cursor-pointer w-full hover:bg-dark-5 px-4 py-4 rounded-none">
<button on:click={async () => await select(t)} class="flex hover:bg-dark-5">
<svelte:component this={t.logoComponent} height={22} width={22} />
<span class="text-sm font-medium bg-transparent px-2"
Expand All @@ -50,5 +120,27 @@
</button>
</li>
{/each}
{#each customTokens as t}
<li class="cursor-pointer w-full hover:bg-dark-5 px-4 py-4">
<button on:click={async () => await select(t)} class="flex hover:bg-dark-5">
<Erc20 height={22} width={22} />
<span class="text-sm font-medium bg-transparent px-2"
>{t.symbol.toUpperCase()}</span
>
</button>
</li>
{/each}
<li class="cursor-pointer hover:bg-dark-5 px-4 py-4">
<button on:click={() => showAddressField = true} class="flex hover:bg-dark-5 justify-between items-center">
<PlusCircle size='25' />
<span class="text-sm font-medium bg-transparent flex-1 w-[100px] px-0 pl-2"
>Add Custom</span
>
</button>
</li>
</ul>

{#if showAddressField}
<AddCustomErc20 bind:showAddressField addERC20={addERC20} bind:loading />
{/if}
</div>
Loading