Skip to content

Commit 6c02b23

Browse files
committed
drop the md
1 parent 381adbf commit 6c02b23

8 files changed

Lines changed: 252 additions & 61 deletions

File tree

packages/web/src/app/AppProviders.tsx

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ReactNode, useState, useMemo } from 'react'
1+
import { ReactNode, useState, useMemo, lazy, Suspense } from 'react'
22

33
import { MediaProvider } from '@audius/harmony/src/contexts'
44
import { QueryClientProvider } from '@tanstack/react-query'
@@ -10,17 +10,18 @@ import {
1010
RouterProvider
1111
} from 'react-router'
1212
import { PersistGate } from 'redux-persist/integration/react'
13-
import { WagmiProvider } from 'wagmi'
1413

1514
import { useIsMobile } from 'hooks/useIsMobile'
1615
import { env } from 'services/env'
1716
import { queryClient } from 'services/query-client'
1817
import { configureStore } from 'store/configureStore'
1918
import { getSystemAppearance, getTheme } from 'utils/theme/theme'
2019

21-
import { wagmiAdapter } from './ReownAppKitModal'
2220
import { createRoutes } from './routes'
2321

22+
// Lazy load ReownProvider to avoid loading @reown packages until needed
23+
const ReownProvider = lazy(() => import('./ReownProvider').then(module => ({ default: module.ReownProvider })))
24+
2425
type AppProvidersProps = {
2526
children?: ReactNode
2627
}
@@ -61,17 +62,19 @@ export const AppProviders = ({ children }: AppProvidersProps) => {
6162
}, [basename])
6263

6364
return (
64-
<WagmiProvider config={wagmiAdapter.wagmiConfig}>
65-
<QueryClientProvider client={queryClient}>
66-
<MediaProvider>
67-
<ReduxProvider store={store}>
68-
<PersistGate loading={null} persistor={persistor}>
69-
<RouterProvider router={router} />
70-
</PersistGate>
71-
</ReduxProvider>
72-
</MediaProvider>
73-
<ReactQueryDevtools />
74-
</QueryClientProvider>
75-
</WagmiProvider>
65+
<Suspense fallback={null}>
66+
<ReownProvider>
67+
<QueryClientProvider client={queryClient}>
68+
<MediaProvider>
69+
<ReduxProvider store={store}>
70+
<PersistGate loading={null} persistor={persistor}>
71+
<RouterProvider router={router} />
72+
</PersistGate>
73+
</ReduxProvider>
74+
</MediaProvider>
75+
<ReactQueryDevtools />
76+
</QueryClientProvider>
77+
</ReownProvider>
78+
</Suspense>
7679
)
7780
}
Lines changed: 71 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,79 @@
1-
import {
2-
mainnet,
3-
solana,
4-
type AppKitNetwork,
5-
type Chain
6-
} from '@reown/appkit/networks'
7-
import { createAppKit } from '@reown/appkit/react'
8-
import { SolanaAdapter } from '@reown/appkit-adapter-solana/react'
9-
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'
1+
// Re-export from lazy-loaded config for backward compatibility
2+
// All new code should import from 'app/reownConfig' instead
3+
// Note: We import audiusChain directly to avoid pulling in @reown packages
4+
import { audiusChain } from './reownConfig'
5+
import { getInitializedConfig } from './reownSyncInit'
106

11-
import { env } from 'services/env'
12-
import zIndex from 'utils/zIndex'
7+
export { audiusChain }
138

