From 6023787fc836cdc297f970608fda0073f66a07a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Tavares?= Date: Thu, 21 Nov 2024 15:10:11 +0000 Subject: [PATCH 1/5] chore: centralize redesigned confirmation decision logic (#28445) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR centralizes the redesigned confirmation decision logic to improve code organization and reduce duplication across the codebase. Currently, redesign confirmation decision logic is scattered across multiple files, making it harder to maintain and more prone to inconsistencies. #### Motivation The existing implementation has several issues: 1. Duplicate logic for handling confirmation decisions across different transaction types 2. Prevent inconsistent handling of redesigned confirmation flows Key changes: - Move supported redesigned confirmation decision logic to the shared dir (to be used both in the `ui` and `app` bundles) - Updated signature metrics tracking to support developer mode enabled Types of changes: - Code style update (changes that do not affect the meaning of the code) [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/28445?quickstart=1) ## **Related issues** Fixes: ## **Manual testing steps** 1. Ensure that when either the experimental confirmations redesign toggle, developer option confirmations redesign toggle or the env ENABLE_CONFIRMATIONS_REDESIGN is enabled the we are presenting the new redesign confirmations. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .../lib/createRPCMethodTrackingMiddleware.js | 20 +- .../createRPCMethodTrackingMiddleware.test.js | 13 ++ app/scripts/lib/transaction/metrics.ts | 32 +-- app/scripts/metamask-controller.js | 43 ++-- shared/lib/confirmation.utils.test.ts | 208 ++++++++++++++++++ shared/lib/confirmation.utils.ts | 169 ++++++++++++++ .../components/confirm/footer/footer.tsx | 7 +- .../components/confirm/header/header-info.tsx | 11 +- .../components/confirm/nav/nav.tsx | 5 +- .../scroll-to-bottom/scroll-to-bottom.tsx | 7 +- .../usePendingTransactionAlerts.ts | 11 +- .../useSigningOrSubmittingAlerts.ts | 11 +- .../hooks/alerts/useBlockaidAlerts.ts | 14 +- .../hooks/useCurrentConfirmation.ts | 55 ++--- ui/pages/confirmations/utils/confirm.test.ts | 22 -- ui/pages/confirmations/utils/confirm.ts | 33 --- ui/pages/routes/routes.component.js | 19 +- 17 files changed, 485 insertions(+), 195 deletions(-) create mode 100644 shared/lib/confirmation.utils.test.ts create mode 100644 shared/lib/confirmation.utils.ts diff --git a/app/scripts/lib/createRPCMethodTrackingMiddleware.js b/app/scripts/lib/createRPCMethodTrackingMiddleware.js index 27358d18f543..5ca2374db05b 100644 --- a/app/scripts/lib/createRPCMethodTrackingMiddleware.js +++ b/app/scripts/lib/createRPCMethodTrackingMiddleware.js @@ -27,7 +27,7 @@ import { } from '../../../ui/helpers/utils/metrics'; // TODO: Remove restricted import // eslint-disable-next-line import/no-restricted-paths -import { REDESIGN_APPROVAL_TYPES } from '../../../ui/pages/confirmations/utils/confirm'; +import { shouldUseRedesignForSignatures } from '../../../shared/lib/confirmation.utils'; import { getSnapAndHardwareInfoForMetrics } from './snap-keyring/metrics'; /** @@ -196,6 +196,7 @@ function finalizeSignatureFragment( * @param {Function} opts.getAccountType * @param {Function} opts.getDeviceModel * @param {Function} opts.isConfirmationRedesignEnabled + * @param {Function} opts.isRedesignedConfirmationsDeveloperEnabled * @param {RestrictedControllerMessenger} opts.snapAndHardwareMessenger * @param {number} [opts.globalRateLimitTimeout] - time, in milliseconds, of the sliding * time window that should limit the number of method calls tracked to globalRateLimitMaxAmount. @@ -214,6 +215,7 @@ export default function createRPCMethodTrackingMiddleware({ getAccountType, getDeviceModel, isConfirmationRedesignEnabled, + isRedesignedConfirmationsDeveloperEnabled, snapAndHardwareMessenger, appStateController, metaMetricsController, @@ -315,13 +317,15 @@ export default function createRPCMethodTrackingMiddleware({ req.securityAlertResponse.description; } - const isConfirmationRedesign = - isConfirmationRedesignEnabled() && - REDESIGN_APPROVAL_TYPES.find( - (type) => type === MESSAGE_TYPE_TO_APPROVAL_TYPE[method], - ); - - if (isConfirmationRedesign) { + if ( + shouldUseRedesignForSignatures({ + approvalType: MESSAGE_TYPE_TO_APPROVAL_TYPE[method], + isRedesignedSignaturesUserSettingEnabled: + isConfirmationRedesignEnabled(), + isRedesignedConfirmationsDeveloperEnabled: + isRedesignedConfirmationsDeveloperEnabled(), + }) + ) { eventProperties.ui_customizations = [ ...(eventProperties.ui_customizations || []), MetaMetricsEventUiCustomization.RedesignedConfirmation, diff --git a/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js b/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js index 9ebb3f92130b..1949ca7f876e 100644 --- a/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js +++ b/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js @@ -118,6 +118,7 @@ const createHandler = (opts) => appStateController, metaMetricsController, isConfirmationRedesignEnabled: () => false, + isRedesignedConfirmationsDeveloperEnabled: () => false, ...opts, }); @@ -217,10 +218,22 @@ describe('createRPCMethodTrackingMiddleware', () => { }); describe('participateInMetaMetrics is set to true', () => { + const originalEnableConfirmationRedesign = + process.env.ENABLE_CONFIRMATION_REDESIGN; + beforeEach(() => { metaMetricsController.setParticipateInMetaMetrics(true); }); + beforeAll(() => { + process.env.ENABLE_CONFIRMATION_REDESIGN = 'false'; + }); + + afterAll(() => { + process.env.ENABLE_CONFIRMATION_REDESIGN = + originalEnableConfirmationRedesign; + }); + it(`should immediately track a ${MetaMetricsEventName.SignatureRequested} event`, async () => { const req = { id: MOCK_ID, diff --git a/app/scripts/lib/transaction/metrics.ts b/app/scripts/lib/transaction/metrics.ts index 3cdc14619b0d..375a8bd4a8ab 100644 --- a/app/scripts/lib/transaction/metrics.ts +++ b/app/scripts/lib/transaction/metrics.ts @@ -43,16 +43,12 @@ import { // TODO: Remove restricted import // eslint-disable-next-line import/no-restricted-paths } from '../../../../ui/helpers/utils/metrics'; -import { - REDESIGN_DEV_TRANSACTION_TYPES, - REDESIGN_USER_TRANSACTION_TYPES, - // TODO: Remove restricted import - // eslint-disable-next-line import/no-restricted-paths -} from '../../../../ui/pages/confirmations/utils'; + import { getSnapAndHardwareInfoForMetrics, type SnapAndHardwareMessenger, } from '../snap-keyring/metrics'; +import { shouldUseRedesignForTransactions } from '../../../../shared/lib/confirmation.utils'; export type TransactionMetricsRequest = { createEventFragment: ( @@ -996,23 +992,15 @@ async function buildEventFragmentProperties({ if (simulationFails) { uiCustomizations.push(MetaMetricsEventUiCustomization.GasEstimationFailed); } - const isRedesignedConfirmationsDeveloperSettingEnabled = - transactionMetricsRequest.getIsRedesignedConfirmationsDeveloperEnabled() || - process.env.ENABLE_CONFIRMATION_REDESIGN === 'true'; - const isRedesignedTransactionsUserSettingEnabled = - transactionMetricsRequest.getRedesignedTransactionsEnabled(); - - if ( - (isRedesignedConfirmationsDeveloperSettingEnabled && - REDESIGN_DEV_TRANSACTION_TYPES.includes( - transactionMeta.type as TransactionType, - )) || - (isRedesignedTransactionsUserSettingEnabled && - REDESIGN_USER_TRANSACTION_TYPES.includes( - transactionMeta.type as TransactionType, - )) - ) { + const isRedesignedForTransaction = shouldUseRedesignForTransactions({ + transactionMetadataType: transactionMeta.type as TransactionType, + isRedesignedTransactionsUserSettingEnabled: + transactionMetricsRequest.getRedesignedTransactionsEnabled(), + isRedesignedConfirmationsDeveloperEnabled: + transactionMetricsRequest.getIsRedesignedConfirmationsDeveloperEnabled(), + }); + if (isRedesignedForTransaction) { uiCustomizations.push( MetaMetricsEventUiCustomization.RedesignedConfirmation, ); diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 0d0344d4e7e3..e297a016fd76 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -5789,16 +5789,14 @@ export default class MetamaskController extends EventEmitter { ), ); - const isConfirmationRedesignEnabled = () => { - return this.preferencesController.state.preferences - .redesignedConfirmationsEnabled; - }; - engine.push( createRPCMethodTrackingMiddleware({ getAccountType: this.getAccountType.bind(this), getDeviceModel: this.getDeviceModel.bind(this), - isConfirmationRedesignEnabled, + isConfirmationRedesignEnabled: + this.isConfirmationRedesignEnabled.bind(this), + isRedesignedConfirmationsDeveloperEnabled: + this.isConfirmationRedesignDeveloperEnabled.bind(this), snapAndHardwareMessenger: this.controllerMessenger.getRestricted({ name: 'SnapAndHardwareMessenger', allowedActions: [ @@ -6436,6 +6434,21 @@ export default class MetamaskController extends EventEmitter { }); } + isConfirmationRedesignEnabled() { + return this.preferencesController.state.preferences + .redesignedConfirmationsEnabled; + } + + isTransactionsRedesignEnabled() { + return this.preferencesController.state.preferences + .redesignedTransactionsEnabled; + } + + isConfirmationRedesignDeveloperEnabled() { + return this.preferencesController.state.preferences + .isRedesignedConfirmationsDeveloperEnabled; + } + /** * The chain list is fetched live at runtime, falling back to a cache. * This preseeds the cache at startup with a static list provided at build. @@ -6620,14 +6633,10 @@ export default class MetamaskController extends EventEmitter { txHash, ); }, - getRedesignedConfirmationsEnabled: () => { - return this.preferencesController.state.preferences - .redesignedConfirmationsEnabled; - }, - getRedesignedTransactionsEnabled: () => { - return this.preferencesController.state.preferences - .redesignedTransactionsEnabled; - }, + getRedesignedConfirmationsEnabled: + this.isConfirmationRedesignEnabled.bind(this), + getRedesignedTransactionsEnabled: + this.isTransactionsRedesignEnabled.bind(this), getMethodData: (data) => { if (!data) { return null; @@ -6645,10 +6654,8 @@ export default class MetamaskController extends EventEmitter { this.provider, ); }, - getIsRedesignedConfirmationsDeveloperEnabled: () => { - return this.preferencesController.state.preferences - .isRedesignedConfirmationsDeveloperEnabled; - }, + getIsRedesignedConfirmationsDeveloperEnabled: + this.isConfirmationRedesignDeveloperEnabled.bind(this), getIsConfirmationAdvancedDetailsOpen: () => { return this.preferencesController.state.preferences .showConfirmationAdvancedDetails; diff --git a/shared/lib/confirmation.utils.test.ts b/shared/lib/confirmation.utils.test.ts new file mode 100644 index 000000000000..552d78827a2e --- /dev/null +++ b/shared/lib/confirmation.utils.test.ts @@ -0,0 +1,208 @@ +import { TransactionType } from '@metamask/transaction-controller'; +import { ApprovalType } from '@metamask/controller-utils'; +import { + shouldUseRedesignForTransactions, + shouldUseRedesignForSignatures, +} from './confirmation.utils'; + +describe('confirmation.utils', () => { + describe('shouldUseRedesignForTransactions', () => { + const supportedTransactionTypes = [ + TransactionType.contractInteraction, + TransactionType.deployContract, + TransactionType.tokenMethodApprove, + TransactionType.tokenMethodIncreaseAllowance, + TransactionType.tokenMethodSetApprovalForAll, + TransactionType.tokenMethodTransfer, + TransactionType.tokenMethodTransferFrom, + TransactionType.tokenMethodSafeTransferFrom, + TransactionType.simpleSend, + ]; + + const unsupportedTransactionType = TransactionType.swap; + + describe('when user setting is enabled', () => { + it('should return true for supported transaction types', () => { + supportedTransactionTypes.forEach((transactionType) => { + expect( + shouldUseRedesignForTransactions({ + transactionMetadataType: transactionType, + isRedesignedTransactionsUserSettingEnabled: true, // user setting enabled + isRedesignedConfirmationsDeveloperEnabled: false, // developer mode disabled + }), + ).toBe(true); + }); + }); + + it('should return false for unsupported transaction types', () => { + expect( + shouldUseRedesignForTransactions({ + transactionMetadataType: unsupportedTransactionType, + isRedesignedTransactionsUserSettingEnabled: true, // user setting enabled + isRedesignedConfirmationsDeveloperEnabled: false, // developer mode disabled + }), + ).toBe(false); + }); + }); + + describe('when developer mode is enabled', () => { + const originalEnv = process.env; + + beforeEach(() => { + process.env = { ...originalEnv }; + }); + + afterEach(() => { + process.env = originalEnv; + }); + + it('should return true for supported transaction types when ENABLE_CONFIRMATION_REDESIGN is true', () => { + process.env.ENABLE_CONFIRMATION_REDESIGN = 'true'; + + supportedTransactionTypes.forEach((transactionType) => { + expect( + shouldUseRedesignForTransactions({ + transactionMetadataType: transactionType, + isRedesignedTransactionsUserSettingEnabled: false, // user setting disabled + isRedesignedConfirmationsDeveloperEnabled: false, // developer setting disabled + }), + ).toBe(true); + }); + }); + + it('should return true for supported transaction types when developer setting is enabled', () => { + supportedTransactionTypes.forEach((transactionType) => { + expect( + shouldUseRedesignForTransactions({ + transactionMetadataType: transactionType, + isRedesignedTransactionsUserSettingEnabled: false, // user setting disabled + isRedesignedConfirmationsDeveloperEnabled: true, // developer setting enabled + }), + ).toBe(true); + }); + }); + + it('should return false for unsupported transaction types even if developer mode is enabled', () => { + process.env.ENABLE_CONFIRMATION_REDESIGN = 'true'; + + expect( + shouldUseRedesignForTransactions({ + transactionMetadataType: unsupportedTransactionType, + isRedesignedTransactionsUserSettingEnabled: false, // user setting disabled + isRedesignedConfirmationsDeveloperEnabled: true, // developer setting enabled + }), + ).toBe(false); + }); + }); + + describe('when both user setting and developer mode are disabled', () => { + const originalEnv = process.env; + + beforeEach(() => { + process.env = { ...originalEnv }; + process.env.ENABLE_CONFIRMATION_REDESIGN = 'false'; + }); + + afterEach(() => { + process.env = originalEnv; + }); + + it('should return false for all transaction types', () => { + [...supportedTransactionTypes, unsupportedTransactionType].forEach( + (transactionType) => { + expect( + shouldUseRedesignForTransactions({ + transactionMetadataType: transactionType, + isRedesignedTransactionsUserSettingEnabled: false, // user setting disabled + isRedesignedConfirmationsDeveloperEnabled: false, // developer setting disabled + }), + ).toBe(false); + }, + ); + }); + }); + }); + + describe('shouldUseRedesignForSignatures', () => { + const originalEnv = process.env; + + const supportedSignatureApprovalTypes = [ + ApprovalType.EthSignTypedData, + ApprovalType.PersonalSign, + ]; + + beforeEach(() => { + jest.resetModules(); + process.env = { ...originalEnv }; + process.env.ENABLE_CONFIRMATION_REDESIGN = 'false'; + }); + + afterEach(() => { + process.env = originalEnv; + }); + + it('should return true for supported approval types when user setting is enabled', () => { + supportedSignatureApprovalTypes.forEach((approvalType) => { + expect( + shouldUseRedesignForSignatures({ + approvalType, + isRedesignedSignaturesUserSettingEnabled: true, // user setting enabled + isRedesignedConfirmationsDeveloperEnabled: false, // developer setting disabled + }), + ).toBe(true); + }); + }); + + it('should return true for supported approval types when developer mode is enabled via env', () => { + process.env.ENABLE_CONFIRMATION_REDESIGN = 'true'; + + supportedSignatureApprovalTypes.forEach((approvalType) => { + expect( + shouldUseRedesignForSignatures({ + approvalType, + isRedesignedSignaturesUserSettingEnabled: false, // user setting disabled + isRedesignedConfirmationsDeveloperEnabled: false, // developer setting disabled + }), + ).toBe(true); + }); + }); + + it('should return true for supported approval types when developer setting is enabled', () => { + supportedSignatureApprovalTypes.forEach((approvalType) => { + expect( + shouldUseRedesignForSignatures({ + approvalType, + isRedesignedSignaturesUserSettingEnabled: false, // user setting disabled + isRedesignedConfirmationsDeveloperEnabled: true, // developer setting enabled + }), + ).toBe(true); + }); + }); + + it('should return false for unsupported approval types', () => { + const unsupportedApprovalType = ApprovalType.AddEthereumChain; + + expect( + shouldUseRedesignForSignatures({ + approvalType: unsupportedApprovalType, + isRedesignedSignaturesUserSettingEnabled: true, // user setting enabled + isRedesignedConfirmationsDeveloperEnabled: true, // developer setting enabled + }), + ).toBe(false); + }); + + it('should return false when both user setting and developer mode are disabled', () => { + process.env.ENABLE_CONFIRMATION_REDESIGN = 'false'; + + supportedSignatureApprovalTypes.forEach((approvalType) => { + expect( + shouldUseRedesignForSignatures({ + approvalType, + isRedesignedSignaturesUserSettingEnabled: false, // user setting disabled + isRedesignedConfirmationsDeveloperEnabled: false, // developer setting disabled + }), + ).toBe(false); + }); + }); + }); +}); diff --git a/shared/lib/confirmation.utils.ts b/shared/lib/confirmation.utils.ts new file mode 100644 index 000000000000..24c5f258a5d0 --- /dev/null +++ b/shared/lib/confirmation.utils.ts @@ -0,0 +1,169 @@ +import { TransactionType } from '@metamask/transaction-controller'; +import { ApprovalType } from '@metamask/controller-utils'; + +/* eslint-disable jsdoc/require-param, jsdoc/check-param-names */ + +/** List of signature approval types that support the redesigned confirmation flow */ +const REDESIGN_SIGNATURE_APPROVAL_TYPES = [ + ApprovalType.EthSignTypedData, + ApprovalType.PersonalSign, +]; + +/** List of transaction types that support the redesigned confirmation flow for users */ +const REDESIGN_USER_TRANSACTION_TYPES = [ + TransactionType.contractInteraction, + TransactionType.deployContract, + TransactionType.tokenMethodApprove, + TransactionType.tokenMethodIncreaseAllowance, + TransactionType.tokenMethodSetApprovalForAll, + TransactionType.tokenMethodTransfer, + TransactionType.tokenMethodTransferFrom, + TransactionType.tokenMethodSafeTransferFrom, + TransactionType.simpleSend, +]; + +/** List of transaction types that support the redesigned confirmation flow for developers */ +const REDESIGN_DEV_TRANSACTION_TYPES = [...REDESIGN_USER_TRANSACTION_TYPES]; + +/** + * Determines whether to use the redesigned confirmation flow for a given transaction + * based on user settings and developer mode + * + * @param opts.transactionMetadataType - The type of transaction to check + * @param opts.isRedesignedTransactionsUserSettingEnabled - Whether the user has enabled the redesigned flow + * @param opts.isRedesignedConfirmationsDeveloperEnabled - Whether developer mode is enabled + */ +export function shouldUseRedesignForTransactions({ + transactionMetadataType, + isRedesignedTransactionsUserSettingEnabled, + isRedesignedConfirmationsDeveloperEnabled, +}: { + transactionMetadataType?: TransactionType; + isRedesignedTransactionsUserSettingEnabled: boolean; + isRedesignedConfirmationsDeveloperEnabled: boolean; +}): boolean { + return ( + shouldUseRedesignForTransactionsUserMode( + isRedesignedTransactionsUserSettingEnabled, + transactionMetadataType, + ) || + shouldUseRedesignForTransactionsDeveloperMode( + isRedesignedConfirmationsDeveloperEnabled, + transactionMetadataType, + ) + ); +} + +/** + * Determines whether to use the redesigned confirmation flow for a given signature + * based on user settings and developer mode + * + * @param opts.approvalType - The type of signature approval to check + * @param opts.isRedesignedSignaturesUserSettingEnabled - Whether the user has enabled the redesigned flow + * @param opts.isRedesignedConfirmationsDeveloperEnabled - Whether developer mode is enabled + */ +export function shouldUseRedesignForSignatures({ + approvalType, + isRedesignedSignaturesUserSettingEnabled, + isRedesignedConfirmationsDeveloperEnabled, +}: { + approvalType?: ApprovalType; + isRedesignedSignaturesUserSettingEnabled: boolean; + isRedesignedConfirmationsDeveloperEnabled: boolean; +}): boolean { + const isRedesignedConfirmationsDeveloperSettingEnabled = + process.env.ENABLE_CONFIRMATION_REDESIGN === 'true' || + isRedesignedConfirmationsDeveloperEnabled; + + if (!isCorrectSignatureApprovalType(approvalType)) { + return false; + } + + return ( + isRedesignedSignaturesUserSettingEnabled || + isRedesignedConfirmationsDeveloperSettingEnabled + ); +} + +/** + * Checks if an redesign approval type is supported for signature redesign + * + * @param approvalType - The type of approval to check + */ +export function isCorrectSignatureApprovalType( + approvalType?: ApprovalType, +): boolean { + if (!approvalType) { + return false; + } + + return REDESIGN_SIGNATURE_APPROVAL_TYPES.includes(approvalType); +} + +/** + * Checks if a redesigned transaction type is supported in developer mode + * + * @param transactionMetadataType - The type of transaction to check + */ +export function isCorrectDeveloperTransactionType( + transactionMetadataType?: TransactionType, +): boolean { + if (!transactionMetadataType) { + return false; + } + + return REDESIGN_DEV_TRANSACTION_TYPES.includes(transactionMetadataType); +} + +/** + * Checks if a redesigned transaction type is supported in user mode + * + * @param transactionMetadataType - The type of transaction to check + */ +function isCorrectUserTransactionType( + transactionMetadataType?: TransactionType, +): boolean { + if (!transactionMetadataType) { + return false; + } + + return REDESIGN_USER_TRANSACTION_TYPES.includes(transactionMetadataType); +} + +/** + * Determines if the redesigned confirmation flow should be used for transactions + * when in developer mode + * + * @param isRedesignedConfirmationsDeveloperEnabled - Whether developer mode is enabled + * @param transactionMetadataType - The type of transaction to check + */ +function shouldUseRedesignForTransactionsDeveloperMode( + isRedesignedConfirmationsDeveloperEnabled: boolean, + transactionMetadataType?: TransactionType, +): boolean { + const isDeveloperModeEnabled = + process.env.ENABLE_CONFIRMATION_REDESIGN === 'true' || + isRedesignedConfirmationsDeveloperEnabled; + + return ( + isDeveloperModeEnabled && + isCorrectDeveloperTransactionType(transactionMetadataType) + ); +} + +/** + * Determines if the redesigned confirmation flow should be used for transactions + * when in user mode + * + * @param isRedesignedTransactionsUserSettingEnabled - Whether the user has enabled the redesigned flow + * @param transactionMetadataType - The type of transaction to check + */ +function shouldUseRedesignForTransactionsUserMode( + isRedesignedTransactionsUserSettingEnabled: boolean, + transactionMetadataType?: TransactionType, +): boolean { + return ( + isRedesignedTransactionsUserSettingEnabled && + isCorrectUserTransactionType(transactionMetadataType) + ); +} diff --git a/ui/pages/confirmations/components/confirm/footer/footer.tsx b/ui/pages/confirmations/components/confirm/footer/footer.tsx index a37812899ec9..a9aea54c03f7 100644 --- a/ui/pages/confirmations/components/confirm/footer/footer.tsx +++ b/ui/pages/confirmations/components/confirm/footer/footer.tsx @@ -34,13 +34,13 @@ import { selectUseTransactionSimulations } from '../../../selectors/preferences' import { isPermitSignatureRequest, isSIWESignatureRequest, - REDESIGN_DEV_TRANSACTION_TYPES, } from '../../../utils'; import { useConfirmContext } from '../../../context/confirm'; import { getConfirmationSender } from '../utils'; import { MetaMetricsEventLocation } from '../../../../../../shared/constants/metametrics'; import { Alert } from '../../../../../ducks/confirm-alerts/confirm-alerts'; import { Severity } from '../../../../../helpers/constants/design-system'; +import { isCorrectDeveloperTransactionType } from '../../../../../../shared/lib/confirmation.utils'; export type OnCancelHandler = ({ location, @@ -218,9 +218,10 @@ const Footer = () => { return; } - const isTransactionConfirmation = REDESIGN_DEV_TRANSACTION_TYPES.find( - (type) => type === currentConfirmation?.type, + const isTransactionConfirmation = isCorrectDeveloperTransactionType( + currentConfirmation?.type, ); + if (isTransactionConfirmation) { const mergeTxDataWithNonce = (transactionData: TransactionMeta) => customNonceValue diff --git a/ui/pages/confirmations/components/confirm/header/header-info.tsx b/ui/pages/confirmations/components/confirm/header/header-info.tsx index 9cc50b0fe676..03eabacef42e 100644 --- a/ui/pages/confirmations/components/confirm/header/header-info.tsx +++ b/ui/pages/confirmations/components/confirm/header/header-info.tsx @@ -1,4 +1,3 @@ -import { TransactionType } from '@metamask/transaction-controller'; import React, { useContext } from 'react'; import { useSelector } from 'react-redux'; import { @@ -42,10 +41,8 @@ import { useConfirmContext } from '../../../context/confirm'; import { useBalance } from '../../../hooks/useBalance'; import useConfirmationRecipientInfo from '../../../hooks/useConfirmationRecipientInfo'; import { SignatureRequestType } from '../../../types/confirm'; -import { - isSignatureTransactionType, - REDESIGN_DEV_TRANSACTION_TYPES, -} from '../../../utils/confirm'; +import { isSignatureTransactionType } from '../../../utils/confirm'; +import { isCorrectDeveloperTransactionType } from '../../../../../../shared/lib/confirmation.utils'; import { AdvancedDetailsButton } from './advanced-details-button'; const HeaderInfo = () => { @@ -89,8 +86,8 @@ const HeaderInfo = () => { trackEvent(event); } - const isShowAdvancedDetailsToggle = REDESIGN_DEV_TRANSACTION_TYPES.includes( - currentConfirmation?.type as TransactionType, + const isShowAdvancedDetailsToggle = isCorrectDeveloperTransactionType( + currentConfirmation?.type, ); return ( diff --git a/ui/pages/confirmations/components/confirm/nav/nav.tsx b/ui/pages/confirmations/components/confirm/nav/nav.tsx index de0637a9f641..4a58e1c364dd 100644 --- a/ui/pages/confirmations/components/confirm/nav/nav.tsx +++ b/ui/pages/confirmations/components/confirm/nav/nav.tsx @@ -3,6 +3,7 @@ import React, { useCallback, useMemo } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; +import { ApprovalType } from '@metamask/controller-utils'; import { QueueType } from '../../../../../../shared/constants/metametrics'; import { Box, @@ -34,7 +35,7 @@ import { pendingConfirmationsSortedSelector } from '../../../../../selectors'; import { rejectPendingApproval } from '../../../../../store/actions'; import { useConfirmContext } from '../../../context/confirm'; import { useQueuedConfirmationsEvent } from '../../../hooks/useQueuedConfirmationEvents'; -import { isSignatureApprovalRequest } from '../../../utils'; +import { isCorrectSignatureApprovalType } from '../../../../../../shared/lib/confirmation.utils'; const Nav = () => { const history = useHistory(); @@ -64,7 +65,7 @@ const Nav = () => { // "/confirm-transaction/" history.replace( `${CONFIRM_TRANSACTION_ROUTE}/${nextConfirmation.id}${ - isSignatureApprovalRequest(nextConfirmation) + isCorrectSignatureApprovalType(nextConfirmation.type as ApprovalType) ? SIGNATURE_REQUEST_PATH : '' }`, diff --git a/ui/pages/confirmations/components/confirm/scroll-to-bottom/scroll-to-bottom.tsx b/ui/pages/confirmations/components/confirm/scroll-to-bottom/scroll-to-bottom.tsx index c61053818923..61cb8f65563c 100644 --- a/ui/pages/confirmations/components/confirm/scroll-to-bottom/scroll-to-bottom.tsx +++ b/ui/pages/confirmations/components/confirm/scroll-to-bottom/scroll-to-bottom.tsx @@ -1,6 +1,5 @@ import React, { useContext, useEffect } from 'react'; import { useSelector } from 'react-redux'; -import { TransactionType } from '@metamask/transaction-controller'; import { Box, ButtonIcon, @@ -21,7 +20,7 @@ import { usePrevious } from '../../../../../hooks/usePrevious'; import { useScrollRequired } from '../../../../../hooks/useScrollRequired'; import { useConfirmContext } from '../../../context/confirm'; import { selectConfirmationAdvancedDetailsOpen } from '../../../selectors/preferences'; -import { REDESIGN_DEV_TRANSACTION_TYPES } from '../../../utils'; +import { isCorrectDeveloperTransactionType } from '../../../../../../shared/lib/confirmation.utils'; type ContentProps = { /** @@ -51,8 +50,8 @@ const ScrollToBottom = ({ children }: ContentProps) => { offsetPxFromBottom: 0, }); - const isTransactionRedesign = REDESIGN_DEV_TRANSACTION_TYPES.includes( - currentConfirmation?.type as TransactionType, + const isTransactionRedesign = isCorrectDeveloperTransactionType( + currentConfirmation?.type, ); const showScrollToBottom = diff --git a/ui/pages/confirmations/hooks/alerts/transactions/usePendingTransactionAlerts.ts b/ui/pages/confirmations/hooks/alerts/transactions/usePendingTransactionAlerts.ts index 7430f3ff4fd0..5753b5329ea8 100644 --- a/ui/pages/confirmations/hooks/alerts/transactions/usePendingTransactionAlerts.ts +++ b/ui/pages/confirmations/hooks/alerts/transactions/usePendingTransactionAlerts.ts @@ -1,7 +1,4 @@ -import { - TransactionMeta, - TransactionType, -} from '@metamask/transaction-controller'; +import { TransactionMeta } from '@metamask/transaction-controller'; import { useMemo } from 'react'; import { useSelector } from 'react-redux'; @@ -9,9 +6,9 @@ import { submittedPendingTransactionsSelector } from '../../../../../selectors'; import { useI18nContext } from '../../../../../hooks/useI18nContext'; import { Alert } from '../../../../../ducks/confirm-alerts/confirm-alerts'; import { Severity } from '../../../../../helpers/constants/design-system'; -import { REDESIGN_DEV_TRANSACTION_TYPES } from '../../../utils'; import { RowAlertKey } from '../../../../../components/app/confirm/info/row/constants'; import { useConfirmContext } from '../../../context/confirm'; +import { isCorrectDeveloperTransactionType } from '../../../../../../shared/lib/confirmation.utils'; export function usePendingTransactionAlerts(): Alert[] { const t = useI18nContext(); @@ -19,9 +16,7 @@ export function usePendingTransactionAlerts(): Alert[] { const { type } = currentConfirmation ?? ({} as TransactionMeta); const pendingTransactions = useSelector(submittedPendingTransactionsSelector); - const isValidType = REDESIGN_DEV_TRANSACTION_TYPES.includes( - type as TransactionType, - ); + const isValidType = isCorrectDeveloperTransactionType(type); const hasPendingTransactions = isValidType && Boolean(pendingTransactions.length); diff --git a/ui/pages/confirmations/hooks/alerts/transactions/useSigningOrSubmittingAlerts.ts b/ui/pages/confirmations/hooks/alerts/transactions/useSigningOrSubmittingAlerts.ts index 11d9f1697a6e..3cb6c45b31e1 100644 --- a/ui/pages/confirmations/hooks/alerts/transactions/useSigningOrSubmittingAlerts.ts +++ b/ui/pages/confirmations/hooks/alerts/transactions/useSigningOrSubmittingAlerts.ts @@ -1,7 +1,4 @@ -import { - TransactionMeta, - TransactionType, -} from '@metamask/transaction-controller'; +import { TransactionMeta } from '@metamask/transaction-controller'; import { useMemo } from 'react'; import { useSelector } from 'react-redux'; @@ -9,8 +6,8 @@ import { getApprovedAndSignedTransactions } from '../../../../../selectors'; import { Severity } from '../../../../../helpers/constants/design-system'; import { useI18nContext } from '../../../../../hooks/useI18nContext'; import { Alert } from '../../../../../ducks/confirm-alerts/confirm-alerts'; -import { REDESIGN_DEV_TRANSACTION_TYPES } from '../../../utils'; import { useConfirmContext } from '../../../context/confirm'; +import { isCorrectDeveloperTransactionType } from '../../../../../../shared/lib/confirmation.utils'; export function useSigningOrSubmittingAlerts(): Alert[] { const t = useI18nContext(); @@ -21,9 +18,7 @@ export function useSigningOrSubmittingAlerts(): Alert[] { getApprovedAndSignedTransactions, ); - const isValidType = REDESIGN_DEV_TRANSACTION_TYPES.includes( - type as TransactionType, - ); + const isValidType = isCorrectDeveloperTransactionType(type); const isSigningOrSubmitting = isValidType && signingOrSubmittingTransactions.length > 0; diff --git a/ui/pages/confirmations/hooks/alerts/useBlockaidAlerts.ts b/ui/pages/confirmations/hooks/alerts/useBlockaidAlerts.ts index 2f26fcefbee9..30ab2e71947e 100644 --- a/ui/pages/confirmations/hooks/alerts/useBlockaidAlerts.ts +++ b/ui/pages/confirmations/hooks/alerts/useBlockaidAlerts.ts @@ -15,10 +15,8 @@ import { import { Alert } from '../../../../ducks/confirm-alerts/confirm-alerts'; import ZENDESK_URLS from '../../../../helpers/constants/zendesk-url'; import { useI18nContext } from '../../../../hooks/useI18nContext'; -import { - SIGNATURE_TRANSACTION_TYPES, - REDESIGN_DEV_TRANSACTION_TYPES, -} from '../../utils'; +import { SIGNATURE_TRANSACTION_TYPES } from '../../utils'; +import { isCorrectDeveloperTransactionType } from '../../../../../shared/lib/confirmation.utils'; import { SecurityAlertResponse, SignatureRequestType, @@ -30,11 +28,6 @@ import { normalizeProviderAlert } from './utils'; // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires const zlib = require('zlib'); -const SUPPORTED_TRANSACTION_TYPES = [ - ...SIGNATURE_TRANSACTION_TYPES, - ...REDESIGN_DEV_TRANSACTION_TYPES, -]; - const IGNORED_RESULT_TYPES = [ BlockaidResultType.Benign, BlockaidResultType.Loading, @@ -74,7 +67,8 @@ const useBlockaidAlerts = (): Alert[] => { signatureSecurityAlertResponse || transactionSecurityAlertResponse; const isTransactionTypeSupported = - SUPPORTED_TRANSACTION_TYPES.includes(transactionType); + isCorrectDeveloperTransactionType(transactionType) || + SIGNATURE_TRANSACTION_TYPES.includes(transactionType); const isResultTypeIgnored = IGNORED_RESULT_TYPES.includes( securityAlertResponse?.result_type as BlockaidResultType, diff --git a/ui/pages/confirmations/hooks/useCurrentConfirmation.ts b/ui/pages/confirmations/hooks/useCurrentConfirmation.ts index cf5e8a1383a2..1771f807de25 100644 --- a/ui/pages/confirmations/hooks/useCurrentConfirmation.ts +++ b/ui/pages/confirmations/hooks/useCurrentConfirmation.ts @@ -1,8 +1,5 @@ import { ApprovalType } from '@metamask/controller-utils'; -import { - TransactionMeta, - TransactionType, -} from '@metamask/transaction-controller'; +import { TransactionMeta } from '@metamask/transaction-controller'; import { useMemo } from 'react'; import { useSelector } from 'react-redux'; import { useParams } from 'react-router-dom'; @@ -17,10 +14,9 @@ import { } from '../../../selectors'; import { selectUnapprovedMessage } from '../../../selectors/signatures'; import { - REDESIGN_APPROVAL_TYPES, - REDESIGN_DEV_TRANSACTION_TYPES, - REDESIGN_USER_TRANSACTION_TYPES, -} from '../utils'; + shouldUseRedesignForSignatures, + shouldUseRedesignForTransactions, +} from '../../../../shared/lib/confirmation.utils'; /** * Determine the current confirmation based on the pending approvals and controller state. @@ -47,10 +43,6 @@ const useCurrentConfirmation = () => { getIsRedesignedConfirmationsDeveloperEnabled, ); - const isRedesignedConfirmationsDeveloperSettingEnabled = - process.env.ENABLE_CONFIRMATION_REDESIGN === 'true' || - isRedesignedConfirmationsDeveloperEnabled; - const pendingApproval = useSelector((state) => selectPendingApproval(state as ApprovalsMetaMaskState, confirmationId), ); @@ -64,37 +56,20 @@ const useCurrentConfirmation = () => { selectUnapprovedMessage(state, confirmationId), ); - const isCorrectUserTransactionType = REDESIGN_USER_TRANSACTION_TYPES.includes( - transactionMetadata?.type as TransactionType, - ); - - const isCorrectDeveloperTransactionType = - REDESIGN_DEV_TRANSACTION_TYPES.includes( - transactionMetadata?.type as TransactionType, - ); - - const isCorrectApprovalType = REDESIGN_APPROVAL_TYPES.includes( - pendingApproval?.type as ApprovalType, - ); - - const shouldUseRedesignForSignatures = - (isRedesignedSignaturesUserSettingEnabled && isCorrectApprovalType) || - (isRedesignedConfirmationsDeveloperSettingEnabled && isCorrectApprovalType); + const useRedesignedForSignatures = shouldUseRedesignForSignatures({ + approvalType: pendingApproval?.type as ApprovalType, + isRedesignedSignaturesUserSettingEnabled, + isRedesignedConfirmationsDeveloperEnabled, + }); - const shouldUseRedesignForTransactions = - (isRedesignedTransactionsUserSettingEnabled && - isCorrectUserTransactionType) || - (isRedesignedConfirmationsDeveloperSettingEnabled && - isCorrectDeveloperTransactionType); + const useRedesignedForTransaction = shouldUseRedesignForTransactions({ + transactionMetadataType: transactionMetadata?.type, + isRedesignedTransactionsUserSettingEnabled, + isRedesignedConfirmationsDeveloperEnabled, + }); - // If the developer toggle or the build time environment variable are enabled, - // all the signatures and transactions in development are shown. If the user - // facing feature toggles for signature or transactions are enabled, we show - // only confirmations that shipped (contained in `REDESIGN_APPROVAL_TYPES` and - // `REDESIGN_USER_TRANSACTION_TYPES` or `REDESIGN_DEV_TRANSACTION_TYPES` - // respectively). const shouldUseRedesign = - shouldUseRedesignForSignatures || shouldUseRedesignForTransactions; + useRedesignedForSignatures || useRedesignedForTransaction; return useMemo(() => { if (!shouldUseRedesign) { diff --git a/ui/pages/confirmations/utils/confirm.test.ts b/ui/pages/confirmations/utils/confirm.test.ts index b1f6494ca627..9a8b3d1a0f8a 100644 --- a/ui/pages/confirmations/utils/confirm.test.ts +++ b/ui/pages/confirmations/utils/confirm.test.ts @@ -1,5 +1,3 @@ -import { ApprovalRequest } from '@metamask/approval-controller'; -import { ApprovalType } from '@metamask/controller-utils'; import { TransactionType } from '@metamask/transaction-controller'; import { @@ -11,7 +9,6 @@ import { SignatureRequestType } from '../types/confirm'; import { isOrderSignatureRequest, isPermitSignatureRequest, - isSignatureApprovalRequest, isSignatureTransactionType, parseSanitizeTypedDataMessage, isValidASCIIURL, @@ -22,25 +19,6 @@ const typedDataMsg = '{"domain":{"chainId":97,"name":"Ether Mail","verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC","version":"1"},"message":{"contents":"Hello, Bob!","from":{"name":"Cow","wallets":["0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826","0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF","0x06195827297c7A80a443b6894d3BDB8824b43896"]},"to":[{"name":"Bob","wallets":["0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB","0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57","0xB0B0b0b0b0b0B000000000000000000000000000"]}]},"primaryType":"Mail","types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Mail":[{"name":"from","type":"Person"},{"name":"to","type":"Person[]"},{"name":"contents","type":"string"}],"Person":[{"name":"name","type":"string"},{"name":"wallets","type":"address[]"}]}}'; describe('confirm util', () => { - describe('isSignatureApprovalRequest', () => { - it('returns true for signature approval requests', () => { - const result = isSignatureApprovalRequest({ - type: ApprovalType.PersonalSign, - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } as ApprovalRequest); - expect(result).toStrictEqual(true); - }); - it('returns false for request not of type signature', () => { - const result = isSignatureApprovalRequest({ - type: ApprovalType.Transaction, - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } as ApprovalRequest); - expect(result).toStrictEqual(false); - }); - }); - describe('parseSanitizeTypedDataMessage', () => { it('parses and sanitizes data passed correctly', () => { const result = parseSanitizeTypedDataMessage(typedDataMsg); diff --git a/ui/pages/confirmations/utils/confirm.ts b/ui/pages/confirmations/utils/confirm.ts index a007ca0aa0b2..f464f51e8159 100644 --- a/ui/pages/confirmations/utils/confirm.ts +++ b/ui/pages/confirmations/utils/confirm.ts @@ -1,7 +1,4 @@ -import { ApprovalRequest } from '@metamask/approval-controller'; -import { ApprovalType } from '@metamask/controller-utils'; import { TransactionType } from '@metamask/transaction-controller'; -import { Json } from '@metamask/utils'; import { PRIMARY_TYPES_ORDER, PRIMARY_TYPES_PERMIT, @@ -11,36 +8,6 @@ import { sanitizeMessage } from '../../../helpers/utils/util'; import { Confirmation, SignatureRequestType } from '../types/confirm'; import { TYPED_SIGNATURE_VERSIONS } from '../constants'; -export const REDESIGN_APPROVAL_TYPES = [ - ApprovalType.EthSignTypedData, - ApprovalType.PersonalSign, -]; - -export const REDESIGN_USER_TRANSACTION_TYPES = [ - TransactionType.contractInteraction, - TransactionType.deployContract, - TransactionType.tokenMethodApprove, - TransactionType.tokenMethodIncreaseAllowance, - TransactionType.tokenMethodSetApprovalForAll, - TransactionType.tokenMethodTransfer, - TransactionType.tokenMethodTransferFrom, - TransactionType.tokenMethodSafeTransferFrom, - TransactionType.simpleSend, -]; - -export const REDESIGN_DEV_TRANSACTION_TYPES = [ - ...REDESIGN_USER_TRANSACTION_TYPES, -]; - -const SIGNATURE_APPROVAL_TYPES = [ - ApprovalType.PersonalSign, - ApprovalType.EthSignTypedData, -]; - -export const isSignatureApprovalRequest = ( - request: ApprovalRequest>, -) => SIGNATURE_APPROVAL_TYPES.includes(request.type as ApprovalType); - export const SIGNATURE_TRANSACTION_TYPES = [ TransactionType.personalSign, TransactionType.signTypedData, diff --git a/ui/pages/routes/routes.component.js b/ui/pages/routes/routes.component.js index 3a2bc2989182..ef0ebbfa9ee3 100644 --- a/ui/pages/routes/routes.component.js +++ b/ui/pages/routes/routes.component.js @@ -115,9 +115,9 @@ import NftFullImage from '../../components/app/assets/nfts/nft-details/nft-full- import CrossChainSwap from '../bridge'; import { ToastMaster } from '../../components/app/toast-master/toast-master'; import { - REDESIGN_APPROVAL_TYPES, - REDESIGN_DEV_TRANSACTION_TYPES, -} from '../confirmations/utils'; + isCorrectDeveloperTransactionType, + isCorrectSignatureApprovalType, +} from '../../../shared/lib/confirmation.utils'; import { getConnectingLabel, hideAppHeader, @@ -471,13 +471,12 @@ export default class Routes extends Component { const pendingApproval = pendingApprovals.find( (approval) => approval.id === confirmationId, ); - const isCorrectApprovalType = REDESIGN_APPROVAL_TYPES.includes( + const isCorrectApprovalType = isCorrectSignatureApprovalType( pendingApproval?.type, ); - const isCorrectDeveloperTransactionType = - REDESIGN_DEV_TRANSACTION_TYPES.includes( - transactionsMetadata[confirmationId]?.type, - ); + const isCorrectTransactionType = isCorrectDeveloperTransactionType( + transactionsMetadata[confirmationId]?.type, + ); let isLoadingShown = isLoading && @@ -485,7 +484,7 @@ export default class Routes extends Component { // In the redesigned screens, we hide the general loading spinner and the // loading states are on a component by component basis. !isCorrectApprovalType && - !isCorrectDeveloperTransactionType; + !isCorrectTransactionType; ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) isLoadingShown = @@ -499,7 +498,7 @@ export default class Routes extends Component { // In the redesigned screens, we hide the general loading spinner and the // loading states are on a component by component basis. !isCorrectApprovalType && - !isCorrectDeveloperTransactionType; + !isCorrectTransactionType; ///: END:ONLY_INCLUDE_IF return ( From a1b6ba7cce7b5fbbd9b50aace2e821384a0edcef Mon Sep 17 00:00:00 2001 From: infiniteflower <139582705+infiniteflower@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:18:23 -0500 Subject: [PATCH 2/5] feat: cross chain swaps - tx submit (#27262) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR implements the following: 1. Submit bridge transaction for normal transactions 3. Submit bridge transaction for native gas tokens that don't require approval 4. Submit bridge transaction for ERC20s that require approval Does not fully: 1. Submit bridge transaction for smart transactions - You can submit an STX, but the status screens don't make the most sense right now. - Improved STX support be handled by https://github.com/MetaMask/metamask-extension/pull/28460 and https://github.com/MetaMask/core/pull/4918/ [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27262?quickstart=1) ## **Related issues** - Targeting: #27522 ## **Manual testing steps** 1. Go to Bridge 2. Fill in source/dest token and amounts 3. Get a quote 4. Execute Bridge ## **Screenshots/Recordings** ### **Before** ### **After** https://github.com/user-attachments/assets/b73f917d-e3e4-468b-b0fa-29f41f559488 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- app/_locales/en/messages.json | 4 + .../bridge/bridge-controller.test.ts | 49 +- .../controllers/bridge/bridge-controller.ts | 38 +- app/scripts/controllers/bridge/constants.ts | 7 + app/scripts/controllers/bridge/types.ts | 2 + app/scripts/metamask-controller.js | 5 + shared/constants/bridge.ts | 4 + shared/constants/metametrics.ts | 1 + shared/constants/security-provider.ts | 2 + test/data/bridge/dummy-quotes.ts | 4005 +++++++++++++++++ ui/ducks/bridge/actions.ts | 13 +- ui/ducks/bridge/selectors.ts | 2 +- ui/ducks/bridge/utils.ts | 47 + ui/hooks/useTransactionDisplayData.js | 9 + ui/pages/bridge/bridge.util.ts | 24 + ui/pages/bridge/hooks/useAddToken.ts | 84 + ui/pages/bridge/hooks/useHandleApprovalTx.ts | 94 + ui/pages/bridge/hooks/useHandleBridgeTx.ts | 48 + ui/pages/bridge/hooks/useHandleTx.ts | 79 + .../hooks/useSubmitBridgeTransaction.test.tsx | 485 ++ .../hooks/useSubmitBridgeTransaction.ts | 49 + ui/pages/bridge/index.tsx | 3 + ui/pages/bridge/prepare/bridge-cta-button.tsx | 11 +- ui/pages/bridge/types.ts | 5 +- ui/pages/swaps/hooks/useSwapsFeatureFlags.ts | 14 + ui/pages/swaps/swaps.util.ts | 2 +- ui/store/actions.ts | 7 +- 27 files changed, 5082 insertions(+), 11 deletions(-) create mode 100644 test/data/bridge/dummy-quotes.ts create mode 100644 ui/ducks/bridge/utils.ts create mode 100644 ui/pages/bridge/hooks/useAddToken.ts create mode 100644 ui/pages/bridge/hooks/useHandleApprovalTx.ts create mode 100644 ui/pages/bridge/hooks/useHandleBridgeTx.ts create mode 100644 ui/pages/bridge/hooks/useHandleTx.ts create mode 100644 ui/pages/bridge/hooks/useSubmitBridgeTransaction.test.tsx create mode 100644 ui/pages/bridge/hooks/useSubmitBridgeTransaction.ts create mode 100644 ui/pages/swaps/hooks/useSwapsFeatureFlags.ts diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index a59a48a21afe..bdba7b1214a3 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -847,6 +847,10 @@ "bridge": { "message": "Bridge" }, + "bridgeApproval": { + "message": "Approve $1 for bridge", + "description": "Used in the transaction display list to describe a transaction that is an approve call on a token that is to be bridged. $1 is the symbol of a token that has been approved." + }, "bridgeCalculatingAmount": { "message": "Calculating..." }, diff --git a/app/scripts/controllers/bridge/bridge-controller.test.ts b/app/scripts/controllers/bridge/bridge-controller.test.ts index 07224ae43c2e..8369d910f78b 100644 --- a/app/scripts/controllers/bridge/bridge-controller.test.ts +++ b/app/scripts/controllers/bridge/bridge-controller.test.ts @@ -22,11 +22,27 @@ const messengerMock = { publish: jest.fn(), } as unknown as jest.Mocked; +jest.mock('@ethersproject/contracts', () => { + return { + Contract: jest.fn(() => ({ + allowance: jest.fn(() => '100000000000000000000'), + })), + }; +}); + +jest.mock('@ethersproject/providers', () => { + return { + Web3Provider: jest.fn(), + }; +}); + describe('BridgeController', function () { let bridgeController: BridgeController; beforeAll(function () { - bridgeController = new BridgeController({ messenger: messengerMock }); + bridgeController = new BridgeController({ + messenger: messengerMock, + }); }); beforeEach(() => { @@ -43,6 +59,18 @@ describe('BridgeController', function () { 'extension-support': true, 'src-network-allowlist': [10, 534352], 'dest-network-allowlist': [137, 42161], + 'approval-gas-multiplier': { + '137': 1.1, + '42161': 1.2, + '10': 1.3, + '534352': 1.4, + }, + 'bridge-gas-multiplier': { + '137': 2.1, + '42161': 2.2, + '10': 2.3, + '534352': 2.4, + }, }); nock(BRIDGE_API_BASE_URL) .get('/getTokens?chainId=10') @@ -507,7 +535,10 @@ describe('BridgeController', function () { bridgeController, 'startPollingByNetworkClientId', ); - messengerMock.call.mockReturnValueOnce({ address: '0x123' } as never); + messengerMock.call.mockReturnValue({ + address: '0x123', + provider: jest.fn(), + } as never); bridgeController.updateBridgeQuoteRequestParams({ srcChainId: 1, @@ -536,4 +567,18 @@ describe('BridgeController', function () { }), ); }); + + describe('getBridgeERC20Allowance', () => { + it('should return the atomic allowance of the ERC20 token contract', async () => { + messengerMock.call.mockReturnValue({ + address: '0x123', + provider: jest.fn(), + } as never); + const allowance = await bridgeController.getBridgeERC20Allowance( + '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', + '0xa', + ); + expect(allowance).toBe('100000000000000000000'); + }); + }); }); diff --git a/app/scripts/controllers/bridge/bridge-controller.ts b/app/scripts/controllers/bridge/bridge-controller.ts index 00d28b044457..2518e9caa9bd 100644 --- a/app/scripts/controllers/bridge/bridge-controller.ts +++ b/app/scripts/controllers/bridge/bridge-controller.ts @@ -1,7 +1,11 @@ -import { StateMetadata } from '@metamask/base-controller'; import { add0x, Hex } from '@metamask/utils'; import { StaticIntervalPollingController } from '@metamask/polling-controller'; import { NetworkClientId } from '@metamask/network-controller'; +import { StateMetadata } from '@metamask/base-controller'; +import { Contract } from '@ethersproject/contracts'; +import { abiERC20 } from '@metamask/metamask-eth-abis'; +import { Web3Provider } from '@ethersproject/providers'; +import { BigNumber } from '@ethersproject/bignumber'; import { fetchBridgeFeatureFlags, fetchBridgeQuotes, @@ -25,6 +29,7 @@ import { DEFAULT_BRIDGE_CONTROLLER_STATE, REFRESH_INTERVAL_MS, RequestStatus, + METABRIDGE_CHAIN_TO_ADDRESS_MAP, } from './constants'; import { BridgeControllerState, @@ -60,6 +65,8 @@ export default class BridgeController extends StaticIntervalPollingController< this.setIntervalLength(REFRESH_INTERVAL_MS); + this.#abortController = new AbortController(); + // Register action handlers this.messagingSystem.registerActionHandler( `${BRIDGE_CONTROLLER_NAME}:setBridgeFeatureFlags`, this.setBridgeFeatureFlags.bind(this), @@ -80,6 +87,10 @@ export default class BridgeController extends StaticIntervalPollingController< `${BRIDGE_CONTROLLER_NAME}:resetState`, this.resetState.bind(this), ); + this.messagingSystem.registerActionHandler( + `${BRIDGE_CONTROLLER_NAME}:getBridgeERC20Allowance`, + this.getBridgeERC20Allowance.bind(this), + ); } _executePoll = async ( @@ -277,4 +288,29 @@ export default class BridgeController extends StaticIntervalPollingController< chainId, ); } + + /** + * + * @param contractAddress - The address of the ERC20 token contract + * @param chainId - The hex chain ID of the bridge network + * @returns The atomic allowance of the ERC20 token contract + */ + getBridgeERC20Allowance = async ( + contractAddress: string, + chainId: Hex, + ): Promise => { + const provider = this.#getSelectedNetworkClient()?.provider; + if (!provider) { + throw new Error('No provider found'); + } + + const web3Provider = new Web3Provider(provider); + const contract = new Contract(contractAddress, abiERC20, web3Provider); + const { address: walletAddress } = this.#getSelectedAccount(); + const allowance = await contract.allowance( + walletAddress, + METABRIDGE_CHAIN_TO_ADDRESS_MAP[chainId], + ); + return BigNumber.from(allowance).toString(); + }; } diff --git a/app/scripts/controllers/bridge/constants.ts b/app/scripts/controllers/bridge/constants.ts index aa2d74f0a08e..ec60f8e6a0a4 100644 --- a/app/scripts/controllers/bridge/constants.ts +++ b/app/scripts/controllers/bridge/constants.ts @@ -1,4 +1,7 @@ import { zeroAddress } from 'ethereumjs-util'; +import { Hex } from '@metamask/utils'; +import { METABRIDGE_ETHEREUM_ADDRESS } from '../../../../shared/constants/bridge'; +import { CHAIN_IDS } from '../../../../shared/constants/network'; import { BridgeControllerState, BridgeFeatureFlagsKey } from './types'; export const BRIDGE_CONTROLLER_NAME = 'BridgeController'; @@ -36,3 +39,7 @@ export const DEFAULT_BRIDGE_CONTROLLER_STATE: BridgeControllerState = { quotesLoadingStatus: undefined, quotesRefreshCount: 0, }; + +export const METABRIDGE_CHAIN_TO_ADDRESS_MAP: Record = { + [CHAIN_IDS.MAINNET]: METABRIDGE_ETHEREUM_ADDRESS, +}; diff --git a/app/scripts/controllers/bridge/types.ts b/app/scripts/controllers/bridge/types.ts index 2ab9ef8e7a37..577a9fa99836 100644 --- a/app/scripts/controllers/bridge/types.ts +++ b/app/scripts/controllers/bridge/types.ts @@ -53,6 +53,7 @@ export enum BridgeUserAction { export enum BridgeBackgroundAction { SET_FEATURE_FLAGS = 'setBridgeFeatureFlags', RESET_STATE = 'resetState', + GET_BRIDGE_ERC20_ALLOWANCE = 'getBridgeERC20Allowance', } type BridgeControllerAction = { @@ -64,6 +65,7 @@ type BridgeControllerAction = { type BridgeControllerActions = | BridgeControllerAction | BridgeControllerAction + | BridgeControllerAction | BridgeControllerAction | BridgeControllerAction | BridgeControllerAction; diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index e297a016fd76..676595dfbff3 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -3985,6 +3985,11 @@ export default class MetamaskController extends EventEmitter { this.controllerMessenger, `${BRIDGE_CONTROLLER_NAME}:${BridgeBackgroundAction.RESET_STATE}`, ), + [BridgeBackgroundAction.GET_BRIDGE_ERC20_ALLOWANCE]: + this.controllerMessenger.call.bind( + this.controllerMessenger, + `${BRIDGE_CONTROLLER_NAME}:${BridgeBackgroundAction.GET_BRIDGE_ERC20_ALLOWANCE}`, + ), [BridgeUserAction.SELECT_SRC_NETWORK]: this.controllerMessenger.call.bind( this.controllerMessenger, `${BRIDGE_CONTROLLER_NAME}:${BridgeUserAction.SELECT_SRC_NETWORK}`, diff --git a/shared/constants/bridge.ts b/shared/constants/bridge.ts index e87b0689777f..ed3b21c6a581 100644 --- a/shared/constants/bridge.ts +++ b/shared/constants/bridge.ts @@ -20,3 +20,7 @@ export const BRIDGE_API_BASE_URL = process.env.BRIDGE_USE_DEV_APIS : BRIDGE_PROD_API_BASE_URL; export const BRIDGE_CLIENT_ID = 'extension'; + +export const ETH_USDT_ADDRESS = '0xdac17f958d2ee523a2206206994597c13d831ec7'; +export const METABRIDGE_ETHEREUM_ADDRESS = + '0x0439e60F02a8900a951603950d8D4527f400C3f1'; diff --git a/shared/constants/metametrics.ts b/shared/constants/metametrics.ts index 8688b8cfa8ae..760e3c26a31f 100644 --- a/shared/constants/metametrics.ts +++ b/shared/constants/metametrics.ts @@ -952,6 +952,7 @@ export enum MetaMetricsNetworkEventSource { Dapp = 'dapp', DeprecatedNetworkModal = 'deprecated_network_modal', NewAddNetworkFlow = 'new_add_network_flow', + Bridge = 'bridge', } export enum MetaMetricsSwapsEventSource { diff --git a/shared/constants/security-provider.ts b/shared/constants/security-provider.ts index c7c4a8df3b2c..82f8814da9da 100644 --- a/shared/constants/security-provider.ts +++ b/shared/constants/security-provider.ts @@ -112,6 +112,8 @@ export const SECURITY_PROVIDER_EXCLUDED_TRANSACTION_TYPES = [ TransactionType.swap, TransactionType.swapApproval, TransactionType.swapAndSend, + TransactionType.bridgeApproval, + TransactionType.bridge, ]; export const LOADING_SECURITY_ALERT_RESPONSE: SecurityAlertResponse = { diff --git a/test/data/bridge/dummy-quotes.ts b/test/data/bridge/dummy-quotes.ts new file mode 100644 index 000000000000..3328960a9b73 --- /dev/null +++ b/test/data/bridge/dummy-quotes.ts @@ -0,0 +1,4005 @@ +export const DummyQuotesNoApproval = { + OP_0_005_ETH_TO_ARB: [ + { + quote: { + requestId: 'be448070-7849-4d14-bb35-8dcdaf7a4d69', + srcChainId: 10, + srcTokenAmount: '4956250000000000', + srcAsset: { + address: '0x0000000000000000000000000000000000000000', + chainId: 10, + symbol: 'ETH', + decimals: 18, + name: 'ETH', + coinKey: 'ETH', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + priceUSD: '2641.2', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + }, + destChainId: 42161, + destTokenAmount: '4927504629714929', + destAsset: { + address: '0x0000000000000000000000000000000000000000', + chainId: 42161, + symbol: 'ETH', + decimals: 18, + name: 'ETH', + coinKey: 'ETH', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + priceUSD: '2641', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + }, + feeData: { + metabridge: { + amount: '43750000000000', + asset: { + address: '0x0000000000000000000000000000000000000000', + chainId: 10, + symbol: 'ETH', + decimals: 18, + name: 'ETH', + coinKey: 'ETH', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + priceUSD: '2641.2', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + }, + }, + }, + bridgeId: 'lifi', + bridges: ['across'], + steps: [ + { + action: 'bridge', + srcChainId: 10, + destChainId: 42161, + protocol: { + name: 'across', + displayName: 'Across', + icon: 'https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/bridges/acrossv2.png', + }, + srcAsset: { + address: '0x0000000000000000000000000000000000000000', + chainId: 10, + symbol: 'ETH', + decimals: 18, + name: 'ETH', + coinKey: 'ETH', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + priceUSD: '2641.2', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + }, + destAsset: { + address: '0x0000000000000000000000000000000000000000', + chainId: 42161, + symbol: 'ETH', + decimals: 18, + name: 'ETH', + coinKey: 'ETH', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + priceUSD: '2641', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + }, + srcAmount: '4956250000000000', + destAmount: '4927504629714929', + }, + ], + }, + trade: { + chainId: 10, + to: '0xB90357f2b86dbfD59c3502215d4060f71DF8ca0e', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x11c37937e08000', + data: '0x3ce33bff000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011c37937e0800000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d6c6966694164617074657256320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000e397c4883ec89ed4fc9d258f00c689708b2799c9000000000000000000000000e397c4883ec89ed4fc9d258f00c689708b2799c9000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000119baee0ab04000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000027ca57357c00000000000000000000000000716a8b9dd056055c84b7a2ba0a016099465a5187000000000000000000000000000000000000000000000000000000000000006c5a39b10ad191481350ef776ac5fe6ef47965741f6f7a4734bf784bf3ae3f24520000a4b100149ae8681b4efd66f30743ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd00dfeeddeadbeef8932eb23bad9bddb5cf81426f78279a53c6c3b710000000000000000000000000000000000000000a98f352a08c48ebdbb94ced425b06cf909d74f41e3dfea3c72061a0d88423d867545801fa572404f63d531757a740fd1fd0f12a89217856e4d59f771328fd4bb1c', + gasLimit: 155983, + }, + estimatedProcessingTimeInSeconds: 15, + }, + { + quote: { + requestId: '7e33348d-726c-4f91-b8a0-152828c565ff', + srcChainId: 10, + srcTokenAmount: '4956250000000000', + srcAsset: { + address: '0x0000000000000000000000000000000000000000', + chainId: 10, + symbol: 'ETH', + decimals: 18, + name: 'ETH', + coinKey: 'ETH', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + priceUSD: '2641.2', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + }, + destChainId: 42161, + destTokenAmount: '4955000000000000', + destAsset: { + address: '0x0000000000000000000000000000000000000000', + chainId: 42161, + symbol: 'ETH', + decimals: 18, + name: 'ETH', + coinKey: 'ETH', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + priceUSD: '2641', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + }, + feeData: { + metabridge: { + amount: '43750000000000', + asset: { + address: '0x0000000000000000000000000000000000000000', + chainId: 10, + symbol: 'ETH', + decimals: 18, + name: 'ETH', + coinKey: 'ETH', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + priceUSD: '2641.2', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + }, + }, + }, + bridgeId: 'lifi', + bridges: ['stargate'], + steps: [ + { + action: 'bridge', + srcChainId: 10, + destChainId: 42161, + protocol: { + name: 'stargate', + displayName: 'StargateV2 (Fast mode)', + icon: 'https://raw.githubusercontent.com/lifinance/types/5685c638772f533edad80fcb210b4bb89e30a50f/src/assets/icons/bridges/stargate.png', + }, + srcAsset: { + address: '0x0000000000000000000000000000000000000000', + chainId: 10, + symbol: 'ETH', + decimals: 18, + name: 'ETH', + coinKey: 'ETH', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + priceUSD: '2641.2', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + }, + destAsset: { + address: '0x0000000000000000000000000000000000000000', + chainId: 42161, + symbol: 'ETH', + decimals: 18, + name: 'ETH', + coinKey: 'ETH', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + priceUSD: '2641', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + }, + srcAmount: '4956250000000000', + destAmount: '4955000000000000', + }, + ], + }, + trade: { + chainId: 10, + to: '0xB90357f2b86dbfD59c3502215d4060f71DF8ca0e', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x11e6cbb0321441', + data: '0x3ce33bff000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011e6cbb032144100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d6c6966694164617074657256320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005400000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae0000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000119baee0ab04000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000027ca57357c00000000000000000000000000716a8b9dd056055c84b7a2ba0a016099465a518700000000000000000000000000000000000000000000000000000000000003e414d53077000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002005828fdd30895f9a246394c8876a30c0a6debe54a9aaed574de790d6e9fe2c1f60000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f245200000000000000000000000000000000000000000000000000119baee0ab0400000000000000000000000000000000000000000000000000000000000000a4b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7374617267617465563200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6d6574616d61736b2d6272696467650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000002352785194410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f2452000000000000000000000000000000000000000000000000000000000000759e000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f245200000000000000000000000000000000000000000000000000119baee0ab0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080c2800c127d224651f5dd852ca8a4abd8a3804aff686dcb794b566b7ea694865f1edd9965ed1810678d845410548d5cae2acc3f8ea98c936e7e566923c1229d1c', + gasLimit: 515457, + }, + estimatedProcessingTimeInSeconds: 51, + }, + { + quote: { + requestId: 'f49a25e4-e396-40d8-a2bf-95ef5ec03d9f', + srcChainId: 10, + srcTokenAmount: '4956250000000000', + srcAsset: { + address: '0x0000000000000000000000000000000000000000', + chainId: 10, + symbol: 'ETH', + decimals: 18, + name: 'ETH', + coinKey: 'ETH', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + priceUSD: '2641.2', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + }, + destChainId: 42161, + destTokenAmount: '4852705984263432', + destAsset: { + address: '0x0000000000000000000000000000000000000000', + chainId: 42161, + symbol: 'ETH', + decimals: 18, + name: 'ETH', + coinKey: 'ETH', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + priceUSD: '2641', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + }, + feeData: { + metabridge: { + amount: '43750000000000', + asset: { + address: '0x0000000000000000000000000000000000000000', + chainId: 10, + symbol: 'ETH', + decimals: 18, + name: 'ETH', + coinKey: 'ETH', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + priceUSD: '2641.2', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + }, + }, + }, + bridgeId: 'lifi', + bridges: ['hop'], + steps: [ + { + action: 'bridge', + srcChainId: 10, + destChainId: 42161, + protocol: { + name: 'hop', + displayName: 'Hop', + icon: 'https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/bridges/hop.png', + }, + srcAsset: { + address: '0x0000000000000000000000000000000000000000', + chainId: 10, + symbol: 'ETH', + decimals: 18, + name: 'ETH', + coinKey: 'ETH', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + priceUSD: '2641.2', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + }, + destAsset: { + address: '0x0000000000000000000000000000000000000000', + chainId: 42161, + symbol: 'ETH', + decimals: 18, + name: 'ETH', + coinKey: 'ETH', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + priceUSD: '2641', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png', + }, + srcAmount: '4956250000000000', + destAmount: '4852705984263432', + }, + ], + }, + trade: { + chainId: 10, + to: '0xB90357f2b86dbfD59c3502215d4060f71DF8ca0e', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x11c37937e08000', + data: '0x3ce33bff000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011c37937e0800000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d6c6966694164617074657256320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000006ef81a18e1e432c289dc0d1a670b78e8bbf9aa350000000000000000000000006ef81a18e1e432c289dc0d1a670b78e8bbf9aa35000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000119baee0ab04000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000027ca57357c00000000000000000000000000716a8b9dd056055c84b7a2ba0a016099465a51870000000000000000000000000000000000000000000000000000000000000044161be542b8c35a6e235f7b26c5fe6ef47965741f6f7a4734bf784bf3ae3f24520000a4b1000000000000000000005eb7c7b0c1c6000000000000000000113dac153d909300000000000000000000000000000000000000000000000000000000d7e5c567b37ba289b97e1a2eb3cda9ebd9811a004255d1fe44b1ccb372b6b41c3aea5aa0d70ad19378485c6e31e10df0eb3a7f957c8441d6474853e81acd4a991b', + gasLimit: 338772, + }, + estimatedProcessingTimeInSeconds: 56, + }, + { + quote: { + requestId: '625e7eb4-065c-4661-90d1-d94f6eb4adcc', + srcChainId: 10, + srcAsset: { + chainId: 10, + address: '0x0000000000000000000000000000000000000000', + symbol: 'ETH', + name: 'Ethereum', + decimals: 18, + icon: 'https://assets.polygon.technology/tokenAssets/eth.svg', + logoURI: 'https://assets.polygon.technology/tokenAssets/eth.svg', + chainAgnosticId: null, + }, + srcTokenAmount: '4956250000000000', + destChainId: 42161, + destAsset: { + chainId: 42161, + address: '0x0000000000000000000000000000000000000000', + symbol: 'ETH', + name: 'Ethereum', + decimals: 18, + icon: 'https://assets.polygon.technology/tokenAssets/eth.svg', + logoURI: 'https://assets.polygon.technology/tokenAssets/eth.svg', + chainAgnosticId: null, + }, + destTokenAmount: '4852928026153929', + feeData: { + metabridge: { + amount: '43750000000000', + asset: { + chainId: 10, + address: '0x0000000000000000000000000000000000000000', + symbol: 'ETH', + name: 'Ethereum', + decimals: 18, + icon: 'https://assets.polygon.technology/tokenAssets/eth.svg', + logoURI: 'https://assets.polygon.technology/tokenAssets/eth.svg', + chainAgnosticId: null, + }, + }, + }, + bridgeId: 'socket', + bridges: ['hop'], + steps: [ + { + action: 'bridge', + srcChainId: 10, + destChainId: 42161, + protocol: { + name: 'hop', + displayName: 'Hop', + icon: 'https://bridgelogos.s3.ap-south-1.amazonaws.com/hop.png', + }, + srcAsset: { + chainId: 10, + address: '0x0000000000000000000000000000000000000000', + symbol: 'ETH', + name: 'Ethereum', + decimals: 18, + icon: 'https://assets.polygon.technology/tokenAssets/eth.svg', + logoURI: 'https://assets.polygon.technology/tokenAssets/eth.svg', + chainAgnosticId: null, + }, + destAsset: { + chainId: 42161, + address: '0x0000000000000000000000000000000000000000', + symbol: 'ETH', + name: 'Ethereum', + decimals: 18, + icon: 'https://assets.polygon.technology/tokenAssets/eth.svg', + logoURI: 'https://assets.polygon.technology/tokenAssets/eth.svg', + chainAgnosticId: null, + }, + srcAmount: '4956250000000000', + destAmount: '4852928026153929', + }, + ], + }, + trade: { + chainId: 10, + to: '0xB90357f2b86dbfD59c3502215d4060f71DF8ca0e', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x11c37937e08000', + data: '0x3ce33bff000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011c37937e0800000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000f736f636b6574416461707465725632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000003a23f943181408eac424116af7b7790c94cb97a5000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000119baee0ab04000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000027ca57357c00000000000000000000000000716a8b9dd056055c84b7a2ba0a016099465a5187000000000000000000000000000000000000000000000000000000000000014800000011c8a6285e000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f245200000000000000000000000086ca30bef97fb651b8d866d45503684b90cb331200000000000000000000000000000000000000000000000000119baee0ab0400000000000000000000000000000000000000000000000000000000000000a4b1000000000000000000000000000000000000000000000000000060dcd8031258000000000000000000000000000000000000000000000000001185250b108f80000000000000000000000000000000000000000000000000000001924963f1dd00000000000000000000000000000000000000000000000000112728d1e75e79000000000000000000000000000000000000000000000000000001924963f1dd00000000000000000000000000000000000000000000000000000000000000c40000000000000000000000000000000000000000000000007d6791da46aae617c18c7b5987f2f25e8bc35083c3c973e71bfa0f7bd70088b0558f63bef3e55bc881d14bd276f41690d864e3d0380bfd4ac557b8b9dde896c51c', + gasLimit: 414453, + }, + estimatedProcessingTimeInSeconds: 60, + }, + ], +}; + +export const DummyQuotesWithApproval = { + ETH_11_USDC_TO_ARB: [ + { + quote: { + requestId: '0cd5caf6-9844-465b-89ad-9c89b639f432', + srcChainId: 1, + srcTokenAmount: '10903750', + srcAsset: { + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + chainId: 1, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0002000400080016', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destChainId: 42161, + destTokenAmount: '10876521', + destAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0002000400080016', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + feeData: { + metabridge: { + amount: '96250', + asset: { + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + chainId: 1, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0002000400080016', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + }, + }, + bridgeId: 'lifi', + bridges: ['across'], + steps: [ + { + action: 'bridge', + srcChainId: 1, + destChainId: 42161, + protocol: { + name: 'across', + displayName: 'Across', + icon: 'https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/bridges/acrossv2.png', + }, + srcAsset: { + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + chainId: 1, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0002000400080016', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0002000400080016', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + srcAmount: '10903750', + destAmount: '10876521', + }, + ], + }, + approval: { + chainId: 1, + to: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x095ea7b30000000000000000000000000439e60f02a8900a951603950d8d4527f400c3f10000000000000000000000000000000000000000000000000000000000a7d8c0', + gasLimit: 56349, + }, + trade: { + chainId: 1, + to: '0x0439e60F02a8900a951603950d8D4527f400C3f1', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d6c6966694164617074657256320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000e397c4883ec89ed4fc9d258f00c689708b2799c9000000000000000000000000e397c4883ec89ed4fc9d258f00c689708b2799c9000000000000000000000000000000000000000000000000000000000000a4b1000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000177fa000000000000000000000000e6b738da243e8fa2a0ed5915645789add5de515200000000000000000000000000000000000000000000000000000000000000902340ab8fc3119af1d016a0eec5fe6ef47965741f6f7a4734bf784bf3ae3f2452a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000a660c60000a4b10008df3abdeb853d66fefedfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd00dfeeddeadbeef8932eb23bad9bddb5cf81426f78279a53c6c3b7100000000000000000000000000000000740cfc1bc02079862368cb4eea1332bd9f2dfa925fc757fd51e40919859b87ca031a2a12d67e4ca4ba67d52b59114b3e18c1e8c839ae015112af82e92251db701b', + gasLimit: 209923, + }, + estimatedProcessingTimeInSeconds: 15, + }, + { + quote: { + requestId: 'f197aa3f-a1ed-46fe-8d5f-80866a860a9b', + srcChainId: 1, + srcTokenAmount: '10903750', + srcAsset: { + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + chainId: 1, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0002000400080016', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destChainId: 42161, + destTokenAmount: '10803750', + destAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0002000400080016', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + feeData: { + metabridge: { + amount: '96250', + asset: { + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + chainId: 1, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0002000400080016', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + }, + }, + bridgeId: 'lifi', + bridges: ['celercircle'], + steps: [ + { + action: 'bridge', + srcChainId: 1, + destChainId: 42161, + protocol: { + name: 'celercircle', + displayName: 'Circle CCTP', + icon: 'https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/bridges/circle.png', + }, + srcAsset: { + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + chainId: 1, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0002000400080016', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0002000400080016', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + srcAmount: '10903750', + destAmount: '10803750', + }, + ], + }, + approval: { + chainId: 1, + to: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x095ea7b30000000000000000000000000439e60f02a8900a951603950d8d4527f400c3f10000000000000000000000000000000000000000000000000000000000a7d8c0', + gasLimit: 56349, + }, + trade: { + chainId: 1, + to: '0x0439e60F02a8900a951603950d8D4527f400C3f1', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d6c6966694164617074657256320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003400000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae0000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae000000000000000000000000000000000000000000000000000000000000a4b1000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000177fa000000000000000000000000e6b738da243e8fa2a0ed5915645789add5de515200000000000000000000000000000000000000000000000000000000000001e4bab657d800000000000000000000000000000000000000000000000000000000000000202210951480e39a2501daae3e15f254f5431a326e0e6ceb775feb685843012458000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f24520000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000a4b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b63656c6572636972636c65000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6d6574616d61736b2d627269646765000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c5f6d5c0d29059e2e6f6c5f03c44aa894aa0b2d888b46f8844d855a89c83b372148e183ab8a90043501865ea48326990c0783e195c85330e0f2f12db7953df991b', + gasLimit: 430753, + }, + estimatedProcessingTimeInSeconds: 989.412, + }, + { + quote: { + requestId: '4a954e96-a11d-4879-a1c0-54b24ae14ebb', + srcChainId: 1, + srcTokenAmount: '10903750', + srcAsset: { + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + chainId: 1, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0002000400080016', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destChainId: 42161, + destTokenAmount: '10903640', + destAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0002000400080016', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + feeData: { + metabridge: { + amount: '96250', + asset: { + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + chainId: 1, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0002000400080016', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + }, + }, + bridgeId: 'lifi', + bridges: ['stargate'], + steps: [ + { + action: 'bridge', + srcChainId: 1, + destChainId: 42161, + protocol: { + name: 'stargate', + displayName: 'StargateV2 (Fast mode)', + icon: 'https://raw.githubusercontent.com/lifinance/types/5685c638772f533edad80fcb210b4bb89e30a50f/src/assets/icons/bridges/stargate.png', + }, + srcAsset: { + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + chainId: 1, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0002000400080016', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0002000400080016', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + srcAmount: '10903750', + destAmount: '10903640', + }, + ], + }, + approval: { + chainId: 1, + to: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x095ea7b30000000000000000000000000439e60f02a8900a951603950d8d4527f400c3f10000000000000000000000000000000000000000000000000000000000a7d8c0', + gasLimit: 56349, + }, + trade: { + chainId: 1, + to: '0x0439e60F02a8900a951603950d8D4527f400C3f1', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x1be3c54359bf', + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d6c6966694164617074657256320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005400000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae0000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae000000000000000000000000000000000000000000000000000000000000a4b1000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000177fa000000000000000000000000e6b738da243e8fa2a0ed5915645789add5de515200000000000000000000000000000000000000000000000000000000000003e414d53077000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002002df432cfa7217ed9dc0aae2d324260c237970c8f9c97439d3faf2a000347d96e000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f24520000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000a4b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7374617267617465563200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6d6574616d61736b2d6272696467650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000001be3c54359bf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f2452000000000000000000000000000000000000000000000000000000000000759e000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f24520000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f4e69f41f7ff5673a2df84fb3f246a59101ad7cc25219d596995a85d89c4a1684e9d9e9b2fb8775295686d52b5189794fc16a1dea348e5487eddeeaaebaec7441b', + gasLimit: 634343, + }, + estimatedProcessingTimeInSeconds: 197, + }, + { + quote: { + requestId: '32ad49ef-d710-4fb9-904a-a5d9cc95bd78', + srcChainId: 1, + srcAsset: { + chainId: 1, + address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + symbol: 'USDC', + name: 'USDCoin', + decimals: 6, + icon: 'https://media.socket.tech/tokens/all/USDC', + logoURI: 'https://media.socket.tech/tokens/all/USDC', + chainAgnosticId: 'USDC', + }, + srcTokenAmount: '10903750', + destChainId: 42161, + destAsset: { + chainId: 42161, + address: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + symbol: 'USDC', + name: 'USD Coin', + decimals: 6, + icon: 'https://media.socket.tech/tokens/all/USDC', + logoURI: 'https://media.socket.tech/tokens/all/USDC', + chainAgnosticId: null, + }, + destTokenAmount: '10503750', + feeData: { + metabridge: { + amount: '96250', + asset: { + chainId: 1, + address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + symbol: 'USDC', + name: 'USDCoin', + decimals: 6, + icon: 'https://media.socket.tech/tokens/all/USDC', + logoURI: 'https://media.socket.tech/tokens/all/USDC', + chainAgnosticId: 'USDC', + }, + }, + }, + bridgeId: 'socket', + bridges: ['celercircle'], + steps: [ + { + action: 'bridge', + srcChainId: 1, + destChainId: 42161, + protocol: { + name: 'cctp', + displayName: 'Circle CCTP', + icon: 'https://movricons.s3.ap-south-1.amazonaws.com/CCTP.svg', + }, + srcAsset: { + chainId: 1, + address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + symbol: 'USDC', + name: 'USDCoin', + decimals: 6, + icon: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + logoURI: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + chainAgnosticId: 'USDC', + }, + destAsset: { + chainId: 42161, + address: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + symbol: 'USDC', + name: 'USD Coin', + decimals: 6, + icon: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + logoURI: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + chainAgnosticId: null, + }, + srcAmount: '10903750', + destAmount: '10503750', + }, + ], + }, + approval: { + chainId: 1, + to: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x095ea7b30000000000000000000000000439e60f02a8900a951603950d8d4527f400c3f10000000000000000000000000000000000000000000000000000000000a7d8c0', + gasLimit: 56349, + }, + trade: { + chainId: 1, + to: '0x0439e60F02a8900a951603950d8D4527f400C3f1', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000f736f636b6574416461707465725632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000003a23f943181408eac424116af7b7790c94cb97a5000000000000000000000000000000000000000000000000000000000000a4b1000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000177fa000000000000000000000000e6b738da243e8fa2a0ed5915645789add5de515200000000000000000000000000000000000000000000000000000000000000e800000197b7dfe9d00000000000000000000000000000000000000000000000000000000000a660c600000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f2452000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000000000a4b100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000061a800000000000000000000000000000000000000000000000002f0cd4583d78e68889d534cc878714e5c66fd0a2867f348f8e969d35f7fddfde3d108c064ffb227225c3e4faaf59aa5df6a967534e63143227b9a9a00c4dd6671c', + gasLimit: 285725, + }, + estimatedProcessingTimeInSeconds: 1020, + }, + ], + ARB_11_USDC_TO_ETH: [ + { + quote: { + requestId: 'edbef62a-d3e6-4b33-aad5-9cdb81f85f53', + srcChainId: 42161, + srcAsset: { + chainId: 42161, + address: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + symbol: 'USDC', + name: 'USD Coin', + decimals: 6, + icon: 'https://media.socket.tech/tokens/all/USDC', + logoURI: 'https://media.socket.tech/tokens/all/USDC', + chainAgnosticId: null, + }, + srcTokenAmount: '10903750', + destChainId: 1, + destAsset: { + chainId: 1, + address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + symbol: 'USDC', + name: 'USDCoin', + decimals: 6, + icon: 'https://media.socket.tech/tokens/all/USDC', + logoURI: 'https://media.socket.tech/tokens/all/USDC', + chainAgnosticId: 'USDC', + }, + destTokenAmount: '7821920', + feeData: { + metabridge: { + amount: '96250', + asset: { + chainId: 42161, + address: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + symbol: 'USDC', + name: 'USD Coin', + decimals: 6, + icon: 'https://media.socket.tech/tokens/all/USDC', + logoURI: 'https://media.socket.tech/tokens/all/USDC', + chainAgnosticId: null, + }, + }, + }, + bridgeId: 'socket', + bridges: ['celercircle'], + steps: [ + { + action: 'bridge', + srcChainId: 42161, + destChainId: 1, + protocol: { + name: 'cctp', + displayName: 'Circle CCTP', + icon: 'https://movricons.s3.ap-south-1.amazonaws.com/CCTP.svg', + }, + srcAsset: { + chainId: 42161, + address: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + symbol: 'USDC', + name: 'USD Coin', + decimals: 6, + icon: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + logoURI: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + chainAgnosticId: null, + }, + destAsset: { + chainId: 1, + address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + symbol: 'USDC', + name: 'USDCoin', + decimals: 6, + icon: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + logoURI: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + chainAgnosticId: 'USDC', + }, + srcAmount: '10903750', + destAmount: '7821920', + }, + ], + }, + approval: { + chainId: 42161, + to: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x095ea7b300000000000000000000000023981fc34e69eedfe2bd9a0a9fcb0719fe09dbfc0000000000000000000000000000000000000000000000000000000000a7d8c0', + gasLimit: 116676, + }, + trade: { + chainId: 42161, + to: '0x23981fC34e69eeDFE2BD9a0a9fCb0719Fe09DbFC', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000f736f636b6574416461707465725632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000000000000000000000000000000000000000000001000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000177fa00000000000000000000000056ca675c3633cc16bd6849e2b431d4e8de5e23bf00000000000000000000000000000000000000000000000000000000000000e80000018cb7dfe9d00000000000000000000000000000000000000000000000000000000000a660c600000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f2452000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002f06660000000000000000000000000000000000000000000000000459142ce9a5e109850e867866af8a8e49ef715600981974e0b7f4e48c2e17044dd8921fac00ee87aae63468a52727e978cdf9debbe4cef61ae994d103092e881c', + gasLimit: 409790, + }, + estimatedProcessingTimeInSeconds: 1140, + }, + ], + ARB_11_USDC_TO_OP: [ + { + quote: { + requestId: 'dc63e7e6-dc9b-4aa8-80bb-714192ecd801', + srcChainId: 42161, + srcTokenAmount: '10903750', + srcAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destChainId: 10, + destTokenAmount: '10897534', + destAsset: { + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + chainId: 10, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + feeData: { + metabridge: { + amount: '96250', + asset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + }, + }, + bridgeId: 'lifi', + bridges: ['across'], + steps: [ + { + action: 'bridge', + srcChainId: 42161, + destChainId: 10, + protocol: { + name: 'across', + displayName: 'Across', + icon: 'https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/bridges/acrossv2.png', + }, + srcAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destAsset: { + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + chainId: 10, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + srcAmount: '10903750', + destAmount: '10897534', + }, + ], + }, + approval: { + chainId: 42161, + to: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x095ea7b300000000000000000000000023981fc34e69eedfe2bd9a0a9fcb0719fe09dbfc0000000000000000000000000000000000000000000000000000000000a7d8c0', + gasLimit: 280491, + }, + trade: { + chainId: 42161, + to: '0x23981fC34e69eeDFE2BD9a0a9fCb0719Fe09DbFC', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d6c6966694164617074657256320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000e397c4883ec89ed4fc9d258f00c689708b2799c9000000000000000000000000e397c4883ec89ed4fc9d258f00c689708b2799c9000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000177fa00000000000000000000000056ca675c3633cc16bd6849e2b431d4e8de5e23bf00000000000000000000000000000000000000000000000000000000000000902340ab8fc7e68ebe53823219c5fe6ef47965741f6f7a4734bf784bf3ae3f2452af88d065e77c8cc2239327c5edb3a432268e583100000000000000000000000000a660c60000000a0002067997b930636705a29bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd00dfeeddeadbeef8932eb23bad9bddb5cf81426f78279a53c6c3b7100000000000000000000000000000000ec7648fdf42336c0860c532fb076be8938251a3349d81d611f21e620d8e1ab9f5719d1f40aac527243e6883beb9d22af9a584b5fb419af9d0970804b97976cbb1c', + gasLimit: 734160, + }, + estimatedProcessingTimeInSeconds: 51, + }, + { + quote: { + requestId: 'dd718a05-ee10-4ec4-99f2-9bc3676640a1', + srcChainId: 42161, + srcTokenAmount: '10903750', + srcAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destChainId: 10, + destTokenAmount: '10903640', + destAsset: { + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + chainId: 10, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + feeData: { + metabridge: { + amount: '96250', + asset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + }, + }, + bridgeId: 'lifi', + bridges: ['stargate'], + steps: [ + { + action: 'bridge', + srcChainId: 42161, + destChainId: 10, + protocol: { + name: 'stargate', + displayName: 'StargateV2 (Fast mode)', + icon: 'https://raw.githubusercontent.com/lifinance/types/5685c638772f533edad80fcb210b4bb89e30a50f/src/assets/icons/bridges/stargate.png', + }, + srcAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destAsset: { + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + chainId: 10, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + srcAmount: '10903750', + destAmount: '10903640', + }, + ], + }, + approval: { + chainId: 42161, + to: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x095ea7b300000000000000000000000023981fc34e69eedfe2bd9a0a9fcb0719fe09dbfc0000000000000000000000000000000000000000000000000000000000a7d8c0', + gasLimit: 280491, + }, + trade: { + chainId: 42161, + to: '0x23981fC34e69eeDFE2BD9a0a9fCb0719Fe09DbFC', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x132018b59ef1', + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d6c6966694164617074657256320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005400000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae0000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000177fa00000000000000000000000056ca675c3633cc16bd6849e2b431d4e8de5e23bf00000000000000000000000000000000000000000000000000000000000003e414d5307700000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200c564a18849d43f86f9dde5b38ad12801f40e4f909559b6195db0903f7398ef75000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f24520000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7374617267617465563200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6d6574616d61736b2d6272696467650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000132018b59ef10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f2452000000000000000000000000000000000000000000000000000000000000759f000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f24520000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d28b64c753bb8cd4ac8863f4da513edc5d10a619ea4af9623a5f8fdb86f4296a4735ddf5981acb464fc0f35741dd26fb730eb9b5323586499631edf7870587ed1b', + gasLimit: 1232971, + }, + estimatedProcessingTimeInSeconds: 33, + }, + { + quote: { + requestId: 'f07aefdc-2be7-4c41-a0ab-87ac2ec16e3a', + srcChainId: 42161, + srcTokenAmount: '10903750', + srcAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destChainId: 10, + destTokenAmount: '10803750', + destAsset: { + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + chainId: 10, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + feeData: { + metabridge: { + amount: '96250', + asset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + }, + }, + bridgeId: 'lifi', + bridges: ['celercircle'], + steps: [ + { + action: 'bridge', + srcChainId: 42161, + destChainId: 10, + protocol: { + name: 'celercircle', + displayName: 'Circle CCTP', + icon: 'https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/bridges/circle.png', + }, + srcAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destAsset: { + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + chainId: 10, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + srcAmount: '10903750', + destAmount: '10803750', + }, + ], + }, + approval: { + chainId: 42161, + to: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x095ea7b300000000000000000000000023981fc34e69eedfe2bd9a0a9fcb0719fe09dbfc0000000000000000000000000000000000000000000000000000000000a7d8c0', + gasLimit: 280491, + }, + trade: { + chainId: 42161, + to: '0x23981fC34e69eeDFE2BD9a0a9fCb0719Fe09DbFC', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d6c6966694164617074657256320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003400000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae0000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000177fa00000000000000000000000056ca675c3633cc16bd6849e2b431d4e8de5e23bf00000000000000000000000000000000000000000000000000000000000001e4bab657d80000000000000000000000000000000000000000000000000000000000000020cc4b6b89255288b4450ce670297679230238eca5fc5572f0b3fdca8fcd60081f000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f24520000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b63656c6572636972636c65000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6d6574616d61736b2d627269646765000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000454801e91c4c31ee115b5b1dadfa6abefc87bb88079879d7a68d6ac78ac9eb917678a2589c527e4819b0d2fd2bd3bf071d761f64f85ff8d77b90cca67ccbb5f01b', + gasLimit: 967319, + }, + estimatedProcessingTimeInSeconds: 1073, + }, + { + quote: { + requestId: 'ef05128f-c693-4d4a-adec-2b103f931a43', + srcChainId: 42161, + srcAsset: { + chainId: 42161, + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + symbol: 'USDC', + name: 'USD Coin', + decimals: 6, + icon: 'https://media.socket.tech/tokens/all/USDC', + logoURI: 'https://media.socket.tech/tokens/all/USDC', + chainAgnosticId: null, + }, + srcTokenAmount: '10903750', + destChainId: 10, + destAsset: { + chainId: 10, + address: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + symbol: 'USDC', + name: 'USD Coin', + decimals: 6, + icon: 'https://media.socket.tech/tokens/all/USDC', + logoURI: 'https://media.socket.tech/tokens/all/USDC', + chainAgnosticId: null, + }, + destTokenAmount: '10703750', + feeData: { + metabridge: { + amount: '96250', + asset: { + chainId: 42161, + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + symbol: 'USDC', + name: 'USD Coin', + decimals: 6, + icon: 'https://media.socket.tech/tokens/all/USDC', + logoURI: 'https://media.socket.tech/tokens/all/USDC', + chainAgnosticId: null, + }, + }, + }, + bridgeId: 'socket', + bridges: ['celercircle'], + steps: [ + { + action: 'bridge', + srcChainId: 42161, + destChainId: 10, + protocol: { + name: 'cctp', + displayName: 'Circle CCTP', + icon: 'https://movricons.s3.ap-south-1.amazonaws.com/CCTP.svg', + }, + srcAsset: { + chainId: 42161, + address: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + symbol: 'USDC', + name: 'USD Coin', + decimals: 6, + icon: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + logoURI: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + chainAgnosticId: null, + }, + destAsset: { + chainId: 10, + address: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + symbol: 'USDC', + name: 'USD Coin', + decimals: 6, + icon: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + logoURI: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + chainAgnosticId: null, + }, + srcAmount: '10903750', + destAmount: '10703750', + }, + ], + }, + approval: { + chainId: 42161, + to: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x095ea7b300000000000000000000000023981fc34e69eedfe2bd9a0a9fcb0719fe09dbfc0000000000000000000000000000000000000000000000000000000000a7d8c0', + gasLimit: 280491, + }, + trade: { + chainId: 42161, + to: '0x23981fC34e69eeDFE2BD9a0a9fCb0719Fe09DbFC', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000f736f636b6574416461707465725632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000003a23f943181408eac424116af7b7790c94cb97a5000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000177fa00000000000000000000000056ca675c3633cc16bd6849e2b431d4e8de5e23bf00000000000000000000000000000000000000000000000000000000000000e80000018cb7dfe9d00000000000000000000000000000000000000000000000000000000000a660c600000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f2452000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000030d40000000000000000000000000000000000000000000000000a798e0436c3787ba6e14fd44badd42b591886ba135ebdb6a441494c203e848c61c89a6a55b51f66c46023f5afda568446168e121a4acdfa1c60d7b8c31f0507c1c', + gasLimit: 783830, + }, + estimatedProcessingTimeInSeconds: 1080, + }, + { + quote: { + requestId: '4a15ec74e270a7ffc07aaad0bd59853e', + srcChainId: 42161, + srcTokenAmount: '10903750', + srcAsset: { + _id: '66d776fb76523303f628495c', + id: '42161_0xaf88d065e77c8cc2239327c5edb3a432268e5831', + symbol: 'USDC', + address: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + chainId: 42161, + chain: { + _id: '66d776eb0befbcf39c0a01d1', + id: '42161', + chainId: '42161', + networkIdentifier: 'arbitrum', + chainName: 'Chain 42161', + axelarChainName: 'Arbitrum', + type: 'evm', + networkName: 'Arbitrum', + nativeCurrency: { + name: 'Arbitrum', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/arbitrum.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/arbitrum.webp', + blockExplorerUrls: ['https://arbiscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'arbitrum', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '3', + tokenMessenger: '0x19330d10D9Cc8751218eaf51E8885D058642E08A', + messageTransmitter: + '0xC30362313FBBA5cf9163F0bb16a0e01f01A896ca', + }, + chainflip: { + vault: '0x79001a5e762f3befc8e5871b42f6734e00498920', + }, + }, + rpcList: ['https://arb1.arbitrum.io/rpc'], + internalRpc: [ + 'https://arb-mainnet.g.alchemy.com/v2/3IBUO-R6MAFGVxOYRHTV-Gt4Pce5jmsz', + 'https://special-wispy-theorem.arbitrum-mainnet.quiknode.pro/befd7d6b704d6477ef747f7ed39299d252994e18', + 'https://arbitrum-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://arb-mainnet.g.alchemy.com/v2/2YR6kg9ueaoGnMxBsvLNXqJyCrmAKC11', + 'https://arb-mainnet.g.alchemy.com/v2/3q9qfCdKJcOA2WbdqVic8jtwnQTZGwlm', + 'https://arbitrum-mainnet.core.chainstack.com/10fd48bf1e4a75d901b11b2ff2c76ada', + ], + chainNativeContracts: { + wrappedNativeToken: '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.733Z', + updatedAt: '2024-09-13T09:57:11.584Z', + __v: 1, + }, + name: 'USDC', + decimals: 6, + usdPrice: 1.0009320510897841, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + volatility: 0, + axelarNetworkSymbol: 'USDC', + subGraphOnly: false, + subGraphIds: [ + 'uusdc', + 'cctp-uusdc-arbitrum-to-noble', + 'btc-usdc-arb', + ], + enabled: true, + createdAt: '2024-09-03T20:52:11.579Z', + updatedAt: '2024-10-08T21:23:55.197Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + }, + destChainId: 10, + destTokenAmount: '10900626', + destAsset: { + _id: '66d776fd76523303f628520c', + id: '10_0x0b2c639c533813f4aa9d7837caf62653d097ff85', + symbol: 'USDC', + address: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + chainId: 10, + chain: { + _id: '66d776eb0befbcf39c0a01d5', + id: '10', + chainId: '10', + networkIdentifier: 'optimism', + chainName: 'Chain 10', + axelarChainName: 'optimism', + type: 'evm', + networkName: 'Optimism', + nativeCurrency: { + name: 'Optimism', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/optimism.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/optimism.webp', + blockExplorerUrls: ['https://optimistic.etherscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'optimism', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '2', + tokenMessenger: '0x2B4069517957735bE00ceE0fadAE88a26365528f', + messageTransmitter: + '0x4d41f22c5a0e5c74090899e5a8fb597a8842b3e8', + }, + }, + rpcList: ['https://mainnet.optimism.io'], + internalRpc: [ + 'https://opt-mainnet.g.alchemy.com/v2/YLCHNNGouPGR8L-KViSmQ-4dCKaE6o6H', + 'https://cool-green-tree.optimism.quiknode.pro/c8f7de54a6b1d0e6a15924c5bf3aae2d6c24f0c0', + 'https://optimism-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://opt-mainnet.g.alchemy.com/v2/wDgIhJ3Yz4PvLRkQlA1k0y67dZRb146a', + 'https://opt-mainnet.g.alchemy.com/v2/E8BiF2_ABVQ5fy394vfMaM1JGkpPkIeY', + 'https://nd-739-933-380.p2pify.com/2c8029def5e92e4da7bec7f7c1c153a4', + ], + chainNativeContracts: { + wrappedNativeToken: '0x4200000000000000000000000000000000000006', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.745Z', + updatedAt: '2024-09-13T09:51:30.869Z', + __v: 1, + }, + name: 'USDC', + decimals: 6, + usdPrice: 1.0009026800874075, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + volatility: 0, + axelarNetworkSymbol: 'USDC', + subGraphOnly: false, + subGraphIds: ['uusdc', 'cctp-uusdc-optimism-to-noble'], + enabled: true, + createdAt: '2024-09-03T20:52:13.858Z', + updatedAt: '2024-10-08T21:23:55.474Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + }, + feeData: { + metabridge: { + amount: '96250', + asset: { + _id: '66d776fb76523303f628495c', + id: '42161_0xaf88d065e77c8cc2239327c5edb3a432268e5831', + symbol: 'USDC', + address: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + chainId: 42161, + chain: { + _id: '66d776eb0befbcf39c0a01d1', + id: '42161', + chainId: '42161', + networkIdentifier: 'arbitrum', + chainName: 'Chain 42161', + axelarChainName: 'Arbitrum', + type: 'evm', + networkName: 'Arbitrum', + nativeCurrency: { + name: 'Arbitrum', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/arbitrum.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/arbitrum.webp', + blockExplorerUrls: ['https://arbiscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'arbitrum', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '3', + tokenMessenger: + '0x19330d10D9Cc8751218eaf51E8885D058642E08A', + messageTransmitter: + '0xC30362313FBBA5cf9163F0bb16a0e01f01A896ca', + }, + chainflip: { + vault: '0x79001a5e762f3befc8e5871b42f6734e00498920', + }, + }, + rpcList: ['https://arb1.arbitrum.io/rpc'], + internalRpc: [ + 'https://arb-mainnet.g.alchemy.com/v2/3IBUO-R6MAFGVxOYRHTV-Gt4Pce5jmsz', + 'https://special-wispy-theorem.arbitrum-mainnet.quiknode.pro/befd7d6b704d6477ef747f7ed39299d252994e18', + 'https://arbitrum-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://arb-mainnet.g.alchemy.com/v2/2YR6kg9ueaoGnMxBsvLNXqJyCrmAKC11', + 'https://arb-mainnet.g.alchemy.com/v2/3q9qfCdKJcOA2WbdqVic8jtwnQTZGwlm', + 'https://arbitrum-mainnet.core.chainstack.com/10fd48bf1e4a75d901b11b2ff2c76ada', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.733Z', + updatedAt: '2024-09-13T09:57:11.584Z', + __v: 1, + }, + name: 'USDC', + decimals: 6, + usdPrice: 1.0009320510897841, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + volatility: 0, + axelarNetworkSymbol: 'USDC', + subGraphOnly: false, + subGraphIds: [ + 'uusdc', + 'cctp-uusdc-arbitrum-to-noble', + 'btc-usdc-arb', + ], + enabled: true, + createdAt: '2024-09-03T20:52:11.579Z', + updatedAt: '2024-10-08T21:23:55.197Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + }, + }, + }, + bridgeId: 'squid', + bridges: ['axelar'], + steps: [ + { + action: 'swap', + srcChainId: 42161, + destChainId: 42161, + protocol: { + name: 'Pancakeswap V3', + displayName: 'Pancakeswap V3', + }, + srcAsset: { + _id: '66d776fb76523303f628495c', + id: '42161_0xaf88d065e77c8cc2239327c5edb3a432268e5831', + symbol: 'USDC', + address: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + chainId: 42161, + chain: { + _id: '66d776eb0befbcf39c0a01d1', + id: '42161', + chainId: '42161', + networkIdentifier: 'arbitrum', + chainName: 'Chain 42161', + axelarChainName: 'Arbitrum', + type: 'evm', + networkName: 'Arbitrum', + nativeCurrency: { + name: 'Arbitrum', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/arbitrum.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/arbitrum.webp', + blockExplorerUrls: ['https://arbiscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'arbitrum', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '3', + tokenMessenger: + '0x19330d10D9Cc8751218eaf51E8885D058642E08A', + messageTransmitter: + '0xC30362313FBBA5cf9163F0bb16a0e01f01A896ca', + }, + chainflip: { + vault: '0x79001a5e762f3befc8e5871b42f6734e00498920', + }, + }, + rpcList: ['https://arb1.arbitrum.io/rpc'], + internalRpc: [ + 'https://arb-mainnet.g.alchemy.com/v2/3IBUO-R6MAFGVxOYRHTV-Gt4Pce5jmsz', + 'https://special-wispy-theorem.arbitrum-mainnet.quiknode.pro/befd7d6b704d6477ef747f7ed39299d252994e18', + 'https://arbitrum-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://arb-mainnet.g.alchemy.com/v2/2YR6kg9ueaoGnMxBsvLNXqJyCrmAKC11', + 'https://arb-mainnet.g.alchemy.com/v2/3q9qfCdKJcOA2WbdqVic8jtwnQTZGwlm', + 'https://arbitrum-mainnet.core.chainstack.com/10fd48bf1e4a75d901b11b2ff2c76ada', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.733Z', + updatedAt: '2024-09-13T09:57:11.584Z', + __v: 1, + }, + name: 'USDC', + decimals: 6, + usdPrice: 1.0009320510897841, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'USDC', + subGraphOnly: false, + subGraphIds: [ + 'uusdc', + 'cctp-uusdc-arbitrum-to-noble', + 'btc-usdc-arb', + ], + enabled: true, + createdAt: '2024-09-03T20:52:11.579Z', + updatedAt: '2024-10-08T21:23:55.197Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + }, + destAsset: { + _id: '66d776fb76523303f628495e', + id: '42161_0xeb466342c4d449bc9f53a865d5cb90586f405215', + symbol: 'USDC.axl', + address: '0xeb466342c4d449bc9f53a865d5cb90586f405215', + chainId: 42161, + chain: { + _id: '66d776eb0befbcf39c0a01d1', + id: '42161', + chainId: '42161', + networkIdentifier: 'arbitrum', + chainName: 'Chain 42161', + axelarChainName: 'Arbitrum', + type: 'evm', + networkName: 'Arbitrum', + nativeCurrency: { + name: 'Arbitrum', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/arbitrum.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/arbitrum.webp', + blockExplorerUrls: ['https://arbiscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'arbitrum', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '3', + tokenMessenger: + '0x19330d10D9Cc8751218eaf51E8885D058642E08A', + messageTransmitter: + '0xC30362313FBBA5cf9163F0bb16a0e01f01A896ca', + }, + chainflip: { + vault: '0x79001a5e762f3befc8e5871b42f6734e00498920', + }, + }, + rpcList: ['https://arb1.arbitrum.io/rpc'], + internalRpc: [ + 'https://arb-mainnet.g.alchemy.com/v2/3IBUO-R6MAFGVxOYRHTV-Gt4Pce5jmsz', + 'https://special-wispy-theorem.arbitrum-mainnet.quiknode.pro/befd7d6b704d6477ef747f7ed39299d252994e18', + 'https://arbitrum-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://arb-mainnet.g.alchemy.com/v2/2YR6kg9ueaoGnMxBsvLNXqJyCrmAKC11', + 'https://arb-mainnet.g.alchemy.com/v2/3q9qfCdKJcOA2WbdqVic8jtwnQTZGwlm', + 'https://arbitrum-mainnet.core.chainstack.com/10fd48bf1e4a75d901b11b2ff2c76ada', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.733Z', + updatedAt: '2024-09-13T09:57:11.584Z', + __v: 1, + }, + name: ' USDC (Axelar)', + decimals: 6, + usdPrice: 1.0009320510897841, + interchainTokenId: null, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'axlUSDC', + subGraphOnly: false, + subGraphIds: ['uusdc'], + enabled: true, + createdAt: '2024-09-03T20:52:11.583Z', + updatedAt: '2024-10-08T21:23:55.197Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + }, + srcAmount: '10903750', + destAmount: '10901792', + }, + { + action: 'bridge', + srcChainId: 42161, + destChainId: 10, + protocol: { + name: 'axelar', + displayName: 'Axelar', + }, + srcAsset: { + _id: '66d776fb76523303f628495e', + id: '42161_0xeb466342c4d449bc9f53a865d5cb90586f405215', + symbol: 'USDC.axl', + address: '0xeb466342c4d449bc9f53a865d5cb90586f405215', + chainId: 42161, + chain: { + _id: '66d776eb0befbcf39c0a01d1', + id: '42161', + chainId: '42161', + networkIdentifier: 'arbitrum', + chainName: 'Chain 42161', + axelarChainName: 'Arbitrum', + type: 'evm', + networkName: 'Arbitrum', + nativeCurrency: { + name: 'Arbitrum', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/arbitrum.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/arbitrum.webp', + blockExplorerUrls: ['https://arbiscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'arbitrum', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '3', + tokenMessenger: + '0x19330d10D9Cc8751218eaf51E8885D058642E08A', + messageTransmitter: + '0xC30362313FBBA5cf9163F0bb16a0e01f01A896ca', + }, + chainflip: { + vault: '0x79001a5e762f3befc8e5871b42f6734e00498920', + }, + }, + rpcList: ['https://arb1.arbitrum.io/rpc'], + internalRpc: [ + 'https://arb-mainnet.g.alchemy.com/v2/3IBUO-R6MAFGVxOYRHTV-Gt4Pce5jmsz', + 'https://special-wispy-theorem.arbitrum-mainnet.quiknode.pro/befd7d6b704d6477ef747f7ed39299d252994e18', + 'https://arbitrum-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://arb-mainnet.g.alchemy.com/v2/2YR6kg9ueaoGnMxBsvLNXqJyCrmAKC11', + 'https://arb-mainnet.g.alchemy.com/v2/3q9qfCdKJcOA2WbdqVic8jtwnQTZGwlm', + 'https://arbitrum-mainnet.core.chainstack.com/10fd48bf1e4a75d901b11b2ff2c76ada', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.733Z', + updatedAt: '2024-09-13T09:57:11.584Z', + __v: 1, + }, + name: ' USDC (Axelar)', + decimals: 6, + usdPrice: 1.0009320510897841, + interchainTokenId: null, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'axlUSDC', + subGraphOnly: false, + subGraphIds: ['uusdc'], + enabled: true, + createdAt: '2024-09-03T20:52:11.583Z', + updatedAt: '2024-10-08T21:23:55.197Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + }, + destAsset: { + _id: '66d776fd76523303f6285210', + id: '10_0xeb466342c4d449bc9f53a865d5cb90586f405215', + symbol: 'USDC.axl', + address: '0xeb466342c4d449bc9f53a865d5cb90586f405215', + chainId: 10, + chain: { + _id: '66d776eb0befbcf39c0a01d5', + id: '10', + chainId: '10', + networkIdentifier: 'optimism', + chainName: 'Chain 10', + axelarChainName: 'optimism', + type: 'evm', + networkName: 'Optimism', + nativeCurrency: { + name: 'Optimism', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/optimism.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/optimism.webp', + blockExplorerUrls: ['https://optimistic.etherscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'optimism', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '2', + tokenMessenger: + '0x2B4069517957735bE00ceE0fadAE88a26365528f', + messageTransmitter: + '0x4d41f22c5a0e5c74090899e5a8fb597a8842b3e8', + }, + }, + rpcList: ['https://mainnet.optimism.io'], + internalRpc: [ + 'https://opt-mainnet.g.alchemy.com/v2/YLCHNNGouPGR8L-KViSmQ-4dCKaE6o6H', + 'https://cool-green-tree.optimism.quiknode.pro/c8f7de54a6b1d0e6a15924c5bf3aae2d6c24f0c0', + 'https://optimism-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://opt-mainnet.g.alchemy.com/v2/wDgIhJ3Yz4PvLRkQlA1k0y67dZRb146a', + 'https://opt-mainnet.g.alchemy.com/v2/E8BiF2_ABVQ5fy394vfMaM1JGkpPkIeY', + 'https://nd-739-933-380.p2pify.com/2c8029def5e92e4da7bec7f7c1c153a4', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x4200000000000000000000000000000000000006', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.745Z', + updatedAt: '2024-09-13T09:51:30.869Z', + __v: 1, + }, + name: ' USDC (Axelar)', + decimals: 6, + usdPrice: 1.0009026800874075, + interchainTokenId: null, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'axlUSDC', + subGraphOnly: false, + subGraphIds: ['uusdc'], + enabled: true, + createdAt: '2024-09-03T20:52:13.860Z', + updatedAt: '2024-10-08T21:23:55.474Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + }, + srcAmount: '10901792', + destAmount: '10901792', + }, + { + action: 'swap', + srcChainId: 10, + destChainId: 10, + protocol: { + name: 'Uniswap V3', + displayName: 'Uniswap V3', + }, + srcAsset: { + _id: '66d776fd76523303f6285210', + id: '10_0xeb466342c4d449bc9f53a865d5cb90586f405215', + symbol: 'USDC.axl', + address: '0xeb466342c4d449bc9f53a865d5cb90586f405215', + chainId: 10, + chain: { + _id: '66d776eb0befbcf39c0a01d5', + id: '10', + chainId: '10', + networkIdentifier: 'optimism', + chainName: 'Chain 10', + axelarChainName: 'optimism', + type: 'evm', + networkName: 'Optimism', + nativeCurrency: { + name: 'Optimism', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/optimism.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/optimism.webp', + blockExplorerUrls: ['https://optimistic.etherscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'optimism', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '2', + tokenMessenger: + '0x2B4069517957735bE00ceE0fadAE88a26365528f', + messageTransmitter: + '0x4d41f22c5a0e5c74090899e5a8fb597a8842b3e8', + }, + }, + rpcList: ['https://mainnet.optimism.io'], + internalRpc: [ + 'https://opt-mainnet.g.alchemy.com/v2/YLCHNNGouPGR8L-KViSmQ-4dCKaE6o6H', + 'https://cool-green-tree.optimism.quiknode.pro/c8f7de54a6b1d0e6a15924c5bf3aae2d6c24f0c0', + 'https://optimism-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://opt-mainnet.g.alchemy.com/v2/wDgIhJ3Yz4PvLRkQlA1k0y67dZRb146a', + 'https://opt-mainnet.g.alchemy.com/v2/E8BiF2_ABVQ5fy394vfMaM1JGkpPkIeY', + 'https://nd-739-933-380.p2pify.com/2c8029def5e92e4da7bec7f7c1c153a4', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x4200000000000000000000000000000000000006', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.745Z', + updatedAt: '2024-09-13T09:51:30.869Z', + __v: 1, + }, + name: ' USDC (Axelar)', + decimals: 6, + usdPrice: 1.0009026800874075, + interchainTokenId: null, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'axlUSDC', + subGraphOnly: false, + subGraphIds: ['uusdc'], + enabled: true, + createdAt: '2024-09-03T20:52:13.860Z', + updatedAt: '2024-10-08T21:23:55.474Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + }, + destAsset: { + _id: '66d776fd76523303f628520a', + id: '10_0x7f5c764cbc14f9669b88837ca1490cca17c31607', + symbol: 'USDC.e', + address: '0x7f5c764cbc14f9669b88837ca1490cca17c31607', + chainId: 10, + chain: { + _id: '66d776eb0befbcf39c0a01d5', + id: '10', + chainId: '10', + networkIdentifier: 'optimism', + chainName: 'Chain 10', + axelarChainName: 'optimism', + type: 'evm', + networkName: 'Optimism', + nativeCurrency: { + name: 'Optimism', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/optimism.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/optimism.webp', + blockExplorerUrls: ['https://optimistic.etherscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'optimism', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '2', + tokenMessenger: + '0x2B4069517957735bE00ceE0fadAE88a26365528f', + messageTransmitter: + '0x4d41f22c5a0e5c74090899e5a8fb597a8842b3e8', + }, + }, + rpcList: ['https://mainnet.optimism.io'], + internalRpc: [ + 'https://opt-mainnet.g.alchemy.com/v2/YLCHNNGouPGR8L-KViSmQ-4dCKaE6o6H', + 'https://cool-green-tree.optimism.quiknode.pro/c8f7de54a6b1d0e6a15924c5bf3aae2d6c24f0c0', + 'https://optimism-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://opt-mainnet.g.alchemy.com/v2/wDgIhJ3Yz4PvLRkQlA1k0y67dZRb146a', + 'https://opt-mainnet.g.alchemy.com/v2/E8BiF2_ABVQ5fy394vfMaM1JGkpPkIeY', + 'https://nd-739-933-380.p2pify.com/2c8029def5e92e4da7bec7f7c1c153a4', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x4200000000000000000000000000000000000006', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.745Z', + updatedAt: '2024-09-13T09:51:30.869Z', + __v: 1, + }, + name: 'USDC.e', + decimals: 6, + usdPrice: 1.0009026800874075, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'USDC.e', + subGraphIds: [], + enabled: true, + createdAt: '2024-09-03T20:52:13.857Z', + updatedAt: '2024-10-08T21:23:55.474Z', + __v: 0, + subGraphOnly: false, + active: true, + icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + }, + srcAmount: '10901792', + destAmount: '10902122', + }, + { + action: 'swap', + srcChainId: 10, + destChainId: 10, + protocol: { + name: 'Uniswap V3', + displayName: 'Uniswap V3', + }, + srcAsset: { + _id: '66d776fd76523303f628520a', + id: '10_0x7f5c764cbc14f9669b88837ca1490cca17c31607', + symbol: 'USDC.e', + address: '0x7f5c764cbc14f9669b88837ca1490cca17c31607', + chainId: 10, + chain: { + _id: '66d776eb0befbcf39c0a01d5', + id: '10', + chainId: '10', + networkIdentifier: 'optimism', + chainName: 'Chain 10', + axelarChainName: 'optimism', + type: 'evm', + networkName: 'Optimism', + nativeCurrency: { + name: 'Optimism', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/optimism.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/optimism.webp', + blockExplorerUrls: ['https://optimistic.etherscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'optimism', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '2', + tokenMessenger: + '0x2B4069517957735bE00ceE0fadAE88a26365528f', + messageTransmitter: + '0x4d41f22c5a0e5c74090899e5a8fb597a8842b3e8', + }, + }, + rpcList: ['https://mainnet.optimism.io'], + internalRpc: [ + 'https://opt-mainnet.g.alchemy.com/v2/YLCHNNGouPGR8L-KViSmQ-4dCKaE6o6H', + 'https://cool-green-tree.optimism.quiknode.pro/c8f7de54a6b1d0e6a15924c5bf3aae2d6c24f0c0', + 'https://optimism-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://opt-mainnet.g.alchemy.com/v2/wDgIhJ3Yz4PvLRkQlA1k0y67dZRb146a', + 'https://opt-mainnet.g.alchemy.com/v2/E8BiF2_ABVQ5fy394vfMaM1JGkpPkIeY', + 'https://nd-739-933-380.p2pify.com/2c8029def5e92e4da7bec7f7c1c153a4', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x4200000000000000000000000000000000000006', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.745Z', + updatedAt: '2024-09-13T09:51:30.869Z', + __v: 1, + }, + name: 'USDC.e', + decimals: 6, + usdPrice: 1.0009026800874075, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'USDC.e', + subGraphIds: [], + enabled: true, + createdAt: '2024-09-03T20:52:13.857Z', + updatedAt: '2024-10-08T21:23:55.474Z', + __v: 0, + subGraphOnly: false, + active: true, + icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + }, + destAsset: { + _id: '66d776fd76523303f628520c', + id: '10_0x0b2c639c533813f4aa9d7837caf62653d097ff85', + symbol: 'USDC', + address: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + chainId: 10, + chain: { + _id: '66d776eb0befbcf39c0a01d5', + id: '10', + chainId: '10', + networkIdentifier: 'optimism', + chainName: 'Chain 10', + axelarChainName: 'optimism', + type: 'evm', + networkName: 'Optimism', + nativeCurrency: { + name: 'Optimism', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/optimism.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/optimism.webp', + blockExplorerUrls: ['https://optimistic.etherscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'optimism', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '2', + tokenMessenger: + '0x2B4069517957735bE00ceE0fadAE88a26365528f', + messageTransmitter: + '0x4d41f22c5a0e5c74090899e5a8fb597a8842b3e8', + }, + }, + rpcList: ['https://mainnet.optimism.io'], + internalRpc: [ + 'https://opt-mainnet.g.alchemy.com/v2/YLCHNNGouPGR8L-KViSmQ-4dCKaE6o6H', + 'https://cool-green-tree.optimism.quiknode.pro/c8f7de54a6b1d0e6a15924c5bf3aae2d6c24f0c0', + 'https://optimism-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://opt-mainnet.g.alchemy.com/v2/wDgIhJ3Yz4PvLRkQlA1k0y67dZRb146a', + 'https://opt-mainnet.g.alchemy.com/v2/E8BiF2_ABVQ5fy394vfMaM1JGkpPkIeY', + 'https://nd-739-933-380.p2pify.com/2c8029def5e92e4da7bec7f7c1c153a4', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x4200000000000000000000000000000000000006', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.745Z', + updatedAt: '2024-09-13T09:51:30.869Z', + __v: 1, + }, + name: 'USDC', + decimals: 6, + usdPrice: 1.0009026800874075, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'USDC', + subGraphOnly: false, + subGraphIds: ['uusdc', 'cctp-uusdc-optimism-to-noble'], + enabled: true, + createdAt: '2024-09-03T20:52:13.858Z', + updatedAt: '2024-10-08T21:23:55.474Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + }, + srcAmount: '10902122', + destAmount: '10900626', + }, + ], + }, + approval: { + chainId: 42161, + to: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x095ea7b300000000000000000000000023981fc34e69eedfe2bd9a0a9fcb0719fe09dbfc0000000000000000000000000000000000000000000000000000000000a7d8c0', + gasLimit: 280491, + }, + trade: { + chainId: 42161, + to: '0x23981fC34e69eeDFE2BD9a0a9fCb0719Fe09DbFC', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x3bcba906c4fc', + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000e737175696441646170746572563200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010e0000000000000000000000000ce16f69375520ab01377ce7b88f5ba8c48f8d666000000000000000000000000ce16f69375520ab01377ce7b88f5ba8c48f8d666000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000177fa00000000000000000000000056ca675c3633cc16bd6849e2b431d4e8de5e23bf0000000000000000000000000000000000000000000000000000000000000f94846a1bc6000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a660c600000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f245200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b300000000000000000000000032226588378236fd0c7c4053999f88ac0e5cac77ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000032226588378236fd0c7c4053999f88ac0e5cac77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000e404e45aaf000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000000000000000000000000000000000000000000064000000000000000000000000ce16f69375520ab01377ce7b88f5ba8c48f8d6660000000000000000000000000000000000000000000000000000000000a660c60000000000000000000000000000000000000000000000000000000000a614fd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000761786c555344430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086f7074696d69736d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a3078636531364636393337353532306162303133373763653742383866354241384334384638443636360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f2452000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f405215000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b300000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000e404e45aaf000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c316070000000000000000000000000000000000000000000000000000000000000064000000000000000000000000ea749fd6ba492dbc14c24fe8a3d08769229b896c0000000000000000000000000000000000000000000000000000000000a659200000000000000000000000000000000000000000000000000000000000a616460000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f405215000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b300000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c316070000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000e404e45aaf0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c316070000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000000000000000000000000000000000000000000064000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f24520000000000000000000000000000000000000000000000000000000000a65a6a0000000000000000000000000000000000000000000000000000000000a6107000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160700000000000000000000000000000000000000000000000000000000000000044a15ec74e270a7ffc07aaad0bd59853e000000000000000000000000000000004a15ec74e270a7ffc07aaad0bd59853e00000000000000000000000051039353c0cc77f171c42153ba91fbce7169a04b7d7aca7d0c6eeb24afe83301731e1c6247d68398068d4e73a5ab2d6e9abc76ed5a0fc5ddf1e6e340ee59bf3c1c', + gasLimit: 1491274, + }, + estimatedProcessingTimeInSeconds: 20, + }, + ], + OP_11_USDC_TO_ARB: [ + { + quote: { + requestId: '01fa78fd-ed49-42b3-ab0e-94c7108feea9', + srcChainId: 10, + srcTokenAmount: '11000000', + srcAsset: { + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + chainId: 10, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destChainId: 42161, + destTokenAmount: '10950676', + destAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + feeData: { + metabridge: { + amount: '0', + asset: { + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + chainId: 10, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + }, + }, + bridgeId: 'lifi', + bridges: ['across'], + steps: [ + { + action: 'bridge', + srcChainId: 10, + destChainId: 42161, + protocol: { + name: 'across', + displayName: 'Across', + icon: 'https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/bridges/acrossv2.png', + }, + srcAsset: { + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + chainId: 10, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + srcAmount: '11000000', + destAmount: '10950676', + }, + ], + }, + approval: { + chainId: 10, + to: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x095ea7b3000000000000000000000000b90357f2b86dbfd59c3502215d4060f71df8ca0e0000000000000000000000000000000000000000000000000000000000a7d8c0', + gasLimit: 61865, + }, + trade: { + chainId: 10, + to: '0xB90357f2b86dbfD59c3502215d4060f71DF8ca0e', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x3ce33bff00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d6c6966694164617074657256320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000e397c4883ec89ed4fc9d258f00c689708b2799c9000000000000000000000000e397c4883ec89ed4fc9d258f00c689708b2799c9000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff85000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000716a8b9dd056055c84b7a2ba0a016099465a518700000000000000000000000000000000000000000000000000000000000000902340ab8f15c1311a1d882e68c5fe6ef47965741f6f7a4734bf784bf3ae3f24520b2c639c533813f4aa9d7837caf62653d097ff8500000000000000000000000000a7d8c00000a4b1000fee2f88fb6d2f6705a29bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd00dfeeddeadbeef8932eb23bad9bddb5cf81426f78279a53c6c3b7100000000000000000000000000000000e901efe0f8781a535ac71317aa666e079e2b867f1a0f1aae7db8afdf38c6f5a663f8638a8fa1f578ba4f5613853bb4ff7b831b0cfeccdcf47bb3e46feff039371c', + gasLimit: 196468, + }, + estimatedProcessingTimeInSeconds: 15, + }, + { + quote: { + requestId: '04064397-73e1-44c0-a2ed-f938e5fe62f0', + srcChainId: 10, + srcTokenAmount: '11000000', + srcAsset: { + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + chainId: 10, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destChainId: 42161, + destTokenAmount: '10999889', + destAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + feeData: { + metabridge: { + amount: '0', + asset: { + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + chainId: 10, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + }, + }, + bridgeId: 'lifi', + bridges: ['stargate'], + steps: [ + { + action: 'bridge', + srcChainId: 10, + destChainId: 42161, + protocol: { + name: 'stargate', + displayName: 'StargateV2 (Fast mode)', + icon: 'https://raw.githubusercontent.com/lifinance/types/5685c638772f533edad80fcb210b4bb89e30a50f/src/assets/icons/bridges/stargate.png', + }, + srcAsset: { + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + chainId: 10, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + srcAmount: '11000000', + destAmount: '10999889', + }, + ], + }, + approval: { + chainId: 10, + to: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x095ea7b3000000000000000000000000b90357f2b86dbfd59c3502215d4060f71df8ca0e0000000000000000000000000000000000000000000000000000000000a7d8c0', + gasLimit: 61865, + }, + trade: { + chainId: 10, + to: '0xB90357f2b86dbfD59c3502215d4060f71DF8ca0e', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x1f7968e0913f', + data: '0x3ce33bff00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d6c6966694164617074657256320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005400000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae0000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff85000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000716a8b9dd056055c84b7a2ba0a016099465a518700000000000000000000000000000000000000000000000000000000000003e414d5307700000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200f02847b1891a30122096ac33055ab7e4286cae991a862dbd35a181006f45b44d0000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff85000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f24520000000000000000000000000000000000000000000000000000000000a7d8c0000000000000000000000000000000000000000000000000000000000000a4b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7374617267617465563200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6d6574616d61736b2d6272696467650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000001f7968e0913f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f2452000000000000000000000000000000000000000000000000000000000000759e000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f24520000000000000000000000000000000000000000000000000000000000a7d8c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ca2568629f30c9780c694cf80af2799e1836b70fd6a221915056dacf1584d63a531f3049719aaeb572635cf719df4410100859da7b9033ba52805691cace86ef1b', + gasLimit: 619670, + }, + estimatedProcessingTimeInSeconds: 50, + }, + { + quote: { + requestId: '26d1486d-1979-4a24-b066-aa87ea6a9cbf', + srcChainId: 10, + srcTokenAmount: '11000000', + srcAsset: { + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + chainId: 10, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destChainId: 42161, + destTokenAmount: '10900000', + destAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + feeData: { + metabridge: { + amount: '0', + asset: { + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + chainId: 10, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + }, + }, + bridgeId: 'lifi', + bridges: ['celercircle'], + steps: [ + { + action: 'bridge', + srcChainId: 10, + destChainId: 42161, + protocol: { + name: 'celercircle', + displayName: 'Circle CCTP', + icon: 'https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/bridges/circle.png', + }, + srcAsset: { + address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', + chainId: 10, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + destAsset: { + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + chainId: 42161, + symbol: 'USDC', + decimals: 6, + name: 'USD Coin', + coinKey: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + priceUSD: '1.0007004903432404', + icon: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + srcAmount: '11000000', + destAmount: '10900000', + }, + ], + }, + approval: { + chainId: 10, + to: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x095ea7b3000000000000000000000000b90357f2b86dbfd59c3502215d4060f71df8ca0e0000000000000000000000000000000000000000000000000000000000a7d8c0', + gasLimit: 61865, + }, + trade: { + chainId: 10, + to: '0xB90357f2b86dbfD59c3502215d4060f71DF8ca0e', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x3ce33bff00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d6c6966694164617074657256320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003400000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae0000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff85000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000716a8b9dd056055c84b7a2ba0a016099465a518700000000000000000000000000000000000000000000000000000000000001e4bab657d80000000000000000000000000000000000000000000000000000000000000020af6b3cbb61978d928e0a59f45df6e973d36326c48aaa054412683aba82adbed60000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff85000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f24520000000000000000000000000000000000000000000000000000000000a7d8c0000000000000000000000000000000000000000000000000000000000000a4b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b63656c6572636972636c65000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6d6574616d61736b2d6272696467650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000e2d38d411f459d41f584802754a11be4cff908688ddd18e4d274400fd0de6d9ff9a6eeb426c654afae9fdb3f99e511bb288a7246018e54432afb60be63691b', + gasLimit: 415725, + }, + estimatedProcessingTimeInSeconds: 1134, + }, + { + quote: { + requestId: '544ebf94-e5d4-4553-8c64-af881b55c6ff', + srcChainId: 10, + srcAsset: { + chainId: 10, + address: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + symbol: 'USDC', + name: 'USD Coin', + decimals: 6, + icon: 'https://media.socket.tech/tokens/all/USDC', + logoURI: 'https://media.socket.tech/tokens/all/USDC', + chainAgnosticId: null, + }, + srcTokenAmount: '11000000', + destChainId: 42161, + destAsset: { + chainId: 42161, + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + symbol: 'USDC', + name: 'USD Coin', + decimals: 6, + icon: 'https://media.socket.tech/tokens/all/USDC', + logoURI: 'https://media.socket.tech/tokens/all/USDC', + chainAgnosticId: null, + }, + destTokenAmount: '10600000', + feeData: { + metabridge: { + amount: '0', + asset: { + chainId: 10, + address: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + symbol: 'USDC', + name: 'USD Coin', + decimals: 6, + icon: 'https://media.socket.tech/tokens/all/USDC', + logoURI: 'https://media.socket.tech/tokens/all/USDC', + chainAgnosticId: null, + }, + }, + }, + bridgeId: 'socket', + bridges: ['celercircle'], + steps: [ + { + action: 'bridge', + srcChainId: 10, + destChainId: 42161, + protocol: { + name: 'cctp', + displayName: 'Circle CCTP', + icon: 'https://movricons.s3.ap-south-1.amazonaws.com/CCTP.svg', + }, + srcAsset: { + chainId: 10, + address: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + symbol: 'USDC', + name: 'USD Coin', + decimals: 6, + icon: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + logoURI: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + chainAgnosticId: null, + }, + destAsset: { + chainId: 42161, + address: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + symbol: 'USDC', + name: 'USD Coin', + decimals: 6, + icon: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + logoURI: 'https://assets.polygon.technology/tokenAssets/usdc.svg', + chainAgnosticId: null, + }, + srcAmount: '11000000', + destAmount: '10600000', + }, + ], + }, + approval: { + chainId: 10, + to: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x095ea7b3000000000000000000000000b90357f2b86dbfd59c3502215d4060f71df8ca0e0000000000000000000000000000000000000000000000000000000000a7d8c0', + gasLimit: 61865, + }, + trade: { + chainId: 10, + to: '0xB90357f2b86dbfD59c3502215d4060f71DF8ca0e', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x3ce33bff00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000f736f636b6574416461707465725632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000003a23f943181408eac424116af7b7790c94cb97a5000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff85000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000716a8b9dd056055c84b7a2ba0a016099465a518700000000000000000000000000000000000000000000000000000000000000e80000018cb7dfe9d00000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f24520000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff85000000000000000000000000000000000000000000000000000000000000a4b100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000061a800000000000000000000000000000000000000000000000000aaa45c155ccfb09c996a750c7d53dc975065d8841b58669213d7f345318d2395a5796ece3d8c0729e128bd0a33dface658f5846a3496dcfbeeca77394fe9b5a1b', + gasLimit: 290954, + }, + estimatedProcessingTimeInSeconds: 1500, + }, + { + quote: { + requestId: '389140aaaebab60eca1d15b4134c27fa', + srcChainId: 10, + srcTokenAmount: '11000000', + srcAsset: { + _id: '66d776fd76523303f628520c', + id: '10_0x0b2c639c533813f4aa9d7837caf62653d097ff85', + symbol: 'USDC', + address: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + chainId: 10, + chain: { + _id: '66d776eb0befbcf39c0a01d5', + id: '10', + chainId: '10', + networkIdentifier: 'optimism', + chainName: 'Chain 10', + axelarChainName: 'optimism', + type: 'evm', + networkName: 'Optimism', + nativeCurrency: { + name: 'Optimism', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/optimism.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/optimism.webp', + blockExplorerUrls: ['https://optimistic.etherscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'optimism', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '2', + tokenMessenger: '0x2B4069517957735bE00ceE0fadAE88a26365528f', + messageTransmitter: + '0x4d41f22c5a0e5c74090899e5a8fb597a8842b3e8', + }, + }, + rpcList: ['https://mainnet.optimism.io'], + internalRpc: [ + 'https://opt-mainnet.g.alchemy.com/v2/YLCHNNGouPGR8L-KViSmQ-4dCKaE6o6H', + 'https://cool-green-tree.optimism.quiknode.pro/c8f7de54a6b1d0e6a15924c5bf3aae2d6c24f0c0', + 'https://optimism-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://opt-mainnet.g.alchemy.com/v2/wDgIhJ3Yz4PvLRkQlA1k0y67dZRb146a', + 'https://opt-mainnet.g.alchemy.com/v2/E8BiF2_ABVQ5fy394vfMaM1JGkpPkIeY', + 'https://nd-739-933-380.p2pify.com/2c8029def5e92e4da7bec7f7c1c153a4', + ], + chainNativeContracts: { + wrappedNativeToken: '0x4200000000000000000000000000000000000006', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.745Z', + updatedAt: '2024-09-13T09:51:30.869Z', + __v: 1, + }, + name: 'USDC', + decimals: 6, + usdPrice: 1.001053579729135, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + volatility: 0, + axelarNetworkSymbol: 'USDC', + subGraphOnly: false, + subGraphIds: ['uusdc', 'cctp-uusdc-optimism-to-noble'], + enabled: true, + createdAt: '2024-09-03T20:52:13.858Z', + updatedAt: '2024-10-08T21:24:40.381Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + }, + destChainId: 42161, + destTokenAmount: '10996548', + destAsset: { + _id: '66d776fb76523303f628495c', + id: '42161_0xaf88d065e77c8cc2239327c5edb3a432268e5831', + symbol: 'USDC', + address: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + chainId: 42161, + chain: { + _id: '66d776eb0befbcf39c0a01d1', + id: '42161', + chainId: '42161', + networkIdentifier: 'arbitrum', + chainName: 'Chain 42161', + axelarChainName: 'Arbitrum', + type: 'evm', + networkName: 'Arbitrum', + nativeCurrency: { + name: 'Arbitrum', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/arbitrum.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/arbitrum.webp', + blockExplorerUrls: ['https://arbiscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'arbitrum', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '3', + tokenMessenger: '0x19330d10D9Cc8751218eaf51E8885D058642E08A', + messageTransmitter: + '0xC30362313FBBA5cf9163F0bb16a0e01f01A896ca', + }, + chainflip: { + vault: '0x79001a5e762f3befc8e5871b42f6734e00498920', + }, + }, + rpcList: ['https://arb1.arbitrum.io/rpc'], + internalRpc: [ + 'https://arb-mainnet.g.alchemy.com/v2/3IBUO-R6MAFGVxOYRHTV-Gt4Pce5jmsz', + 'https://special-wispy-theorem.arbitrum-mainnet.quiknode.pro/befd7d6b704d6477ef747f7ed39299d252994e18', + 'https://arbitrum-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://arb-mainnet.g.alchemy.com/v2/2YR6kg9ueaoGnMxBsvLNXqJyCrmAKC11', + 'https://arb-mainnet.g.alchemy.com/v2/3q9qfCdKJcOA2WbdqVic8jtwnQTZGwlm', + 'https://arbitrum-mainnet.core.chainstack.com/10fd48bf1e4a75d901b11b2ff2c76ada', + ], + chainNativeContracts: { + wrappedNativeToken: '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.733Z', + updatedAt: '2024-09-13T09:57:11.584Z', + __v: 1, + }, + name: 'USDC', + decimals: 6, + usdPrice: 1.001053579729135, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + volatility: 0, + axelarNetworkSymbol: 'USDC', + subGraphOnly: false, + subGraphIds: [ + 'uusdc', + 'cctp-uusdc-arbitrum-to-noble', + 'btc-usdc-arb', + ], + enabled: true, + createdAt: '2024-09-03T20:52:11.579Z', + updatedAt: '2024-10-08T21:24:40.127Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + }, + feeData: { + metabridge: { + amount: '0', + asset: { + _id: '66d776fd76523303f628520c', + id: '10_0x0b2c639c533813f4aa9d7837caf62653d097ff85', + symbol: 'USDC', + address: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + chainId: 10, + chain: { + _id: '66d776eb0befbcf39c0a01d5', + id: '10', + chainId: '10', + networkIdentifier: 'optimism', + chainName: 'Chain 10', + axelarChainName: 'optimism', + type: 'evm', + networkName: 'Optimism', + nativeCurrency: { + name: 'Optimism', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/optimism.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/optimism.webp', + blockExplorerUrls: ['https://optimistic.etherscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'optimism', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '2', + tokenMessenger: + '0x2B4069517957735bE00ceE0fadAE88a26365528f', + messageTransmitter: + '0x4d41f22c5a0e5c74090899e5a8fb597a8842b3e8', + }, + }, + rpcList: ['https://mainnet.optimism.io'], + internalRpc: [ + 'https://opt-mainnet.g.alchemy.com/v2/YLCHNNGouPGR8L-KViSmQ-4dCKaE6o6H', + 'https://cool-green-tree.optimism.quiknode.pro/c8f7de54a6b1d0e6a15924c5bf3aae2d6c24f0c0', + 'https://optimism-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://opt-mainnet.g.alchemy.com/v2/wDgIhJ3Yz4PvLRkQlA1k0y67dZRb146a', + 'https://opt-mainnet.g.alchemy.com/v2/E8BiF2_ABVQ5fy394vfMaM1JGkpPkIeY', + 'https://nd-739-933-380.p2pify.com/2c8029def5e92e4da7bec7f7c1c153a4', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x4200000000000000000000000000000000000006', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.745Z', + updatedAt: '2024-09-13T09:51:30.869Z', + __v: 1, + }, + name: 'USDC', + decimals: 6, + usdPrice: 1.001053579729135, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + volatility: 0, + axelarNetworkSymbol: 'USDC', + subGraphOnly: false, + subGraphIds: ['uusdc', 'cctp-uusdc-optimism-to-noble'], + enabled: true, + createdAt: '2024-09-03T20:52:13.858Z', + updatedAt: '2024-10-08T21:24:40.381Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + }, + }, + }, + bridgeId: 'squid', + bridges: ['axelar'], + steps: [ + { + action: 'swap', + srcChainId: 10, + destChainId: 10, + protocol: { + name: 'Uniswap V3', + displayName: 'Uniswap V3', + }, + srcAsset: { + _id: '66d776fd76523303f628520c', + id: '10_0x0b2c639c533813f4aa9d7837caf62653d097ff85', + symbol: 'USDC', + address: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + chainId: 10, + chain: { + _id: '66d776eb0befbcf39c0a01d5', + id: '10', + chainId: '10', + networkIdentifier: 'optimism', + chainName: 'Chain 10', + axelarChainName: 'optimism', + type: 'evm', + networkName: 'Optimism', + nativeCurrency: { + name: 'Optimism', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/optimism.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/optimism.webp', + blockExplorerUrls: ['https://optimistic.etherscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'optimism', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '2', + tokenMessenger: + '0x2B4069517957735bE00ceE0fadAE88a26365528f', + messageTransmitter: + '0x4d41f22c5a0e5c74090899e5a8fb597a8842b3e8', + }, + }, + rpcList: ['https://mainnet.optimism.io'], + internalRpc: [ + 'https://opt-mainnet.g.alchemy.com/v2/YLCHNNGouPGR8L-KViSmQ-4dCKaE6o6H', + 'https://cool-green-tree.optimism.quiknode.pro/c8f7de54a6b1d0e6a15924c5bf3aae2d6c24f0c0', + 'https://optimism-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://opt-mainnet.g.alchemy.com/v2/wDgIhJ3Yz4PvLRkQlA1k0y67dZRb146a', + 'https://opt-mainnet.g.alchemy.com/v2/E8BiF2_ABVQ5fy394vfMaM1JGkpPkIeY', + 'https://nd-739-933-380.p2pify.com/2c8029def5e92e4da7bec7f7c1c153a4', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x4200000000000000000000000000000000000006', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.745Z', + updatedAt: '2024-09-13T09:51:30.869Z', + __v: 1, + }, + name: 'USDC', + decimals: 6, + usdPrice: 1.001053579729135, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'USDC', + subGraphOnly: false, + subGraphIds: ['uusdc', 'cctp-uusdc-optimism-to-noble'], + enabled: true, + createdAt: '2024-09-03T20:52:13.858Z', + updatedAt: '2024-10-08T21:24:40.381Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + }, + destAsset: { + _id: '66d776fd76523303f628520a', + id: '10_0x7f5c764cbc14f9669b88837ca1490cca17c31607', + symbol: 'USDC.e', + address: '0x7f5c764cbc14f9669b88837ca1490cca17c31607', + chainId: 10, + chain: { + _id: '66d776eb0befbcf39c0a01d5', + id: '10', + chainId: '10', + networkIdentifier: 'optimism', + chainName: 'Chain 10', + axelarChainName: 'optimism', + type: 'evm', + networkName: 'Optimism', + nativeCurrency: { + name: 'Optimism', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/optimism.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/optimism.webp', + blockExplorerUrls: ['https://optimistic.etherscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'optimism', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '2', + tokenMessenger: + '0x2B4069517957735bE00ceE0fadAE88a26365528f', + messageTransmitter: + '0x4d41f22c5a0e5c74090899e5a8fb597a8842b3e8', + }, + }, + rpcList: ['https://mainnet.optimism.io'], + internalRpc: [ + 'https://opt-mainnet.g.alchemy.com/v2/YLCHNNGouPGR8L-KViSmQ-4dCKaE6o6H', + 'https://cool-green-tree.optimism.quiknode.pro/c8f7de54a6b1d0e6a15924c5bf3aae2d6c24f0c0', + 'https://optimism-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://opt-mainnet.g.alchemy.com/v2/wDgIhJ3Yz4PvLRkQlA1k0y67dZRb146a', + 'https://opt-mainnet.g.alchemy.com/v2/E8BiF2_ABVQ5fy394vfMaM1JGkpPkIeY', + 'https://nd-739-933-380.p2pify.com/2c8029def5e92e4da7bec7f7c1c153a4', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x4200000000000000000000000000000000000006', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.745Z', + updatedAt: '2024-09-13T09:51:30.869Z', + __v: 1, + }, + name: 'USDC.e', + decimals: 6, + usdPrice: 1.001053579729135, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'USDC.e', + subGraphIds: [], + enabled: true, + createdAt: '2024-09-03T20:52:13.857Z', + updatedAt: '2024-10-08T21:24:40.381Z', + __v: 0, + subGraphOnly: false, + active: true, + icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + }, + srcAmount: '11000000', + destAmount: '10999308', + }, + { + action: 'swap', + srcChainId: 10, + destChainId: 10, + protocol: { + name: 'Uniswap V3', + displayName: 'Uniswap V3', + }, + srcAsset: { + _id: '66d776fd76523303f628520a', + id: '10_0x7f5c764cbc14f9669b88837ca1490cca17c31607', + symbol: 'USDC.e', + address: '0x7f5c764cbc14f9669b88837ca1490cca17c31607', + chainId: 10, + chain: { + _id: '66d776eb0befbcf39c0a01d5', + id: '10', + chainId: '10', + networkIdentifier: 'optimism', + chainName: 'Chain 10', + axelarChainName: 'optimism', + type: 'evm', + networkName: 'Optimism', + nativeCurrency: { + name: 'Optimism', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/optimism.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/optimism.webp', + blockExplorerUrls: ['https://optimistic.etherscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'optimism', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '2', + tokenMessenger: + '0x2B4069517957735bE00ceE0fadAE88a26365528f', + messageTransmitter: + '0x4d41f22c5a0e5c74090899e5a8fb597a8842b3e8', + }, + }, + rpcList: ['https://mainnet.optimism.io'], + internalRpc: [ + 'https://opt-mainnet.g.alchemy.com/v2/YLCHNNGouPGR8L-KViSmQ-4dCKaE6o6H', + 'https://cool-green-tree.optimism.quiknode.pro/c8f7de54a6b1d0e6a15924c5bf3aae2d6c24f0c0', + 'https://optimism-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://opt-mainnet.g.alchemy.com/v2/wDgIhJ3Yz4PvLRkQlA1k0y67dZRb146a', + 'https://opt-mainnet.g.alchemy.com/v2/E8BiF2_ABVQ5fy394vfMaM1JGkpPkIeY', + 'https://nd-739-933-380.p2pify.com/2c8029def5e92e4da7bec7f7c1c153a4', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x4200000000000000000000000000000000000006', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.745Z', + updatedAt: '2024-09-13T09:51:30.869Z', + __v: 1, + }, + name: 'USDC.e', + decimals: 6, + usdPrice: 1.001053579729135, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'USDC.e', + subGraphIds: [], + enabled: true, + createdAt: '2024-09-03T20:52:13.857Z', + updatedAt: '2024-10-08T21:24:40.381Z', + __v: 0, + subGraphOnly: false, + active: true, + icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + }, + destAsset: { + _id: '66d776fd76523303f6285210', + id: '10_0xeb466342c4d449bc9f53a865d5cb90586f405215', + symbol: 'USDC.axl', + address: '0xeb466342c4d449bc9f53a865d5cb90586f405215', + chainId: 10, + chain: { + _id: '66d776eb0befbcf39c0a01d5', + id: '10', + chainId: '10', + networkIdentifier: 'optimism', + chainName: 'Chain 10', + axelarChainName: 'optimism', + type: 'evm', + networkName: 'Optimism', + nativeCurrency: { + name: 'Optimism', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/optimism.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/optimism.webp', + blockExplorerUrls: ['https://optimistic.etherscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'optimism', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '2', + tokenMessenger: + '0x2B4069517957735bE00ceE0fadAE88a26365528f', + messageTransmitter: + '0x4d41f22c5a0e5c74090899e5a8fb597a8842b3e8', + }, + }, + rpcList: ['https://mainnet.optimism.io'], + internalRpc: [ + 'https://opt-mainnet.g.alchemy.com/v2/YLCHNNGouPGR8L-KViSmQ-4dCKaE6o6H', + 'https://cool-green-tree.optimism.quiknode.pro/c8f7de54a6b1d0e6a15924c5bf3aae2d6c24f0c0', + 'https://optimism-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://opt-mainnet.g.alchemy.com/v2/wDgIhJ3Yz4PvLRkQlA1k0y67dZRb146a', + 'https://opt-mainnet.g.alchemy.com/v2/E8BiF2_ABVQ5fy394vfMaM1JGkpPkIeY', + 'https://nd-739-933-380.p2pify.com/2c8029def5e92e4da7bec7f7c1c153a4', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x4200000000000000000000000000000000000006', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.745Z', + updatedAt: '2024-09-13T09:51:30.869Z', + __v: 1, + }, + name: ' USDC (Axelar)', + decimals: 6, + usdPrice: 1.001053579729135, + interchainTokenId: null, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'axlUSDC', + subGraphOnly: false, + subGraphIds: ['uusdc'], + enabled: true, + createdAt: '2024-09-03T20:52:13.860Z', + updatedAt: '2024-10-08T21:24:40.381Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + }, + srcAmount: '10999308', + destAmount: '10996775', + }, + { + action: 'bridge', + srcChainId: 10, + destChainId: 42161, + protocol: { + name: 'axelar', + displayName: 'Axelar', + }, + srcAsset: { + _id: '66d776fd76523303f6285210', + id: '10_0xeb466342c4d449bc9f53a865d5cb90586f405215', + symbol: 'USDC.axl', + address: '0xeb466342c4d449bc9f53a865d5cb90586f405215', + chainId: 10, + chain: { + _id: '66d776eb0befbcf39c0a01d5', + id: '10', + chainId: '10', + networkIdentifier: 'optimism', + chainName: 'Chain 10', + axelarChainName: 'optimism', + type: 'evm', + networkName: 'Optimism', + nativeCurrency: { + name: 'Optimism', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/optimism.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/optimism.webp', + blockExplorerUrls: ['https://optimistic.etherscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'optimism', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '2', + tokenMessenger: + '0x2B4069517957735bE00ceE0fadAE88a26365528f', + messageTransmitter: + '0x4d41f22c5a0e5c74090899e5a8fb597a8842b3e8', + }, + }, + rpcList: ['https://mainnet.optimism.io'], + internalRpc: [ + 'https://opt-mainnet.g.alchemy.com/v2/YLCHNNGouPGR8L-KViSmQ-4dCKaE6o6H', + 'https://cool-green-tree.optimism.quiknode.pro/c8f7de54a6b1d0e6a15924c5bf3aae2d6c24f0c0', + 'https://optimism-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://opt-mainnet.g.alchemy.com/v2/wDgIhJ3Yz4PvLRkQlA1k0y67dZRb146a', + 'https://opt-mainnet.g.alchemy.com/v2/E8BiF2_ABVQ5fy394vfMaM1JGkpPkIeY', + 'https://nd-739-933-380.p2pify.com/2c8029def5e92e4da7bec7f7c1c153a4', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x4200000000000000000000000000000000000006', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.745Z', + updatedAt: '2024-09-13T09:51:30.869Z', + __v: 1, + }, + name: ' USDC (Axelar)', + decimals: 6, + usdPrice: 1.001053579729135, + interchainTokenId: null, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'axlUSDC', + subGraphOnly: false, + subGraphIds: ['uusdc'], + enabled: true, + createdAt: '2024-09-03T20:52:13.860Z', + updatedAt: '2024-10-08T21:24:40.381Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + }, + destAsset: { + _id: '66d776fb76523303f628495e', + id: '42161_0xeb466342c4d449bc9f53a865d5cb90586f405215', + symbol: 'USDC.axl', + address: '0xeb466342c4d449bc9f53a865d5cb90586f405215', + chainId: 42161, + chain: { + _id: '66d776eb0befbcf39c0a01d1', + id: '42161', + chainId: '42161', + networkIdentifier: 'arbitrum', + chainName: 'Chain 42161', + axelarChainName: 'Arbitrum', + type: 'evm', + networkName: 'Arbitrum', + nativeCurrency: { + name: 'Arbitrum', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/arbitrum.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/arbitrum.webp', + blockExplorerUrls: ['https://arbiscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'arbitrum', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '3', + tokenMessenger: + '0x19330d10D9Cc8751218eaf51E8885D058642E08A', + messageTransmitter: + '0xC30362313FBBA5cf9163F0bb16a0e01f01A896ca', + }, + chainflip: { + vault: '0x79001a5e762f3befc8e5871b42f6734e00498920', + }, + }, + rpcList: ['https://arb1.arbitrum.io/rpc'], + internalRpc: [ + 'https://arb-mainnet.g.alchemy.com/v2/3IBUO-R6MAFGVxOYRHTV-Gt4Pce5jmsz', + 'https://special-wispy-theorem.arbitrum-mainnet.quiknode.pro/befd7d6b704d6477ef747f7ed39299d252994e18', + 'https://arbitrum-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://arb-mainnet.g.alchemy.com/v2/2YR6kg9ueaoGnMxBsvLNXqJyCrmAKC11', + 'https://arb-mainnet.g.alchemy.com/v2/3q9qfCdKJcOA2WbdqVic8jtwnQTZGwlm', + 'https://arbitrum-mainnet.core.chainstack.com/10fd48bf1e4a75d901b11b2ff2c76ada', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.733Z', + updatedAt: '2024-09-13T09:57:11.584Z', + __v: 1, + }, + name: ' USDC (Axelar)', + decimals: 6, + usdPrice: 1.001053579729135, + interchainTokenId: null, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'axlUSDC', + subGraphOnly: false, + subGraphIds: ['uusdc'], + enabled: true, + createdAt: '2024-09-03T20:52:11.583Z', + updatedAt: '2024-10-08T21:24:40.127Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + }, + srcAmount: '10996775', + destAmount: '10996775', + }, + { + action: 'swap', + srcChainId: 42161, + destChainId: 42161, + protocol: { + name: 'Pancakeswap V3', + displayName: 'Pancakeswap V3', + }, + srcAsset: { + _id: '66d776fb76523303f628495e', + id: '42161_0xeb466342c4d449bc9f53a865d5cb90586f405215', + symbol: 'USDC.axl', + address: '0xeb466342c4d449bc9f53a865d5cb90586f405215', + chainId: 42161, + chain: { + _id: '66d776eb0befbcf39c0a01d1', + id: '42161', + chainId: '42161', + networkIdentifier: 'arbitrum', + chainName: 'Chain 42161', + axelarChainName: 'Arbitrum', + type: 'evm', + networkName: 'Arbitrum', + nativeCurrency: { + name: 'Arbitrum', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/arbitrum.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/arbitrum.webp', + blockExplorerUrls: ['https://arbiscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'arbitrum', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '3', + tokenMessenger: + '0x19330d10D9Cc8751218eaf51E8885D058642E08A', + messageTransmitter: + '0xC30362313FBBA5cf9163F0bb16a0e01f01A896ca', + }, + chainflip: { + vault: '0x79001a5e762f3befc8e5871b42f6734e00498920', + }, + }, + rpcList: ['https://arb1.arbitrum.io/rpc'], + internalRpc: [ + 'https://arb-mainnet.g.alchemy.com/v2/3IBUO-R6MAFGVxOYRHTV-Gt4Pce5jmsz', + 'https://special-wispy-theorem.arbitrum-mainnet.quiknode.pro/befd7d6b704d6477ef747f7ed39299d252994e18', + 'https://arbitrum-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://arb-mainnet.g.alchemy.com/v2/2YR6kg9ueaoGnMxBsvLNXqJyCrmAKC11', + 'https://arb-mainnet.g.alchemy.com/v2/3q9qfCdKJcOA2WbdqVic8jtwnQTZGwlm', + 'https://arbitrum-mainnet.core.chainstack.com/10fd48bf1e4a75d901b11b2ff2c76ada', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.733Z', + updatedAt: '2024-09-13T09:57:11.584Z', + __v: 1, + }, + name: ' USDC (Axelar)', + decimals: 6, + usdPrice: 1.001053579729135, + interchainTokenId: null, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'axlUSDC', + subGraphOnly: false, + subGraphIds: ['uusdc'], + enabled: true, + createdAt: '2024-09-03T20:52:11.583Z', + updatedAt: '2024-10-08T21:24:40.127Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/usdc.svg', + }, + destAsset: { + _id: '66d776fb76523303f628495c', + id: '42161_0xaf88d065e77c8cc2239327c5edb3a432268e5831', + symbol: 'USDC', + address: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + chainId: 42161, + chain: { + _id: '66d776eb0befbcf39c0a01d1', + id: '42161', + chainId: '42161', + networkIdentifier: 'arbitrum', + chainName: 'Chain 42161', + axelarChainName: 'Arbitrum', + type: 'evm', + networkName: 'Arbitrum', + nativeCurrency: { + name: 'Arbitrum', + symbol: 'ETH', + decimals: 18, + icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/arbitrum.svg', + }, + chainIconURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/webp128/chains/arbitrum.webp', + blockExplorerUrls: ['https://arbiscan.io/'], + swapAmountForGas: '2000000', + sameChainSwapsSupported: true, + squidContracts: { + squidRouter: '0xce16F69375520ab01377ce7B88f5BA8C48F8D666', + defaultCrosschainToken: + '0xEB466342C4d449BC9f53A865D5Cb90586f405215', + squidMulticall: '0xEa749Fd6bA492dbc14c24FE8A3d08769229b896c', + squidFeeCollector: + '0xd3F8F338FdAD6DEb491F0F225d09422A7a70cc45', + }, + compliance: { + trmIdentifier: 'arbitrum', + }, + boostSupported: true, + enableBoostByDefault: true, + bridges: { + axelar: { + gateway: '0xe432150cce91c13a887f7D836923d5597adD8E31', + itsService: '0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C', + }, + cctp: { + cctpDomain: '3', + tokenMessenger: + '0x19330d10D9Cc8751218eaf51E8885D058642E08A', + messageTransmitter: + '0xC30362313FBBA5cf9163F0bb16a0e01f01A896ca', + }, + chainflip: { + vault: '0x79001a5e762f3befc8e5871b42f6734e00498920', + }, + }, + rpcList: ['https://arb1.arbitrum.io/rpc'], + internalRpc: [ + 'https://arb-mainnet.g.alchemy.com/v2/3IBUO-R6MAFGVxOYRHTV-Gt4Pce5jmsz', + 'https://special-wispy-theorem.arbitrum-mainnet.quiknode.pro/befd7d6b704d6477ef747f7ed39299d252994e18', + 'https://arbitrum-mainnet.infura.io/v3/273aad656cd94f9aa022e4899b87dd6c', + 'https://arb-mainnet.g.alchemy.com/v2/2YR6kg9ueaoGnMxBsvLNXqJyCrmAKC11', + 'https://arb-mainnet.g.alchemy.com/v2/3q9qfCdKJcOA2WbdqVic8jtwnQTZGwlm', + 'https://arbitrum-mainnet.core.chainstack.com/10fd48bf1e4a75d901b11b2ff2c76ada', + ], + chainNativeContracts: { + wrappedNativeToken: + '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', + ensRegistry: '', + multicall: '0xcA11bde05977b3631167028862bE2a173976CA11', + usdcToken: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', + }, + feeCurrencies: [], + currencies: [], + features: [], + enabled: true, + createdAt: '2024-09-03T20:51:55.733Z', + updatedAt: '2024-09-13T09:57:11.584Z', + __v: 1, + }, + name: 'USDC', + decimals: 6, + usdPrice: 1.001053579729135, + coingeckoId: 'usd-coin', + type: 'evm', + logoURI: + 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + axelarNetworkSymbol: 'USDC', + subGraphOnly: false, + subGraphIds: [ + 'uusdc', + 'cctp-uusdc-arbitrum-to-noble', + 'btc-usdc-arb', + ], + enabled: true, + createdAt: '2024-09-03T20:52:11.579Z', + updatedAt: '2024-10-08T21:24:40.127Z', + __v: 0, + active: true, + icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/usdc.svg', + }, + srcAmount: '10996775', + destAmount: '10996548', + }, + ], + }, + approval: { + chainId: 10, + to: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x00', + data: '0x095ea7b3000000000000000000000000b90357f2b86dbfd59c3502215d4060f71df8ca0e0000000000000000000000000000000000000000000000000000000000a7d8c0', + gasLimit: 61865, + }, + trade: { + chainId: 10, + to: '0xB90357f2b86dbfD59c3502215d4060f71DF8ca0e', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + value: '0x46366a86b7c6', + data: '0x3ce33bff00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000e737175696441646170746572563200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010e0000000000000000000000000ce16f69375520ab01377ce7b88f5ba8c48f8d666000000000000000000000000ce16f69375520ab01377ce7b88f5ba8c48f8d666000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff85000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000716a8b9dd056055c84b7a2ba0a016099465a51870000000000000000000000000000000000000000000000000000000000000f94846a1bc60000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000000000000000000000000000000000000000a7d8c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000098000000000000000000000000000000000000000000000000000000000000009e0000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f24520000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff85000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b300000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000e404e45aaf0000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c316070000000000000000000000000000000000000000000000000000000000000064000000000000000000000000ea749fd6ba492dbc14c24fe8a3d08769229b896c0000000000000000000000000000000000000000000000000000000000a7d8c00000000000000000000000000000000000000000000000000000000000a7914d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff85000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b300000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c316070000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000e404e45aaf0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000000000000000000000000000000000000000000064000000000000000000000000ce16f69375520ab01377ce7b88f5ba8c48f8d6660000000000000000000000000000000000000000000000000000000000a7d60c0000000000000000000000000000000000000000000000000000000000a7876c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c316070000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000761786c55534443000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008417262697472756d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a3078636531364636393337353532306162303133373763653742383866354241384334384638443636360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000040000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f245200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f405215000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b300000000000000000000000032226588378236fd0c7c4053999f88ac0e5cac77ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000032226588378236fd0c7c4053999f88ac0e5cac77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000e404e45aaf000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f405215000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000000064000000000000000000000000c5fe6ef47965741f6f7a4734bf784bf3ae3f24520000000000000000000000000000000000000000000000000000000000a7cc270000000000000000000000000000000000000000000000000000000000a786890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000000000000000000000000000000000000000000004389140aaaebab60eca1d15b4134c27fa00000000000000000000000000000000389140aaaebab60eca1d15b4134c27fa0000000000000000000000004f83a94a67ba9e24e0fee7799e54ddb2575d8454082cf56a7c0292457ce280df23aa57920d0bef49660cda25b12442e1fc410a745097e2ef21491f05082aa8661b', + gasLimit: 565594, + }, + estimatedProcessingTimeInSeconds: 20, + }, + ], +}; diff --git a/ui/ducks/bridge/actions.ts b/ui/ducks/bridge/actions.ts index f045c0dfbc12..a61d2fdcd8fd 100644 --- a/ui/ducks/bridge/actions.ts +++ b/ui/ducks/bridge/actions.ts @@ -7,11 +7,10 @@ import { // TODO: Remove restricted import // eslint-disable-next-line import/no-restricted-paths } from '../../../app/scripts/controllers/bridge/types'; - import { forceUpdateMetamaskState } from '../../store/actions'; import { submitRequestToBackground } from '../../store/background-connection'; -import { MetaMaskReduxDispatch } from '../../store/store'; import { QuoteRequest } from '../../pages/bridge/types'; +import { MetaMaskReduxDispatch } from '../../store/store'; import { bridgeSlice } from './bridge'; const { @@ -86,3 +85,13 @@ export const updateQuoteRequestParams = (params: Partial) => { ); }; }; + +export const getBridgeERC20Allowance = async ( + contractAddress: string, + chainId: Hex, +): Promise => { + return await submitRequestToBackground( + BridgeBackgroundAction.GET_BRIDGE_ERC20_ALLOWANCE, + [contractAddress, chainId], + ); +}; diff --git a/ui/ducks/bridge/selectors.ts b/ui/ducks/bridge/selectors.ts index 60704aa6f094..5624a0ec5569 100644 --- a/ui/ducks/bridge/selectors.ts +++ b/ui/ducks/bridge/selectors.ts @@ -26,7 +26,7 @@ import { calcTokenAmount } from '../../../shared/lib/transactions-controller-uti import { RequestStatus } from '../../../app/scripts/controllers/bridge/constants'; import { BridgeState } from './bridge'; -type BridgeAppState = { +export type BridgeAppState = { metamask: NetworkState & { bridgeState: BridgeControllerState } & { useExternalServices: boolean; }; diff --git a/ui/ducks/bridge/utils.ts b/ui/ducks/bridge/utils.ts new file mode 100644 index 000000000000..853c344310fe --- /dev/null +++ b/ui/ducks/bridge/utils.ts @@ -0,0 +1,47 @@ +import { Hex } from '@metamask/utils'; +import { BigNumber } from 'bignumber.js'; +import { decGWEIToHexWEI } from '../../../shared/modules/conversion.utils'; +import { Numeric } from '../../../shared/modules/Numeric'; +import { TxData } from '../../pages/bridge/types'; +import { getTransaction1559GasFeeEstimates } from '../../pages/swaps/swaps.util'; + +// We don't need to use gas multipliers here because the gasLimit from Bridge API already included it +export const getHexMaxGasLimit = (gasLimit: number) => { + return new Numeric( + new BigNumber(gasLimit).toString(), + 10, + ).toPrefixedHexString() as Hex; +}; +export const getTxGasEstimates = async ({ + networkAndAccountSupports1559, + networkGasFeeEstimates, + txParams, + hexChainId, +}: { + networkAndAccountSupports1559: boolean; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + networkGasFeeEstimates: any; + txParams: TxData; + hexChainId: Hex; +}) => { + if (networkAndAccountSupports1559) { + const { estimatedBaseFeeGwei = '0' } = networkGasFeeEstimates; + const hexEstimatedBaseFee = decGWEIToHexWEI(estimatedBaseFeeGwei) as Hex; + const txGasFeeEstimates = await getTransaction1559GasFeeEstimates( + { + ...txParams, + chainId: hexChainId, + gasLimit: txParams.gasLimit?.toString(), + }, + hexEstimatedBaseFee, + hexChainId, + ); + return txGasFeeEstimates; + } + + return { + baseAndPriorityFeePerGas: undefined, + maxFeePerGas: undefined, + maxPriorityFeePerGas: undefined, + }; +}; diff --git a/ui/hooks/useTransactionDisplayData.js b/ui/hooks/useTransactionDisplayData.js index 4b551b318b62..b008f2fdaf7d 100644 --- a/ui/hooks/useTransactionDisplayData.js +++ b/ui/hooks/useTransactionDisplayData.js @@ -357,6 +357,15 @@ export function useTransactionDisplayData(transactionGroup) { category = TransactionGroupCategory.send; title = t('send'); subtitle = t('toAddress', [shortenAddress(recipientAddress)]); + } else if (type === TransactionType.bridgeApproval) { + title = t('bridgeApproval'); + category = TransactionGroupCategory.approval; + title = t('bridgeApproval', [primaryTransaction.sourceTokenSymbol]); + subtitle = origin; + subtitleContainsOrigin = true; + primarySuffix = primaryTransaction.sourceTokenSymbol; // TODO this will be undefined right now + } else if (type === TransactionType.bridge) { + title = t('bridge'); } else { dispatch( captureSingleException( diff --git a/ui/pages/bridge/bridge.util.ts b/ui/pages/bridge/bridge.util.ts index bbdddab53658..577b1827b160 100644 --- a/ui/pages/bridge/bridge.util.ts +++ b/ui/pages/bridge/bridge.util.ts @@ -1,4 +1,6 @@ +import { Contract } from '@ethersproject/contracts'; import { Hex, add0x } from '@metamask/utils'; +import { abiERC20 } from '@metamask/metamask-eth-abis'; import { BridgeFeatureFlagsKey, BridgeFeatureFlags, @@ -8,6 +10,8 @@ import { import { BRIDGE_API_BASE_URL, BRIDGE_CLIENT_ID, + ETH_USDT_ADDRESS, + METABRIDGE_ETHEREUM_ADDRESS, } from '../../../shared/constants/bridge'; import { MINUTE } from '../../../shared/constants/time'; import fetchWithCache from '../../../shared/lib/fetch-with-cache'; @@ -26,6 +30,7 @@ import { // TODO: Remove restricted import // eslint-disable-next-line import/no-restricted-paths import { REFRESH_INTERVAL_MS } from '../../../app/scripts/controllers/bridge/constants'; +import { CHAIN_IDS } from '../../../shared/constants/network'; import { BridgeAsset, BridgeFlag, @@ -185,3 +190,22 @@ export async function fetchBridgeQuotes( }); return filteredQuotes; } +/** + * A function to return the txParam data for setting allowance to 0 for USDT on Ethereum + * + * @returns The txParam data that will reset allowance to 0, combine it with the approval tx params received from Bridge API + */ +export const getEthUsdtResetData = () => { + const UsdtContractInterface = new Contract(ETH_USDT_ADDRESS, abiERC20) + .interface; + const data = UsdtContractInterface.encodeFunctionData('approve', [ + METABRIDGE_ETHEREUM_ADDRESS, + '0', + ]); + + return data; +}; + +export const isEthUsdt = (chainId: Hex, address: string) => + chainId === CHAIN_IDS.MAINNET && + address.toLowerCase() === ETH_USDT_ADDRESS.toLowerCase(); diff --git a/ui/pages/bridge/hooks/useAddToken.ts b/ui/pages/bridge/hooks/useAddToken.ts new file mode 100644 index 000000000000..597149b16e49 --- /dev/null +++ b/ui/pages/bridge/hooks/useAddToken.ts @@ -0,0 +1,84 @@ +import { useDispatch, useSelector } from 'react-redux'; +import { NetworkConfiguration } from '@metamask/network-controller'; +import { Numeric } from '../../../../shared/modules/Numeric'; +import { QuoteResponse } from '../types'; +import { + getNetworkConfigurationsByChainId, + getSelectedNetworkClientId, +} from '../../../selectors'; +import { FEATURED_RPCS } from '../../../../shared/constants/network'; +import { addToken, addNetwork } from '../../../store/actions'; + +export default function useAddToken() { + const dispatch = useDispatch(); + const networkConfigurations = useSelector(getNetworkConfigurationsByChainId); + const sourceNetworkClientId = useSelector(getSelectedNetworkClientId); + + const addSourceToken = (quoteResponse: QuoteResponse) => { + const { + address, + decimals, + symbol, + icon: image, + } = quoteResponse.quote.srcAsset; + dispatch( + addToken({ + address, + decimals, + symbol, + image, + networkClientId: sourceNetworkClientId, + }), + ); + }; + + const addDestToken = async (quoteResponse: QuoteResponse) => { + // Look up the destination chain + const hexDestChainId = new Numeric(quoteResponse.quote.destChainId, 10) + .toPrefixedHexString() + .toLowerCase() as `0x${string}`; + const foundDestNetworkConfig: NetworkConfiguration | undefined = + networkConfigurations[hexDestChainId]; + let addedDestNetworkConfig: NetworkConfiguration | undefined; + + // If user has not added the network in MetaMask, add it for them silently + if (!foundDestNetworkConfig) { + const featuredRpc = FEATURED_RPCS.find( + (rpc) => rpc.chainId === hexDestChainId, + ); + if (!featuredRpc) { + throw new Error('No featured RPC found'); + } + addedDestNetworkConfig = (await dispatch( + addNetwork(featuredRpc), + )) as unknown as NetworkConfiguration; + } + + const destNetworkConfig = foundDestNetworkConfig || addedDestNetworkConfig; + if (!destNetworkConfig) { + throw new Error('No destination network configuration found'); + } + + // Add the token after network is guaranteed to exist + const rpcEndpointIndex = destNetworkConfig.defaultRpcEndpointIndex; + const destNetworkClientId = + destNetworkConfig.rpcEndpoints[rpcEndpointIndex].networkClientId; + const { + address, + decimals, + symbol, + icon: image, + } = quoteResponse.quote.destAsset; + await dispatch( + addToken({ + address, + decimals, + symbol, + image, + networkClientId: destNetworkClientId, + }), + ); + }; + + return { addSourceToken, addDestToken }; +} diff --git a/ui/pages/bridge/hooks/useHandleApprovalTx.ts b/ui/pages/bridge/hooks/useHandleApprovalTx.ts new file mode 100644 index 000000000000..67f2abf67e7e --- /dev/null +++ b/ui/pages/bridge/hooks/useHandleApprovalTx.ts @@ -0,0 +1,94 @@ +import { TransactionType } from '@metamask/transaction-controller'; +import { Hex } from '@metamask/utils'; +import { BigNumber } from 'bignumber.js'; +import { TxData, QuoteResponse, FeeType } from '../types'; +import { isEthUsdt, getEthUsdtResetData } from '../bridge.util'; +import { Numeric } from '../../../../shared/modules/Numeric'; +import { ETH_USDT_ADDRESS } from '../../../../shared/constants/bridge'; +import { getBridgeERC20Allowance } from '../../../ducks/bridge/actions'; +import useHandleTx from './useHandleTx'; + +export default function useHandleApprovalTx() { + const { handleTx } = useHandleTx(); + + const handleEthUsdtAllowanceReset = async ({ + approval, + quoteResponse, + hexChainId, + }: { + approval: TxData; + quoteResponse: QuoteResponse; + hexChainId: Hex; + }) => { + const allowance = new BigNumber( + await getBridgeERC20Allowance(ETH_USDT_ADDRESS, hexChainId), + ); + + // quote.srcTokenAmount is actually after the fees + // so we need to add fees back in for total allowance to give + const sentAmount = new BigNumber(quoteResponse.quote.srcTokenAmount) + .plus(quoteResponse.quote.feeData[FeeType.METABRIDGE].amount) + .toString(); + + const shouldResetApproval = allowance.lt(sentAmount) && allowance.gt(0); + + if (shouldResetApproval) { + const resetData = getEthUsdtResetData(); + const txParams = { + ...approval, + data: resetData, + }; + + await handleTx({ + txType: TransactionType.bridgeApproval, + txParams, + swapsOptions: { + hasApproveTx: true, + meta: { + type: TransactionType.bridgeApproval, + }, + }, + }); + } + }; + + const handleApprovalTx = async ({ + approval, + quoteResponse, + }: { + approval: TxData; + quoteResponse: QuoteResponse; + }) => { + const hexChainId = new Numeric( + approval.chainId, + 10, + ).toPrefixedHexString() as `0x${string}`; + + // On Ethereum, we need to reset the allowance to 0 for USDT first if we need to set a new allowance + // https://www.google.com/url?q=https://docs.unizen.io/trade-api/before-you-get-started/token-allowance-management-for-non-updatable-allowance-tokens&sa=D&source=docs&ust=1727386175513609&usg=AOvVaw3Opm6BSJeu7qO0Ve5iLTOh + if (isEthUsdt(hexChainId, quoteResponse.quote.srcAsset.address)) { + await handleEthUsdtAllowanceReset({ + approval, + quoteResponse, + hexChainId, + }); + } + + const txMeta = await handleTx({ + txType: TransactionType.bridgeApproval, + txParams: approval, + swapsOptions: { + hasApproveTx: true, + meta: { + type: TransactionType.bridgeApproval, + sourceTokenSymbol: quoteResponse.quote.srcAsset.symbol, + }, + }, + }); + + return txMeta.id; + }; + return { + handleApprovalTx, + }; +} diff --git a/ui/pages/bridge/hooks/useHandleBridgeTx.ts b/ui/pages/bridge/hooks/useHandleBridgeTx.ts new file mode 100644 index 000000000000..22b2a74fa077 --- /dev/null +++ b/ui/pages/bridge/hooks/useHandleBridgeTx.ts @@ -0,0 +1,48 @@ +import { BigNumber } from 'bignumber.js'; +import { TransactionType } from '@metamask/transaction-controller'; +import { Numeric } from '../../../../shared/modules/Numeric'; +import { FeeType, QuoteResponse } from '../types'; +import useHandleTx from './useHandleTx'; + +export default function useHandleBridgeTx() { + const { handleTx } = useHandleTx(); + + const handleBridgeTx = async ({ + quoteResponse, + approvalTxId, + }: { + quoteResponse: QuoteResponse; + approvalTxId: string | undefined; + }) => { + const sentAmount = new BigNumber(quoteResponse.quote.srcTokenAmount).plus( + quoteResponse.quote.feeData[FeeType.METABRIDGE].amount, + ); + const sentAmountDec = new Numeric(sentAmount, 10) + .shiftedBy(quoteResponse.quote.srcAsset.decimals) + .toString(); + + const txMeta = await handleTx({ + txType: TransactionType.bridge, + txParams: quoteResponse.trade, + swapsOptions: { + hasApproveTx: Boolean(quoteResponse?.approval), + meta: { + // estimatedBaseFee: decEstimatedBaseFee, + // swapMetaData, + type: TransactionType.bridge, + sourceTokenSymbol: quoteResponse.quote.srcAsset.symbol, + destinationTokenSymbol: quoteResponse.quote.destAsset.symbol, + destinationTokenDecimals: quoteResponse.quote.destAsset.decimals, + destinationTokenAddress: quoteResponse.quote.destAsset.address, + approvalTxId, + // this is the decimal (non atomic) amount (not USD value) of source token to swap + swapTokenValue: sentAmountDec, + }, + }, + }); + + return txMeta.id; + }; + + return { handleBridgeTx }; +} diff --git a/ui/pages/bridge/hooks/useHandleTx.ts b/ui/pages/bridge/hooks/useHandleTx.ts new file mode 100644 index 000000000000..a4cbf631c338 --- /dev/null +++ b/ui/pages/bridge/hooks/useHandleTx.ts @@ -0,0 +1,79 @@ +import { + TransactionMeta, + TransactionType, +} from '@metamask/transaction-controller'; +import { useDispatch, useSelector } from 'react-redux'; +import { + forceUpdateMetamaskState, + addTransactionAndWaitForPublish, +} from '../../../store/actions'; +import { + getHexMaxGasLimit, + getTxGasEstimates, +} from '../../../ducks/bridge/utils'; +import { getGasFeeEstimates } from '../../../ducks/metamask/metamask'; +import { checkNetworkAndAccountSupports1559 } from '../../../selectors'; +import { ChainId } from '../types'; +import { Numeric } from '../../../../shared/modules/Numeric'; + +export default function useHandleTx() { + const dispatch = useDispatch(); + const networkAndAccountSupports1559 = useSelector( + checkNetworkAndAccountSupports1559, + ); + const networkGasFeeEstimates = useSelector(getGasFeeEstimates); + + const handleTx = async ({ + txType, + txParams, + swapsOptions, + }: { + txType: TransactionType.bridgeApproval | TransactionType.bridge; + txParams: { + chainId: ChainId; + to: string; + from: string; + value: string; + data: string; + gasLimit: number | null; + }; + swapsOptions: { + hasApproveTx: boolean; + meta: Partial; + }; + }) => { + const hexChainId = new Numeric( + txParams.chainId, + 10, + ).toPrefixedHexString() as `0x${string}`; + + const { maxFeePerGas, maxPriorityFeePerGas } = await getTxGasEstimates({ + networkAndAccountSupports1559, + networkGasFeeEstimates, + txParams, + hexChainId, + }); + const maxGasLimit = getHexMaxGasLimit(txParams.gasLimit ?? 0); + + const finalTxParams = { + ...txParams, + chainId: hexChainId, + gasLimit: maxGasLimit, + gas: maxGasLimit, + maxFeePerGas, + maxPriorityFeePerGas, + }; + + const txMeta = await addTransactionAndWaitForPublish(finalTxParams, { + requireApproval: false, + type: txType, + swaps: swapsOptions, + }); + + await forceUpdateMetamaskState(dispatch); + + return txMeta; + }; + + return { handleTx }; +} diff --git a/ui/pages/bridge/hooks/useSubmitBridgeTransaction.test.tsx b/ui/pages/bridge/hooks/useSubmitBridgeTransaction.test.tsx new file mode 100644 index 000000000000..20f471b1065b --- /dev/null +++ b/ui/pages/bridge/hooks/useSubmitBridgeTransaction.test.tsx @@ -0,0 +1,485 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { renderHook } from '@testing-library/react-hooks'; +import { Provider } from 'react-redux'; +import { MemoryRouter, useHistory } from 'react-router-dom'; +import { createBridgeMockStore } from '../../../../test/jest/mock-store'; +import * as actions from '../../../store/actions'; +import * as selectors from '../../../selectors'; +import { + DummyQuotesNoApproval, + DummyQuotesWithApproval, +} from '../../../../test/data/bridge/dummy-quotes'; +import useSubmitBridgeTransaction from './useSubmitBridgeTransaction'; + +jest.mock('react-router-dom', () => { + const original = jest.requireActual('react-router-dom'); + return { + ...original, + useHistory: jest.fn().mockImplementation(original.useHistory), + }; +}); + +jest.mock('../../../ducks/bridge/utils', () => ({ + ...jest.requireActual('../../../ducks/bridge/utils'), + getTxGasEstimates: jest.fn(() => ({ + baseAndPriorityFeePerGas: '0', + maxFeePerGas: '0x1036640', + maxPriorityFeePerGas: '0x0', + })), +})); + +jest.mock('../../../store/actions', () => { + const original = jest.requireActual('../../../store/actions'); + return { + ...original, + addTransactionAndWaitForPublish: jest.fn(), + addToken: jest.fn().mockImplementation(original.addToken), + addNetwork: jest.fn().mockImplementation(original.addNetwork), + }; +}); + +jest.mock('../../../selectors', () => { + const original = jest.requireActual('../../../selectors'); + return { + ...original, + getIsBridgeEnabled: () => true, + getIsBridgeChain: () => true, + checkNetworkAndAccountSupports1559: () => true, + getSelectedNetworkClientId: () => 'mainnet', + getNetworkConfigurationsByChainId: jest.fn(() => ({ + '0x1': { + blockExplorerUrls: ['https://etherscan.io'], + chainId: '0x1', + defaultBlockExplorerUrlIndex: 0, + defaultRpcEndpointIndex: 0, + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + networkClientId: 'mainnet', + type: 'infura', + url: 'https://mainnet.infura.io/v3/infuraProjectId', + }, + ], + }, + '0xa4b1': { + blockExplorerUrls: ['https://explorer.arbitrum.io'], + chainId: '0xa4b1', + defaultBlockExplorerUrlIndex: 0, + defaultRpcEndpointIndex: 0, + name: 'Arbitrum One', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + networkClientId: '3725601d-f497-43aa-9afa-97c26e9033a3', + type: 'custom', + url: 'https://arbitrum-mainnet.infura.io/v3/infuraProjectId', + }, + ], + }, + })), + }; +}); + +const middleware = [thunk]; + +const makeMockStore = () => { + const store = configureMockStore(middleware)( + createBridgeMockStore( + {}, + {}, + {}, + { + gasFeeEstimates: { + high: { + maxWaitTimeEstimate: 30000, + minWaitTimeEstimate: 15000, + suggestedMaxFeePerGas: '14.226414113', + suggestedMaxPriorityFeePerGas: '2', + }, + }, + useExternalServices: true, + }, + ), + ); + return store; +}; + +const makeWrapper = + (store: ReturnType) => + ({ children }: { children: React.ReactNode }) => { + return ( + + {children} + + ); + }; + +describe('ui/pages/bridge/hooks/useSubmitBridgeTransaction', () => { + describe('submitBridgeTransaction', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + it('executes bridge transaction', async () => { + // Setup + const mockAddTransactionAndWaitForPublish = jest.fn(() => { + return { + id: 'txMetaId-01', + }; + }); + + // For some reason, setBackgroundConnection does not work, gets hung up on the promise, so mock this way instead + (actions.addTransactionAndWaitForPublish as jest.Mock).mockImplementation( + mockAddTransactionAndWaitForPublish, + ); + const store = makeMockStore(); + const { result } = renderHook(() => useSubmitBridgeTransaction(), { + wrapper: makeWrapper(store), + }); + + // Execute + await result.current.submitBridgeTransaction( + DummyQuotesWithApproval.ETH_11_USDC_TO_ARB[0] as any, + ); + + // Assert + expect(mockAddTransactionAndWaitForPublish).toHaveBeenLastCalledWith( + { + chainId: '0x1', + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d6c6966694164617074657256320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000e397c4883ec89ed4fc9d258f00c689708b2799c9000000000000000000000000e397c4883ec89ed4fc9d258f00c689708b2799c9000000000000000000000000000000000000000000000000000000000000a4b1000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000177fa000000000000000000000000e6b738da243e8fa2a0ed5915645789add5de515200000000000000000000000000000000000000000000000000000000000000902340ab8fc3119af1d016a0eec5fe6ef47965741f6f7a4734bf784bf3ae3f2452a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000a660c60000a4b10008df3abdeb853d66fefedfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd00dfeeddeadbeef8932eb23bad9bddb5cf81426f78279a53c6c3b7100000000000000000000000000000000740cfc1bc02079862368cb4eea1332bd9f2dfa925fc757fd51e40919859b87ca031a2a12d67e4ca4ba67d52b59114b3e18c1e8c839ae015112af82e92251db701b', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + gas: '0x33403', + gasLimit: '0x33403', + maxFeePerGas: '0x1036640', + maxPriorityFeePerGas: '0x0', + to: '0x0439e60F02a8900a951603950d8D4527f400C3f1', + value: '0x00', + }, + { + requireApproval: false, + swaps: { + hasApproveTx: true, + meta: { + approvalTxId: 'txMetaId-01', + destinationTokenAddress: + '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + destinationTokenDecimals: 6, + destinationTokenSymbol: 'USDC', + sourceTokenSymbol: 'USDC', + swapTokenValue: '11', + type: 'bridge', + }, + }, + type: 'bridge', + }, + ); + }); + it('executes approval transaction if it exists', async () => { + // Setup + const mockAddTransactionAndWaitForPublish = jest.fn(() => { + return { + id: 'txMetaId-01', + }; + }); + + // For some reason, setBackgroundConnection does not work, gets hung up on the promise, so mock this way instead + (actions.addTransactionAndWaitForPublish as jest.Mock).mockImplementation( + mockAddTransactionAndWaitForPublish, + ); + const store = makeMockStore(); + const { result } = renderHook(() => useSubmitBridgeTransaction(), { + wrapper: makeWrapper(store), + }); + + // Execute + await result.current.submitBridgeTransaction( + DummyQuotesWithApproval.ETH_11_USDC_TO_ARB[0] as any, + ); + + // Assert + expect(mockAddTransactionAndWaitForPublish).toHaveBeenNthCalledWith( + 1, + { + chainId: '0x1', + data: '0x095ea7b30000000000000000000000000439e60f02a8900a951603950d8d4527f400c3f10000000000000000000000000000000000000000000000000000000000a7d8c0', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + gas: '0xdc1d', + gasLimit: '0xdc1d', + maxFeePerGas: '0x1036640', + maxPriorityFeePerGas: '0x0', + to: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + value: '0x00', + }, + { + requireApproval: false, + swaps: { + hasApproveTx: true, + meta: { sourceTokenSymbol: 'USDC', type: 'bridgeApproval' }, + }, + type: 'bridgeApproval', + }, + ); + expect(mockAddTransactionAndWaitForPublish).toHaveBeenNthCalledWith( + 2, + { + chainId: '0x1', + data: '0x3ce33bff0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000a7d8c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d6c6966694164617074657256320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000e397c4883ec89ed4fc9d258f00c689708b2799c9000000000000000000000000e397c4883ec89ed4fc9d258f00c689708b2799c9000000000000000000000000000000000000000000000000000000000000a4b1000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000a660c6000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000177fa000000000000000000000000e6b738da243e8fa2a0ed5915645789add5de515200000000000000000000000000000000000000000000000000000000000000902340ab8fc3119af1d016a0eec5fe6ef47965741f6f7a4734bf784bf3ae3f2452a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000a660c60000a4b10008df3abdeb853d66fefedfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd00dfeeddeadbeef8932eb23bad9bddb5cf81426f78279a53c6c3b7100000000000000000000000000000000740cfc1bc02079862368cb4eea1332bd9f2dfa925fc757fd51e40919859b87ca031a2a12d67e4ca4ba67d52b59114b3e18c1e8c839ae015112af82e92251db701b', + from: '0xc5fe6ef47965741f6f7a4734bf784bf3ae3f2452', + gas: '0x33403', + gasLimit: '0x33403', + maxFeePerGas: '0x1036640', + maxPriorityFeePerGas: '0x0', + to: '0x0439e60F02a8900a951603950d8D4527f400C3f1', + value: '0x00', + }, + { + requireApproval: false, + swaps: { + hasApproveTx: true, + meta: { + approvalTxId: 'txMetaId-01', + destinationTokenAddress: + '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + destinationTokenDecimals: 6, + destinationTokenSymbol: 'USDC', + sourceTokenSymbol: 'USDC', + swapTokenValue: '11', + type: 'bridge', + }, + }, + type: 'bridge', + }, + ); + }); + it('adds source token if it not the native gas token', async () => { + // Setup + const store = makeMockStore(); + const { result } = renderHook(() => useSubmitBridgeTransaction(), { + wrapper: makeWrapper(store), + }); + + (actions.addToken as jest.Mock).mockImplementation( + () => async () => ({}), + ); + + // Execute + await result.current.submitBridgeTransaction( + DummyQuotesWithApproval.ETH_11_USDC_TO_ARB[0] as any, + ); + + // Assert + expect(actions.addToken).toHaveBeenCalledWith({ + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + decimals: 6, + image: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + networkClientId: 'mainnet', + symbol: 'USDC', + }); + + // Reset + const originalAddToken = jest.requireActual( + '../../../store/actions', + ).addToken; + (actions.addToken as jest.Mock).mockImplementation(originalAddToken); + }); + it('does not add source token if source token is native gas token', async () => { + // Setup + const store = makeMockStore(); + const { result } = renderHook(() => useSubmitBridgeTransaction(), { + wrapper: makeWrapper(store), + }); + + const mockAddTransactionAndWaitForPublish = jest.fn(() => { + return { + id: 'txMetaId-01', + }; + }); + // For some reason, setBackgroundConnection does not work, gets hung up on the promise, so mock this way instead + (actions.addTransactionAndWaitForPublish as jest.Mock).mockImplementation( + mockAddTransactionAndWaitForPublish, + ); + (actions.addToken as jest.Mock).mockImplementation( + () => async () => ({}), + ); + + // Execute + await result.current.submitBridgeTransaction( + DummyQuotesNoApproval.OP_0_005_ETH_TO_ARB[0] as any, + ); + + // Assert + expect(actions.addToken).not.toHaveBeenCalled(); + + // Reset + const originalAddToken = jest.requireActual( + '../../../store/actions', + ).addToken; + (actions.addToken as jest.Mock).mockImplementation(originalAddToken); + }); + it('adds dest token if it not the native gas token', async () => { + // Setup + const store = makeMockStore(); + const { result } = renderHook(() => useSubmitBridgeTransaction(), { + wrapper: makeWrapper(store), + }); + + (actions.addToken as jest.Mock).mockImplementation( + () => async () => ({}), + ); + + // Execute + await result.current.submitBridgeTransaction( + DummyQuotesWithApproval.ETH_11_USDC_TO_ARB[0] as any, + ); + + // Assert + expect(actions.addToken).toHaveBeenCalledWith({ + address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', + decimals: 6, + image: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + networkClientId: '3725601d-f497-43aa-9afa-97c26e9033a3', + symbol: 'USDC', + }); + + // Reset + const originalAddToken = jest.requireActual( + '../../../store/actions', + ).addToken; + (actions.addToken as jest.Mock).mockImplementation(originalAddToken); + }); + it('does not add dest token if dest token is native gas token', async () => { + // Setup + const store = makeMockStore(); + const { result } = renderHook(() => useSubmitBridgeTransaction(), { + wrapper: makeWrapper(store), + }); + + const mockAddTransactionAndWaitForPublish = jest.fn(() => { + return { + id: 'txMetaId-01', + }; + }); + // For some reason, setBackgroundConnection does not work, gets hung up on the promise, so mock this way instead + (actions.addTransactionAndWaitForPublish as jest.Mock).mockImplementation( + mockAddTransactionAndWaitForPublish, + ); + (actions.addToken as jest.Mock).mockImplementation( + () => async () => ({}), + ); + + // Execute + await result.current.submitBridgeTransaction( + DummyQuotesNoApproval.OP_0_005_ETH_TO_ARB[0] as any, + ); + + // Assert + expect(actions.addToken).not.toHaveBeenCalled(); + + // Reset + const originalAddToken = jest.requireActual( + '../../../store/actions', + ).addToken; + (actions.addToken as jest.Mock).mockImplementation(originalAddToken); + }); + it('adds dest network if it does not exist', async () => { + // Setup + const store = makeMockStore(); + + const mockAddTransactionAndWaitForPublish = jest.fn(() => { + return { + id: 'txMetaId-01', + }; + }); + // For some reason, setBackgroundConnection does not work, gets hung up on the promise, so mock this way instead + (actions.addTransactionAndWaitForPublish as jest.Mock).mockImplementation( + mockAddTransactionAndWaitForPublish, + ); + const mockedGetNetworkConfigurationsByChainId = + // @ts-expect-error this is a jest mock + selectors.getNetworkConfigurationsByChainId as jest.Mock; + mockedGetNetworkConfigurationsByChainId.mockImplementationOnce(() => ({ + '0x1': { + blockExplorerUrls: ['https://etherscan.io'], + chainId: '0x1', + defaultBlockExplorerUrlIndex: 0, + defaultRpcEndpointIndex: 0, + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + networkClientId: 'mainnet', + type: 'infura', + url: 'https://mainnet.infura.io/v3/infuraProjectId', + }, + ], + }, + })); + (actions.addNetwork as jest.Mock).mockImplementationOnce( + () => async () => ({ + blockExplorerUrls: ['https://explorer.arbitrum.io'], + chainId: '0xa4b1', + defaultBlockExplorerUrlIndex: 0, + defaultRpcEndpointIndex: 0, + name: 'Arbitrum One', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + networkClientId: '3725601d-f497-43aa-9afa-97c26e9033a3', + type: 'custom', + url: 'https://arbitrum-mainnet.infura.io/v3/infuraProjectId', + }, + ], + }), + ); + const { result } = renderHook(() => useSubmitBridgeTransaction(), { + wrapper: makeWrapper(store), + }); + + // Execute + await result.current.submitBridgeTransaction( + DummyQuotesWithApproval.ETH_11_USDC_TO_ARB[0] as any, + ); + + // Assert + expect(actions.addNetwork).toHaveBeenCalledWith({ + blockExplorerUrls: ['https://explorer.arbitrum.io'], + chainId: '0xa4b1', + defaultBlockExplorerUrlIndex: 0, + defaultRpcEndpointIndex: 0, + name: 'Arbitrum One', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + type: 'custom', + url: 'https://arbitrum-mainnet.infura.io/v3/undefined', + }, + ], + }); + }); + it('routes to activity tab', async () => { + const store = makeMockStore(); + + const mockHistory = { + push: jest.fn(), + }; + (useHistory as jest.Mock).mockImplementationOnce(() => mockHistory); + const { result } = renderHook(() => useSubmitBridgeTransaction(), { + wrapper: makeWrapper(store), + }); + + // Execute + await result.current.submitBridgeTransaction( + DummyQuotesWithApproval.ETH_11_USDC_TO_ARB[0] as any, + ); + + // Assert + expect(mockHistory.push).toHaveBeenCalledWith('/'); + }); + }); +}); diff --git a/ui/pages/bridge/hooks/useSubmitBridgeTransaction.ts b/ui/pages/bridge/hooks/useSubmitBridgeTransaction.ts new file mode 100644 index 000000000000..db3b1c86ca06 --- /dev/null +++ b/ui/pages/bridge/hooks/useSubmitBridgeTransaction.ts @@ -0,0 +1,49 @@ +import { useDispatch } from 'react-redux'; +import { zeroAddress } from 'ethereumjs-util'; +import { useHistory } from 'react-router-dom'; +import { QuoteResponse } from '../types'; +import { DEFAULT_ROUTE } from '../../../helpers/constants/routes'; +import { setDefaultHomeActiveTabName } from '../../../store/actions'; +import useAddToken from './useAddToken'; +import useHandleApprovalTx from './useHandleApprovalTx'; +import useHandleBridgeTx from './useHandleBridgeTx'; + +export default function useSubmitBridgeTransaction() { + const history = useHistory(); + const dispatch = useDispatch(); + const { addSourceToken, addDestToken } = useAddToken(); + const { handleApprovalTx } = useHandleApprovalTx(); + const { handleBridgeTx } = useHandleBridgeTx(); + + const submitBridgeTransaction = async (quoteResponse: QuoteResponse) => { + // Execute transaction(s) + let approvalTxId: string | undefined; + if (quoteResponse?.approval) { + approvalTxId = await handleApprovalTx({ + approval: quoteResponse.approval, + quoteResponse, + }); + } + + await handleBridgeTx({ + quoteResponse, + approvalTxId, + }); + + // Add tokens if not the native gas token + if (quoteResponse.quote.srcAsset.address !== zeroAddress()) { + addSourceToken(quoteResponse); + } + if (quoteResponse.quote.destAsset.address !== zeroAddress()) { + await addDestToken(quoteResponse); + } + + // Route user to activity tab on Home page + await dispatch(setDefaultHomeActiveTabName('activity')); + history.push(DEFAULT_ROUTE); + }; + + return { + submitBridgeTransaction, + }; +} diff --git a/ui/pages/bridge/index.tsx b/ui/pages/bridge/index.tsx index 62244e5793e5..2c9f082519e9 100644 --- a/ui/pages/bridge/index.tsx +++ b/ui/pages/bridge/index.tsx @@ -25,12 +25,15 @@ import { } from '../../components/multichain/pages/page'; import { getProviderConfig } from '../../ducks/metamask/metamask'; import { resetBridgeState, setFromChain } from '../../ducks/bridge/actions'; +import { useSwapsFeatureFlags } from '../swaps/hooks/useSwapsFeatureFlags'; import PrepareBridgePage from './prepare/prepare-bridge-page'; import { BridgeCTAButton } from './prepare/bridge-cta-button'; const CrossChainSwap = () => { const t = useContext(I18nContext); + // Load swaps feature flags so that we can use smart transactions + useSwapsFeatureFlags(); useBridging(); const history = useHistory(); diff --git a/ui/pages/bridge/prepare/bridge-cta-button.tsx b/ui/pages/bridge/prepare/bridge-cta-button.tsx index 28a1a2c1fbd6..06d784f2e0ea 100644 --- a/ui/pages/bridge/prepare/bridge-cta-button.tsx +++ b/ui/pages/bridge/prepare/bridge-cta-button.tsx @@ -1,19 +1,23 @@ import React, { useMemo } from 'react'; -import { useSelector } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { Button } from '../../../components/component-library'; import { getBridgeQuotes, getFromAmount, getFromChain, getFromToken, + getRecommendedQuote, getToAmount, getToChain, getToToken, } from '../../../ducks/bridge/selectors'; import { useI18nContext } from '../../../hooks/useI18nContext'; +import useSubmitBridgeTransaction from '../hooks/useSubmitBridgeTransaction'; export const BridgeCTAButton = () => { + const dispatch = useDispatch(); const t = useI18nContext(); + const fromToken = useSelector(getFromToken); const toToken = useSelector(getToToken); @@ -24,6 +28,9 @@ export const BridgeCTAButton = () => { const toAmount = useSelector(getToAmount); const { isLoading } = useSelector(getBridgeQuotes); + const quoteResponse = useSelector(getRecommendedQuote); + + const { submitBridgeTransaction } = useSubmitBridgeTransaction(); const isTxSubmittable = fromToken && toToken && fromChain && toChain && fromAmount && toAmount; @@ -52,7 +59,7 @@ export const BridgeCTAButton = () => { data-testid="bridge-cta-button" onClick={() => { if (isTxSubmittable) { - // dispatch tx submission + dispatch(submitBridgeTransaction(quoteResponse)); } }} disabled={!isTxSubmittable} diff --git a/ui/pages/bridge/types.ts b/ui/pages/bridge/types.ts index 5d001e7ef7fc..a1ee163eca48 100644 --- a/ui/pages/bridge/types.ts +++ b/ui/pages/bridge/types.ts @@ -6,6 +6,9 @@ export enum BridgeFlag { NETWORK_DEST_ALLOWLIST = 'dest-network-allowlist', } +type DecimalChainId = string; +export type GasMultiplierByChainId = Record; + export type FeatureFlagResponse = { [BridgeFlag.EXTENSION_CONFIG]: { refreshRate: number; @@ -89,7 +92,7 @@ export type QuoteResponse = { estimatedProcessingTimeInSeconds: number; }; -enum ChainId { +export enum ChainId { ETH = 1, OPTIMISM = 10, BSC = 56, diff --git a/ui/pages/swaps/hooks/useSwapsFeatureFlags.ts b/ui/pages/swaps/hooks/useSwapsFeatureFlags.ts new file mode 100644 index 000000000000..93460c892d7f --- /dev/null +++ b/ui/pages/swaps/hooks/useSwapsFeatureFlags.ts @@ -0,0 +1,14 @@ +import { useEffect } from 'react'; +import { useDispatch } from 'react-redux'; +import { fetchSwapsLivenessAndFeatureFlags } from '../../../ducks/swaps/swaps'; + +export function useSwapsFeatureFlags() { + const dispatch = useDispatch(); + + useEffect(() => { + const fetchSwapsLivenessAndFeatureFlagsWrapper = async () => { + await dispatch(fetchSwapsLivenessAndFeatureFlags()); + }; + fetchSwapsLivenessAndFeatureFlagsWrapper(); + }, [dispatch]); +} diff --git a/ui/pages/swaps/swaps.util.ts b/ui/pages/swaps/swaps.util.ts index 9cbf0b67a867..7065c7ae90dc 100644 --- a/ui/pages/swaps/swaps.util.ts +++ b/ui/pages/swaps/swaps.util.ts @@ -823,7 +823,7 @@ export const getSwap1559GasFeeEstimates = async ( }; }; -async function getTransaction1559GasFeeEstimates( +export async function getTransaction1559GasFeeEstimates( transactionParams: TransactionParams, estimatedBaseFee: Hex, chainId: Hex, diff --git a/ui/store/actions.ts b/ui/store/actions.ts index 6344f823aa02..01c34dc2fe3d 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -2448,7 +2448,12 @@ export function createRetryTransaction( export function addNetwork( networkConfiguration: AddNetworkFields | UpdateNetworkFields, -): ThunkAction, MetaMaskReduxState, unknown, AnyAction> { +): ThunkAction< + Promise, + MetaMaskReduxState, + unknown, + AnyAction +> { return async (dispatch: MetaMaskReduxDispatch) => { log.debug(`background.addNetwork`, networkConfiguration); try { From 02d52b49c06a6b1d8b65e4ee4450aa7db2357220 Mon Sep 17 00:00:00 2001 From: julesat22 <142838415+julesat22@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:38:43 -0800 Subject: [PATCH 3/5] feat: Hook in Portfolio Entry Points (#27607) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** 1. What is the reason for the change? Portfolio has requested to add in some entry points into the extension, so users can easily navigate to the Portfolio to view/ manage their spending caps. 2. What is the improvement/solution? This adds value for the users who would like to view/ manage their spending caps as well as their portfolio. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27607?quickstart=1) ## **Manual testing steps** 1. Connect an account 2. Go to this the assets page in the extension 3. Click on an asset 4. Under "Token details", there should be a category for all native and non-native token types for "Spending caps" 5. Next to Spending caps, check the there is a link that routes the user to the portfolio with the "spendingCaps" tab and the user's account address passed as query params 6. Check that the link redirects to Portfolio ## **Screenshots/Recordings** ### **Before** Screenshot 2024-10-03 at 10 45 22 AM ### **After** Screenshot 2024-10-03 at 9 37 54 AM Screenshot 2024-10-03 at 9 33 21 AM Screenshot 2024-10-03 at 9 32 20 AM ## **Pre-merge author checklist** - [X] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md). - [X] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [X] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: Julia Collins Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com> Co-authored-by: Ziad Saab Co-authored-by: georgewrmarshall --- app/_locales/en/messages.json | 6 + ui/pages/asset/asset.scss | 20 +- .../__snapshots__/asset-page.test.tsx.snap | 224 ++++++++++++------ ui/pages/asset/components/asset-page.tsx | 77 ++++-- 4 files changed, 237 insertions(+), 90 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index bdba7b1214a3..624c7e2b163b 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1830,6 +1830,9 @@ "editGasTooLow": { "message": "Unknown processing time" }, + "editInPortfolio": { + "message": "Edit in Portfolio" + }, "editNetworkLink": { "message": "edit the original network" }, @@ -5382,6 +5385,9 @@ "spendingCapTooltipDesc": { "message": "This is the amount of tokens the spender will be able to access on your behalf." }, + "spendingCaps": { + "message": "Spending caps" + }, "srpInputNumberOfWords": { "message": "I have a $1-word phrase", "description": "This is the text for each option in the dropdown where a user selects how many words their secret recovery phrase has during import. The $1 is the number of words (either 12, 15, 18, 21, or 24)." diff --git a/ui/pages/asset/asset.scss b/ui/pages/asset/asset.scss index 8d682beae58b..d6f6a3d39d9b 100644 --- a/ui/pages/asset/asset.scss +++ b/ui/pages/asset/asset.scss @@ -1,4 +1,4 @@ -@use "design-system"; +@use 'design-system'; .asset { &__container { @@ -42,5 +42,19 @@ } } -.chart-up { stroke: var(--color-success-default); } -.chart-down { stroke: var(--color-error-default); } +.chart-up { + stroke: var(--color-success-default); +} + +.chart-down { + stroke: var(--color-error-default); +} + +.asset-page__spending-caps { + text-decoration: none; + + &:hover { + color: var(--color-primary-alternative); + text-decoration: underline; + } +} diff --git a/ui/pages/asset/components/__snapshots__/asset-page.test.tsx.snap b/ui/pages/asset/components/__snapshots__/asset-page.test.tsx.snap index b5ebc0a83eb6..8a5c60e340cb 100644 --- a/ui/pages/asset/components/__snapshots__/asset-page.test.tsx.snap +++ b/ui/pages/asset/components/__snapshots__/asset-page.test.tsx.snap @@ -254,6 +254,36 @@ exports[`AssetPage should render a native asset 1`] = `
+
+

+ Token details +

+
+
+

+ Spending caps +

+ + Edit in Portfolio + +
+
+
@@ -555,59 +585,84 @@ exports[`AssetPage should render an ERC20 asset without prices 1`] = ` Token details
-

- Contract address -

-
- + +
+ 0x30937...C4936 +
+
+ + +
+
+
+
+
+

+ Token decimal +

+

+ 18 +

+
-
-

- Token decimal + Spending caps

-

- 18 -

+ Edit in Portfolio +
@@ -1038,59 +1093,84 @@ exports[`AssetPage should render an ERC20 token with prices 1`] = ` Token details
-

- Contract address -

-
- + +
+ 0xe4246...85f55 +
+
+ + +
+
+
+
+
+

+ Token decimal +

+

+ 18 +

+
- -

- Token decimal + Spending caps

-

- 18 -

+ Edit in Portfolio +
diff --git a/ui/pages/asset/components/asset-page.tsx b/ui/pages/asset/components/asset-page.tsx index 29078e3a248c..818ceb792ec3 100644 --- a/ui/pages/asset/components/asset-page.tsx +++ b/ui/pages/asset/components/asset-page.tsx @@ -1,4 +1,4 @@ -import React, { ReactNode } from 'react'; +import React, { ReactNode, useMemo } from 'react'; import { useHistory } from 'react-router-dom'; import { useSelector } from 'react-redux'; @@ -6,8 +6,11 @@ import { EthMethod } from '@metamask/keyring-api'; import { isEqual } from 'lodash'; import { getCurrentCurrency, + getDataCollectionForMarketing, getIsBridgeChain, getIsSwapsChain, + getMetaMetricsId, + getParticipateInMetaMetrics, getSelectedInternalAccount, getSwapsDefaultToken, getTokensMarketData, @@ -24,6 +27,7 @@ import { Box, ButtonIcon, ButtonIconSize, + ButtonLink, IconName, Text, } from '../../../components/component-library'; @@ -42,6 +46,7 @@ import { getConversionRate } from '../../../ducks/metamask/metamask'; import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; import CoinButtons from '../../../components/app/wallet-overview/coin-buttons'; import { getIsNativeTokenBuyable } from '../../../ducks/ramps'; +import { getPortfolioUrl } from '../../../helpers/utils/portfolio'; import AssetChart from './chart/asset-chart'; import TokenButtons from './token-buttons'; @@ -110,6 +115,10 @@ const AssetPage = ({ account.methods.includes(EthMethod.SignTransaction) || account.methods.includes(EthMethod.SignUserOperation); + const isMetaMetricsEnabled = useSelector(getParticipateInMetaMetrics); + const isMarketingEnabled = useSelector(getDataCollectionForMarketing); + const metaMetricsId = useSelector(getMetaMetricsId); + const { chainId, type, symbol, name, image, balance } = asset; const address = @@ -124,6 +133,20 @@ const AssetPage = ({ ? conversionRate * marketData.price : undefined; + const portfolioSpendingCapsUrl = useMemo( + () => + getPortfolioUrl( + '', + 'asset_page', + metaMetricsId, + isMetaMetricsEnabled, + isMarketingEnabled, + account.address, + 'spending-caps', + ), + [account.address, isMarketingEnabled, isMetaMetricsEnabled, metaMetricsId], + ); + return ( - {type === AssetType.token && ( + {[AssetType.token, AssetType.native].includes(type) && ( {t('tokenDetails')} - {renderRow( - t('contractAddress'), - , - )} - {asset.decimals !== undefined && - renderRow(t('tokenDecimal'), {asset.decimals})} - {asset.aggregators && asset.aggregators?.length > 0 && ( + {type === AssetType.token && ( - , + )} + - {t('tokenList')} - - {asset.aggregators?.join(', ')} + {asset.decimals !== undefined && + renderRow( + t('tokenDecimal'), + {asset.decimals}, + )} + {asset.aggregators && asset.aggregators.length > 0 && ( + + + {t('tokenList')} + + {asset.aggregators.join(', ')} + + )} + )} + {renderRow( + t('spendingCaps'), + + {t('editInPortfolio')} + , + )} )} From 874c372bbe276479f11a24e395016fc13c899c0e Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Thu, 21 Nov 2024 08:49:01 -0800 Subject: [PATCH 4/5] fix: Block explorer bug, redirect if no explorer present --- ui/pages/asset/components/token-asset.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ui/pages/asset/components/token-asset.tsx b/ui/pages/asset/components/token-asset.tsx index 78d4cd0cc628..137639056024 100644 --- a/ui/pages/asset/components/token-asset.tsx +++ b/ui/pages/asset/components/token-asset.tsx @@ -6,7 +6,7 @@ import { useHistory } from 'react-router-dom'; import { Hex } from '@metamask/utils'; import { NetworkConfiguration } from '@metamask/network-controller'; import { - getAllEnabledNetworks, + getNetworkConfigurationsByChainId, getSelectedInternalAccount, getTokenList, selectERC20TokensByChain, @@ -31,11 +31,15 @@ const TokenAsset = ({ token, chainId }: { token: Token; chainId: Hex }) => { const tokenList = useSelector(getTokenList); const allNetworks: { [key: `0x${string}`]: NetworkConfiguration; - } = useSelector(getAllEnabledNetworks); + } = useSelector(getNetworkConfigurationsByChainId); // get the correct rpc url for the current token - const defaultIdx = allNetworks[chainId].defaultBlockExplorerUrlIndex; + const defaultIdx = allNetworks[chainId]?.defaultBlockExplorerUrlIndex; const currentTokenBlockExplorer = - allNetworks[chainId]?.blockExplorerUrls[defaultIdx ?? 0]; + defaultIdx === undefined + ? null + : allNetworks[chainId]?.blockExplorerUrls[defaultIdx]; + + console.log('currentTokenBlockExplorer', currentTokenBlockExplorer); const { address: walletAddress } = useSelector(getSelectedInternalAccount); const erc20TokensByChain = useSelector(selectERC20TokensByChain); From 660ed55a8795a6f225825a0256d9d384a45e49ee Mon Sep 17 00:00:00 2001 From: Nicholas Gambino Date: Thu, 21 Nov 2024 09:10:57 -0800 Subject: [PATCH 5/5] fix: Cleanup --- ui/pages/asset/components/token-asset.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ui/pages/asset/components/token-asset.tsx b/ui/pages/asset/components/token-asset.tsx index 137639056024..ef91b92aae5d 100644 --- a/ui/pages/asset/components/token-asset.tsx +++ b/ui/pages/asset/components/token-asset.tsx @@ -39,8 +39,6 @@ const TokenAsset = ({ token, chainId }: { token: Token; chainId: Hex }) => { ? null : allNetworks[chainId]?.blockExplorerUrls[defaultIdx]; - console.log('currentTokenBlockExplorer', currentTokenBlockExplorer); - const { address: walletAddress } = useSelector(getSelectedInternalAccount); const erc20TokensByChain = useSelector(selectERC20TokensByChain); @@ -76,8 +74,9 @@ const TokenAsset = ({ token, chainId }: { token: Token; chainId: Hex }) => { chainId, '', walletAddress, - { blockExplorerUrl: currentTokenBlockExplorer }, + { blockExplorerUrl: currentTokenBlockExplorer ?? '' }, ); + console.log(tokenTrackerLink); return (