diff --git a/advanced/wallets/react-wallet-v2/src/components/MultibridgeRequestModal.tsx b/advanced/wallets/react-wallet-v2/src/components/MultibridgeRequestModal.tsx index 290a9daf2..7350801b6 100644 --- a/advanced/wallets/react-wallet-v2/src/components/MultibridgeRequestModal.tsx +++ b/advanced/wallets/react-wallet-v2/src/components/MultibridgeRequestModal.tsx @@ -1,18 +1,15 @@ import { LoaderProps } from '@/components/ModalFooter' import RequestMethodCard from '@/components/RequestMethodCard' -import { Avatar, Col, Container, Divider, Row, Text } from '@nextui-org/react' +import { Avatar, Col, Divider, Row, Text } from '@nextui-org/react' import { walletkit } from '@/utils/WalletConnectUtil' import RequestModal from './RequestModal' import ModalStore from '@/store/ModalStore' import { useCallback, useState } from 'react' import { - bridgeFunds, - BridgingRequest, convertTokenBalance, decodeErc20Transaction, - getAssetByContractAddress, - supportedAssets + getAssetByContractAddress } from '@/utils/MultibridgeUtil' import { getWallet } from '@/utils/EIP155WalletUtil' @@ -25,7 +22,7 @@ import { providers } from 'ethers' interface IProps { onReject: () => void transactions?: Transaction[] - orchestrationId:string + orchestrationId: string rejectLoader?: LoaderProps } @@ -35,13 +32,14 @@ export default function MultibridgeRequestModal({ onReject, rejectLoader }: IProps) { - const [isLoadingApprove, setIsLoadingApprove] = useState(false) const bridgingTransactions = transactions?.slice(0, transactions.length - 1) || [] - const initialTransaction = transactions?.[transactions.length - 1] - const eip155ChainsFundsSourcedFrom = transactions ? new Set(bridgingTransactions.map(transaction => transaction.chainId)) : new Set([]) - console.log({eip155ChainsFundsSourcedFrom}) + const initialTransaction = transactions?.[transactions.length - 1] + const eip155ChainsFundsSourcedFrom = transactions + ? new Set(bridgingTransactions.map(transaction => transaction.chainId)) + : new Set([]) const eip155ChainFundsDestination = initialTransaction?.chainId + // Get request and wallet data from store const requestEvent = ModalStore.state.data?.requestEvent const requestSession = ModalStore.state.data?.requestSession @@ -51,39 +49,7 @@ export default function MultibridgeRequestModal({ const chainId = params?.chainId const request = params?.request - const caService = new ChainAbstractionService(); - - // const bridge = useCallback(async () => { - // if (!bridgingRequest) { - // throw new Error('Bridging request is unavailable') - // } - - // const wallet = await getWallet(params) - - // const asset = getAssetByContractAddress(bridgingRequest.transfer.contract) - // if (!asset) { - // throw new Error('Source chain asset unavailable') - // } - // const sourceChainAssetAddress = supportedAssets[asset][bridgingRequest.sourceChain] - // if (!sourceChainAssetAddress) { - // throw new Error('Source chain asset address unavailable') - // } - - // await bridgeFunds( - // { - // fromChainId: bridgingRequest.sourceChain, - // toChainId: bridgingRequest.targetChain, - // fromAssetAddress: sourceChainAssetAddress, - // toAssetAddress: bridgingRequest.transfer.contract, - // amount: bridgingRequest.transfer.amount, - // userAddress: wallet.getAddress(), - // uniqueRoutesPerBridge: true, - // sort: 'time', - // singleTxOnly: true - // }, - // wallet - // ) - // }, [params, bridgingRequest]) + const caService = new ChainAbstractionService() const bridgeRouteFunds = useCallback(async () => { if (!transactions) { @@ -91,25 +57,28 @@ export default function MultibridgeRequestModal({ } const wallet = await getWallet(params) - for(const transaction of bridgingTransactions){ + console.log( + 'Bridge funds from', + eip155ChainsFundsSourcedFrom, + 'to', + eip155ChainFundsDestination + ) + for (const transaction of bridgingTransactions) { + console.log('Bridging transaction', transaction) const chainId = transaction.chainId const chainProvider = new providers.JsonRpcProvider( EIP155_CHAINS[chainId as TEIP155Chain].rpc ) const chainConnectedWallet = await wallet.connect(chainProvider) const walletAddress = wallet.getAddress() - console.log({walletAddress}) - const gasPrice = await chainProvider.getGasPrice(); - console.log({ gasPrice }); - - console.log('gasEstimation starting: '); + const gasPrice = await chainProvider.getGasPrice() const gasEstimate = await chainProvider.estimateGas({ from: walletAddress, to: transaction.to, value: transaction.value, data: transaction.data, - gasPrice: gasPrice, - }); + gasPrice: gasPrice + }) const hash = await chainConnectedWallet.sendTransaction({ from: walletAddress, @@ -117,62 +86,64 @@ export default function MultibridgeRequestModal({ value: transaction.value, data: transaction.data, gasPrice: gasPrice, - gasLimit: gasEstimate, - }); - const receipt = typeof hash === 'string' ? hash : hash?.hash; - console.log('Transaction broadcasted', { receipt }); + gasLimit: gasEstimate + }) + const receipt = typeof hash === 'string' ? hash : hash?.hash + console.log(`Transaction broadcasted on chain ${chainId} , ${{ receipt }}`) } - + // Call the polling function - try{ - pollOrchestrationStatus(orchestrationId) - }catch(e){ + try { + await pollOrchestrationStatus(orchestrationId) + } catch (e) { console.error(e) onReject() } - }, []) - + }, []) - async function pollOrchestrationStatus(orchestrationId:string, maxAttempts = 100, interval = 1500) { + async function pollOrchestrationStatus( + orchestrationId: string, + maxAttempts = 100, + interval = 1500 + ) { for (let attempt = 0; attempt < maxAttempts; attempt++) { - const { status } = await caService.getOrchestrationStatus(orchestrationId); - console.log(attempt,'- Orchestration status:', status); + const { status } = await caService.getOrchestrationStatus(orchestrationId) + console.log(attempt, '- Orchestration status:', status) if (status === 'completed') { - console.log('Bridging completed'); - return; // Exit if the status is completed + console.log('Bridging completed') + return // Exit if the status is completed } // Wait for the specified interval before the next attempt - await new Promise(resolve => setTimeout(resolve, interval)); + await new Promise(resolve => setTimeout(resolve, interval)) } - console.log('Max attempts reached. Orchestration not completed.'); - throw new Error('Max attempts reached. Orchestration not completed.'); + console.log('Max attempts reached. Orchestration not completed.') + throw new Error('Max attempts reached. Orchestration not completed.') } const onApprove = useCallback(async () => { if (requestEvent && topic) { setIsLoadingApprove(true) try { + performance.mark('startInititalTransactionSend') await bridgeRouteFunds() - // await bridge() - // performance.mark('startInititalTransactionSend') - // const response = await approveEIP155Request(requestEvent) - // performance.mark('endInititalTransactionSend') - // console.log( - // `Initial transaction send: ${ - // performance.measure( - // 'initial-tx-send', - // 'startInititalTransactionSend', - // 'endInititalTransactionSend' - // ).duration - // } ms` - // ) - - // await walletkit.respondSessionRequest({ - // topic, - // response - // }) + const response = await approveEIP155Request(requestEvent) + performance.mark('endInititalTransactionSend') + console.log( + `Initial transaction send: ${ + performance.measure( + 'initial-tx-send', + 'startInititalTransactionSend', + 'endInititalTransactionSend' + ).duration + } ms` + ) + + await walletkit.respondSessionRequest({ + topic, + response + }) } catch (e) { console.log('Error') console.error(e) @@ -190,9 +161,9 @@ export default function MultibridgeRequestModal({ return Request not found } const transfer = decodeErc20Transaction(request.params[0]) - if(!transfer) { + if (!transfer) { return Invalid transfer request - } + } const asset = getAssetByContractAddress(transfer.contract) const amount = convertTokenBalance(asset, transfer.amount) diff --git a/advanced/wallets/react-wallet-v2/src/utils/ChainAbstractionService.ts b/advanced/wallets/react-wallet-v2/src/utils/ChainAbstractionService.ts index 770028d46..54e7a0403 100644 --- a/advanced/wallets/react-wallet-v2/src/utils/ChainAbstractionService.ts +++ b/advanced/wallets/react-wallet-v2/src/utils/ChainAbstractionService.ts @@ -1,43 +1,42 @@ -import axios from 'axios'; -import { CA_ORCHESTRATOR_BASE_URL } from './ConstantsUtil'; +import axios from 'axios' +import { CA_ORCHESTRATOR_BASE_URL } from './ConstantsUtil' export interface Transaction { - from: string; - to: string; - value: string; - gas: string; - gasPrice: string; - data: string; - nonce: string; - maxFeePerGas: string; - maxPriorityFeePerGas: string; - chainId: string; + from: string + to: string + value: string + gas: string + gasPrice: string + data: string + nonce: string + maxFeePerGas: string + maxPriorityFeePerGas: string + chainId: string } interface CheckResponse { - requiresMultiChain: boolean; + requiresMultiChain: boolean } interface RouteResponse { - transactions: Transaction[]; - orchestrationId: string; + transactions: Transaction[] + orchestrationId: string } interface OrchestrationStatusResponse { - status: "pending" | "completed" | "error", + status: 'pending' | 'completed' | 'error' createdAt: number } - export class ChainAbstractionService { - private baseUrl: string; - private projectId: string; + private baseUrl: string + private projectId: string constructor() { - this.baseUrl = CA_ORCHESTRATOR_BASE_URL; - if(!process.env.NEXT_PUBLIC_PROJECT_ID){ - throw new Error("Project ID is not defined"); + this.baseUrl = CA_ORCHESTRATOR_BASE_URL + if (!process.env.NEXT_PUBLIC_PROJECT_ID) { + throw new Error('Project ID is not defined') } - this.projectId = process.env.NEXT_PUBLIC_PROJECT_ID; + this.projectId = process.env.NEXT_PUBLIC_PROJECT_ID } async checkTransaction(transaction: Transaction): Promise { @@ -45,11 +44,11 @@ export class ChainAbstractionService { const response = await axios.post( `${this.baseUrl}/check?projectId=${this.projectId}`, { transaction } - ); - return response.data.requiresMultiChain; + ) + return response.data.requiresMultiChain } catch (error) { - console.error('ChainAbstractionService: Error checking transaction:', error); - throw error; + console.error('ChainAbstractionService: Error checking transaction:', error) + throw error } } @@ -58,23 +57,22 @@ export class ChainAbstractionService { const response = await axios.post( `${this.baseUrl}/route?projectId=${this.projectId}`, { transaction } - ); - return response.data; + ) + return response.data } catch (error) { - console.error('ChainAbstractionService: Error routing transaction:', error); - throw error; + console.error('ChainAbstractionService: Error routing transaction:', error) + throw error } } async getOrchestrationStatus(orchestrationId: string): Promise { try { - const response = await axios.get( - `${this.baseUrl}/status?projectId=${this.projectId}&orchestrationId=${orchestrationId}`, - ); - return response.data; + `${this.baseUrl}/status?projectId=${this.projectId}&orchestrationId=${orchestrationId}` + ) + return response.data } catch (error) { - console.error('ChainAbstractionService: Error getting orchestration status :', error); - throw error; + console.error('ChainAbstractionService: Error getting orchestration status :', error) + throw error } } -} \ No newline at end of file +} diff --git a/advanced/wallets/react-wallet-v2/src/utils/ConstantsUtil.ts b/advanced/wallets/react-wallet-v2/src/utils/ConstantsUtil.ts index bbb236189..43b1ecee0 100644 --- a/advanced/wallets/react-wallet-v2/src/utils/ConstantsUtil.ts +++ b/advanced/wallets/react-wallet-v2/src/utils/ConstantsUtil.ts @@ -1,3 +1,2 @@ export const COSIGNER_BASE_URL = 'https://rpc.walletconnect.org/v1/sessions' export const CA_ORCHESTRATOR_BASE_URL = 'https://rpc.walletconnect.org/v1/ca/orchestrator' -// export const CA_ORCHESTRATOR_BASE_URL = 'https://maksy.ngrok.dev/v1/ca/orchestrator' \ No newline at end of file diff --git a/advanced/wallets/react-wallet-v2/src/utils/MultibridgeUtil.ts b/advanced/wallets/react-wallet-v2/src/utils/MultibridgeUtil.ts index 63508b3e4..1fc7e03be 100644 --- a/advanced/wallets/react-wallet-v2/src/utils/MultibridgeUtil.ts +++ b/advanced/wallets/react-wallet-v2/src/utils/MultibridgeUtil.ts @@ -1,8 +1,6 @@ import { createPublicClient, decodeFunctionData, erc20Abi, getContract, Hex, http } from 'viem' import { arbitrum, base, optimism } from 'viem/chains' import { getChainById } from './ChainUtil' -import EIP155Lib from '@/lib/EIP155Lib' -import { SmartAccountLib } from '@/lib/smart-accounts/SmartAccountLib' import { providers } from 'ethers' import { EIP155_CHAINS, TEIP155Chain } from '@/data/EIP155Data' @@ -82,12 +80,6 @@ export async function getErc20TokenBalance( return Number(balance) } -export type BridgingRequest = { - transfer: Erc20Transfer - sourceChain: number - targetChain: number -} - type Erc20Transfer = { from: Hex to: Hex @@ -326,38 +318,3 @@ async function getBridgingTransactions( }) return transactions } - -export async function bridgeFunds( - bridgingParams: BridgingParams, - wallet: EIP155Lib | SmartAccountLib -): Promise { - const originalAmount = bridgingParams.amount - const sourceChainProvider = new providers.JsonRpcProvider( - EIP155_CHAINS[`eip155:${bridgingParams.fromChainId}` as TEIP155Chain].rpc - ) - const sourceChainConnectedWallet = await wallet.connect(sourceChainProvider) - const walletAddress = wallet.getAddress() - console.log('Getting bridging transactions') - const transactions = await getBridgingTransactions(bridgingParams, walletAddress) - console.log('Bridging transactions', transactions) - for (const transaction of transactions) { - const hash = await sourceChainConnectedWallet.sendTransaction(transaction) - const receipt = typeof hash === 'string' ? hash : hash?.hash - console.log('Transaction broadcasted', { receipt }) - } - let interations = 0 - while (interations < 20) { - const balance = await getErc20TokenBalance( - bridgingParams.toAssetAddress as Hex, - bridgingParams.toChainId, - walletAddress as Hex, - false - ) - if (balance >= originalAmount) { - console.log('Bridging completed') - return - } - await new Promise(resolve => setTimeout(resolve, 1500)) - interations++ - } -} diff --git a/advanced/wallets/react-wallet-v2/src/views/SessionSendTransactionModal.tsx b/advanced/wallets/react-wallet-v2/src/views/SessionSendTransactionModal.tsx index c7b089ddd..ae7d94846 100644 --- a/advanced/wallets/react-wallet-v2/src/views/SessionSendTransactionModal.tsx +++ b/advanced/wallets/react-wallet-v2/src/views/SessionSendTransactionModal.tsx @@ -12,7 +12,6 @@ import RequestModal from '@/components/RequestModal' import MultibridgeRequestModal from '@/components/MultibridgeRequestModal' import SettingsStore from '@/store/SettingsStore' import { ChainAbstractionService, Transaction } from '@/utils/ChainAbstractionService' -import { getChainById } from '@/utils/ChainUtil' export default function SessionSendTransactionModal() { const [isLoadingApprove, setIsLoadingApprove] = useState(false) @@ -34,29 +33,22 @@ export default function SessionSendTransactionModal() { useEffect(() => { const multibridgeCheck = async () => { setIsTypeResolved(false) - if(!chainId){ + if (!chainId) { throw new Error('Chain ID is not available') } - console.log({chainId: chainId.split(':')[1]}) - const chain = getChainById(parseInt(chainId.split(':')[1])) + console.log({ chainId: chainId.split(':')[1] }) try { if (!request) { setIsTypeResolved(true) return } - console.log({chain}) - if (!SettingsStore.state.chainAbstractionEnabled) { setIsTypeResolved(true) return } - const { - data, - from, - to - } = request.params[0] - + const { data, from, to } = request.params[0] + const caService = new ChainAbstractionService() const isRequiresMultiChain = await caService.checkTransaction({ from: from, @@ -70,8 +62,8 @@ export default function SessionSendTransactionModal() { maxPriorityFeePerGas: '0', chainId: chainId }) - console.log('Checking multibridge availability', {isRequiresMultiChain}) - if(isRequiresMultiChain){ + console.log('Checking multibridge availability', { isRequiresMultiChain }) + if (isRequiresMultiChain) { const routeTransactions = await caService.routeTransaction({ from: from, to: to, @@ -84,14 +76,11 @@ export default function SessionSendTransactionModal() { maxPriorityFeePerGas: '0', chainId: chainId }) - const status = await caService.getOrchestrationStatus(routeTransactions.orchestrationId) - console.log('Orchestration status', status) - console.log('Route transactions', routeTransactions) + console.log('Route transactions', routeTransactions) setRequiresMultiChain(isRequiresMultiChain) setRouteTransactions(routeTransactions.transactions) setOrchestrationId(routeTransactions.orchestrationId) } - } catch (error) { console.log('Unable to check multibridge availability', error) } finally { @@ -154,7 +143,9 @@ export default function SessionSendTransactionModal() { ) } - return !requiresMultiChain && isTypeResolved || (orchestrationId === null || orchestrationId === undefined) ? ( + return (!requiresMultiChain && isTypeResolved) || + orchestrationId === null || + orchestrationId === undefined ? ( - ); + ) }