diff --git a/packages/checkout/sdk/src/Checkout.test.ts b/packages/checkout/sdk/src/Checkout.test.ts index 5eb987a153..725f35a55c 100644 --- a/packages/checkout/sdk/src/Checkout.test.ts +++ b/packages/checkout/sdk/src/Checkout.test.ts @@ -101,7 +101,6 @@ describe('Connect', () => { }); expect(connectSite).toBeCalledTimes(1); - expect(getNetworkInfo).toBeCalledTimes(1); }); it('should call getBalance when no contract address provided', async () => { diff --git a/packages/checkout/sdk/src/Checkout.ts b/packages/checkout/sdk/src/Checkout.ts index eb6b0b6809..0acbf31fe7 100644 --- a/packages/checkout/sdk/src/Checkout.ts +++ b/packages/checkout/sdk/src/Checkout.ts @@ -134,13 +134,10 @@ export class Checkout { params.provider, { allowUnsupportedProvider: true } as ValidateProviderOptions, ); + await connect.connectSite(web3Provider); - const networkInfo = await network.getNetworkInfo(this.config, web3Provider); - return { - provider: web3Provider, - network: networkInfo, - }; + return { provider: web3Provider }; } /** diff --git a/packages/checkout/sdk/src/types/connect.ts b/packages/checkout/sdk/src/types/connect.ts index 24b7b280f8..95ee18d843 100644 --- a/packages/checkout/sdk/src/types/connect.ts +++ b/packages/checkout/sdk/src/types/connect.ts @@ -1,5 +1,4 @@ import { Web3Provider } from '@ethersproject/providers'; -import { NetworkInfo } from './networkInfo'; /** * Interface representing the params of {@link Checkout.connect}. @@ -12,11 +11,9 @@ export interface ConnectParams { /** * Interface representing the result of {@link Checkout.connect}. * @property {Web3Provider} provider - The provider used to connect to the network. - * @property {NetworkInfo} network - Information about the connected network. */ export interface ConnectResult { provider: Web3Provider; - network: NetworkInfo; } /** diff --git a/packages/checkout/widgets-lib/src/components/ConnectLoader/ConnectLoader.cy.tsx b/packages/checkout/widgets-lib/src/components/ConnectLoader/ConnectLoader.cy.tsx index fbde96ef40..394cd3b9bb 100644 --- a/packages/checkout/widgets-lib/src/components/ConnectLoader/ConnectLoader.cy.tsx +++ b/packages/checkout/widgets-lib/src/components/ConnectLoader/ConnectLoader.cy.tsx @@ -150,6 +150,7 @@ describe('ConnectLoader', () => { provider, getSigner: () => ({ getAddress: async () => Promise.resolve(''), + getChainId: async () => Promise.resolve(ChainId.IMTBL_ZKEVM_TESTNET), }), isMetaMask: true, } as any as Web3Provider, diff --git a/packages/checkout/widgets-lib/src/lib/analytics/identifyUser.ts b/packages/checkout/widgets-lib/src/lib/analytics/identifyUser.ts index 8c3f563168..e466242304 100644 --- a/packages/checkout/widgets-lib/src/lib/analytics/identifyUser.ts +++ b/packages/checkout/widgets-lib/src/lib/analytics/identifyUser.ts @@ -14,8 +14,11 @@ export async function identifyUser( const walletAddress = (await provider.getSigner().getAddress()).toLowerCase(); const isMetaMask = isMetaMaskProvider(provider); const isPassport = isPassportProvider(provider); - identify(walletAddress, { - isMetaMask, - isPassportWallet: isPassport, - }); + try { + identify(walletAddress, { + isMetaMask, + isPassportWallet: isPassport, + }); + // eslint-disable-next-line no-console + } catch (error: any) { console.error('analytics: unable to identify user: ', error); } } diff --git a/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidget.cy.tsx b/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidget.cy.tsx index 8736758530..9d784118c6 100644 --- a/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidget.cy.tsx +++ b/packages/checkout/widgets-lib/src/widgets/connect/ConnectWidget.cy.tsx @@ -266,209 +266,250 @@ describe('ConnectWidget tests', () => { }); describe('SwitchNetwork', () => { - beforeEach(() => { - cy.stub(Checkout.prototype, 'connect').as('connectStub').resolves({ - provider: baseMockProvider as Web3Provider, - }); - cy.stub(Checkout.prototype, 'createProvider') - .as('createProviderStub') - .resolves({ - provider: baseMockProvider as Web3Provider, + describe('No Switch', () => { + beforeEach(() => { + cy.stub(Checkout.prototype, 'connect').as('connectStub').resolves({ + provider: { + getSigner: () => ({ + getAddress: () => Promise.resolve(''), + getChainId: async () => Promise.resolve(ChainId.IMTBL_ZKEVM_TESTNET), + }), + } as Web3Provider, }); - }); + cy.stub(Checkout.prototype, 'createProvider') + .as('createProviderStub') + .resolves({ + provider: { + getSigner: () => ({ + getAddress: () => Promise.resolve(''), + getChainId: async () => Promise.resolve(ChainId.IMTBL_ZKEVM_TESTNET), + }), + } as Web3Provider, + }); + }); - it('should not show switch to zkEVM network if already connected to immutable-zkevm', () => { - cy.stub(Checkout.prototype, 'getNetworkInfo') - .as('getNetworkInfoStub') - .resolves({ - name: ChainName.IMTBL_ZKEVM_TESTNET, - chainId: ChainId.IMTBL_ZKEVM_TESTNET, - }); - mountConnectWidgetAndGoToReadyToConnect(); - cySmartGet('ready-to-connect').should('be.visible'); - cySmartGet('footer-button').should('have.text', 'Ready to connect'); - cySmartGet('footer-button').click(); - cySmartGet('switch-network-view').should('not.exist'); - cySmartGet('success-view').should('be.visible'); + it('should not show switch to ZKEVM network if already connected to ZKEVM', () => { + mountConnectWidgetAndGoToReadyToConnect(); + cySmartGet('ready-to-connect').should('be.visible'); + cySmartGet('footer-button').should('have.text', 'Ready to connect'); + cySmartGet('footer-button').click(); + cySmartGet('switch-network-view').should('not.exist'); + cySmartGet('success-view').should('be.visible'); + }); }); - it('should show switch to zkEVM network if not connected to immutable-zkevm', () => { - cy.stub(Checkout.prototype, 'getNetworkInfo') - .as('getNetworkInfoStub') - .resolves({ - name: 'Ethereum', - chainId: ChainId.ETHEREUM, + describe('Switch', () => { + beforeEach(() => { + cy.stub(Checkout.prototype, 'connect').as('connectStub').resolves({ + provider: { + getSigner: () => ({ + getAddress: () => Promise.resolve(''), + getChainId: async () => Promise.resolve(ChainId.SEPOLIA), + }), + } as Web3Provider, }); - mountConnectWidgetAndGoToReadyToConnect(); - cySmartGet('ready-to-connect').should('be.visible'); - cySmartGet('footer-button').should('have.text', 'Ready to connect'); - cySmartGet('footer-button').click(); - cySmartGet('switch-network-view').should('be.visible'); - }); + cy.stub(Checkout.prototype, 'createProvider') + .as('createProviderStub') + .resolves({ + provider: { + getSigner: () => ({ + getAddress: () => Promise.resolve(''), + getChainId: async () => Promise.resolve(ChainId.SEPOLIA), + }), + } as Web3Provider, + }); + }); - it('should show success when ready to connect pressed and network switched', () => { - cy.stub(Checkout.prototype, 'getNetworkInfo') - .as('getNetworkInfoStub') - .resolves({ - name: 'Ethereum', - chainId: ChainId.ETHEREUM, - }); - cy.stub(Checkout.prototype, 'switchNetwork') - .as('switchNetworkStub') - .resolves({ - provider: baseMockProvider as Web3Provider, - network: { - name: ChainName.IMTBL_ZKEVM_TESTNET, - chainId: ChainId.IMTBL_ZKEVM_TESTNET, - }, - }); - mountConnectWidgetAndGoToReadyToConnect(); - cySmartGet('ready-to-connect').should('be.visible'); - cySmartGet('footer-button').should('have.text', 'Ready to connect'); - cySmartGet('footer-button').click(); - cySmartGet('switch-network-view').should('be.visible'); - cySmartGet('footer-button').click(); - cySmartGet('success-view').should('be.visible'); - }); + it('should show switch to zkEVM network if not connected to immutable-zkevm', () => { + cy.stub(Checkout.prototype, 'getNetworkInfo') + .as('getNetworkInfoStub') + .resolves({ + name: 'Ethereum', + chainId: ChainId.ETHEREUM, + }); + mountConnectWidgetAndGoToReadyToConnect(); + cySmartGet('ready-to-connect').should('be.visible'); + cySmartGet('footer-button').should('have.text', 'Ready to connect'); + cySmartGet('footer-button').click(); + cySmartGet('switch-network-view').should('be.visible'); + }); - it('should show try again if network switch was rejected', () => { - cy.stub(Checkout.prototype, 'getNetworkInfo') - .as('getNetworkInfoStub') - .resolves({ - name: 'Ethereum', - chainId: ChainId.ETHEREUM, - }); - cy.stub(Checkout.prototype, 'switchNetwork') - .as('switchNetworkStub') - .rejects({}); - mountConnectWidgetAndGoToReadyToConnect(); - cySmartGet('ready-to-connect').should('be.visible'); - cySmartGet('footer-button').should('have.text', 'Ready to connect'); - cySmartGet('footer-button').click(); - cySmartGet('switch-network-view').should('be.visible'); - cySmartGet('footer-button').click(); - cySmartGet('footer-button').should('have.text', 'Try Again'); - }); + it('should show success when ready to connect pressed and network switched', () => { + cy.stub(Checkout.prototype, 'getNetworkInfo') + .as('getNetworkInfoStub') + .resolves({ + name: 'Ethereum', + chainId: ChainId.ETHEREUM, + }); + cy.stub(Checkout.prototype, 'switchNetwork') + .as('switchNetworkStub') + .resolves({ + provider: baseMockProvider as Web3Provider, + network: { + name: ChainName.IMTBL_ZKEVM_TESTNET, + chainId: ChainId.IMTBL_ZKEVM_TESTNET, + }, + }); + mountConnectWidgetAndGoToReadyToConnect(); + cySmartGet('ready-to-connect').should('be.visible'); + cySmartGet('footer-button').should('have.text', 'Ready to connect'); + cySmartGet('footer-button').click(); + cySmartGet('switch-network-view').should('be.visible'); + cySmartGet('footer-button').click(); + cySmartGet('success-view').should('be.visible'); + }); - it('should show success if try again and switch network succeeds', () => { - cy.stub(Checkout.prototype, 'getNetworkInfo') - .as('getNetworkInfoStub') - .resolves({ - name: 'Ethereum', - chainId: ChainId.ETHEREUM, - }); - cy.stub(Checkout.prototype, 'switchNetwork') - .as('switchNetworkStub') - .onFirstCall() - .rejects({}) - .onSecondCall() - .resolves({ - provider: baseMockProvider as Web3Provider, - }); - mountConnectWidgetAndGoToReadyToConnect(); - cySmartGet('ready-to-connect').should('be.visible'); - cySmartGet('footer-button').should('have.text', 'Ready to connect'); - cySmartGet('footer-button').click(); - cySmartGet('switch-network-view').should('be.visible'); - cySmartGet('footer-button').click(); - cySmartGet('footer-button').should('have.text', 'Try Again'); - cySmartGet('footer-button').click(); - cySmartGet('success-view').should('be.visible'); - }); + it('should show try again if network switch was rejected', () => { + cy.stub(Checkout.prototype, 'getNetworkInfo') + .as('getNetworkInfoStub') + .resolves({ + name: 'Ethereum', + chainId: ChainId.ETHEREUM, + }); + cy.stub(Checkout.prototype, 'switchNetwork') + .as('switchNetworkStub') + .rejects({}); + mountConnectWidgetAndGoToReadyToConnect(); + cySmartGet('ready-to-connect').should('be.visible'); + cySmartGet('footer-button').should('have.text', 'Ready to connect'); + cySmartGet('footer-button').click(); + cySmartGet('switch-network-view').should('be.visible'); + cySmartGet('footer-button').click(); + cySmartGet('footer-button').should('have.text', 'Try Again'); + }); - it('should not show success if try again and switch network fails', () => { - cy.stub(Checkout.prototype, 'getNetworkInfo') - .as('getNetworkInfoStub') - .resolves({ - name: 'Ethereum', - chainId: ChainId.ETHEREUM, - }); - cy.stub(Checkout.prototype, 'switchNetwork') - .as('switchNetworkStub') - .onFirstCall() - .rejects({}) - .onSecondCall() - .rejects({}); - mountConnectWidgetAndGoToReadyToConnect(); - cySmartGet('ready-to-connect').should('be.visible'); - cySmartGet('footer-button').should('have.text', 'Ready to connect'); - cySmartGet('footer-button').click(); - cySmartGet('switch-network-view').should('be.visible'); - cySmartGet('footer-button').click(); - cySmartGet('footer-button').should('have.text', 'Try Again'); - cySmartGet('footer-button').click(); - cySmartGet('footer-button').should('have.text', 'Try Again'); - cySmartGet('success-view').should('not.exist'); - }); - }); + it('should show success if try again and switch network succeeds', () => { + cy.stub(Checkout.prototype, 'getNetworkInfo') + .as('getNetworkInfoStub') + .resolves({ + name: 'Ethereum', + chainId: ChainId.ETHEREUM, + }); + cy.stub(Checkout.prototype, 'switchNetwork') + .as('switchNetworkStub') + .onFirstCall() + .rejects({}) + .onSecondCall() + .resolves({ + provider: baseMockProvider as Web3Provider, + }); + mountConnectWidgetAndGoToReadyToConnect(); + cySmartGet('ready-to-connect').should('be.visible'); + cySmartGet('footer-button').should('have.text', 'Ready to connect'); + cySmartGet('footer-button').click(); + cySmartGet('switch-network-view').should('be.visible'); + cySmartGet('footer-button').click(); + cySmartGet('footer-button').should('have.text', 'Try Again'); + cySmartGet('footer-button').click(); + cySmartGet('success-view').should('be.visible'); + }); - describe('BridgeComingSoon for Passport', () => { - beforeEach(() => { - cy.stub(Checkout.prototype, 'connect').as('connectStub').resolves({ - provider: { ...baseMockProvider, provider: { isPassport: true } as ExternalProvider } as Web3Provider, + it('should not show success if try again and switch network fails', () => { + cy.stub(Checkout.prototype, 'getNetworkInfo') + .as('getNetworkInfoStub') + .resolves({ + name: 'Ethereum', + chainId: ChainId.ETHEREUM, + }); + cy.stub(Checkout.prototype, 'switchNetwork') + .as('switchNetworkStub') + .onFirstCall() + .rejects({}) + .onSecondCall() + .rejects({}); + mountConnectWidgetAndGoToReadyToConnect(); + cySmartGet('ready-to-connect').should('be.visible'); + cySmartGet('footer-button').should('have.text', 'Ready to connect'); + cySmartGet('footer-button').click(); + cySmartGet('switch-network-view').should('be.visible'); + cySmartGet('footer-button').click(); + cySmartGet('footer-button').should('have.text', 'Try Again'); + cySmartGet('footer-button').click(); + cySmartGet('footer-button').should('have.text', 'Try Again'); + cySmartGet('success-view').should('not.exist'); }); - cy.stub(Checkout.prototype, 'createProvider') - .as('createProviderStub') - .resolves({ - provider: { ...baseMockProvider, provider: { isPassport: true } as ExternalProvider } as Web3Provider, - }); }); - it('should show BridgeComingSoon for Passport users if trying to switch to L1', () => { - cy.stub(Checkout.prototype, 'getNetworkInfo') - .as('getNetworkInfoStub') - .resolves({ - name: ChainName.IMTBL_ZKEVM_TESTNET, - chainId: ChainId.IMTBL_ZKEVM_TESTNET, + describe('BridgeComingSoon for Passport', () => { + beforeEach(() => { + cy.stub(Checkout.prototype, 'connect').as('connectStub').resolves({ + provider: { + provider: { isPassport: true }, + getSigner: () => ({ + getAddress: () => Promise.resolve(''), + getChainId: async () => Promise.resolve(ChainId.IMTBL_ZKEVM_TESTNET), + }), + }, }); + cy.stub(Checkout.prototype, 'createProvider') + .as('createProviderStub') + .resolves({ + provider: { + provider: { isPassport: true }, + getSigner: () => ({ + getAddress: () => Promise.resolve(''), + getChainId: async () => Promise.resolve(ChainId.IMTBL_ZKEVM_TESTNET), + }), + }, + }); + }); - const passportProvider = mockPassportProvider('resolve'); - const testPassportInstance = { - connectEvm: cy.stub().as('connectEvmStub').returns(passportProvider), - } as any as Passport; - const passportParams = { - passport: testPassportInstance, - targetLayer: ConnectTargetLayer.LAYER1, - } as ConnectWidgetParams; - - mount( - - - , - ); - cySmartGet('wallet-list-passport').click(); - cySmartGet('footer-button').click(); + it('should show BridgeComingSoon for Passport users if trying to switch to L1', () => { + cy.stub(Checkout.prototype, 'getNetworkInfo') + .as('getNetworkInfoStub') + .resolves({ + name: ChainName.IMTBL_ZKEVM_TESTNET, + chainId: ChainId.IMTBL_ZKEVM_TESTNET, + }); + + const passportProvider = mockPassportProvider('resolve'); + const testPassportInstance = { + connectEvm: cy.stub().as('connectEvmStub').returns(passportProvider), + } as any as Passport; + const passportParams = { + passport: testPassportInstance, + targetLayer: ConnectTargetLayer.LAYER1, + } as ConnectWidgetParams; + + mount( + + + , + ); + cySmartGet('wallet-list-passport').click(); + cySmartGet('footer-button').click(); - cySmartGet('bridge-coming-soon').should('be.visible'); + cySmartGet('bridge-coming-soon').should('be.visible'); + }); }); - }); - describe('Error Connecting', () => { - it('should show error view if unable to create provider', () => { - cy.stub(Checkout.prototype, 'connect').as('connectStub').resolves({}); - cy.stub(Checkout.prototype, 'createProvider') - .as('createProviderStub') - .rejects({}); + describe('Error Connecting', () => { + it('should show error view if unable to create provider', () => { + cy.stub(Checkout.prototype, 'connect').as('connectStub').resolves({}); + cy.stub(Checkout.prototype, 'createProvider') + .as('createProviderStub') + .rejects({}); - const params = {} as ConnectWidgetParams; + const params = {} as ConnectWidgetParams; - mount( - - - , - ); + mount( + + + , + ); - cySmartGet('wallet-list-metamask').click(); - cySmartGet('simple-text-body__heading').should('have.text', "Something's gone wrong"); - cySmartGet('footer-button').should('have.text', 'Try again'); - cySmartGet('footer-button').click(); - cySmartGet('wallet-list-metamask').should('be.visible'); + cySmartGet('wallet-list-metamask').click(); + cySmartGet('simple-text-body__heading').should('have.text', "Something's gone wrong"); + cySmartGet('footer-button').should('have.text', 'Try again'); + cySmartGet('footer-button').click(); + cySmartGet('wallet-list-metamask').should('be.visible'); + }); }); }); }); diff --git a/packages/checkout/widgets-lib/src/widgets/connect/views/ReadyToConnect.tsx b/packages/checkout/widgets-lib/src/widgets/connect/views/ReadyToConnect.tsx index 6b59178de1..1d9c35fa6d 100644 --- a/packages/checkout/widgets-lib/src/widgets/connect/views/ReadyToConnect.tsx +++ b/packages/checkout/widgets-lib/src/widgets/connect/views/ReadyToConnect.tsx @@ -1,5 +1,5 @@ import { Web3Provider } from '@ethersproject/providers'; -import { ChainId, Checkout, WalletProviderName } from '@imtbl/checkout-sdk'; +import { ChainId, WalletProviderName } from '@imtbl/checkout-sdk'; import { useContext, useState, useCallback, useMemo, useEffect, } from 'react'; @@ -88,16 +88,9 @@ export function ReadyToConnect({ targetChainId }: ReadyToConnectProps) { return true; }, [history]); - const handleConnectViewUpdate = async ( - // TODO: variable is already declared above - // eslint-disable-next-line - checkout: Checkout, - // eslint-disable-next-line - provider: Web3Provider, - ) => { - const networkInfo = await checkout.getNetworkInfo({ provider }); - - if (networkInfo.chainId !== targetChainId) { + // eslint-disable-next-line @typescript-eslint/no-shadow + const handleConnectViewUpdate = async (provider: Web3Provider) => { + if (await provider.getSigner().getChainId() !== targetChainId) { viewDispatch({ payload: { type: ViewActions.UPDATE_VIEW, @@ -117,31 +110,34 @@ export function ReadyToConnect({ targetChainId }: ReadyToConnectProps) { const onConnectClick = useCallback(async () => { if (loading) return; + if (!checkout) return; + if (!provider) return; + setLoading(true); - if (checkout && provider) { - try { - track({ - userJourney: UserJourney.CONNECT, - screen: 'ReadyToConnect', - control: 'Connect', - controlType: 'Button', - }); - const connectResult = await checkout.connect({ - provider, - }); - await identifyUser(identify, connectResult.provider); - - connectDispatch({ - payload: { - type: ConnectActions.SET_PROVIDER, - provider: connectResult.provider, - }, - }); - handleConnectViewUpdate(checkout, provider); - } catch (err: any) { - setLoading(false); - setFooterButtonText(footer.buttonText2); - } + + try { + track({ + userJourney: UserJourney.CONNECT, + screen: 'ReadyToConnect', + control: 'Connect', + controlType: 'Button', + }); + const connectResult = await checkout.connect({ + provider, + }); + + await identifyUser(identify, connectResult.provider); + + connectDispatch({ + payload: { + type: ConnectActions.SET_PROVIDER, + provider: connectResult.provider, + }, + }); + handleConnectViewUpdate(provider); + } catch (err: any) { + setLoading(false); + setFooterButtonText(footer.buttonText2); } }, [checkout, provider, connectDispatch, viewDispatch, footer.buttonText2, identify]);