14-
// Audius ACDC chain (now ports to Core)
15-
export const audiusChain = {
16-
id: env.AUDIUS_NETWORK_CHAIN_ID,
17-
name: 'Audius',
18-
nativeCurrency: { name: '-', symbol: '-', decimals: 18 },
19-
rpcUrls: {
20-
default: { http: [`${env.API_URL}/core/erpc`] }
21-
}
22-
} as const satisfies Chain
9+
// Dynamic import to avoid pulling in @reown packages at module load time
10+
const getReownConfigDynamic = async () => {
11+
const module = await import('./reownConfig')
12+
return module.getReownConfig()
13+
}
14+
15+
// Lazy getters for backward compatibility (async version)
16+
export const getWagmiAdapter = async () => {
17+
const config = await getReownConfigDynamic()
18+
return config.wagmiAdapter
19+
}
20+
21+
export const getAppkitModal = async () => {
22+
const config = await getReownConfigDynamic()
23+
return config.appkitModal
24+
}
2325

24-
const projectId = env.REOWN_PROJECT_ID
25-
const networks: [AppKitNetwork, ...AppKitNetwork[]] = [
26-
mainnet,
27-
solana,
28-
audiusChain
29-
]
30-
export const wagmiAdapter = new WagmiAdapter({
31-
networks,
32-
projectId
26+
export const getReownConfig = getReownConfigDynamic
27+
28+
// For backward compatibility - synchronous access after ReownProvider initializes
29+
// These will throw if accessed before ReownProvider mounts
30+
export const wagmiAdapter = new Proxy({} as any, {
31+
get(_target, prop) {
32+
const config = getInitializedConfig()
33+
return config.wagmiAdapter[prop]
34+
},
35+
has(_target, prop) {
36+
try {
37+
const config = getInitializedConfig()
38+
return prop in config.wagmiAdapter
39+
} catch {
40+
return false
41+
}
42+
},
43+
ownKeys(_target) {
44+
const config = getInitializedConfig()
45+
return Reflect.ownKeys(config.wagmiAdapter)
46+
},
47+
getOwnPropertyDescriptor(_target, prop) {
48+
const config = getInitializedConfig()
49+
return Reflect.getOwnPropertyDescriptor(config.wagmiAdapter, prop)
50+
}
3351
})
34-
const solanaAdapter = new SolanaAdapter()
3552

36-
export const appkitModal = createAppKit({
37-
adapters: [wagmiAdapter, solanaAdapter],
38-
networks,
39-
projectId,
40-
themeVariables: {
41-
'--w3m-z-index': zIndex.REOWN_APPKIT_MODAL // above ConnectWalletModal
53+
// Proxy for appkitModal - maintains synchronous API after initialization
54+
export const appkitModal = new Proxy({} as any, {
55+
get(_target, prop) {
56+
const config = getInitializedConfig()
57+
const value = config.appkitModal[prop as keyof typeof config.appkitModal]
58+
if (typeof value === 'function') {
59+
return value.bind(config.appkitModal)
60+
}
61+
return value
62+
},
63+
has(_target, prop) {
64+
try {
65+
const config = getInitializedConfig()
66+
return prop in config.appkitModal
67+
} catch {
68+
return false
69+
}
70+
},
71+
ownKeys(_target) {
72+
const config = getInitializedConfig()
73+
return Reflect.ownKeys(config.appkitModal)
4274
},
43-
features: {
44-
send: false,
45-
swaps: false,
46-
onramp: false,
47-
socials: false,
48-
email: false
75+
getOwnPropertyDescriptor(_target, prop) {
76+
const config = getInitializedConfig()
77+
return Reflect.getOwnPropertyDescriptor(config.appkitModal, prop)
4978
}
5079
})
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { ReactNode, useEffect, useState } from 'react'
2+
import { WagmiProvider } from 'wagmi'
3+
4+
import { getReownConfig } from './reownConfig'
5+
import { initializeReownSync } from './reownSyncInit'
6+
7+
type ReownProviderProps = {
8+
children: ReactNode
9+
}
10+
11+
/**
12+
* Lazy-loaded provider that initializes Reown AppKit and wraps children with WagmiProvider.
13+
* This ensures @reown packages are only loaded when this component is rendered.
14+
*/
15+
export const ReownProvider = ({ children }: ReownProviderProps) => {
16+
const [wagmiConfig, setWagmiConfig] = useState<any>(null)
17+
18+
useEffect(() => {
19+
// Eagerly initialize Reown config when provider mounts
20+
// This ensures appkitModal and wagmiAdapter are available synchronously
21+
getReownConfig().then((config) => {
22+
initializeReownSync(config)
23+
setWagmiConfig(config.wagmiAdapter.wagmiConfig)
24+
})
25+
}, [])
26+
27+
if (!wagmiConfig) {
28+
return null
29+
}
30+
31+
return <WagmiProvider config={wagmiConfig}>{children}</WagmiProvider>
32+
}
33+
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { env } from 'services/env'
2+
import zIndex from 'utils/zIndex'
3+
4+
// Audius ACDC chain (now ports to Core)
5+
// This is defined here to avoid importing Chain type from @reown
6+
export const audiusChain = {
7+
id: env.AUDIUS_NETWORK_CHAIN_ID,
8+
name: 'Audius',
9+
nativeCurrency: { name: '-', symbol: '-', decimals: 18 },
10+
rpcUrls: {
11+
default: { http: [`${env.API_URL}/core/erpc`] }
12+
}
13+
} as const
14+
15+
let wagmiAdapterInstance: any | null = null
16+
let appkitModalInstance: any | null = null
17+
let configPromise: Promise<any> | null = null
18+
19+
/**
20+
* Lazy initialization function for Reown AppKit.
21+
* Uses dynamic imports to ensure @reown packages are only loaded when this function is called.
22+
*/
23+
export const getReownConfig = async () => {
24+
if (wagmiAdapterInstance && appkitModalInstance) {
25+
return {
26+
wagmiAdapter: wagmiAdapterInstance,
27+
appkitModal: appkitModalInstance,
28+
audiusChain
29+
}
30+
}
31+
32+
// If already initializing, wait for that promise
33+
if (configPromise) {
34+
return configPromise
35+
}
36+
37+
// Use dynamic imports to lazy-load @reown packages
38+
console.log('[Reown] Lazy loading @reown packages...')
39+
configPromise = Promise.all([
40+
import('@reown/appkit/networks'),
41+
import('@reown/appkit/react'),
42+
import('@reown/appkit-adapter-solana/react'),
43+
import('@reown/appkit-adapter-wagmi')
44+
]).then(
45+
([
46+
{ mainnet, solana },
47+
{ createAppKit },
48+
{ SolanaAdapter },
49+
{ WagmiAdapter }
50+
]) => {
51+
const projectId = env.REOWN_PROJECT_ID
52+
const networks = [mainnet, solana, audiusChain]
53+
54+
wagmiAdapterInstance = new WagmiAdapter({
55+
networks,
56+
projectId
57+
})
58+
59+
const solanaAdapter = new SolanaAdapter()
60+
61+
appkitModalInstance = createAppKit({
62+
adapters: [wagmiAdapterInstance, solanaAdapter],
63+
networks,
64+
projectId,
65+
themeVariables: {
66+
'--w3m-z-index': zIndex.REOWN_APPKIT_MODAL // above ConnectWalletModal
67+
},
68+
features: {
69+
send: false,
70+
swaps: false,
71+
onramp: false,
72+
socials: false,
73+
email: false
74+
}
75+
})
76+
77+
console.log('[Reown] @reown packages loaded successfully')
78+
return {
79+
wagmiAdapter: wagmiAdapterInstance,
80+
appkitModal: appkitModalInstance,
81+
audiusChain
82+
}
83+
}
84+
)
85+
86+
return configPromise
87+
}
88+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// This module provides synchronous access to Reown config after it's been initialized
2+
// It's used to bridge the async initialization with the synchronous API
3+
4+
let initializedConfig: {
5+
wagmiAdapter: any
6+
appkitModal: any
7+
audiusChain: any
8+
} | null = null
9+
10+
export const initializeReownSync = (config: {
11+
wagmiAdapter: any
12+
appkitModal: any
13+
audiusChain: any
14+
}) => {
15+
initializedConfig = config
16+
}
17+
18+
export const getInitializedConfig = () => {
19+
if (!initializedConfig) {
20+
throw new Error(
21+
'Reown config not initialized. Make sure ReownProvider is mounted.'
22+
)
23+
}
24+
return initializedConfig
25+
}
26+

packages/web/src/pages/modals/Modals.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ import { AlbumTrackRemoveConfirmationModal } from 'components/album-track-remove
99
import AppCTAModal from 'components/app-cta-modal/AppCTAModal'
1010
import { ArtistPickModal } from 'components/artist-pick-modal/ArtistPickModal'
1111
import BrowserPushConfirmationModal from 'components/browser-push-confirmation-modal/BrowserPushConfirmationModal'
12-
import { BuySellModal } from 'components/buy-sell-modal/BuySellModal'
12+
// Lazy load BuySellModal to avoid loading @reown packages until needed
13+
const BuySellModal = lazy(() =>
14+
import('components/buy-sell-modal/BuySellModal').then((m) => ({
15+
default: m.BuySellModal
16+
}))
17+
)
1318
import CoinflowOnrampModal from 'components/coinflow-onramp-modal'
1419
import ConfirmerPreview from 'components/confirmer-preview/ConfirmerPreview'
1520
import DeletePlaylistConfirmationModal from 'components/delete-playlist-confirmation-modal/DeletePlaylistConfirmationModal'

packages/web/src/services/audius-sdk/auth.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@ import {
99
import { getWalletClient } from '@wagmi/core'
1010
import { type WalletClient } from 'viem'
1111

12-
import { audiusChain, wagmiAdapter } from 'app/ReownAppKitModal'
12+
import { audiusChain, getWagmiAdapter } from 'app/ReownAppKitModal'
1313

1414
import { env } from '../env'
1515
import { localStorage } from '../local-storage'
1616

17-
const wagmiConfig = wagmiAdapter.wagmiConfig
17+
// Lazy-load wagmiConfig when needed (async)
18+
const getWagmiConfig = async () => {
19+
const adapter = await getWagmiAdapter()
20+
return adapter.wagmiConfig
21+
}
1822

1923
export const getAudiusWalletClient = async (): Promise<AudiusWalletClient> => {
2024
// Check if the user has already connected Hedgehog first...
@@ -33,6 +37,7 @@ export const getAudiusWalletClient = async (): Promise<AudiusWalletClient> => {
3337
console.debug('[audiusSdk] Initializing SDK with external wallet...')
3438

3539
// Wait for the wallet to finish connecting/reconnecting
40+
const wagmiConfig = await getWagmiConfig()
3641
if (
3742
wagmiConfig.state.status === 'reconnecting' ||
3843
wagmiConfig.state.status === 'connecting'

packages/web/src/store/sign-out/sagas.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import { push } from 'utils/navigation'
1515
const { resetAccount, unsubscribeBrowserPushNotifications } = accountActions
1616
const { signOut: signOutAction } = signOutActions
1717

18-
const wagmiConfig = wagmiAdapter.wagmiConfig
18+
// Use synchronous accessor - by the time saga runs, ReownProvider should be initialized
19+
const getWagmiConfig = () => wagmiAdapter.wagmiConfig
1920

2021
function* watchSignOut() {
2122
const localStorage = yield* getContext('localStorage')
@@ -24,6 +25,7 @@ function* watchSignOut() {
2425
yield takeLatest(
2526
signOutAction.type,
2627
function* (action: ReturnType<typeof signOutAction>) {
28+
const wagmiConfig = getWagmiConfig()
2729
if (wagmiConfig.state.status === 'connected') {
2830
yield call(disconnect, wagmiConfig)
2931
}

0 commit comments

Comments
 (0)