Skip to content

Commit d359d65

Browse files
ci(release): publish latest release
1 parent 4125476 commit d359d65

File tree

9 files changed

+116
-59
lines changed

9 files changed

+116
-59
lines changed

RELEASE

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
IPFS hash of the deployment:
2-
- CIDv0: `QmQnLKt6cNikkDbuWwWk4ff53z8nE8UkNvSaFaASBUe88u`
3-
- CIDv1: `bafybeibejoyf6nwfx7e2yegqssu3gtcx7oifdiqccnuf3hbzyhrvxqwchy`
2+
- CIDv0: `QmUkJyrJfaSMjpdv5afUJLWfqHyBDTsNPn2mb6XwutWecr`
3+
- CIDv1: `bafybeic7gxapw2yactpmoap3uux7gv4kkesw3if44x775vbhjkxnbjrrbm`
44

55
The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org).
66

@@ -10,14 +10,14 @@ You can also access the Uniswap Interface from an IPFS gateway.
1010
Your Uniswap settings are never remembered across different URLs.
1111

1212
IPFS gateways:
13-
- https://bafybeibejoyf6nwfx7e2yegqssu3gtcx7oifdiqccnuf3hbzyhrvxqwchy.ipfs.dweb.link/
14-
- [ipfs://QmQnLKt6cNikkDbuWwWk4ff53z8nE8UkNvSaFaASBUe88u/](ipfs://QmQnLKt6cNikkDbuWwWk4ff53z8nE8UkNvSaFaASBUe88u/)
13+
- https://bafybeic7gxapw2yactpmoap3uux7gv4kkesw3if44x775vbhjkxnbjrrbm.ipfs.dweb.link/
14+
- [ipfs://QmUkJyrJfaSMjpdv5afUJLWfqHyBDTsNPn2mb6XwutWecr/](ipfs://QmUkJyrJfaSMjpdv5afUJLWfqHyBDTsNPn2mb6XwutWecr/)
1515

16-
### 5.119.5 (2025-11-24)
16+
### 5.119.6 (2025-11-24)
1717

1818

1919
### Bug Fixes
2020

21-
* **web:** Monad cherry-picks for web 2 (#25752) f66f7d8
21+
* **web:** sessions initialization - wait for statsig to finish loading (#25779) 35e02c1
2222

2323

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
web/5.119.5
1+
web/5.119.6

apps/extension/src/app/core/BaseAppContainer.tsx

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { ApiInit, getEntryGatewayUrl, provideSessionService } from '@universe/api'
2-
import { getIsSessionServiceEnabled, getIsSessionUpgradeAutoEnabled } from '@universe/gating'
2+
import {
3+
getIsSessionServiceEnabled,
4+
getIsSessionUpgradeAutoEnabled,
5+
useIsSessionServiceEnabled,
6+
} from '@universe/gating'
37
import {
48
createChallengeSolverService,
59
createSessionInitializationService,
@@ -32,35 +36,43 @@ const provideSessionInitializationService = (): SessionInitializationService =>
3236
getIsSessionUpgradeAutoEnabled,
3337
})
3438

39+
function BaseAppContainerInner({ children }: PropsWithChildren): JSX.Element {
40+
const isSessionServiceEnabled = useIsSessionServiceEnabled()
41+
42+
return (
43+
<I18nextProvider i18n={i18n}>
44+
<SharedWalletProvider reduxStore={getReduxStore()}>
45+
<ErrorBoundary>
46+
<AccountsStoreContextProvider>
47+
<GraphqlProvider>
48+
<BlankUrlProvider>
49+
<SmartWalletNudgesProvider>
50+
<LocalizationContextProvider>
51+
<TraceUserProperties />
52+
<ApiInit
53+
getSessionInitService={provideSessionInitializationService}
54+
isSessionServiceEnabled={isSessionServiceEnabled}
55+
/>
56+
{children}
57+
</LocalizationContextProvider>
58+
</SmartWalletNudgesProvider>
59+
</BlankUrlProvider>
60+
</GraphqlProvider>
61+
</AccountsStoreContextProvider>
62+
</ErrorBoundary>
63+
</SharedWalletProvider>
64+
</I18nextProvider>
65+
)
66+
}
67+
3568
export function BaseAppContainer({
3669
children,
3770
appName,
3871
}: PropsWithChildren<{ appName: DatadogAppNameTag }>): JSX.Element {
3972
return (
4073
<Trace>
4174
<ExtensionStatsigProvider appName={appName}>
42-
<I18nextProvider i18n={i18n}>
43-
<SharedWalletProvider reduxStore={getReduxStore()}>
44-
<ErrorBoundary>
45-
<AccountsStoreContextProvider>
46-
<GraphqlProvider>
47-
<BlankUrlProvider>
48-
<SmartWalletNudgesProvider>
49-
<LocalizationContextProvider>
50-
<TraceUserProperties />
51-
<ApiInit
52-
getSessionInitService={provideSessionInitializationService}
53-
getIsSessionServiceEnabled={getIsSessionServiceEnabled}
54-
/>
55-
{children}
56-
</LocalizationContextProvider>
57-
</SmartWalletNudgesProvider>
58-
</BlankUrlProvider>
59-
</GraphqlProvider>
60-
</AccountsStoreContextProvider>
61-
</ErrorBoundary>
62-
</SharedWalletProvider>
63-
</I18nextProvider>
75+
<BaseAppContainerInner>{children}</BaseAppContainerInner>
6476
</ExtensionStatsigProvider>
6577
</Trace>
6678
)

apps/mobile/src/app/App.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
StatsigCustomAppValue,
1616
StatsigUser,
1717
Storage,
18+
useIsSessionServiceEnabled,
1819
WALLET_FEATURE_FLAG_NAMES,
1920
} from '@universe/gating'
2021
import {
@@ -361,6 +362,7 @@ function DataUpdaters(): JSX.Element {
361362
const { locale } = useCurrentLanguageInfo()
362363
const { code } = useAppFiatCurrencyInfo()
363364
const finishedOnboarding = useSelector(selectFinishedOnboarding)
365+
const isSessionServiceEnabled = useIsSessionServiceEnabled()
364366

365367
useDatadogUserAttributesTracking({ isOnboarded: !!finishedOnboarding })
366368
useHeartbeatReporter({ isOnboarded: !!finishedOnboarding })
@@ -387,7 +389,7 @@ function DataUpdaters(): JSX.Element {
387389
<TraceUserProperties />
388390
<ApiInit
389391
getSessionInitService={provideSessionInitializationService}
390-
getIsSessionServiceEnabled={getIsSessionServiceEnabled}
392+
isSessionServiceEnabled={isSessionServiceEnabled}
391393
/>
392394
<TransactionHistoryUpdater />
393395
</>

apps/web/src/index.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ import { ApolloProvider } from '@apollo/client'
99
import { datadogRum } from '@datadog/browser-rum'
1010
import { ApiInit, getEntryGatewayUrl, provideSessionService } from '@universe/api'
1111
import type { StatsigUser } from '@universe/gating'
12-
import { getIsSessionServiceEnabled, getIsSessionUpgradeAutoEnabled } from '@universe/gating'
12+
import {
13+
getIsSessionServiceEnabled,
14+
getIsSessionUpgradeAutoEnabled,
15+
useIsSessionServiceEnabled,
16+
} from '@universe/gating'
1317
import { createChallengeSolverService, createSessionInitializationService } from '@universe/sessions'
1418
import { QueryClientPersistProvider } from 'components/PersistQueryClient'
1519
import { createWeb3Provider, WalletCapabilitiesEffects } from 'components/Web3Provider/createWeb3Provider'
@@ -92,6 +96,7 @@ const provideSessionInitService = () =>
9296

9397
function Updaters() {
9498
const location = useLocation()
99+
const isSessionServiceEnabled = useIsSessionServiceEnabled()
95100

96101
const ListsUpdater = useDeferredComponent(loadListsUpdater)
97102
const SystemThemeUpdater = useDeferredComponent(loadSystemThemeUpdater)
@@ -116,10 +121,7 @@ function Updaters() {
116121
{FiatOnRampTransactionsUpdater && <FiatOnRampTransactionsUpdater />}
117122
{WebAccountsStoreUpdater && <WebAccountsStoreUpdater />}
118123
<AccountsStoreDevTool />
119-
<ApiInit
120-
getSessionInitService={provideSessionInitService}
121-
getIsSessionServiceEnabled={getIsSessionServiceEnabled}
122-
/>
124+
<ApiInit getSessionInitService={provideSessionInitService} isSessionServiceEnabled={isSessionServiceEnabled} />
123125
</>
124126
)
125127
}

packages/api/src/components/ApiInit.test.tsx

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ vi.mock('utilities/src/platform', () => ({
2727
isInterface: false,
2828
}))
2929

30-
const getIsSessionServiceEnabled = vi.fn(() => true)
31-
3230
describe('ApiInit Integration', () => {
3331
// Services and mocked boundaries
3432
let queryClient: QueryClient
@@ -44,11 +42,12 @@ describe('ApiInit Integration', () => {
4442
let uniswapIdentifierService: UniswapIdentifierService
4543
let sessionService: SessionService
4644
let initService: SessionInitializationService
45+
let isSessionServiceEnabled: boolean
4746

4847
beforeEach(() => {
4948
vi.clearAllMocks()
50-
// Reset the feature flag mock to return true by default
51-
getIsSessionServiceEnabled.mockReturnValue(true)
49+
// Default to enabled
50+
isSessionServiceEnabled = true
5251

5352
// Mock only the boundaries (storage and network)
5453
mockStorage = new Map()
@@ -144,7 +143,7 @@ describe('ApiInit Integration', () => {
144143
// Act: Render the component
145144
render(
146145
<QueryClientProvider client={queryClient}>
147-
<ApiInit getSessionInitService={() => initService} getIsSessionServiceEnabled={getIsSessionServiceEnabled} />
146+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
148147
</QueryClientProvider>,
149148
)
150149

@@ -175,7 +174,7 @@ describe('ApiInit Integration', () => {
175174
// Act
176175
render(
177176
<QueryClientProvider client={queryClient}>
178-
<ApiInit getSessionInitService={() => initService} getIsSessionServiceEnabled={getIsSessionServiceEnabled} />
177+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
179178
</QueryClientProvider>,
180179
)
181180

@@ -203,7 +202,7 @@ describe('ApiInit Integration', () => {
203202
// Act
204203
render(
205204
<QueryClientProvider client={queryClient}>
206-
<ApiInit getSessionInitService={() => initService} getIsSessionServiceEnabled={getIsSessionServiceEnabled} />
205+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
207206
</QueryClientProvider>,
208207
)
209208

@@ -246,7 +245,7 @@ describe('ApiInit Integration', () => {
246245
// Act
247246
render(
248247
<QueryClientProvider client={retryClient}>
249-
<ApiInit getSessionInitService={() => initService} getIsSessionServiceEnabled={getIsSessionServiceEnabled} />
248+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
250249
</QueryClientProvider>,
251250
)
252251

@@ -271,7 +270,7 @@ describe('ApiInit Integration', () => {
271270
it('prevents duplicate initialization on re-renders', async () => {
272271
const { rerender } = render(
273272
<QueryClientProvider client={queryClient}>
274-
<ApiInit getSessionInitService={() => initService} getIsSessionServiceEnabled={getIsSessionServiceEnabled} />
273+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
275274
</QueryClientProvider>,
276275
)
277276

@@ -282,13 +281,13 @@ describe('ApiInit Integration', () => {
282281
// Re-render multiple times
283282
rerender(
284283
<QueryClientProvider client={queryClient}>
285-
<ApiInit getSessionInitService={() => initService} getIsSessionServiceEnabled={getIsSessionServiceEnabled} />
284+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
286285
</QueryClientProvider>,
287286
)
288287

289288
rerender(
290289
<QueryClientProvider client={queryClient}>
291-
<ApiInit getSessionInitService={() => initService} getIsSessionServiceEnabled={getIsSessionServiceEnabled} />
290+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
292291
</QueryClientProvider>,
293292
)
294293

@@ -300,12 +299,12 @@ describe('ApiInit Integration', () => {
300299
})
301300

302301
it('should not initialize session when feature flag is disabled', async () => {
303-
// Mock the feature flag as disabled
304-
vi.mocked(getIsSessionServiceEnabled).mockReturnValue(false)
302+
// Set feature flag as disabled
303+
isSessionServiceEnabled = false
305304

306305
render(
307306
<QueryClientProvider client={queryClient}>
308-
<ApiInit getSessionInitService={() => initService} getIsSessionServiceEnabled={getIsSessionServiceEnabled} />
307+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
309308
</QueryClientProvider>,
310309
)
311310

@@ -317,4 +316,44 @@ describe('ApiInit Integration', () => {
317316
expect(mockApiClient.challenge).not.toHaveBeenCalled()
318317
expect(mockApiClient.upgradeSession).not.toHaveBeenCalled()
319318
})
319+
320+
it('should wait for feature flag to be enabled before initializing session', async () => {
321+
// Start with feature flag disabled (simulating Statsig loading)
322+
isSessionServiceEnabled = false
323+
324+
const { rerender } = render(
325+
<QueryClientProvider client={queryClient}>
326+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
327+
</QueryClientProvider>,
328+
)
329+
330+
// Assert that initialization does not happen while flag is disabled
331+
// Use a try/catch with waitFor to verify the call never happens
332+
await expect(
333+
waitFor(
334+
() => {
335+
expect(mockApiClient.initSession).toHaveBeenCalled()
336+
},
337+
{ timeout: 100 },
338+
),
339+
).rejects.toThrow()
340+
341+
// Verify it still hasn't been called
342+
expect(mockApiClient.initSession).not.toHaveBeenCalled()
343+
344+
// Now simulate feature flag becoming enabled (Statsig loaded)
345+
isSessionServiceEnabled = true
346+
347+
// Trigger a re-render
348+
rerender(
349+
<QueryClientProvider client={queryClient}>
350+
<ApiInit getSessionInitService={() => initService} isSessionServiceEnabled={isSessionServiceEnabled} />
351+
</QueryClientProvider>,
352+
)
353+
354+
// Now session initialization should occur
355+
await waitFor(() => {
356+
expect(mockApiClient.initSession).toHaveBeenCalled()
357+
})
358+
})
320359
})

packages/api/src/components/ApiInit.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { ReactQueryCacheKey } from 'utilities/src/reactQuery/cache'
66

77
interface ApiInitProps {
88
getSessionInitService: () => SessionInitializationService
9-
getIsSessionServiceEnabled: () => boolean
9+
isSessionServiceEnabled: boolean
1010
}
1111
function createInitServiceQuery(ctx: {
1212
getSessionInitService: () => SessionInitializationService
@@ -31,15 +31,12 @@ function createInitServiceQuery(ctx: {
3131
})
3232
}
3333

34-
function ApiInit({ getSessionInitService, getIsSessionServiceEnabled }: ApiInitProps): null {
34+
function ApiInit({ getSessionInitService, isSessionServiceEnabled }: ApiInitProps): null {
3535
const [query] = useState(() => createInitServiceQuery({ getSessionInitService }))
3636

37-
// Short-circuit if session service is disabled
38-
const shouldInitialize = getIsSessionServiceEnabled()
39-
4037
useQuery({
4138
...query,
42-
enabled: shouldInitialize,
39+
enabled: isSessionServiceEnabled,
4340
})
4441

4542
return null
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import { getConfig } from '@universe/config'
22
import { FeatureFlags } from '@universe/gating/src/flags'
3-
import { getFeatureFlag } from '@universe/gating/src/hooks'
3+
import { getFeatureFlag, useFeatureFlag } from '@universe/gating/src/hooks'
44

55
function getIsSessionServiceEnabled(): boolean {
66
return getConfig().enableSessionService || getFeatureFlag(FeatureFlags.SessionsServiceEnabled)
77
}
88

9-
export { getIsSessionServiceEnabled }
9+
function useIsSessionServiceEnabled(): boolean {
10+
const featureFlagEnabled = useFeatureFlag(FeatureFlags.SessionsServiceEnabled)
11+
return getConfig().enableSessionService || featureFlagEnabled
12+
}
13+
14+
export { getIsSessionServiceEnabled, useIsSessionServiceEnabled }

packages/gating/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export {
5151
WALLET_FEATURE_FLAG_NAMES,
5252
WEB_FEATURE_FLAG_NAMES,
5353
} from '@universe/gating/src/flags'
54-
export { getIsSessionServiceEnabled } from '@universe/gating/src/getIsSessionServiceEnabled'
54+
export { getIsSessionServiceEnabled, useIsSessionServiceEnabled } from '@universe/gating/src/getIsSessionServiceEnabled'
5555
export { getIsSessionUpgradeAutoEnabled } from '@universe/gating/src/getIsSessionUpgradeAutoEnabled'
5656
export { getStatsigEnvName } from '@universe/gating/src/getStatsigEnvName'
5757
export {

0 commit comments

Comments
 (0)