diff --git a/packages/bridge-ui/src/app.css b/packages/bridge-ui/src/app.css
index f1e9de666cd..fba7e9c29ed 100644
--- a/packages/bridge-ui/src/app.css
+++ b/packages/bridge-ui/src/app.css
@@ -27,7 +27,6 @@
 .btn.btn-accent {
   background-color: hsla(var(--af) / var(--tw-bg-opacity, 1));
   border-color: hsla(var(--af) / var(--tw-bg-opacity, 1));
-  height: 60px;
 }
 
 .btn.btn-accent:hover {
diff --git a/packages/bridge-ui/src/bridge/ERC20Bridge.ts b/packages/bridge-ui/src/bridge/ERC20Bridge.ts
index 2e79e42faca..e00a1e35813 100644
--- a/packages/bridge-ui/src/bridge/ERC20Bridge.ts
+++ b/packages/bridge-ui/src/bridge/ERC20Bridge.ts
@@ -173,15 +173,15 @@ export class ERC20Bridge implements Bridge {
 
     if (messageStatus === MessageStatus.New) {
       const proof = await this.prover.generateProof({
-        srcChain: opts.message.srcChainId.toNumber(),
+        srcChain: opts.message.srcChainId,
         msgHash: opts.msgHash,
         sender: opts.srcBridgeAddress,
         srcBridgeAddress: opts.srcBridgeAddress,
-        destChain: opts.message.destChainId.toNumber(),
+        destChain: opts.message.destChainId,
         destHeaderSyncAddress:
-          chains[opts.message.destChainId.toNumber()].headerSyncAddress,
+          chains[opts.message.destChainId].headerSyncAddress,
         srcSignalServiceAddress:
-          chains[opts.message.srcChainId.toNumber()].signalServiceAddress,
+          chains[opts.message.srcChainId].signalServiceAddress,
       });
 
       if (opts.message.gasLimit.gt(BigNumber.from(2500000))) {
@@ -234,15 +234,14 @@ export class ERC20Bridge implements Bridge {
 
     if (messageStatus === MessageStatus.Failed) {
       const proofOpts = {
-        srcChain: opts.message.srcChainId.toNumber(),
+        srcChain: opts.message.srcChainId,
         msgHash: opts.msgHash,
         sender: opts.srcBridgeAddress,
         destBridgeAddress: opts.destBridgeAddress,
-        destChain: opts.message.destChainId.toNumber(),
+        destChain: opts.message.destChainId,
         destHeaderSyncAddress:
-          chains[opts.message.destChainId.toNumber()].headerSyncAddress,
-        srcHeaderSyncAddress:
-          chains[opts.message.srcChainId.toNumber()].headerSyncAddress,
+          chains[opts.message.destChainId].headerSyncAddress,
+        srcHeaderSyncAddress: chains[opts.message.srcChainId].headerSyncAddress,
       };
 
       const proof = await this.prover.generateReleaseProof(proofOpts);
diff --git a/packages/bridge-ui/src/bridge/ETHBridge.ts b/packages/bridge-ui/src/bridge/ETHBridge.ts
index 8aceb3b8341..c82f6407ab5 100644
--- a/packages/bridge-ui/src/bridge/ETHBridge.ts
+++ b/packages/bridge-ui/src/bridge/ETHBridge.ts
@@ -7,11 +7,10 @@ import type {
   ClaimOpts,
   ReleaseOpts,
 } from '../domain/bridge';
-import TokenVault from '../constants/abi/TokenVault';
 import type { Prover } from '../domain/proof';
-import { MessageStatus } from '../domain/message';
 import BridgeABI from '../constants/abi/Bridge';
 import { chains } from '../chain/chains';
+import { type Message, MessageStatus } from '../domain/message';
 
 export class ETHBridge implements Bridge {
   private readonly prover: Prover;
@@ -22,7 +21,7 @@ export class ETHBridge implements Bridge {
 
   static async prepareTransaction(
     opts: BridgeOpts,
-  ): Promise<{ contract: Contract; message: any; owner: string }> {
+  ): Promise<{ contract: Contract; message: Message; owner: string }> {
     const contract: Contract = new Contract(
       opts.bridgeAddress,
       BridgeABI,
@@ -30,7 +29,7 @@ export class ETHBridge implements Bridge {
     );
 
     const owner = await opts.signer.getAddress();
-    const message = {
+    const message: Message = {
       sender: owner,
       srcChainId: opts.fromChainId,
       destChainId: opts.toChainId,
@@ -113,15 +112,15 @@ export class ETHBridge implements Bridge {
 
     if (messageStatus === MessageStatus.New) {
       const proofOpts = {
-        srcChain: opts.message.srcChainId.toNumber(),
+        srcChain: opts.message.srcChainId,
         msgHash: opts.msgHash,
         sender: opts.srcBridgeAddress,
         srcBridgeAddress: opts.srcBridgeAddress,
-        destChain: opts.message.destChainId.toNumber(),
+        destChain: opts.message.destChainId,
         destHeaderSyncAddress:
-          chains[opts.message.destChainId.toNumber()].headerSyncAddress,
+          chains[opts.message.destChainId].headerSyncAddress,
         srcSignalServiceAddress:
-          chains[opts.message.srcChainId.toNumber()].signalServiceAddress,
+          chains[opts.message.srcChainId].signalServiceAddress,
       };
 
       const proof = await this.prover.generateProof(proofOpts);
@@ -169,15 +168,14 @@ export class ETHBridge implements Bridge {
 
     if (messageStatus === MessageStatus.Failed) {
       const proofOpts = {
-        srcChain: opts.message.srcChainId.toNumber(),
+        srcChain: opts.message.srcChainId,
         msgHash: opts.msgHash,
         sender: opts.srcBridgeAddress,
         destBridgeAddress: opts.destBridgeAddress,
-        destChain: opts.message.destChainId.toNumber(),
+        destChain: opts.message.destChainId,
         destHeaderSyncAddress:
-          chains[opts.message.destChainId.toNumber()].headerSyncAddress,
-        srcHeaderSyncAddress:
-          chains[opts.message.srcChainId.toNumber()].headerSyncAddress,
+          chains[opts.message.destChainId].headerSyncAddress,
+        srcHeaderSyncAddress: chains[opts.message.srcChainId].headerSyncAddress,
       };
 
       const proof = await this.prover.generateReleaseProof(proofOpts);
diff --git a/packages/bridge-ui/src/components/ChainDropdown.svelte b/packages/bridge-ui/src/components/ChainDropdown.svelte
index db6d8e8c485..453e62a6421 100644
--- a/packages/bridge-ui/src/components/ChainDropdown.svelte
+++ b/packages/bridge-ui/src/components/ChainDropdown.svelte
@@ -1,5 +1,4 @@
 <script lang="ts">
-  import { _ } from 'svelte-i18n';
   import { fromChain, toChain } from '../store/chain';
   import type { Chain } from '../domain/chain';
   import { ethers } from 'ethers';
diff --git a/packages/bridge-ui/src/components/TaikoBanner.svelte b/packages/bridge-ui/src/components/TaikoBanner.svelte
index f04b21d13bc..0e38aa07021 100644
--- a/packages/bridge-ui/src/components/TaikoBanner.svelte
+++ b/packages/bridge-ui/src/components/TaikoBanner.svelte
@@ -1,5 +1,4 @@
 <script>
-  import { _ } from 'svelte-i18n';
   import SelectChain from './form/SelectChain.svelte';
 </script>
 
diff --git a/packages/bridge-ui/src/components/Transactions.svelte b/packages/bridge-ui/src/components/Transactions.svelte
deleted file mode 100644
index 67bd281025a..00000000000
--- a/packages/bridge-ui/src/components/Transactions.svelte
+++ /dev/null
@@ -1,58 +0,0 @@
-<script lang="ts">
-  import { transactions } from '../store/transactions';
-  import Transaction from './Transaction.svelte';
-  import TransactionDetail from './TransactionDetail.svelte';
-  import MessageStatusTooltip from './MessageStatusTooltip.svelte';
-  import InsufficientBalanceTooltip from './InsufficientBalanceTooltip.svelte';
-  import type { BridgeTransaction } from '../domain/transactions';
-  import { chains } from '../chain/chains';
-
-  let selectedTransaction: BridgeTransaction;
-  let showMessageStatusTooltip: boolean;
-  let showInsufficientBalance: boolean;
-</script>
-
-<div class="my-4 md:px-4">
-  {#if $transactions.length}
-    <table class="table-auto">
-      <thead>
-        <tr class="text-transaction-table">
-          <th>From</th>
-          <th>To</th>
-          <th>Amount</th>
-          <th>Status</th>
-          <th>Details</th>
-        </tr>
-      </thead>
-      <tbody class="text-sm md:text-base">
-        {#each $transactions as transaction}
-          <Transaction
-            onTooltipClick={(showInsufficientBalanceMessage = false) => {
-              if (showInsufficientBalanceMessage) {
-                showInsufficientBalance = true;
-              } else {
-                showMessageStatusTooltip = true;
-              }
-            }}
-            onShowTransactionDetailsClick={() => {
-              selectedTransaction = transaction;
-            }}
-            toChain={chains[transaction.toChainId]}
-            fromChain={chains[transaction.fromChainId]}
-            {transaction} />
-        {/each}
-      </tbody>
-    </table>
-  {:else}
-    No transactions
-  {/if}
-
-  {#if selectedTransaction}
-    <TransactionDetail
-      transaction={selectedTransaction}
-      onClose={() => (selectedTransaction = null)} />
-  {/if}
-
-  <MessageStatusTooltip bind:show={showMessageStatusTooltip} />
-  <InsufficientBalanceTooltip bind:show={showInsufficientBalance} />
-</div>
diff --git a/packages/bridge-ui/src/components/InsufficientBalanceTooltip.svelte b/packages/bridge-ui/src/components/Transactions/InsufficientBalanceTooltip.svelte
similarity index 87%
rename from packages/bridge-ui/src/components/InsufficientBalanceTooltip.svelte
rename to packages/bridge-ui/src/components/Transactions/InsufficientBalanceTooltip.svelte
index f5a5dc6064b..68415e8460e 100644
--- a/packages/bridge-ui/src/components/InsufficientBalanceTooltip.svelte
+++ b/packages/bridge-ui/src/components/Transactions/InsufficientBalanceTooltip.svelte
@@ -1,5 +1,5 @@
 <script lang="ts">
-  import TooltipModal from './modals/TooltipModal.svelte';
+  import TooltipModal from '../modals/TooltipModal.svelte';
 
   export let show: boolean;
 </script>
diff --git a/packages/bridge-ui/src/components/MessageStatusTooltip.svelte b/packages/bridge-ui/src/components/Transactions/MessageStatusTooltip.svelte
similarity index 72%
rename from packages/bridge-ui/src/components/MessageStatusTooltip.svelte
rename to packages/bridge-ui/src/components/Transactions/MessageStatusTooltip.svelte
index e98c856b45c..e6a9df8181d 100644
--- a/packages/bridge-ui/src/components/MessageStatusTooltip.svelte
+++ b/packages/bridge-ui/src/components/Transactions/MessageStatusTooltip.svelte
@@ -1,5 +1,6 @@
 <script lang="ts">
-  import TooltipModal from './modals/TooltipModal.svelte';
+  import { L1_CHAIN_NAME, L2_CHAIN_NAME } from '../../constants/envVars';
+  import TooltipModal from '../modals/TooltipModal.svelte';
 
   export let show: boolean;
 </script>
@@ -12,14 +13,9 @@
       <ul class="list-disc ml-4">
         <li class="mb-2">
           <strong>Pending</strong>: Your asset is not ready to be bridged. Taiko
-          A2 => {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.
+          A2 => {L2_CHAIN_NAME} bridging can take several hours before being ready.
+          {L1_CHAIN_NAME} => {L2_CHAIN_NAME} should be available to claim within
+          minutes.
         </li>
         <li class="mb-2">
           <strong>Claim</strong>: Your asset is ready to be claimed on the
diff --git a/packages/bridge-ui/src/components/Transaction.svelte b/packages/bridge-ui/src/components/Transactions/Transaction.svelte
similarity index 68%
rename from packages/bridge-ui/src/components/Transaction.svelte
rename to packages/bridge-ui/src/components/Transactions/Transaction.svelte
index 749cfc1ab5c..a83ec3d1b06 100644
--- a/packages/bridge-ui/src/components/Transaction.svelte
+++ b/packages/bridge-ui/src/components/Transactions/Transaction.svelte
@@ -1,43 +1,45 @@
 <script lang="ts">
-  import type { BridgeTransaction } from '../domain/transactions';
-  import type { Chain } from '../domain/chain';
+  import { createEventDispatcher } from 'svelte';
+  import type { BridgeTransaction } from '../../domain/transactions';
   import { ArrowTopRightOnSquare } from 'svelte-heros-v2';
-  import { MessageStatus } from '../domain/message';
+  import { MessageStatus } from '../../domain/message';
   import { Contract, ethers } from 'ethers';
-  import { signer } from '../store/signer';
-  import { pendingTransactions } from '../store/transactions';
+  import { signer } from '../../store/signer';
+  import { pendingTransactions } from '../../store/transactions';
   import { _ } from 'svelte-i18n';
-  import {
-    fromChain as fromChainStore,
-    toChain as toChainStore,
-  } from '../store/chain';
-  import { BridgeType } from '../domain/bridge';
+  import { fromChain } from '../../store/chain';
+  import { BridgeType } from '../../domain/bridge';
   import { onDestroy, onMount } from 'svelte';
 
   import { LottiePlayer } from '@lottiefiles/svelte-lottie-player';
-  import { errorToast, successToast } from './Toast.svelte';
-  import HeaderSyncABI from '../constants/abi/HeaderSync';
-  import { fetchSigner, switchNetwork } from '@wagmi/core';
-  import BridgeABI from '../constants/abi/Bridge';
-  import ButtonWithTooltip from './ButtonWithTooltip.svelte';
-  import TokenVaultABI from '../constants/abi/TokenVault';
-  import { chains, mainnetChain, taikoChain } from '../chain/chains';
-  import { providers } from '../provider/providers';
-  import { bridges } from '../bridge/bridges';
-  import { tokenVaults } from '../vault/tokenVaults';
-  import { isOnCorrectChain } from '../utils/isOnCorrectChain';
+  import { errorToast, successToast } from '../Toast.svelte';
+  import HeaderSyncABI from '../../constants/abi/HeaderSync';
+  import BridgeABI from '../../constants/abi/Bridge';
+  import ButtonWithTooltip from '../ButtonWithTooltip.svelte';
+  import TokenVaultABI from '../../constants/abi/TokenVault';
+  import { chains } from '../../chain/chains';
+  import { providers } from '../../provider/providers';
+  import { bridges } from '../../bridge/bridges';
+  import { tokenVaults } from '../../vault/tokenVaults';
+  import { isOnCorrectChain } from '../../utils/isOnCorrectChain';
+  import Button from '../buttons/Button.svelte';
+  import { switchChainAndSetSigner } from '../../utils/switchChainAndSetSigner';
 
   export let transaction: BridgeTransaction;
-  export let fromChain: Chain;
-  export let toChain: Chain;
 
-  export let onTooltipClick: (showInsufficientBalanceMessage: boolean) => void;
-  export let onShowTransactionDetailsClick: () => void;
+  const dispatch = createEventDispatcher<{
+    tooltipClick: void;
+    insufficientBalance: void;
+    transactionDetailsClick: BridgeTransaction;
+    relayerAutoClaim: (informed: boolean) => Promise<void>;
+  }>();
 
   let loading: boolean;
-
   let processable: boolean = false;
   let interval: ReturnType<typeof setInterval>;
+  let txToChain = chains[transaction.toChainId];
+  let txFromChain = chains[transaction.fromChainId];
+  let alreadyInformedAboutClaim = false;
 
   onMount(async () => {
     processable = await isProcessable();
@@ -50,30 +52,35 @@
     }
   });
 
-  async function switchChainAndSetSigner(chain: Chain) {
-    await switchNetwork({
-      chainId: chain.id,
-    });
-    const provider = new ethers.providers.Web3Provider(window.ethereum);
-    await provider.send('eth_requestAccounts', []);
-
-    fromChainStore.set(chain);
-    if (chain === mainnetChain) {
-      toChainStore.set(taikoChain);
+  async function onClaimClick() {
+    // Has the user sent processing fees?. We also check if the user
+    // has already been informed about the relayer auto-claim.
+    const processingFee = transaction.message?.processingFee.toString();
+    if (processingFee && processingFee !== '0' && !alreadyInformedAboutClaim) {
+      dispatch(
+        'relayerAutoClaim',
+        // TODO: this is a hack. The idea is to move all these
+        //       functions outside of the component, where they
+        //       make more sense. We don't need to repeat the same
+        //       logic per transaction.
+        async (informed) => {
+          alreadyInformedAboutClaim = informed;
+          await claim(transaction);
+        },
+      );
     } else {
-      toChainStore.set(mainnetChain);
+      await claim(transaction);
     }
-    const wagmiSigner = await fetchSigner();
-    signer.set(wagmiSigner);
   }
 
+  // TODO: move outside of component
   async function claim(bridgeTx: BridgeTransaction) {
     try {
       loading = true;
       // if the current "from chain", ie, the chain youre connected to, is not the destination
       // of the bridge transaction, we need to change chains so your wallet is pointed
       // to the right network.
-      if ($fromChainStore.id !== bridgeTx.toChainId) {
+      if ($fromChain.id !== bridgeTx.toChainId) {
         const chain = chains[bridgeTx.toChainId];
         await switchChainAndSetSigner(chain);
       }
@@ -88,7 +95,7 @@
       // TODO: estimate Claim transaction
       const userBalance = await $signer.getBalance('latest');
       if (!userBalance.gt(ethers.utils.parseEther('0.0001'))) {
-        onTooltipClick(true);
+        dispatch('insufficientBalance');
         return;
       }
 
@@ -110,6 +117,7 @@
       });
 
       successToast($_('toast.transactionSent'));
+      // TODO: keep the MessageStatus as contract and use another way.
       transaction.status = MessageStatus.ClaimInProgress;
     } catch (e) {
       console.error(e);
@@ -119,10 +127,11 @@
     }
   }
 
+  // TODO: move outside of component
   async function releaseTokens(bridgeTx: BridgeTransaction) {
     try {
       loading = true;
-      if (fromChain.id !== bridgeTx.fromChainId) {
+      if (txFromChain.id !== bridgeTx.fromChainId) {
         const chain = chains[bridgeTx.fromChainId];
         await switchChainAndSetSigner(chain);
       }
@@ -161,6 +170,7 @@
     }
   }
 
+  // TODO: this could also live in an utility: isTransactionProcessable?
   async function isProcessable() {
     if (!transaction.receipt) return false;
     if (!transaction.message) return false;
@@ -180,6 +190,7 @@
     return transaction.receipt.blockNumber <= srcBlock.number;
   }
 
+  // TODO: web worker?
   function startInterval() {
     return setInterval(async () => {
       processable = await isProcessable();
@@ -234,14 +245,15 @@
 
 <tr class="text-transaction-table">
   <td>
-    <svelte:component this={fromChain.icon} height={18} width={18} />
-    <span class="ml-2 hidden md:inline-block">{fromChain.name}</span>
+    <svelte:component this={txFromChain.icon} height={18} width={18} />
+    <span class="ml-2 hidden md:inline-block">{txFromChain.name}</span>
   </td>
   <td>
-    <svelte:component this={toChain.icon} height={18} width={18} />
-    <span class="ml-2 hidden md:inline-block">{toChain.name}</span>
+    <svelte:component this={txToChain.icon} height={18} width={18} />
+    <span class="ml-2 hidden md:inline-block">{txToChain.name}</span>
   </td>
   <td>
+    <!-- TODO: function to check is we're dealing with ETH or ERC20? -->
     {transaction.message &&
     (transaction.message?.data === '0x' || !transaction.message?.data)
       ? ethers.utils.formatEther(
@@ -254,11 +266,9 @@
   </td>
 
   <td>
-    <ButtonWithTooltip onClick={() => onTooltipClick(false)}>
+    <ButtonWithTooltip onClick={() => dispatch('tooltipClick')}>
       <span slot="buttonText">
-        {#if transaction.receipt && transaction.receipt.status !== 1}
-          <span class="border border-transparent p-0">Failed</span>
-        {:else if !processable}
+        {#if !processable}
           Pending
         {:else if (!transaction.receipt && transaction.status === MessageStatus.New) || loading}
           <div class="inline-block">
@@ -274,29 +284,35 @@
               controlsLayout={[]} />
           </div>
         {:else if transaction.receipt && [MessageStatus.New, MessageStatus.ClaimInProgress].includes(transaction.status)}
-          <button
-            class="cursor-pointer border rounded p-1 btn btn-sm border-white disabled:border-gray-800"
-            on:click={async () => await claim(transaction)}
+          <!-- 
+            TODO: we need some destructuring here. 
+                  We keep on accessing transaction props
+                  over and over again.
+          -->
+          <Button
+            type="accent"
+            size="sm"
+            on:click={onClaimClick}
             disabled={transaction.status === MessageStatus.ClaimInProgress}>
             Claim
-          </button>
+          </Button>
         {:else if transaction.status === MessageStatus.Retriable}
-          <button
-            class="cursor-pointer border rounded p-1 btn btn-sm border-white"
-            on:click={async () => await claim(transaction)}>
-            Retry
-          </button>
+          <Button type="accent" size="sm" on:click={onClaimClick}>Retry</Button>
         {:else if transaction.status === MessageStatus.Failed}
           <!-- todo: releaseTokens() on src bridge with proof from destBridge-->
-          <button
-            class="cursor-pointer border rounded p-1 btn btn-sm border-white"
+          <Button
+            type="accent"
+            size="sm"
             on:click={async () => await releaseTokens(transaction)}>
             Release
-          </button>
+          </Button>
         {:else if transaction.status === MessageStatus.Done}
           <span class="border border-transparent p-0">Claimed</span>
         {:else if transaction.status === MessageStatus.FailedReleased}
           <span class="border border-transparent p-0">Released</span>
+        {:else if transaction.receipt && transaction.receipt.status !== 1}
+          <!-- TODO: make sure this is now respecting the correct flow -->
+          <span class="border border-transparent p-0">Failed</span>
         {/if}
       </span>
     </ButtonWithTooltip>
@@ -305,7 +321,7 @@
   <td>
     <button
       class="cursor-pointer inline-block"
-      on:click={onShowTransactionDetailsClick}>
+      on:click={() => dispatch('transactionDetailsClick', transaction)}>
       <ArrowTopRightOnSquare />
     </button>
   </td>
diff --git a/packages/bridge-ui/src/components/TransactionDetail.svelte b/packages/bridge-ui/src/components/Transactions/TransactionDetail.svelte
similarity index 89%
rename from packages/bridge-ui/src/components/TransactionDetail.svelte
rename to packages/bridge-ui/src/components/Transactions/TransactionDetail.svelte
index e5f3868acc5..d3a9f88246f 100644
--- a/packages/bridge-ui/src/components/TransactionDetail.svelte
+++ b/packages/bridge-ui/src/components/Transactions/TransactionDetail.svelte
@@ -1,11 +1,10 @@
 <script lang="ts">
   import { ethers } from 'ethers';
   import { ArrowTopRightOnSquare } from 'svelte-heros-v2';
-  import { truncateString } from '../utils/truncateString';
-  import Modal from './modals/Modal.svelte';
-  import type { BridgeTransaction } from '../domain/transactions';
-  import { addressSubsection } from '../utils/addressSubsection';
-  import { chains } from '../chain/chains';
+  import Modal from '../modals/Modal.svelte';
+  import type { BridgeTransaction } from '../../domain/transactions';
+  import { addressSubsection } from '../../utils/addressSubsection';
+  import { chains } from '../../chain/chains';
 
   // TODO: can we always guarantee that this object is defined?
   //       in which case we need to guard => transaction?.prop
diff --git a/packages/bridge-ui/src/components/Transactions/Transactions.svelte b/packages/bridge-ui/src/components/Transactions/Transactions.svelte
new file mode 100644
index 00000000000..13b34ff3e46
--- /dev/null
+++ b/packages/bridge-ui/src/components/Transactions/Transactions.svelte
@@ -0,0 +1,75 @@
+<script lang="ts">
+  import { transactions } from '../../store/transactions';
+  import Transaction from './Transaction.svelte';
+  import TransactionDetail from './TransactionDetail.svelte';
+  import MessageStatusTooltip from './MessageStatusTooltip.svelte';
+  import InsufficientBalanceTooltip from './InsufficientBalanceTooltip.svelte';
+  import type { BridgeTransaction } from '../../domain/transactions';
+  import NoticeModal from '../modals/NoticeModal.svelte';
+
+  let selectedTransaction: BridgeTransaction;
+  let showMessageStatusTooltip: boolean;
+  let showInsufficientBalance: boolean;
+  let showRelayerAutoclaimTooltip: boolean;
+
+  // TODO: temporary hack until we move the claim and release functions
+  //       outside of the Transaction component.
+  let confirmNotice: (informed: boolean) => Promise<void>;
+</script>
+
+<div class="my-4 md:px-4">
+  {#if $transactions.length}
+    <table class="table-auto">
+      <thead>
+        <tr class="text-transaction-table">
+          <th>From</th>
+          <th>To</th>
+          <th>Amount</th>
+          <th>Status</th>
+          <th>Details</th>
+        </tr>
+      </thead>
+      <tbody class="text-sm md:text-base">
+        {#each $transactions as transaction}
+          <Transaction
+            on:tooltipClick={() => (showMessageStatusTooltip = true)}
+            on:insufficientBalance={() => (showInsufficientBalance = true)}
+            on:relayerAutoClaim={({ detail }) => {
+              // We're passing the claiming of the transaction here, which
+              // will be called after confirming the notice.
+              confirmNotice = detail;
+              showRelayerAutoclaimTooltip = true;
+            }}
+            on:transactionDetailsClick={() => {
+              selectedTransaction = transaction;
+            }}
+            {transaction} />
+        {/each}
+      </tbody>
+    </table>
+  {:else}
+    No transactions
+  {/if}
+
+  {#if selectedTransaction}
+    <TransactionDetail
+      transaction={selectedTransaction}
+      onClose={() => (selectedTransaction = null)} />
+  {/if}
+
+  <MessageStatusTooltip bind:show={showMessageStatusTooltip} />
+
+  <InsufficientBalanceTooltip bind:show={showInsufficientBalance} />
+
+  <NoticeModal
+    bind:show={showRelayerAutoclaimTooltip}
+    onConfirm={confirmNotice}
+    name="RelayerAutoclaim">
+    <!-- TODO: translations? -->
+    <div class="text-center">
+      When bridging, you selected the <strong>Recommended</strong> or
+      <strong>Custom</strong> amount for the Processing Fee. You can wait for the
+      relayer to auto-claim the bridged token or manually claim it now.
+    </div>
+  </NoticeModal>
+</div>
diff --git a/packages/bridge-ui/src/components/Transactions/index.ts b/packages/bridge-ui/src/components/Transactions/index.ts
new file mode 100644
index 00000000000..5c914036b27
--- /dev/null
+++ b/packages/bridge-ui/src/components/Transactions/index.ts
@@ -0,0 +1 @@
+export { default } from './Transactions.svelte';
diff --git a/packages/bridge-ui/src/components/buttons/Button.svelte b/packages/bridge-ui/src/components/buttons/Button.svelte
new file mode 100644
index 00000000000..5c994c9d590
--- /dev/null
+++ b/packages/bridge-ui/src/components/buttons/Button.svelte
@@ -0,0 +1,16 @@
+<!--
+  TODO: this is a PoC. The idea would be to have a button component that can be
+  styled based on props following daisyUI classes.
+-->
+<script lang="ts">
+  import type { SizeButton, TypeButton } from '../../domain/button';
+
+  export let type: TypeButton = '';
+  export let size: SizeButton = 'md';
+
+  const classes = `btn ${`btn-${type}`} ${`btn-${size}`} ${$$props.class}`;
+</script>
+
+<button {...$$restProps} on:click class={classes}>
+  <slot />
+</button>
diff --git a/packages/bridge-ui/src/components/form/BridgeForm.svelte b/packages/bridge-ui/src/components/form/BridgeForm.svelte
index 256ebd02baf..a485da08382 100644
--- a/packages/bridge-ui/src/components/form/BridgeForm.svelte
+++ b/packages/bridge-ui/src/components/form/BridgeForm.svelte
@@ -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';
@@ -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';
@@ -39,20 +37,22 @@
   import { providers } from '../../provider/providers';
   import { tokenVaults } from '../../vault/tokenVaults';
   import { isOnCorrectChain } from '../../utils/isOnCorrectChain';
+  import { ProcessingFeeMethod } from '../../domain/fee';
+  import Button from '../buttons/Button.svelte';
 
   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.
@@ -333,10 +333,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);
         }
@@ -362,17 +364,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);
@@ -458,12 +454,12 @@
 
 <To bind:showTo bind:to />
 
-<ProcessingFee bind:customFee bind:recommendedFee />
+<ProcessingFee bind:method={feeMethod} bind:amount={feeAmount} />
 
 <Memo bind:memo bind:memoError />
 
 {#if loading}
-  <button class="btn btn-accent w-full" disabled={true}>
+  <Button type="accent" size="lg" class="w-full" disabled={true}>
     <LottiePlayer
       src="/lottie/loader.json"
       autoplay={true}
@@ -474,21 +470,24 @@
       height={26}
       width={26}
       controlsLayout={[]} />
-  </button>
+  </Button>
 {:else if !requiresAllowance}
-  <button
-    class="btn btn-accent w-full mt-4"
+  <Button
+    type="accent"
+    size="lg"
+    class="w-full"
     on:click={bridge}
     disabled={btnDisabled}>
     {$_('home.bridge')}
-  </button>
+  </Button>
 {:else}
-  <button
-    class="btn btn-accent approve-btn w-full mt-4"
+  <Button
+    type="accent"
+    class="w-full"
     on:click={approve}
     disabled={btnDisabled}>
     {$_('home.approve')}
-  </button>
+  </Button>
 {/if}
 
 <style>
diff --git a/packages/bridge-ui/src/components/form/Memo.svelte b/packages/bridge-ui/src/components/form/Memo.svelte
index 0e21be6519f..5c0347a7060 100644
--- a/packages/bridge-ui/src/components/form/Memo.svelte
+++ b/packages/bridge-ui/src/components/form/Memo.svelte
@@ -1,6 +1,5 @@
 <script lang="ts">
   import TooltipModal from '../modals/TooltipModal.svelte';
-  import Tooltip from '../Tooltip.svelte';
   import ButtonWithTooltip from '../ButtonWithTooltip.svelte';
 
   export let memo: string = '';
diff --git a/packages/bridge-ui/src/components/form/ProcessingFee.svelte b/packages/bridge-ui/src/components/form/ProcessingFee.svelte
deleted file mode 100644
index 37de24a0a90..00000000000
--- a/packages/bridge-ui/src/components/form/ProcessingFee.svelte
+++ /dev/null
@@ -1,108 +0,0 @@
-<script lang="ts">
-  import { _ } from 'svelte-i18n';
-  import { processingFee } from '../../store/fee';
-  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 TooltipModal from '../modals/TooltipModal.svelte';
-  import ButtonWithTooltip from '../ButtonWithTooltip.svelte';
-  import { processingFees } from '../../fee/processingFees';
-
-  export let customFee: string;
-  export let recommendedFee: string = '0';
-
-  let tooltipOpen: boolean = false;
-
-  $: recommendProcessingFee(
-    $toChain,
-    $fromChain,
-    $processingFee,
-    $token,
-    $signer,
-  )
-    .then((fee) => (recommendedFee = fee))
-    .catch((e) => console.error(e));
-
-  function selectProcessingFee(fee) {
-    $processingFee = fee;
-  }
-
-  function updateAmount(e: any) {
-    customFee = (e.target.value as number).toString();
-  }
-</script>
-
-<div class="my-10">
-  <div class="flex flex-row justify-between">
-    <ButtonWithTooltip onClick={() => (tooltipOpen = true)}>
-      <span slot="buttonText">{$_('bridgeForm.processingFeeLabel')}</span>
-    </ButtonWithTooltip>
-  </div>
-
-  {#if $processingFee === ProcessingFeeMethod.CUSTOM}
-    <label class="mt-2 input-group relative">
-      <input
-        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 $processingFee === ProcessingFeeMethod.RECOMMENDED}
-    <div class="flex flex-row">
-      <span class="mt-2 text-sm">{recommendedFee} ETH</span>
-    </div>
-  {/if}
-
-  <div class="flex mt-2 space-x-2">
-    {#each Array.from(processingFees) as fee}
-      <button
-        class="{$processingFee === fee[0]
-          ? 'border-accent hover:border-accent'
-          : ''} btn btn-md text-xs font-semibold md:w-32 dark:bg-dark-5"
-        on:click={() => selectProcessingFee(fee[0])}
-        >{fee[1].displayText}</button>
-    {/each}
-  </div>
-</div>
-
-<TooltipModal title="Processing Fees" bind:isOpen={tooltipOpen}>
-  <span slot="body">
-    <div class="text-left">
-      The amount you pay the relayer to process your bridge message on the
-      destination chain.
-      <br /><br />
-      <ul class="list-disc ml-4">
-        <li>
-          <strong>Recommended</strong>: The recommended fee is the lowest fee
-          that will get your transaction processed in a reasonable amount of
-          time.
-        </li>
-        <li>
-          <strong>Custom</strong>: You can set a custom fee for the relayer to
-          incentivize them to prioritize your request. A lower fee may result in
-          longer processing time.
-        </li>
-        <li>
-          <strong>None</strong>: You can select no fee if you want to come back
-          here and claim the bridged asset yourself.
-        </li>
-      </ul>
-    </div>
-  </span>
-</TooltipModal>
-
-<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>
diff --git a/packages/bridge-ui/src/components/form/ProcessingFee/ProcessingFee.svelte b/packages/bridge-ui/src/components/form/ProcessingFee/ProcessingFee.svelte
new file mode 100644
index 00000000000..3d3dded0985
--- /dev/null
+++ b/packages/bridge-ui/src/components/form/ProcessingFee/ProcessingFee.svelte
@@ -0,0 +1,107 @@
+<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 NoticeModal from '../../modals/NoticeModal.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} />
+
+<NoticeModal bind:show={showNoneFeeTooltip} name="NoneFeeTooltip">
+  <!-- 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>
+</NoticeModal>
+
+<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>
diff --git a/packages/bridge-ui/src/components/form/ProcessingFee/ProcessingFeeTooltip.svelte b/packages/bridge-ui/src/components/form/ProcessingFee/ProcessingFeeTooltip.svelte
new file mode 100644
index 00000000000..4bac37572cd
--- /dev/null
+++ b/packages/bridge-ui/src/components/form/ProcessingFee/ProcessingFeeTooltip.svelte
@@ -0,0 +1,31 @@
+<script>
+  import TooltipModal from '../../modals/TooltipModal.svelte';
+
+  export let show = false;
+</script>
+
+<TooltipModal title="Processing Fees" bind:isOpen={show}>
+  <span slot="body">
+    <div class="text-left">
+      The amount you pay the relayer to process your bridge message on the
+      destination chain.
+      <br /><br />
+      <ul class="list-disc ml-4">
+        <li>
+          <strong>Recommended</strong>: The recommended fee is the lowest fee
+          that will get your transaction processed in a reasonable amount of
+          time.
+        </li>
+        <li>
+          <strong>Custom</strong>: You can set a custom fee for the relayer to
+          incentivize them to prioritize your request. A lower fee may result in
+          longer processing time.
+        </li>
+        <li>
+          <strong>None</strong>: You can select no fee if you want to come back
+          here and claim the bridged asset yourself.
+        </li>
+      </ul>
+    </div>
+  </span>
+</TooltipModal>
diff --git a/packages/bridge-ui/src/components/form/ProcessingFee/index.ts b/packages/bridge-ui/src/components/form/ProcessingFee/index.ts
new file mode 100644
index 00000000000..645d7e05066
--- /dev/null
+++ b/packages/bridge-ui/src/components/form/ProcessingFee/index.ts
@@ -0,0 +1 @@
+export { default } from './ProcessingFee.svelte';
diff --git a/packages/bridge-ui/src/components/modals/Modal.svelte b/packages/bridge-ui/src/components/modals/Modal.svelte
index cf82cfaf6b7..3e618fc827b 100644
--- a/packages/bridge-ui/src/components/modals/Modal.svelte
+++ b/packages/bridge-ui/src/components/modals/Modal.svelte
@@ -1,23 +1,22 @@
 <script lang="ts">
   export let title: string = null;
   export let isOpen: boolean = false;
-  export let onClose: () => void = null;
   export let showXButton: boolean = true;
+  export let onClose: () => void = null;
 
   const onCloseClicked = () => {
     isOpen = false;
-    if (onClose) {
-      onClose();
-    }
+    onClose?.();
   };
-</script>
 
-<svelte:window
-  on:keydown={function (e) {
+  const onWindowKeydownPressed = (e) => {
     if (e.key === 'Escape') {
       onCloseClicked();
     }
-  }} />
+  };
+</script>
+
+<svelte:window on:keydown={onWindowKeydownPressed} />
 
 <div class="modal bg-black/60" class:modal-open={isOpen}>
   <div class="modal-box bg-dark-2">
diff --git a/packages/bridge-ui/src/components/modals/NoticeModal.svelte b/packages/bridge-ui/src/components/modals/NoticeModal.svelte
new file mode 100644
index 00000000000..65b15e44826
--- /dev/null
+++ b/packages/bridge-ui/src/components/modals/NoticeModal.svelte
@@ -0,0 +1,68 @@
+<script lang="ts">
+  import { onMount } from 'svelte';
+  import { localStoragePrefix } from '../../config';
+  import Button from '../buttons/Button.svelte';
+  import Modal from './Modal.svelte';
+
+  export let show = false;
+  export let name = 'NoticeModal';
+  export let title = 'Notice';
+  export let onConfirm: (noShowAgain: boolean) => void = null;
+
+  let noShowAgainLocalStorageKey = `${localStoragePrefix}_${name}_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;
+
+    onConfirm?.(noShowAgainCheckbox);
+  }
+</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.
+-->
+<Modal {title} isOpen={show && !noShowAgainStorage} showXButton={false}>
+  <div
+    class="
+      flex
+      w-full
+      flex-col
+      justify-between
+      space-y-6
+    ">
+    <slot />
+
+    <div class="text-left flex items-center">
+      <input
+        style:border-radius="0.5rem"
+        type="checkbox"
+        id="noShowAgain_{name}"
+        bind:checked={noShowAgainCheckbox}
+        class="checkbox checkbox-secundary mr-2" />
+      <label for="noShowAgain_{name}">Do not show this message again</label>
+    </div>
+
+    <div class="flex justify-center">
+      <Button type="accent" on:click={onConfirmNotice}>Confirm</Button>
+    </div>
+  </div>
+</Modal>
diff --git a/packages/bridge-ui/src/config.ts b/packages/bridge-ui/src/config.ts
new file mode 100644
index 00000000000..f0b417feb5d
--- /dev/null
+++ b/packages/bridge-ui/src/config.ts
@@ -0,0 +1,3 @@
+export const localStoragePrefix = 'bridge-ui';
+
+// Add more configuration items here
diff --git a/packages/bridge-ui/src/domain/bridge.ts b/packages/bridge-ui/src/domain/bridge.ts
index 9f467c22c27..2a69bd1b129 100644
--- a/packages/bridge-ui/src/domain/bridge.ts
+++ b/packages/bridge-ui/src/domain/bridge.ts
@@ -1,4 +1,5 @@
 import type { BigNumber, ethers, Transaction } from 'ethers';
+import type { ChainID } from './chain';
 import type { Message } from './message';
 
 export enum BridgeType {
@@ -19,8 +20,8 @@ export type BridgeOpts = {
   amountInWei: BigNumber;
   signer: ethers.Signer;
   tokenAddress: string;
-  fromChainId: number;
-  toChainId: number;
+  fromChainId: ChainID;
+  toChainId: ChainID;
   tokenVaultAddress?: string;
   bridgeAddress?: string;
   processingFeeInWei?: BigNumber;
diff --git a/packages/bridge-ui/src/domain/button.ts b/packages/bridge-ui/src/domain/button.ts
new file mode 100644
index 00000000000..3d9456c3726
--- /dev/null
+++ b/packages/bridge-ui/src/domain/button.ts
@@ -0,0 +1,5 @@
+// TODO: still to figure out after design
+
+export type TypeButton = 'primary' | 'secondary' | 'accent' | ''; // TODO: daisyUI?
+
+export type SizeButton = 'sm' | 'md' | 'lg';
diff --git a/packages/bridge-ui/src/domain/fee.ts b/packages/bridge-ui/src/domain/fee.ts
index d27615c0b17..c68f0d0b0b1 100644
--- a/packages/bridge-ui/src/domain/fee.ts
+++ b/packages/bridge-ui/src/domain/fee.ts
@@ -5,6 +5,7 @@ export enum ProcessingFeeMethod {
 }
 
 export interface ProcessingFeeDetails {
+  method: ProcessingFeeMethod;
   displayText: string;
   timeToConfirm: number;
 }
diff --git a/packages/bridge-ui/src/domain/message.ts b/packages/bridge-ui/src/domain/message.ts
index 2d01befb0c4..fb50ca74a17 100644
--- a/packages/bridge-ui/src/domain/message.ts
+++ b/packages/bridge-ui/src/domain/message.ts
@@ -1,4 +1,5 @@
 import type { BigNumber } from 'ethers';
+import type { ChainID } from './chain';
 
 export enum MessageStatus {
   New,
@@ -12,8 +13,8 @@ export enum MessageStatus {
 export type Message = {
   id: number;
   sender: string;
-  srcChainId: BigNumber;
-  destChainId: BigNumber;
+  srcChainId: ChainID;
+  destChainId: ChainID;
   owner: string;
   to: string;
   refundAddress: string;
diff --git a/packages/bridge-ui/src/domain/relayerApi.ts b/packages/bridge-ui/src/domain/relayerApi.ts
index e323d670695..a7e64c35f00 100644
--- a/packages/bridge-ui/src/domain/relayerApi.ts
+++ b/packages/bridge-ui/src/domain/relayerApi.ts
@@ -1,3 +1,4 @@
+import type { Address, ChainID } from './chain';
 import type { BridgeTransaction } from './transactions';
 
 export interface RelayerAPI {
@@ -9,12 +10,31 @@ export interface RelayerAPI {
   getBlockInfo(): Promise<Map<number, RelayerBlockInfo>>;
 }
 
+export type TransactionData = {
+  Message: {
+    Id: number;
+    SrcChainId: ChainID;
+    DestChainId: ChainID;
+    To: string;
+    Memo: string;
+    Owner: Address;
+    Sender: Address;
+    GasLimit: number;
+    CallValue: number;
+    DepositValue: number;
+    ProcessingFee: number;
+    RefundAddress: Address;
+    Data: string;
+  };
+  Raw: {
+    transactionHash: string;
+  };
+};
+
 export type APIResponseTransaction = {
   id: number;
   name: string;
-  data: {
-    [key: string]: any;
-  };
+  data: TransactionData;
   status: number;
   eventType: number;
   chainID: number;
diff --git a/packages/bridge-ui/src/domain/transactions.ts b/packages/bridge-ui/src/domain/transactions.ts
index 6ea4aa3bc75..45ed00ebce9 100644
--- a/packages/bridge-ui/src/domain/transactions.ts
+++ b/packages/bridge-ui/src/domain/transactions.ts
@@ -1,4 +1,5 @@
 import type { BigNumber, ethers } from 'ethers';
+import type { ChainID } from './chain';
 import type { Message, MessageStatus } from './message';
 
 export type BridgeTransaction = {
@@ -11,8 +12,8 @@ export type BridgeTransaction = {
   interval?: NodeJS.Timer;
   amountInWei?: BigNumber;
   symbol?: string;
-  fromChainId: number;
-  toChainId: number;
+  fromChainId: ChainID;
+  toChainId: ChainID;
 };
 
 export interface Transactioner {
diff --git a/packages/bridge-ui/src/fee/processingFees.ts b/packages/bridge-ui/src/fee/processingFees.ts
index 1991718a298..d61b17dd3f2 100644
--- a/packages/bridge-ui/src/fee/processingFees.ts
+++ b/packages/bridge-ui/src/fee/processingFees.ts
@@ -6,6 +6,7 @@ export const processingFees: Map<ProcessingFeeMethod, ProcessingFeeDetails> =
     [
       ProcessingFeeMethod.RECOMMENDED,
       {
+        method: ProcessingFeeMethod.RECOMMENDED,
         displayText: 'Recommended',
         timeToConfirm: 15 * 60 * 1000,
       },
@@ -13,6 +14,7 @@ export const processingFees: Map<ProcessingFeeMethod, ProcessingFeeDetails> =
     [
       ProcessingFeeMethod.CUSTOM,
       {
+        method: ProcessingFeeMethod.CUSTOM,
         displayText: 'Custom',
         timeToConfirm: 15 * 60 * 1000,
       },
@@ -20,6 +22,7 @@ export const processingFees: Map<ProcessingFeeMethod, ProcessingFeeDetails> =
     [
       ProcessingFeeMethod.NONE,
       {
+        method: ProcessingFeeMethod.NONE,
         displayText: 'None',
         timeToConfirm: 15 * 60 * 1000,
       },
diff --git a/packages/bridge-ui/src/pages/home/Home.svelte b/packages/bridge-ui/src/pages/home/Home.svelte
index b4d1903f9d3..744b102884e 100644
--- a/packages/bridge-ui/src/pages/home/Home.svelte
+++ b/packages/bridge-ui/src/pages/home/Home.svelte
@@ -1,10 +1,9 @@
 <script lang="ts">
-  import { _ } from 'svelte-i18n';
   import { location } from 'svelte-spa-router';
   import { transactions } from '../../store/transactions';
   import BridgeForm from '../../components/form/BridgeForm.svelte';
   import TaikoBanner from '../../components/TaikoBanner.svelte';
-  import Transactions from '../../components/Transactions.svelte';
+  import Transactions from '../../components/Transactions';
   import { Tabs, TabList, Tab, TabPanel } from '../../components/Tabs';
 
   let bridgeWidth: number;
diff --git a/packages/bridge-ui/src/relayer-api/RelayerAPIService.ts b/packages/bridge-ui/src/relayer-api/RelayerAPIService.ts
index 3430bd62cf0..0acbe50135c 100644
--- a/packages/bridge-ui/src/relayer-api/RelayerAPIService.ts
+++ b/packages/bridge-ui/src/relayer-api/RelayerAPIService.ts
@@ -94,9 +94,9 @@ export class RelayerAPIService implements RelayerAPI {
           owner: tx.data.Message.Owner,
           sender: tx.data.Message.Sender,
           gasLimit: BigNumber.from(tx.data.Message.GasLimit),
-          callValue: tx.data.Message.CallValue,
-          srcChainId: BigNumber.from(tx.data.Message.SrcChainId),
-          destChainId: BigNumber.from(tx.data.Message.DestChainId),
+          callValue: BigNumber.from(tx.data.Message.CallValue),
+          srcChainId: tx.data.Message.SrcChainId,
+          destChainId: tx.data.Message.DestChainId,
           depositValue: BigNumber.from(`${tx.data.Message.DepositValue}`),
           processingFee: BigNumber.from(`${tx.data.Message.ProcessingFee}`),
           refundAddress: tx.data.Message.RefundAddress,
diff --git a/packages/bridge-ui/src/storage/StorageService.spec.ts b/packages/bridge-ui/src/storage/StorageService.spec.ts
index d6252abd0df..d9e5e799ee7 100644
--- a/packages/bridge-ui/src/storage/StorageService.spec.ts
+++ b/packages/bridge-ui/src/storage/StorageService.spec.ts
@@ -96,7 +96,7 @@ describe('storage tests', () => {
 
     const svc = new StorageService(mockStorage as any, providers);
 
-    const addresses = await svc.getAllByAddress('0x123', L2_CHAIN_ID);
+    const addresses = await svc.getAllByAddress('0x123');
 
     expect(addresses).toEqual([]);
   });
@@ -120,7 +120,7 @@ describe('storage tests', () => {
 
     const svc = new StorageService(mockStorage as any, providers);
 
-    const addresses = await svc.getAllByAddress('0x123', L1_CHAIN_ID);
+    const addresses = await svc.getAllByAddress('0x123');
 
     expect(addresses).toEqual([
       {
@@ -156,7 +156,7 @@ describe('storage tests', () => {
 
     const svc = new StorageService(mockStorage as any, providers);
 
-    const addresses = await svc.getAllByAddress('0x123', L1_CHAIN_ID);
+    const addresses = await svc.getAllByAddress('0x123');
 
     expect(addresses).toEqual([
       {
@@ -201,7 +201,7 @@ describe('storage tests', () => {
 
     const svc = new StorageService(mockStorage as any, providers);
 
-    const addresses = await svc.getAllByAddress('0x123', L1_CHAIN_ID);
+    const addresses = await svc.getAllByAddress('0x123');
 
     expect(addresses).toEqual([
       {
@@ -253,7 +253,7 @@ describe('storage tests', () => {
 
     const svc = new StorageService(mockStorage as any, providers);
 
-    const addresses = await svc.getAllByAddress('0x123', L2_CHAIN_ID);
+    const addresses = await svc.getAllByAddress('0x123');
 
     expect(addresses).toEqual([
       {
diff --git a/packages/bridge-ui/src/storage/StorageService.ts b/packages/bridge-ui/src/storage/StorageService.ts
index f632b61a7a9..855699b5a66 100644
--- a/packages/bridge-ui/src/storage/StorageService.ts
+++ b/packages/bridge-ui/src/storage/StorageService.ts
@@ -23,10 +23,7 @@ export class StorageService implements Transactioner {
     this.providers = providers;
   }
 
-  async getAllByAddress(
-    address: string,
-    chainID?: number,
-  ): Promise<BridgeTransaction[]> {
+  async getAllByAddress(address: string): Promise<BridgeTransaction[]> {
     const txs: BridgeTransaction[] = JSON.parse(
       this.storage.getItem(`transactions-${address.toLowerCase()}`),
     );
diff --git a/packages/bridge-ui/src/store/fee.ts b/packages/bridge-ui/src/store/fee.ts
deleted file mode 100644
index 21d5a41bad0..00000000000
--- a/packages/bridge-ui/src/store/fee.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { writable } from 'svelte/store';
-import { ProcessingFeeMethod } from '../domain/fee';
-
-export const processingFee = writable<ProcessingFeeMethod>(
-  ProcessingFeeMethod.RECOMMENDED,
-);
diff --git a/packages/bridge-ui/src/store/userToken.ts b/packages/bridge-ui/src/store/userToken.ts
index c415a14d019..e4556e7d7a7 100644
--- a/packages/bridge-ui/src/store/userToken.ts
+++ b/packages/bridge-ui/src/store/userToken.ts
@@ -1,4 +1,4 @@
-import type { Token, TokenService } from 'src/domain/token';
+import type { Token, TokenService } from '../domain/token';
 import { writable } from 'svelte/store';
 
 const tokenService = writable<TokenService>();
diff --git a/packages/bridge-ui/src/utils/switchChainAndSetSigner.ts b/packages/bridge-ui/src/utils/switchChainAndSetSigner.ts
new file mode 100644
index 00000000000..11ec1490706
--- /dev/null
+++ b/packages/bridge-ui/src/utils/switchChainAndSetSigner.ts
@@ -0,0 +1,26 @@
+import { fetchSigner, switchNetwork } from '@wagmi/core';
+import { ethers } from 'ethers';
+import { fromChain, toChain } from '../store/chain';
+import type { Chain } from '../domain/chain';
+import { mainnetChain, taikoChain } from '../chain/chains';
+import { signer } from '../store/signer';
+
+export async function switchChainAndSetSigner(chain: Chain) {
+  const chainId = chain.id;
+
+  await switchNetwork({ chainId });
+
+  const provider = new ethers.providers.Web3Provider(globalThis.ethereum);
+  await provider.send('eth_requestAccounts', []);
+
+  fromChain.set(chain);
+  if (chain.id === mainnetChain.id) {
+    toChain.set(taikoChain);
+  } else {
+    toChain.set(mainnetChain);
+  }
+
+  const wagmiSigner = await fetchSigner({ chainId });
+
+  signer.set(wagmiSigner);
+}
diff --git a/packages/bridge-ui/tailwind.config.cjs b/packages/bridge-ui/tailwind.config.cjs
index 548e97c5efc..b365f4b8297 100644
--- a/packages/bridge-ui/tailwind.config.cjs
+++ b/packages/bridge-ui/tailwind.config.cjs
@@ -28,7 +28,6 @@ module.exports = {
   },
   daisyui: {
     styled: true,
-    themes: true,
     base: true,
     utils: true,
     logs: true,