diff --git a/packages/bridge-ui-v2/src/app.config.ts b/packages/bridge-ui-v2/src/app.config.ts
index 5584560c844..0c49606a95c 100644
--- a/packages/bridge-ui-v2/src/app.config.ts
+++ b/packages/bridge-ui-v2/src/app.config.ts
@@ -8,3 +8,8 @@ export const processingFeeComponent = {
closingDelayOptionClick: 300,
intervalComputeRecommendedFee: 20000,
};
+
+export const bridge = {
+ noOwnerGasLimit: BigInt(140000),
+ noTokenDeployedGasLimit: BigInt(3000000),
+};
diff --git a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte
index d2cd50a02cc..02e08753648 100644
--- a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte
+++ b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/AmountInput.svelte
@@ -1,26 +1,158 @@
diff --git a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/Balance.svelte b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/Balance.svelte
index 18000188fa6..a82bc0d8fa2 100644
--- a/packages/bridge-ui-v2/src/components/Bridge/AmountInput/Balance.svelte
+++ b/packages/bridge-ui-v2/src/components/Bridge/AmountInput/Balance.svelte
@@ -10,7 +10,8 @@
import { destNetwork, selectedToken } from '../state';
- let tokenBalance: Maybe;
+ export let value: Maybe;
+
let computingTokenBalance = false;
let errorComputingTokenBalance = false;
@@ -21,14 +22,14 @@
errorComputingTokenBalance = false;
try {
- tokenBalance = await getTokenBalance({
+ value = await getTokenBalance({
token,
destChainId,
userAddress: account.address,
chainId: srcChainId,
});
- } catch (error) {
- console.error(error);
+ } catch (err) {
+ console.error(err);
errorComputingTokenBalance = true;
} finally {
computingTokenBalance = false;
@@ -50,7 +51,7 @@
{:else}
- {renderTokenBalance(tokenBalance)}
+ {renderTokenBalance(value)}
{/if}
diff --git a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/NoneOption.svelte b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/NoneOption.svelte
index fb5dbd614f8..99af71c167a 100644
--- a/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/NoneOption.svelte
+++ b/packages/bridge-ui-v2/src/components/Bridge/ProcessingFee/NoneOption.svelte
@@ -1,5 +1,5 @@
-
+
diff --git a/packages/bridge-ui-v2/src/i18n/en.json b/packages/bridge-ui-v2/src/i18n/en.json
index cc9e3ca9999..56ab85e6681 100644
--- a/packages/bridge-ui-v2/src/i18n/en.json
+++ b/packages/bridge-ui-v2/src/i18n/en.json
@@ -84,7 +84,11 @@
"amount_input": {
"label": "Amount",
"balance": "Balance",
- "button.max": "Max"
+ "button": {
+ "max": "Max",
+ "failed_max": "Coult not estimate max amount to bridge."
+ },
+ "error.insufficient_balance": "Insufficient balance"
},
"chain_selector": {
diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC1155Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC1155Bridge.ts
new file mode 100644
index 00000000000..ddad81ecab1
--- /dev/null
+++ b/packages/bridge-ui-v2/src/libs/bridge/ERC1155Bridge.ts
@@ -0,0 +1,7 @@
+import type { Bridge } from './types';
+
+export class ERC1155Bridge implements Bridge {
+ async estimateGas(): Promise {
+ return Promise.resolve(BigInt(0));
+ }
+}
diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts
new file mode 100644
index 00000000000..074bc062a27
--- /dev/null
+++ b/packages/bridge-ui-v2/src/libs/bridge/ERC20Bridge.ts
@@ -0,0 +1,67 @@
+import { getContract } from '@wagmi/core';
+
+import { tokenVaultABI } from '$abi';
+import { bridge } from '$config';
+import { getConnectedWallet } from '$libs/util/getWallet';
+import { getLogger } from '$libs/util/logger';
+
+import type { Bridge, ERC20BridgeArgs, SendERC20Args } from './types';
+
+const log = getLogger('ERC20Bridge');
+
+export class ERC20Bridge implements Bridge {
+ private static async _prepareTransaction(args: ERC20BridgeArgs) {
+ const walletClient = await getConnectedWallet();
+
+ const {
+ to,
+ memo = '',
+ amount,
+ destChainId,
+ tokenAddress,
+ processingFee,
+ tokenVaultAddress,
+ isTokenAlreadyDeployed,
+ } = args;
+
+ const tokenVaultContract = getContract({
+ walletClient,
+ abi: tokenVaultABI,
+ address: tokenVaultAddress,
+ });
+
+ const refundAddress = walletClient.account.address;
+
+ const gasLimit = !isTokenAlreadyDeployed
+ ? BigInt(bridge.noTokenDeployedGasLimit)
+ : processingFee > 0
+ ? bridge.noOwnerGasLimit
+ : BigInt(0);
+
+ const sendERC20Args: SendERC20Args = [
+ BigInt(destChainId),
+ to,
+ tokenAddress,
+ amount,
+ gasLimit,
+ processingFee,
+ refundAddress,
+ memo,
+ ];
+
+ log('Preparing transaction with args', sendERC20Args);
+
+ return { tokenVaultContract, sendERC20Args };
+ }
+
+ async estimateGas(args: ERC20BridgeArgs) {
+ const { tokenVaultContract, sendERC20Args } = await ERC20Bridge._prepareTransaction(args);
+ const [, , , , , processingFee] = sendERC20Args;
+
+ const value = processingFee;
+
+ log('Estimating gas for sendERC20 call. Sending value', value);
+
+ return tokenVaultContract.estimateGas.sendERC20([...sendERC20Args], { value });
+ }
+}
diff --git a/packages/bridge-ui-v2/src/libs/bridge/ERC721Bridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ERC721Bridge.ts
new file mode 100644
index 00000000000..a9d03418e55
--- /dev/null
+++ b/packages/bridge-ui-v2/src/libs/bridge/ERC721Bridge.ts
@@ -0,0 +1,7 @@
+import type { Bridge } from './types';
+
+export class ERC721Bridge implements Bridge {
+ async estimateGas(): Promise {
+ return Promise.resolve(BigInt(0));
+ }
+}
diff --git a/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts
new file mode 100644
index 00000000000..45c54f813a9
--- /dev/null
+++ b/packages/bridge-ui-v2/src/libs/bridge/ETHBridge.ts
@@ -0,0 +1,69 @@
+import { getContract } from '@wagmi/core';
+
+import { bridgeABI } from '$abi';
+import { bridge } from '$config';
+import { getConnectedWallet } from '$libs/util/getWallet';
+import { getLogger } from '$libs/util/logger';
+
+import type { Bridge, ETHBridgeArgs, Message } from './types';
+
+const log = getLogger('ETHBridge');
+
+export class ETHBridge implements Bridge {
+ private static async _prepareTransaction(args: ETHBridgeArgs) {
+ const walletClient = await getConnectedWallet();
+
+ const { to, memo = '', amount, srcChainId, destChainId, bridgeAddress, processingFee } = args;
+
+ const bridgeContract = getContract({
+ walletClient,
+ abi: bridgeABI,
+ address: bridgeAddress,
+ });
+
+ const owner = walletClient.account.address;
+
+ // TODO: contract actually supports bridging to ourselves as well as
+ // to another address at the same time
+ const [depositValue, callValue] =
+ to.toLowerCase() === owner.toLowerCase() ? [amount, BigInt(0)] : [BigInt(0), amount];
+
+ // If there is a processing fee, use the specified message gas limit
+ // if not called by the owner
+ const gasLimit = processingFee > 0 ? bridge.noOwnerGasLimit : BigInt(0);
+
+ const message: Message = {
+ to,
+ owner,
+ sender: owner,
+ refundAddress: owner,
+
+ srcChainId: BigInt(srcChainId),
+ destChainId: BigInt(destChainId),
+
+ gasLimit,
+ callValue,
+ depositValue,
+ processingFee,
+
+ memo,
+ data: '0x',
+ id: BigInt(0), // will be set in contract
+ };
+
+ log('Preparing transaction with message', message);
+
+ return { bridgeContract, message };
+ }
+
+ async estimateGas(args: ETHBridgeArgs) {
+ const { bridgeContract, message } = await ETHBridge._prepareTransaction(args);
+ const { depositValue, callValue, processingFee } = message;
+
+ const value = depositValue + callValue + processingFee;
+
+ log('Estimating gas for sendMessage call. Sending value', value);
+
+ return bridgeContract.estimateGas.sendMessage([message], { value });
+ }
+}
diff --git a/packages/bridge-ui-v2/src/libs/bridge/bridges.ts b/packages/bridge-ui-v2/src/libs/bridge/bridges.ts
new file mode 100644
index 00000000000..8eefde0a6dd
--- /dev/null
+++ b/packages/bridge-ui-v2/src/libs/bridge/bridges.ts
@@ -0,0 +1,12 @@
+import { ERC20Bridge } from './ERC20Bridge';
+import { ERC721Bridge } from './ERC721Bridge';
+import { ERC1155Bridge } from './ERC1155Bridge';
+import { ETHBridge } from './ETHBridge';
+import type { Bridge, BridgeType } from './types';
+
+export const bridges: Record = {
+ ETH: new ETHBridge(),
+ ERC20: new ERC20Bridge(),
+ ERC721: new ERC721Bridge(),
+ ERC1155: new ERC1155Bridge(),
+};
diff --git a/packages/bridge-ui-v2/src/libs/bridge/estimateCostOfBridging.ts b/packages/bridge-ui-v2/src/libs/bridge/estimateCostOfBridging.ts
new file mode 100644
index 00000000000..adcb8c81d74
--- /dev/null
+++ b/packages/bridge-ui-v2/src/libs/bridge/estimateCostOfBridging.ts
@@ -0,0 +1,12 @@
+import { getPublicClient } from '@wagmi/core';
+
+import type { Bridge, BridgeArgs } from './types';
+
+export async function estimateCostOfBridging(bridge: Bridge, bridgeArgs: BridgeArgs) {
+ const publicClient = getPublicClient();
+
+ // Calculate the estimated cost of bridging
+ const estimatedGas = await bridge.estimateGas(bridgeArgs);
+ const gasPrice = await publicClient.getGasPrice();
+ return estimatedGas * gasPrice;
+}
diff --git a/packages/bridge-ui-v2/src/libs/bridge/getMaxToBridge.ts b/packages/bridge-ui-v2/src/libs/bridge/getMaxToBridge.ts
new file mode 100644
index 00000000000..041567139a4
--- /dev/null
+++ b/packages/bridge-ui-v2/src/libs/bridge/getMaxToBridge.ts
@@ -0,0 +1,60 @@
+import type { Address } from 'viem';
+
+import { chainContractsMap, chains } from '$libs/chain';
+import { isETH, type Token } from '$libs/token';
+import { getLogger } from '$libs/util/logger';
+
+import { bridges } from './bridges';
+import { estimateCostOfBridging } from './estimateCostOfBridging';
+import type { ETHBridgeArgs } from './types';
+
+type GetMaxToBridgeArgs = {
+ token: Token;
+ balance: bigint;
+ srcChainId: number;
+ userAddress: Address;
+ processingFee: bigint;
+ destChainId?: number;
+ amount?: bigint;
+};
+
+const log = getLogger('getMaxToBridge');
+
+export async function getMaxToBridge({
+ token,
+ balance,
+ srcChainId,
+ userAddress,
+ processingFee,
+ destChainId,
+ amount,
+}: GetMaxToBridgeArgs) {
+ if (isETH(token)) {
+ const to = userAddress;
+ const { bridgeAddress } = chainContractsMap[srcChainId.toString()];
+
+ const bridgeArgs = {
+ to,
+ srcChainId,
+ bridgeAddress,
+ processingFee,
+
+ // If no amount passed in, use whatever just to get an estimation
+ amount: amount ?? BigInt(1),
+
+ // If no destination chain is selected, find another chain to estimate
+ // TODO: we might want to really find a compatible chain to bridge to
+ // if we have multiple layers
+ destChainId: destChainId ?? chains.find((chain) => chain.id !== srcChainId)?.id,
+ } as ETHBridgeArgs;
+
+ const estimatedCost = await estimateCostOfBridging(bridges.ETH, bridgeArgs);
+
+ log('Estimated cost of bridging', estimatedCost, 'with argument', bridgeArgs);
+
+ return balance - processingFee - estimatedCost;
+ }
+
+ // For ERC20 tokens, we can bridge the whole balance
+ return balance;
+}
diff --git a/packages/bridge-ui-v2/src/libs/bridge/index.ts b/packages/bridge-ui-v2/src/libs/bridge/index.ts
new file mode 100644
index 00000000000..5187917dc4b
--- /dev/null
+++ b/packages/bridge-ui-v2/src/libs/bridge/index.ts
@@ -0,0 +1,3 @@
+export { bridges } from './bridges';
+export { estimateCostOfBridging } from './estimateCostOfBridging';
+export * from './types';
diff --git a/packages/bridge-ui-v2/src/libs/bridge/types.ts b/packages/bridge-ui-v2/src/libs/bridge/types.ts
new file mode 100644
index 00000000000..7dd0f52172c
--- /dev/null
+++ b/packages/bridge-ui-v2/src/libs/bridge/types.ts
@@ -0,0 +1,97 @@
+import type { Address, Hex } from 'viem';
+
+export enum BridgeType {
+ ETH = 'ETH',
+
+ // https://ethereum.org/en/developers/docs/standards/tokens/erc-20/
+ ERC20 = 'ERC20',
+
+ // https://ethereum.org/en/developers/docs/standards/tokens/erc-721/
+ ERC721 = 'ERC721',
+
+ // https://ethereum.org/en/developers/docs/standards/tokens/erc-1155/
+ ERC1155 = 'ERC1155',
+}
+
+// Bridge sendMessage(message: Message)
+export type Message = {
+ // Message ID. Will be set in contract
+ id: bigint;
+ // Message sender address (auto filled)
+ sender: Address;
+ // Source chain ID (auto filled)
+ srcChainId: bigint;
+ // Destination chain ID where the `to` address lives (auto filled)
+ destChainId: bigint;
+ // Owner address of the bridged asset.
+ owner: Address;
+ // Destination owner address
+ to: Address;
+ // Alternate address to send any refund. If blank, defaults to owner.
+ refundAddress: Address;
+ // Deposited Ether minus the processingFee.
+ depositValue: bigint;
+ // callValue to invoke on the destination chain, for ERC20 transfers.
+ callValue: bigint;
+ // Processing fee for the relayer. Zero if owner will process themself.
+ processingFee: bigint;
+ // gasLimit to invoke on the destination chain, for ERC20 transfers.
+ gasLimit: bigint;
+ // callData to invoke on the destination chain, for ERC20 transfers.
+ data: Hex;
+ // Optional memo.
+ memo: string;
+};
+
+// TokenVault sendERC20(...args)
+export type SendERC20Args = [
+ bigint, // destChainId
+ Address, // to
+ Address, // token
+ bigint, // amount
+ bigint, // gasLimit
+ bigint, // processingFee
+ Address, // refundAddress
+ string, // memo
+];
+
+// TODO: future sendToken(op: BridgeTransferOp)
+export type BridgeTransferOp = {
+ destChainId: bigint;
+ to: Address;
+ token: Address;
+ amount: bigint;
+ gasLimit: bigint;
+ processingFee: bigint;
+ refundAddress: Address;
+ memo: string;
+};
+
+export type ApproveArgs = {
+ amount: bigint;
+ tokenAddress: Address;
+ spenderAddress: Address;
+};
+
+export type BridgeArgs = {
+ to: Address;
+ srcChainId: number;
+ destChainId: number;
+ amount: bigint;
+ processingFee: bigint;
+ memo?: string;
+};
+
+export type ETHBridgeArgs = BridgeArgs & {
+ bridgeAddress: Address;
+};
+
+export type ERC20BridgeArgs = BridgeArgs & {
+ tokenAddress: Address;
+ tokenVaultAddress: Address;
+ isTokenAlreadyDeployed?: boolean;
+};
+
+export interface Bridge {
+ estimateGas(args: BridgeArgs): Promise;
+}
diff --git a/packages/bridge-ui-v2/src/libs/chain/chains.ts b/packages/bridge-ui-v2/src/libs/chain/chains.ts
index 2779bff7880..496137b14ba 100644
--- a/packages/bridge-ui-v2/src/libs/chain/chains.ts
+++ b/packages/bridge-ui-v2/src/libs/chain/chains.ts
@@ -1,5 +1,4 @@
-import type { Chain } from '@wagmi/core';
-import type { Address } from 'abitype';
+import type { Address, Chain } from '@wagmi/core';
import {
PUBLIC_L1_BRIDGE_ADDRESS,
diff --git a/packages/bridge-ui-v2/src/libs/token/checkMintable.test.ts b/packages/bridge-ui-v2/src/libs/token/checkMintable.test.ts
index 3066604fa6c..503542c036e 100644
--- a/packages/bridge-ui-v2/src/libs/token/checkMintable.test.ts
+++ b/packages/bridge-ui-v2/src/libs/token/checkMintable.test.ts
@@ -45,24 +45,15 @@ describe('checkMintable', () => {
vi.mocked(getPublicClient).mockReturnValue(mockPublicClient);
});
- it('should throw when wallet is not connected', async () => {
- vi.mocked(getWalletClient).mockResolvedValueOnce(null);
-
- try {
- await checkMintable(BLLToken, mainnetChain);
- expect.fail('should have thrown');
- } catch (error) {
- const { cause } = error as Error;
- expect(cause).toBe(MintableError.NOT_CONNECTED);
- expect(getWalletClient).toHaveBeenCalledWith({ chainId: mainnetChain.id });
- }
+ beforeEach(() => {
+ vi.clearAllMocks();
});
it('should throw when user has already minted', async () => {
vi.mocked(mockTokenContract.read.minters).mockResolvedValueOnce(true);
try {
- await checkMintable(BLLToken, mainnetChain);
+ await checkMintable(BLLToken, mainnetChain.id);
expect.fail('should have thrown');
} catch (error) {
const { cause } = error as Error;
@@ -91,12 +82,12 @@ describe('checkMintable', () => {
vi.mocked(mockPublicClient.getBalance).mockResolvedValueOnce(BigInt(100));
try {
- await checkMintable(BLLToken, mainnetChain);
+ await checkMintable(BLLToken, mainnetChain.id);
expect.fail('should have thrown');
} catch (error) {
const { cause } = error as Error;
expect(cause).toBe(MintableError.INSUFFICIENT_BALANCE);
- expect(getPublicClient).toHaveBeenCalledWith({ chainId: mainnetChain.id });
+ expect(getPublicClient).toHaveBeenCalled();
expect(mockTokenContract.estimateGas.mint).toHaveBeenCalledWith([mockWalletClient.account.address]);
expect(mockPublicClient.getBalance).toHaveBeenCalledWith({ address: mockWalletClient.account.address });
}
@@ -117,7 +108,7 @@ describe('checkMintable', () => {
vi.mocked(mockPublicClient.getBalance).mockResolvedValueOnce(BigInt(300));
try {
- await checkMintable(BLLToken, mainnetChain);
+ await checkMintable(BLLToken, mainnetChain.id);
} catch (error) {
expect.fail('should not have thrown');
}
diff --git a/packages/bridge-ui-v2/src/libs/token/checkMintable.ts b/packages/bridge-ui-v2/src/libs/token/checkMintable.ts
index 848de485316..2c91d47a4eb 100644
--- a/packages/bridge-ui-v2/src/libs/token/checkMintable.ts
+++ b/packages/bridge-ui-v2/src/libs/token/checkMintable.ts
@@ -1,21 +1,15 @@
-import { type Chain, getContract, getPublicClient, getWalletClient } from '@wagmi/core';
-import { formatEther } from 'viem';
+import { getContract, getPublicClient } from '@wagmi/core';
import { freeMintErc20ABI } from '$abi';
+import { getConnectedWallet } from '$libs/util/getWallet';
import { MintableError, type Token } from './types';
// Throws an error if:
-// 1. User is not connected to the network
-// 2. User has already minted this token
-// 3. User has insufficient balance to mint this token
-export async function checkMintable(token: Token, network: Chain) {
- const chainId = network.id;
- const walletClient = await getWalletClient({ chainId });
-
- if (!walletClient) {
- throw Error(`user is not connected to ${network.name}`, { cause: MintableError.NOT_CONNECTED });
- }
+// 1. User has already minted this token
+// 2. User has insufficient balance to mint this token
+export async function checkMintable(token: Token, chainId: number) {
+ const walletClient = await getConnectedWallet();
const tokenContract = getContract({
walletClient,
@@ -28,12 +22,13 @@ export async function checkMintable(token: Token, network: Chain) {
const hasMinted = await tokenContract.read.minters([userAddress]);
if (hasMinted) {
- throw Error(`token ${token.symbol} has already been minted`, { cause: MintableError.TOKEN_MINTED });
+ throw Error(`token already minted`, { cause: MintableError.TOKEN_MINTED });
}
// Check whether the user has enough balance to mint.
// Compute the cost of the transaction:
- const publicClient = getPublicClient({ chainId });
+ const publicClient = getPublicClient();
+
const estimatedGas = await tokenContract.estimateGas.mint([userAddress]);
const gasPrice = await publicClient.getGasPrice();
const estimatedCost = estimatedGas * gasPrice;
@@ -41,7 +36,7 @@ export async function checkMintable(token: Token, network: Chain) {
const userBalance = await publicClient.getBalance({ address: userAddress });
if (estimatedCost > userBalance) {
- throw Error(`user has insufficient balance to mint ${token.symbol}: ${formatEther(userBalance)}`, {
+ throw Error('user has insufficient balance', {
cause: MintableError.INSUFFICIENT_BALANCE,
});
}
diff --git a/packages/bridge-ui-v2/src/libs/token/getBalance.test.ts b/packages/bridge-ui-v2/src/libs/token/getBalance.test.ts
index a6846bb2be6..7b9d00d2e70 100644
--- a/packages/bridge-ui-v2/src/libs/token/getBalance.test.ts
+++ b/packages/bridge-ui-v2/src/libs/token/getBalance.test.ts
@@ -68,7 +68,6 @@ describe('getBalance', () => {
});
expect(fetchBalance).toHaveBeenCalledWith({
address: mockWalletClient.account.address,
- chainId: Number(PUBLIC_L1_CHAIN_ID),
token: BLLToken.addresses[PUBLIC_L1_CHAIN_ID],
});
});
diff --git a/packages/bridge-ui-v2/src/libs/token/getBalance.ts b/packages/bridge-ui-v2/src/libs/token/getBalance.ts
index ebb974455e1..f4715362bd5 100644
--- a/packages/bridge-ui-v2/src/libs/token/getBalance.ts
+++ b/packages/bridge-ui-v2/src/libs/token/getBalance.ts
@@ -1,6 +1,5 @@
import { fetchBalance, type FetchBalanceResult } from '@wagmi/core';
-import type { Address } from 'abitype';
-import { zeroAddress } from 'viem';
+import { type Address, zeroAddress } from 'viem';
import { getLogger } from '$libs/util/logger';
@@ -21,7 +20,7 @@ export async function getBalance({ token, userAddress, chainId, destChainId }: G
let tokenBalance: FetchBalanceResult | null = null;
if (isETH(token)) {
- tokenBalance = await fetchBalance({ address: userAddress, chainId });
+ tokenBalance = await fetchBalance({ address: userAddress });
} else {
// We are dealing with an ERC20 token. We need to first find out its address
// on the current chain in order to fetch the balance.
@@ -32,7 +31,6 @@ export async function getBalance({ token, userAddress, chainId, destChainId }: G
// Wagmi is such an amazing library. We had to do this
// more manually before.
tokenBalance = await fetchBalance({
- chainId,
address: userAddress,
token: tokenAddress,
});
diff --git a/packages/bridge-ui-v2/src/libs/token/mint.test.ts b/packages/bridge-ui-v2/src/libs/token/mint.test.ts
index 379c5798d88..2be21d8334d 100644
--- a/packages/bridge-ui-v2/src/libs/token/mint.test.ts
+++ b/packages/bridge-ui-v2/src/libs/token/mint.test.ts
@@ -28,7 +28,7 @@ describe('mint', () => {
vi.mocked(getContract).mockReturnValue(mockTokenContract);
vi.mocked(mockTokenContract.write.mint).mockResolvedValue('0x123456');
- await expect(mint(BLLToken, mockWalletClient)).resolves.toEqual('0x123456');
+ await expect(mint(BLLToken)).resolves.toEqual('0x123456');
expect(mockTokenContract.write.mint).toHaveBeenCalledWith([mockWalletClient.account.address]);
});
});
diff --git a/packages/bridge-ui-v2/src/libs/token/mint.ts b/packages/bridge-ui-v2/src/libs/token/mint.ts
index cfd35b3b331..c9585583711 100644
--- a/packages/bridge-ui-v2/src/libs/token/mint.ts
+++ b/packages/bridge-ui-v2/src/libs/token/mint.ts
@@ -1,13 +1,16 @@
-import { getContract, type WalletClient } from '@wagmi/core';
+import { getContract } from '@wagmi/core';
import { freeMintErc20ABI } from '$abi';
+import { getConnectedWallet } from '$libs/util/getWallet';
import { getLogger } from '../util/logger';
import type { Token } from './types';
const log = getLogger('token:mint');
-export async function mint(token: Token, walletClient: WalletClient) {
+export async function mint(token: Token) {
+ const walletClient = await getConnectedWallet();
+
const tokenSymbol = token.symbol;
const userAddress = walletClient.account.address;
const chainId = walletClient.chain.id;
diff --git a/packages/bridge-ui-v2/src/libs/token/types.ts b/packages/bridge-ui-v2/src/libs/token/types.ts
index c47b27f7fa3..230e5814d1d 100644
--- a/packages/bridge-ui-v2/src/libs/token/types.ts
+++ b/packages/bridge-ui-v2/src/libs/token/types.ts
@@ -1,4 +1,4 @@
-import type { Address } from 'abitype';
+import type { Address } from 'viem';
export type Token = {
name: string;
@@ -14,7 +14,6 @@ export type TokenEnv = {
};
export enum MintableError {
- NOT_CONNECTED = 'NOT_CONNECTED',
TOKEN_MINTED = 'TOKEN_MINTED',
INSUFFICIENT_BALANCE = 'INSUFFICIENT_BALANCE',
}
diff --git a/packages/bridge-ui-v2/src/libs/util/debounce.ts b/packages/bridge-ui-v2/src/libs/util/debounce.ts
new file mode 100644
index 00000000000..75cdc862732
--- /dev/null
+++ b/packages/bridge-ui-v2/src/libs/util/debounce.ts
@@ -0,0 +1,14 @@
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export function debounce ReturnType>(
+ callback: T,
+ timeout: number,
+): (...args: Parameters) => void {
+ let timer: ReturnType;
+
+ return (...args: Parameters) => {
+ clearTimeout(timer);
+ timer = setTimeout(() => {
+ callback(...args);
+ }, timeout);
+ };
+}
diff --git a/packages/bridge-ui-v2/src/libs/util/getWallet.ts b/packages/bridge-ui-v2/src/libs/util/getWallet.ts
new file mode 100644
index 00000000000..d609ef62344
--- /dev/null
+++ b/packages/bridge-ui-v2/src/libs/util/getWallet.ts
@@ -0,0 +1,11 @@
+import { getWalletClient } from '@wagmi/core';
+
+export async function getConnectedWallet() {
+ const walletClient = await getWalletClient();
+
+ if (!walletClient) {
+ throw Error('wallet is not connected');
+ }
+
+ return walletClient;
+}
diff --git a/packages/bridge-ui-v2/src/libs/util/truncateDecimal.ts b/packages/bridge-ui-v2/src/libs/util/truncateDecimal.ts
new file mode 100644
index 00000000000..bd3391864cb
--- /dev/null
+++ b/packages/bridge-ui-v2/src/libs/util/truncateDecimal.ts
@@ -0,0 +1,4 @@
+export function truncateDecimal(num: number, decimalPlaces: number) {
+ const factor = 10 ** decimalPlaces;
+ return Math.floor(num * factor) / factor;
+}
diff --git a/packages/bridge-ui-v2/src/styles/components.css b/packages/bridge-ui-v2/src/styles/components.css
index 7b82bbfa2c6..839066bb4d9 100644
--- a/packages/bridge-ui-v2/src/styles/components.css
+++ b/packages/bridge-ui-v2/src/styles/components.css
@@ -83,7 +83,11 @@
/* focus:border-[3px] */
/* focus:border-primary-border-accent */
- focus:shadow-[0_0_0_3px_#E81899];
+ focus:!shadow-[0_0_0_3px_#E81899];
+ }
+
+ .input-box.error {
+ @apply !shadow-[0_0_0_3px_#F15C5D];
}
/* Separatos */