Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Lazy load mpc core kit #2808

Merged
merged 5 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 4 additions & 37 deletions .github/workflows/nextjs_bundle_analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ jobs:
with:
secrets: ${{ toJSON(secrets) }}

# Here's the first place where next-bundle-analysis' own script is used
# This step pulls the raw bundle stats for the current bundle
- name: Analyze bundle
run: npx -p nextjs-bundle-analysis report

Expand All @@ -47,19 +45,6 @@ jobs:
branch: ${{ github.event.pull_request.base.ref }}
path: .next/analyze/base

# And here's the second place - this runs after we have both the current and
# base branch bundle stats, and will compare them to determine what changed.
# There are two configurable arguments that come from package.json:
#
# - budget: optional, set a budget (bytes) against which size changes are measured
# it's set to 350kb here by default, as informed by the following piece:
# https://infrequently.org/2021/03/the-performance-inequality-gap/
#
# - red-status-percentage: sets the percent size increase where you get a red
# status indicator, defaults to 20%
#
# Either of these arguments can be changed or removed by editing the `nextBundleAnalysis`
# entry in your package.json file.
- name: Compare with base branch bundle
if: success() && github.event.number
run: ls -laR .next/analyze/base && npx -p nextjs-bundle-analysis compare
Expand All @@ -73,26 +58,8 @@ jobs:
echo "$(cat .next/analyze/__bundle_analysis_comment.txt)" >> $GITHUB_OUTPUT
echo EOF >> $GITHUB_OUTPUT

- name: Find Comment
uses: peter-evans/find-comment@v2
if: success() && github.event.number
id: fc
with:
issue-number: ${{ github.event.number }}
body-includes: '<!-- __NEXTJS_BUNDLE -->'

- name: Create Comment
uses: peter-evans/create-or-update-comment@v2
if: success() && github.event.number && steps.fc.outputs.comment-id == 0
with:
issue-number: ${{ github.event.number }}
body: ${{ steps.get-comment-body.outputs.body }}

