From fac13f0e0bc0d575e35d5eb5160406d7b3935ff5 Mon Sep 17 00:00:00 2001 From: impelcrypto Date: Mon, 25 Nov 2024 23:50:44 +0800 Subject: [PATCH] fix: send from Minato --- src/config/web3/index.ts | 9 -- src/hooks/bridge/useCcipBridge.ts | 101 ++++++++---------- src/modules/ccip-bridge/index.ts | 2 - .../implementations/CcipBridgeRepository.ts | 13 +-- .../implementations/CcipBridgeService.ts | 1 - 5 files changed, 54 insertions(+), 72 deletions(-) diff --git a/src/config/web3/index.ts b/src/config/web3/index.ts index 1817aab4f..e39200628 100644 --- a/src/config/web3/index.ts +++ b/src/config/web3/index.ts @@ -51,7 +51,6 @@ export enum EVM { SONEIUM_MINATO_TESTNET = 1946, // Todo: update SONEIUM = 9999, - OP_SEPOLIA_TESTNET = 11155420, } export const chainName = { @@ -70,7 +69,6 @@ export const chainName = { [EVM.MOONBEAM]: 'Moonbeam Mainnet', [EVM.SONEIUM_MINATO_TESTNET]: 'Soneium Minato Testnet', [EVM.SONEIUM]: 'Soneium Mainnet', - [EVM.OP_SEPOLIA_TESTNET]: 'OP Sepolia Testnet', }; export const nativeCurrency = { @@ -149,11 +147,6 @@ export const nativeCurrency = { symbol: 'ETH', decimals: 18, }, - [EVM.OP_SEPOLIA_TESTNET]: { - name: 'ETH', - symbol: 'ETH', - decimals: 18, - }, }; export const rpcUrls = { @@ -175,7 +168,6 @@ export const rpcUrls = { [EVM.SONEIUM_MINATO_TESTNET]: ['https://rpc.minato.soneium.org'], // Todo: update [EVM.SONEIUM]: ['https://rpc.minato.soneium.org'], - [EVM.OP_SEPOLIA_TESTNET]: ['https://sepolia.optimism.io'], }; export const blockExplorerUrls = { @@ -194,7 +186,6 @@ export const blockExplorerUrls = { [EVM.SONEIUM_MINATO_TESTNET]: ['https://soneium-minato.blockscout.com'], // Todo: update [EVM.SONEIUM]: ['https://soneium-minato.blockscout.com'], - [EVM.OP_SEPOLIA_TESTNET]: ['https://sepolia-optimism.etherscan.io'], }; export const CHAIN_INFORMATION = { diff --git a/src/hooks/bridge/useCcipBridge.ts b/src/hooks/bridge/useCcipBridge.ts index b872ff704..f129ab5be 100644 --- a/src/hooks/bridge/useCcipBridge.ts +++ b/src/hooks/bridge/useCcipBridge.ts @@ -1,5 +1,5 @@ import { debounce } from 'lodash-es'; -import { getTokenBal, setupNetwork } from 'src/config/web3'; +import { checkAllowance, getTokenBal, setupNetwork } from 'src/config/web3'; import { useAccount, useNetworkInfo } from 'src/hooks'; import { ccipChainId, @@ -19,6 +19,7 @@ import { container } from 'src/v2/common'; import { ICcipBridgeService } from 'src/v2/services'; import { Symbols } from 'src/v2/symbols'; import { ethers, constants as ethersConstants } from 'ethers'; +import { astarNativeTokenErcAddr } from 'src/modules/xcm'; export const useCcipBridge = () => { const { isShibuya } = useNetworkInfo(); @@ -49,6 +50,7 @@ export const useCcipBridge = () => { fromBridgeBalance.value = 0; toBridgeBalance.value = 0; transactionFee.value = 0; + bridgeFee.value = 0; errMsg.value = ''; isApproveMaxAmount.value = false; isApproving.value = false; @@ -68,7 +70,9 @@ export const useCcipBridge = () => { const toChainId = computed(() => ccipChainId[toChainName.value as CcipNetworkName]); const isToSoneium = computed(() => - Boolean(toChainId.value === CcipChainId.SoneiumMinato || CcipChainId.Soneium) + Boolean( + toChainId.value === CcipChainId.SoneiumMinato || toChainId.value === CcipChainId.Soneium + ) ); const isDisabledBridge = computed(() => { @@ -82,8 +86,30 @@ export const useCcipBridge = () => { }; const setIsApproved = async (): Promise => { - try { + const senderAddress = currentAccount.value; + const fromChainIdRef = fromChainId.value; + const contractAddress = ccipBridgeAddress[fromChainIdRef]; + const tokenAddress = selectedToken.value.tokenAddress[fromChainId.value] as string; + const decimals = selectedToken.value.decimals; + const amount = bridgeAmt.value ?? '0'; + + const isApprovalRequired = tokenAddress !== astarNativeTokenErcAddr; + + if (!isApprovalRequired) { isApproved.value = true; + return; + } + if (!amount) return; + try { + const amountAllowance = await checkAllowance({ + srcChainId: fromChainIdRef as number, + senderAddress, + contractAddress, + tokenAddress, + }); + const formattedAllowance = ethers.utils.formatUnits(amountAllowance, decimals).toString(); + console.info('allowance: ', formattedAllowance); + isApproved.value = Number(formattedAllowance) >= Number(amount); } catch (error) { console.error(error); isApproved.value = false; @@ -215,7 +241,7 @@ export const useCcipBridge = () => { if (!bridgeAmt.value || !isApproved.value) return ''; const ccipBridgeService = container.get(Symbols.CcipBridgeService); const amount = Number(bridgeAmt.value); - const fromNetworkId = ccipChainId[fromChainName.value]; + const fromNetworkId = fromChainId.value; const hash = await ccipBridgeService.bridgeCcipAsset({ senderAddress: currentAccount.value, @@ -249,7 +275,8 @@ export const useCcipBridge = () => { if (errMsg.value || !currentAccount.value) return; isFetchingFee.value = true; const ccipBridgeService = container.get(Symbols.CcipBridgeService); - const amount = Number(bridgeAmt.value); + const amount = bridgeAmt.value ? Number(bridgeAmt.value) : 0.00001; + const fromNetworkId = fromChainId.value; const fee = await ccipBridgeService.fetchFee({ senderAddress: currentAccount.value, @@ -261,45 +288,24 @@ export const useCcipBridge = () => { }); bridgeFee.value = Number(fee); - // transactionFee.value = fee; - // isGasPayable.value = resIsGasPayable; - } catch (error) { - // Memo: can be ignore 'outOfFund' error due to the token balance is not enough because of hardcoding in amount variable above - console.error(error); - } finally { - isFetchingFee.value = false; - } - }; - const setIsGasPayable = async (): Promise => { - try { - if (errMsg.value || !currentAccount.value) return; - // isLoadingGasPayable.value = true; - // const lzBridgeService = container.get(Symbols.LzBridgeService); - // const amount = bridgeAmt.value ? Number(bridgeAmt.value) : 0.01; - // const isNativeToken = - // fromChainName.value === LayerZeroNetworkName.AstarEvm && - // selectedToken.value.symbol === 'ASTR'; - - // const { isGasPayable: resIsGasPayable, fee } = await lzBridgeService.dryRunBridgeAsset({ - // senderAddress: currentAccount.value, - // amount, - // minAmount: calcMinAmount(amount), - // fromNetworkId: fromLzId.value, - // destNetworkId: toLzId.value, - // tokenAddress: selectedToken.value.tokenAddress[fromLzId.value], - // isNativeToken, - // token: selectedToken.value, - // fromChainId: fromChainId.value, - // }); - // transactionFee.value = fee; - // isGasPayable.value = resIsGasPayable; - isGasPayable.value = true; + const { isGasPayable: resIsGasPayable, fee: transferFee } = + await ccipBridgeService.dryRunBridgeAsset({ + senderAddress: currentAccount.value, + amount, + fromNetworkId, + destNetworkId: ccipChainId[toChainName.value], + tokenAddress: selectedToken.value.tokenAddress[fromNetworkId] as string, + token: selectedToken.value, + }); + + transactionFee.value = transferFee; + isGasPayable.value = resIsGasPayable; } catch (error) { // Memo: can be ignore 'outOfFund' error due to the token balance is not enough because of hardcoding in amount variable above console.error(error); } finally { - isLoadingGasPayable.value = false; + isFetchingFee.value = false; } }; @@ -309,28 +315,18 @@ export const useCcipBridge = () => { }); watch([fromChainName, selectedToken, currentAccount], setBridgeBalance, { - immediate: false, + immediate: true, }); - // watch([currentAccount, fromChainName], initLzTokens, { immediate: true }); const debounceDelay = 500; - const debounceIsGasPayable = 1000; const debounceFetchFee = 2000; const debouncedSetIsApproved = debounce(setIsApproved, debounceDelay); - const debouncedSetIsGasPayable = debounce(setIsGasPayable, debounceIsGasPayable); const debouncedSetIsFetchFee = debounce(getBridgeFee, debounceFetchFee); watch([selectedToken, fromChainId, currentAccount, bridgeAmt], debouncedSetIsApproved, { immediate: true, }); - watch( - [bridgeAmt, fromChainName, currentAccount, errMsg, providerChainId, currentAccount], - debouncedSetIsGasPayable, - { - immediate: false, - } - ); watch( [bridgeAmt, fromChainName, currentAccount, errMsg, providerChainId, currentAccount], debouncedSetIsFetchFee, @@ -364,19 +360,16 @@ export const useCcipBridge = () => { toBridgeBalance, fromChainName, toChainName, - // importTokenAddress, fromChainId, toChainId, - // lzTokens, selectedToken, isApproved, isApproving, isApproveMaxAmount, transactionFee, + bridgeFee, setIsApproving, - // setSelectedToken, inputHandler, - // inputImportTokenHandler, resetStates, reverseChain, handleBridge, diff --git a/src/modules/ccip-bridge/index.ts b/src/modules/ccip-bridge/index.ts index d36626bb8..0a1b93d59 100644 --- a/src/modules/ccip-bridge/index.ts +++ b/src/modules/ccip-bridge/index.ts @@ -44,8 +44,6 @@ export const ccipBridgeAddress = { [CcipChainId.SoneiumMinato]: routerSoneiumMinato, // Todo: update [CcipChainId.Soneium]: routerSoneium, - // [CcipChainId.Sepolia]: etherSenderReceiverSepolia, - // [CcipChainId.OpSepolia]: routerOpSepolia, }; export const ccipBridgeIcon = { diff --git a/src/v2/repositories/implementations/CcipBridgeRepository.ts b/src/v2/repositories/implementations/CcipBridgeRepository.ts index 6c542103e..38dd66b00 100644 --- a/src/v2/repositories/implementations/CcipBridgeRepository.ts +++ b/src/v2/repositories/implementations/CcipBridgeRepository.ts @@ -39,7 +39,9 @@ export class CcipBridgeRepository implements ICcipBridgeRepository { const defaultAbiCoder = ethers.utils.defaultAbiCoder; const destinationChainSelector = ccipChainSelector[destNetworkId]; - const isToSoneium = destNetworkId === CcipChainId.SoneiumMinato || CcipChainId.Soneium; + const isToSoneium = Boolean( + destNetworkId === CcipChainId.SoneiumMinato || destNetworkId === CcipChainId.Soneium + ); const receiverAddress = isToSoneium ? senderAddress : ccipBridgeAddress[fromNetworkId]; const receiver = defaultAbiCoder.encode(['address'], [receiverAddress]); @@ -83,8 +85,10 @@ export class CcipBridgeRepository implements ICcipBridgeRepository { param: ParamBridgeCcipAsset; web3: Web3; }): Promise<{ txParam: TransactionConfig; nativeFee: number }> { - const isToSoneium = param.destNetworkId === CcipChainId.SoneiumMinato || CcipChainId.Soneium; - + const isToSoneium = Boolean( + param.destNetworkId === CcipChainId.SoneiumMinato || + param.destNetworkId === CcipChainId.Soneium + ); const { message, destinationChainSelector } = this.getMessageArgs(param); const contractAddress = ccipBridgeAddress[param.fromNetworkId]; const abi = ETHER_SENDER_RECEIVER_ABI; @@ -96,9 +100,6 @@ export class CcipBridgeRepository implements ICcipBridgeRepository { const gasTokenBridge = ethers.utils.parseEther(isToSoneium ? String(param.amount) : '0'); const value = (BigInt(gasTokenBridge.toString()) + BigInt(fee)).toString(); - console.log('gasTokenBridge', gasTokenBridge.toString()); - console.log('fee', fee); - return { txParam: { from: param.senderAddress, diff --git a/src/v2/services/implementations/CcipBridgeService.ts b/src/v2/services/implementations/CcipBridgeService.ts index 4ba0014a3..512afc6a7 100644 --- a/src/v2/services/implementations/CcipBridgeService.ts +++ b/src/v2/services/implementations/CcipBridgeService.ts @@ -119,7 +119,6 @@ export class CcipBridgeService implements ICcipBridgeService { const estimatedGas = await web3.eth.estimateGas({ ...tx }); const gasFee = gasPrice * Number(estimatedGas); const accountBalance = Number(ethers.utils.formatEther(accountBalanceWei.toString())); - const amountNativeToken = param.tokenAddress === astarNativeTokenErcAddr ? Number(param.amount) + nativeFee