- name: Update Comment
uses: peter-evans/create-or-update-comment@v2
if: success() && github.event.number && steps.fc.outputs.comment-id != 0
- name: Comment
uses: marocchino/sticky-pull-request-comment@v2
with:
issue-number: ${{ github.event.number }}
body: ${{ steps.get-comment-body.outputs.body }}
comment-id: ${{ steps.fc.outputs.comment-id }}
edit-mode: replace
header: next-bundle-analysis
message: ${{ steps.get-comment-body.outputs.body }}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@ yalc.lock
/public/worker-*.js
/public/workbox-*.js
/public/workbox-*.js.map
/public/fallback*
/public/fallback*
/public/*.js.LICENSE.txt
9 changes: 7 additions & 2 deletions src/components/common/ConnectWallet/WalletDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { Box, Divider, SvgIcon, Typography } from '@mui/material'
import { Box, Divider, Skeleton, SvgIcon, Typography } from '@mui/material'
import dynamic from 'next/dynamic'
import type { ReactElement } from 'react'

import LockIcon from '@/public/images/common/lock.svg'
import SocialSigner from '@/components/common/SocialSigner'

const SocialSigner = dynamic(() => import('@/components/common/SocialSigner'), {
loading: () => <Skeleton variant="rounded" height={42} width="100%" />,
})

import WalletLogin from '@/components/welcome/WelcomeLogin/WalletLogin'

const WalletDetails = ({ onConnect }: { onConnect: () => void }): ReactElement => {
Expand Down
7 changes: 4 additions & 3 deletions src/components/common/SocialSigner/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import useSocialWallet from '@/hooks/wallets/mpc/useSocialWallet'
import { type ISocialWalletService } from '@/services/mpc/interfaces'
import { Box, Button, LinearProgress, SvgIcon, Tooltip, Typography } from '@mui/material'
import { COREKIT_STATUS } from '@web3auth/mpc-core-kit'
import { useCallback, useContext, useMemo, useState } from 'react'
import { PasswordRecovery } from '@/components/common/SocialSigner/PasswordRecovery'
import GoogleLogo from '@/public/images/welcome/logo-google.svg'
Expand All @@ -15,8 +18,6 @@ import { isSocialLoginWallet } from '@/services/mpc/SocialLoginModule'
import { CGW_NAMES } from '@/hooks/wallets/consts'
import { type ChainInfo } from '@safe-global/safe-gateway-typescript-sdk'
import { TxModalContext } from '@/components/tx-flow'
import { COREKIT_STATUS } from '@web3auth/mpc-core-kit'
import useSocialWallet from '@/hooks/wallets/mpc/useSocialWallet'
import madProps from '@/utils/mad-props'
import { asError } from '@/services/exceptions/utils'
import ErrorMessage from '@/components/tx/ErrorMessage'
Expand All @@ -41,7 +42,7 @@ const useIsSocialWalletEnabled = () => {
}

type SocialSignerLoginProps = {
socialWalletService: ReturnType<typeof useSocialWallet>
socialWalletService: ISocialWalletService | undefined
wallet: ReturnType<typeof useWallet>
supportedChains: ReturnType<typeof useGetSupportedChains>
isMPCLoginEnabled: ReturnType<typeof useIsSocialWalletEnabled>
Expand Down
8 changes: 6 additions & 2 deletions src/components/welcome/WelcomeLogin/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import SocialSigner from '@/components/common/SocialSigner'
import { AppRoutes } from '@/config/routes'
import { useHasFeature } from '@/hooks/useChains'
import { FEATURES } from '@/utils/chains'
import { Paper, SvgIcon, Typography, Divider, Link, Box } from '@mui/material'
import { Paper, SvgIcon, Typography, Divider, Link, Box, Skeleton } from '@mui/material'
import SafeLogo from '@/public/images/logo-text.svg'
import dynamic from 'next/dynamic'
import css from './styles.module.css'
import { useRouter } from 'next/router'
import WalletLogin from './WalletLogin'
import { LOAD_SAFE_EVENTS, CREATE_SAFE_EVENTS } from '@/services/analytics/events/createLoadSafe'
import Track from '@/components/common/Track'
import { trackEvent } from '@/services/analytics'

const SocialSigner = dynamic(() => import('@/components/common/SocialSigner'), {
loading: () => <Skeleton variant="rounded" height={42} width="100%" />,
})

const WelcomeLogin = () => {
const router = useRouter()
const isSocialLoginEnabled = useHasFeature(FEATURES.SOCIAL_LOGIN)
Expand Down
134 changes: 40 additions & 94 deletions src/hooks/wallets/mpc/__tests__/useMPC.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import * as useOnboard from '@/hooks/wallets/useOnboard'
import * as socialWalletOptions from '@/services/mpc/config'
import { renderHook, waitFor } from '@/tests/test-utils'
import { _getMPCCoreKitInstance, setMPCCoreKitInstance, useInitMPC } from '../useMPC'
import * as useChains from '@/hooks/useChains'
import { waitFor } from '@/tests/test-utils'
import { _getMPCCoreKitInstance, initMPC, setMPCCoreKitInstance } from '../useMPC'
import { type ChainInfo, RPC_AUTHENTICATION } from '@safe-global/safe-gateway-typescript-sdk'
import { hexZeroPad } from 'ethers/lib/utils'
import { ONBOARD_MPC_MODULE_LABEL } from '@/services/mpc/SocialLoginModule'
Expand Down Expand Up @@ -63,95 +62,70 @@ class EventEmittingMockProvider {
}
}

describe('useInitMPC', () => {
describe('initMPC', () => {
const mockOnboard = {
state: {
get: () => ({
wallets: [],
walletModules: [],
}),
},
} as unknown as OnboardAPI

const mockChain = {
chainId: '5',
chainName: 'Goerli',
blockExplorerUriTemplate: {
address: 'https://goerli.someprovider.io/{address}',
txHash: 'https://goerli.someprovider.io/{txHash}',
api: 'https://goerli.someprovider.io/',
},
nativeCurrency: {
decimals: 18,
logoUri: 'https://logo.goerli.com',
name: 'Goerli ETH',
symbol: 'ETH',
},
rpcUri: {
authentication: RPC_AUTHENTICATION.NO_AUTHENTICATION,
value: 'https://goerli.somerpc.io',
},
} as unknown as ChainInfo

beforeEach(() => {
jest.resetAllMocks()
jest.spyOn(socialWalletOptions, 'isSocialWalletOptions').mockReturnValue(true)
})

it('should set the coreKit if user is not logged in yet', async () => {
const connectWalletSpy = jest.fn().mockImplementation(() => Promise.resolve())
jest.spyOn(useOnboard, 'connectWallet').mockImplementation(connectWalletSpy)
jest.spyOn(useOnboard, 'connectWallet').mockImplementation(() => Promise.resolve(undefined))
jest.spyOn(useOnboard, 'getConnectedWallet').mockReturnValue(null)
jest.spyOn(useOnboard, 'default').mockReturnValue({
state: {
get: () => ({
wallets: [],
walletModules: [],
}),
},
} as unknown as OnboardAPI)
jest.spyOn(useChains, 'useCurrentChain').mockReturnValue({
chainId: '5',
chainName: 'Goerli',
blockExplorerUriTemplate: {
address: 'https://goerli.someprovider.io/{address}',
txHash: 'https://goerli.someprovider.io/{txHash}',
api: 'https://goerli.someprovider.io/',
},
nativeCurrency: {
decimals: 18,
logoUri: 'https://logo.goerli.com',
name: 'Goerli ETH',
symbol: 'ETH',
},
rpcUri: {
authentication: RPC_AUTHENTICATION.NO_AUTHENTICATION,
value: 'https://goerli.somerpc.io',
},
} as unknown as ChainInfo)

const mockWeb3AuthMpcCoreKit = jest.spyOn(require('@web3auth/mpc-core-kit'), 'Web3AuthMPCCoreKit')
mockWeb3AuthMpcCoreKit.mockImplementation(() => {
return new MockMPCCoreKit(COREKIT_STATUS.INITIALIZED, null)
})

renderHook(() => useInitMPC())
await initMPC(mockChain, mockOnboard)

await waitFor(() => {
expect(_getMPCCoreKitInstance()).toBeDefined()
expect(connectWalletSpy).not.toBeCalled()
expect(useOnboard.connectWallet).not.toBeCalled()
})
})

it('should call connectWallet after rehydrating a web3auth session', async () => {
const connectWalletSpy = jest.fn().mockImplementation(() => Promise.resolve())
jest.spyOn(useOnboard, 'connectWallet').mockImplementation(connectWalletSpy)
jest.spyOn(useOnboard, 'getConnectedWallet').mockReturnValue(null)
jest.spyOn(useOnboard, 'default').mockReturnValue({
state: {
get: () => ({
wallets: [],
walletModules: [],
}),
},
} as unknown as OnboardAPI)
jest.spyOn(useChains, 'useCurrentChain').mockReturnValue({
chainId: '5',
chainName: 'Goerli',
blockExplorerUriTemplate: {
address: 'https://goerli.someprovider.io/{address}',
txHash: 'https://goerli.someprovider.io/{txHash}',
api: 'https://goerli.someprovider.io/',
},
nativeCurrency: {
decimals: 18,
logoUri: 'https://logo.goerli.com',
name: 'Goerli ETH',
symbol: 'ETH',
},
rpcUri: {
authentication: RPC_AUTHENTICATION.NO_AUTHENTICATION,
value: 'https://goerli.somerpc.io',
},
} as unknown as ChainInfo)

const mockWeb3AuthMpcCoreKit = jest.spyOn(require('@web3auth/mpc-core-kit'), 'Web3AuthMPCCoreKit')
const mockProvider = jest.fn()
mockWeb3AuthMpcCoreKit.mockImplementation(() => {
return new MockMPCCoreKit(COREKIT_STATUS.LOGGED_IN, mockProvider as unknown as MPCProvider)
})

renderHook(() => useInitMPC())
await initMPC(mockChain, mockOnboard)

await waitFor(() => {
expect(connectWalletSpy).toBeCalled()
Expand All @@ -160,41 +134,13 @@ describe('useInitMPC', () => {
})

it('should copy event handlers and emit chainChanged if the current chain is updated', async () => {
const connectWalletSpy = jest.fn().mockImplementation(() => Promise.resolve())
jest.spyOn(useOnboard, 'connectWallet').mockImplementation(connectWalletSpy)
jest.spyOn(useOnboard, 'connectWallet').mockImplementation(() => Promise.resolve(undefined))
jest.spyOn(useOnboard, 'getConnectedWallet').mockReturnValue({
address: hexZeroPad('0x1', 20),
label: ONBOARD_MPC_MODULE_LABEL,
chainId: '1',
provider: {} as unknown as EIP1193Provider,
})
jest.spyOn(useOnboard, 'default').mockReturnValue({
state: {
get: () => ({
wallets: [],
walletModules: [],
}),
},
} as unknown as OnboardAPI)
jest.spyOn(useChains, 'useCurrentChain').mockReturnValue({
chainId: '5',
chainName: 'Goerli',
blockExplorerUriTemplate: {
address: 'https://goerli.someprovider.io/{address}',
txHash: 'https://goerli.someprovider.io/{txHash}',
api: 'https://goerli.someprovider.io/',
},
nativeCurrency: {
decimals: 18,
logoUri: 'https://logo.goerli.com',
name: 'Goerli ETH',
symbol: 'ETH',
},
rpcUri: {
authentication: RPC_AUTHENTICATION.NO_AUTHENTICATION,
value: 'https://goerli.somerpc.io',
},
} as unknown as ChainInfo)

const mockWeb3AuthMpcCoreKit = jest.spyOn(require('@web3auth/mpc-core-kit'), 'Web3AuthMPCCoreKit')
const mockChainChangedListener = jest.fn()
Expand All @@ -215,12 +161,12 @@ describe('useInitMPC', () => {
return new MockMPCCoreKit(COREKIT_STATUS.LOGGED_IN, mockProvider as unknown as MPCProvider)
})

renderHook(() => useInitMPC())
await initMPC(mockChain, mockOnboard)

await waitFor(() => {
expect(mockChainChangedListener).toHaveBeenCalledWith('0x5')
expect(_getMPCCoreKitInstance()).toBeDefined()
expect(connectWalletSpy).not.toBeCalled()
expect(useOnboard.connectWallet).not.toBeCalled()
})
})
})
Loading
Loading