Skip to content

Commit ee72afe

Browse files
ci(release): publish latest release
1 parent 07a043e commit ee72afe

538 files changed

Lines changed: 11010 additions & 6339 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,6 @@ claude.md
6666
claude.local.md
6767
CLAUDE.md
6868
CLAUDE.local.md
69+
70+
# cursor
71+
.cursor/mcp.json

RELEASE

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
IPFS hash of the deployment:
2-
- CIDv0: `QmcZ3ZA5ioacWp41C6dYKycAusqLzbqKMFsUA9bxBYVLLK`
3-
- CIDv1: `bafybeigtgbvryas2rxg4yaksru5ahf4nyoafgxxwgszew7afvebehd4slq`
2+
- CIDv0: `QmQiJKLRhhiAWuvL6mKxtcWf5cpKf5nikT6Z9Fc3K9cFY8`
3+
- CIDv1: `bafybeibdiml7uybjmgqqttpv5pebkphbfhrhrcvgelyie5t3oiarysxchu`
44

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

@@ -10,14 +10,76 @@ 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://bafybeigtgbvryas2rxg4yaksru5ahf4nyoafgxxwgszew7afvebehd4slq.ipfs.dweb.link/
14-
- [ipfs://QmcZ3ZA5ioacWp41C6dYKycAusqLzbqKMFsUA9bxBYVLLK/](ipfs://QmcZ3ZA5ioacWp41C6dYKycAusqLzbqKMFsUA9bxBYVLLK/)
13+
- https://bafybeibdiml7uybjmgqqttpv5pebkphbfhrhrcvgelyie5t3oiarysxchu.ipfs.dweb.link/
14+
- [ipfs://QmQiJKLRhhiAWuvL6mKxtcWf5cpKf5nikT6Z9Fc3K9cFY8/](ipfs://QmQiJKLRhhiAWuvL6mKxtcWf5cpKf5nikT6Z9Fc3K9cFY8/)
1515

16-
### 5.100.2 (2025-06-26)
16+
## 5.101.0 (2025-07-02)
17+
18+
19+
### Features
20+
21+
* **web:** add binance wallet (#21350) 09813bd
22+
* **web:** adding analytics for polling (#21306) f0ca7b9
23+
* **web:** migrate PDP chart text to tamagui and add mobile styling (#21146) 3ad371e
24+
* **web:** polling retry with exponential backoff (#21300) 2162953
25+
* **web:** swap confirmation experiment (#21301) f1d5fb7
26+
* **web:** trading api polling (#21222) 95bf994
1727

1828

1929
### Bug Fixes
2030

21-
* **web:** hotfix try/catch WC analytics (#21290) fb57836
31+
* **web:** (vite) dedupe react to fix local wrangler build (#21194) ab45c27
32+
* **web:** 07 01 fix web approval for v2 migrations staging (#21397) bc9c07f
33+
* **web:** add analytics to pool search clicked (#21304) d690e98
34+
* **web:** attempt flaky navbar e2e fix (#21127) a8f159b
35+
* **web:** ensure table loader is visible (#21183) d6c794a
36+
* **web:** filter out Monad Testnet from explore dropdown (#21161) d42eaf7
37+
* **web:** fix fee display playwright test (#21224) ac7c9db
38+
* **web:** fix font/image loading in Cloudflare functions for Workers (#21203) 37efc78
39+
* **web:** fix issue with custom range and creating a pool (#21408) 33c7a40
40+
* **web:** fix merging of dynamic and regular fee tiers (#21407) 090b3fb
41+
* **web:** fix modal component to allow setting mx to center modal horizontally (#21160) a6f66aa
42+
* **web:** fix typo in GIT_COMMIT_HASH env variable for vite (#21281) 8c43a3a
43+
* **web:** halve displayed TVL amounts at current tick (#21323) a54f3a0
44+
* **web:** improve scroll lock performance (#21039) bf404d6
45+
* **web:** increase text padding in send form (#21101) 9fba69e
46+
* **web:** liquidity chart rerenders (#21120) 08a5214
47+
* **web:** LP create crash: check hook address checksum (#21132) 2e01381
48+
* **web:** navigation e2e test fix (#21100) 55bca5f
49+
* **web:** overflow in table error component (#21272) 122a914
50+
* **web:** remove trailing comma from jsonc (#21121) 6bcfa30
51+
* **web:** reuse addEventListener shim for vite and craco (#21172) 17e43a6
52+
* **web:** revert scroll lock performance (#21429) cd862fe
53+
* **web:** send dynamic fee for create lp reqs (#21198) 5a333cd
54+
* **web:** send dynamic fee for parse rest position (#21213) 9e96c67
55+
* **web:** send form insufficient balance for 0 balance (#21181) 89af656
56+
* **web:** try/catch WC analytics (#21327) 1299b3e
57+
* **web:** turn off CDN caching for JS assets (#20942) cad9461
58+
* **web:** update orientation of disconnected positions page (#21215) f65fb05
59+
* **web:** update tokens in web deploy workflows to new Service Account PATs (#21265) 9d6285d
60+
* **web:** update zone-events shim for android/chrome (#21253) 32df46f
61+
* **web:** wrangler config for functions - fix invalid options (#21188) 63fed2a
62+
63+
64+
### Continuous Integration
65+
66+
* **web:** update sitemaps f92b90f
67+
68+
69+
### Code Refactoring
70+
71+
* **web:** migrate claim uni enum value to uniswap enum (#21048) 32a4482
72+
* **web:** migrate collect fees enum value to uniswap enum (#21075) 84635cc
73+
* **web:** migrate create position enum value to uniswap enum (#21107) 24170cb
74+
* **web:** migrate liquidity decrease enum value to uniswap enum (#21105) 06f5848
75+
* **web:** migrate liquidity increase enum value to uniswap enum (#21103) 42a7e18
76+
* **web:** migrate v2tov3 enum value to uniswap enum (#21066) e4a573d
77+
* **web:** migrate wrap enum value to uniswap enum (#21064) c05b9e1
78+
* **web:** move v2tov3 info type to uniswap (#21067) ab50ce3
79+
* **web:** use liquidity decrease info type from uniswap (#21106) 38183bc
80+
* **web:** use liquidity increase info type from uniswap (#21104) ce273e2
81+
* **web:** use pool creation info type from uniswap (#21108) d2d8d7d
82+
* **web:** use swap info types from uniswap (#21047) e609c74
83+
* **web:** use wrap info type from uniswap (#21065) 8ffb18a
2284

2385

VERSION

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

apps/extension/src/app/features/biometricUnlock/useBiometricUnlockSetupMutation.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ describe('useBiometricUnlockSetupMutation', () => {
118118
{ type: 'public-key', alg: -8 },
119119
]),
120120
}),
121+
signal: expect.any(AbortSignal),
121122
})
122123

123124
// Verify the stored secret payload has all required properties

apps/extension/src/app/features/biometricUnlock/useBiometricUnlockSetupMutation.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
BiometricUnlockStorageData,
55
} from 'src/app/features/biometricUnlock/BiometricUnlockStorage'
66
import { biometricUnlockCredentialQuery } from 'src/app/features/biometricUnlock/biometricUnlockCredentialQuery'
7+
import { startNavigatorCredentialRequest } from 'src/app/features/biometricUnlock/useNavigatorCredentialAbortSignal'
78
import { assertPublicKeyCredential } from 'src/app/features/biometricUnlock/utils/assertPublicKeyCredential'
89
import { isUserVerifyingPlatformAuthenticatorAvailable } from 'src/app/utils/device/builtInBiometricCapabilitiesQuery'
910
import { logger } from 'utilities/src/logger/logger'
@@ -23,8 +24,13 @@ export function useBiometricUnlockSetupMutation(options?: {
2324

2425
return useMutation({
2526
mutationFn: async (password: string) => {
27+
const { abortSignal } = startNavigatorCredentialRequest('New biometric setup request initiated')
28+
2629
await assertIsUserVerifyingPlatformAuthenticatorAvailable()
27-
const biometricStorageData = await createCredentialAndEncryptPassword({ password })
30+
const biometricStorageData = await createCredentialAndEncryptPassword({
31+
password,
32+
abortSignal,
33+
})
2834
await BiometricUnlockStorage.set(biometricStorageData)
2935
},
3036
retry: false,
@@ -47,8 +53,10 @@ export function useBiometricUnlockSetupMutation(options?: {
4753

4854
async function createCredentialAndEncryptPassword({
4955
password,
56+
abortSignal,
5057
}: {
5158
password: string
59+
abortSignal: AbortSignal
5260
}): Promise<BiometricUnlockStorageData> {
5361
// Encrypt the password using the same approach we use in `Keyring`
5462
const secretPayload = await createEmptySecretPayload()
@@ -61,7 +69,10 @@ async function createCredentialAndEncryptPassword({
6169

6270
const rawKey = await window.crypto.subtle.exportKey('raw', encryptionKey)
6371

64-
const { credentialId } = await createCredential({ encryptionKey: rawKey })
72+
const { credentialId } = await createCredential({
73+
encryptionKey: rawKey,
74+
abortSignal,
75+
})
6576

6677
const secretPayloadWithCiphertext = await addEncryptedCiphertextToSecretPayload({
6778
secretPayload,
@@ -102,7 +113,13 @@ const CREDENTIAL_ALGORITHMS: PublicKeyCredentialParameters[] = [
102113
},
103114
]
104115

105-
async function createCredential({ encryptionKey }: { encryptionKey: ArrayBuffer }): Promise<{ credentialId: string }> {
116+
async function createCredential({
117+
encryptionKey,
118+
abortSignal,
119+
}: {
120+
encryptionKey: ArrayBuffer
121+
abortSignal: AbortSignal
122+
}): Promise<{ credentialId: string }> {
106123
// Create WebAuthn credential with platform authenticator (Touch ID, Windows Hello, etc.) forced
107124
const credential = await navigator.credentials.create({
108125
publicKey: {
@@ -127,6 +144,7 @@ async function createCredential({ encryptionKey }: { encryptionKey: ArrayBuffer
127144
pubKeyCredParams: CREDENTIAL_ALGORITHMS,
128145
timeout: 15 * ONE_SECOND_MS,
129146
},
147+
signal: abortSignal,
130148
})
131149

132150
const publicKeyCredential = assertPublicKeyCredential(credential)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const abortControllerRef: { current: AbortController | null } = { current: null }
2+
3+
export function startNavigatorCredentialRequest(reason: string): { abortSignal: AbortSignal } {
4+
// Cancel any pending requests.
5+
// This is needed because of a bug in how Chrome handles passkey requests inside the side panel.
6+
// Chrome bug: https://issues.chromium.org/issues/381056235
7+
// Video: https://github.com/Uniswap/universe/pull/21241
8+
abortControllerRef.current?.abort(reason)
9+
abortControllerRef.current = new AbortController()
10+
return { abortSignal: abortControllerRef.current.signal }
11+
}

apps/extension/src/app/features/biometricUnlock/useUnlockWithBiometricCredentialMutation.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ describe('useUnlockWithBiometricCredentialMutation', () => {
145145
userVerification: 'required',
146146
timeout: 15000, // 15 seconds
147147
},
148+
signal: expect.any(AbortSignal),
148149
})
149150

150151
// 3. Should dispatch unlock action with the decrypted password

apps/extension/src/app/features/biometricUnlock/useUnlockWithBiometricCredentialMutation.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
BiometricUnlockStorage,
44
BiometricUnlockStorageData,
55
} from 'src/app/features/biometricUnlock/BiometricUnlockStorage'
6+
import { startNavigatorCredentialRequest } from 'src/app/features/biometricUnlock/useNavigatorCredentialAbortSignal'
67
import { assertAuthenticatorAssertionResponse } from 'src/app/features/biometricUnlock/utils/assertAuthenticatorAssertionResponse'
78
import { assertPublicKeyCredential } from 'src/app/features/biometricUnlock/utils/assertPublicKeyCredential'
89
import { useUnlockWithPassword } from 'src/app/features/lockScreen/useUnlockWithPassword'
@@ -21,7 +22,8 @@ export function useUnlockWithBiometricCredentialMutation(): UseMutationResult<vo
2122
const unlockWithPassword = useUnlockWithPassword()
2223

2324
const unlockWithBiometric = useEvent(async (): Promise<void> => {
24-
const password = await getPasswordFromBiometricCredential()
25+
const { abortSignal } = startNavigatorCredentialRequest('New biometric unlock request initiated')
26+
const password = await getPasswordFromBiometricCredential(abortSignal)
2527
unlockWithPassword({ password })
2628
})
2729

@@ -48,15 +50,16 @@ export function useUnlockWithBiometricCredentialMutation(): UseMutationResult<vo
4850
*/
4951
export async function reauthenticateWithBiometricCredential(): Promise<{ password: string | null }> {
5052
try {
51-
const password = await getPasswordFromBiometricCredential()
53+
const { abortSignal } = startNavigatorCredentialRequest('New biometric reauthentication request initiated')
54+
const password = await getPasswordFromBiometricCredential(abortSignal)
5255
const success = await Keyring.checkPassword(password)
5356
return { password: success ? password : null }
5457
} catch (error) {
5558
return { password: null }
5659
}
5760
}
5861

59-
async function getPasswordFromBiometricCredential(): Promise<string> {
62+
async function getPasswordFromBiometricCredential(abortSignal: AbortSignal): Promise<string> {
6063
const biometricUnlockCredential = await BiometricUnlockStorage.get()
6164

6265
if (!biometricUnlockCredential) {
@@ -66,12 +69,18 @@ async function getPasswordFromBiometricCredential(): Promise<string> {
6669
const { credentialId } = biometricUnlockCredential
6770

6871
// Authenticate with WebAuthn using the stored credential and decrypt password
69-
const publicKeyCredential = await authenticateWithCredential({ credentialId })
72+
const publicKeyCredential = await authenticateWithCredential({ credentialId, abortSignal })
7073
const password = await decryptPasswordFromCredential({ publicKeyCredential, biometricUnlockCredential })
7174
return password
7275
}
7376

74-
async function authenticateWithCredential({ credentialId }: { credentialId: string }): Promise<PublicKeyCredential> {
77+
async function authenticateWithCredential({
78+
credentialId,
79+
abortSignal,
80+
}: {
81+
credentialId: string
82+
abortSignal: AbortSignal
83+
}): Promise<PublicKeyCredential> {
7584
// Convert stored credential ID back to binary format
7685
const credentialIdBuffer = Uint8Array.from(atob(credentialId), (c) => c.charCodeAt(0))
7786

@@ -87,6 +96,7 @@ async function authenticateWithCredential({ credentialId }: { credentialId: stri
8796
userVerification: 'required',
8897
timeout: 15 * ONE_SECOND_MS,
8998
},
99+
signal: abortSignal,
90100
})
91101

92102
const publicKeyCredential = assertPublicKeyCredential(credential)

apps/extension/src/app/features/dappRequests/DappRequestContent.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ interface DappRequestFooterProps {
5757
onConfirm?: (requestToCancel?: DappRequestStoreItem) => void
5858
showAllNetworks?: boolean
5959
showNetworkCost?: boolean
60+
showSmartWalletActivation?: boolean
6061
transactionGasFeeResult?: GasFeeResult
6162
isUniswapX?: boolean
6263
disableConfirm?: boolean
@@ -101,6 +102,7 @@ export function DappRequestContent({
101102
onConfirm,
102103
showAllNetworks,
103104
showNetworkCost,
105+
showSmartWalletActivation,
104106
transactionGasFeeResult,
105107
children,
106108
isUniswapX,
@@ -125,6 +127,7 @@ export function DappRequestContent({
125127
maybeCloseOnConfirm={maybeCloseOnConfirm}
126128
showAllNetworks={showAllNetworks}
127129
showNetworkCost={showNetworkCost}
130+
showSmartWalletActivation={showSmartWalletActivation}
128131
transactionGasFeeResult={transactionGasFeeResult}
129132
disableConfirm={disableConfirm}
130133
onCancel={onCancel}
@@ -186,6 +189,7 @@ function DappRequestFooter({
186189
onCancel,
187190
onConfirm,
188191
showNetworkCost,
192+
showSmartWalletActivation,
189193
transactionGasFeeResult,
190194
isUniswapX,
191195
disableConfirm,
@@ -282,6 +286,7 @@ function DappRequestFooter({
282286
isUniswapX={isUniswapX}
283287
showNetworkLogo={!!transactionGasFeeResult}
284288
requestMethod={request.dappRequest.type}
289+
showSmartWalletActivation={showSmartWalletActivation}
285290
/>
286291
)}
287292
<AddressFooter

apps/extension/src/app/features/dappRequests/requestContent/EthSend/Swap/SwapDisplay.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export function SwapDisplay({
2020
outputCurrencyInfo,
2121
chainId,
2222
transactionGasFeeResult,
23+
showSmartWalletActivation,
2324
onCancel,
2425
onConfirm,
2526
isUniswapX,
@@ -32,6 +33,7 @@ export function SwapDisplay({
3233
outputCurrencyInfo: Maybe<CurrencyInfo>
3334
chainId: UniverseChainId | null
3435
transactionGasFeeResult?: GasFeeResult
36+
showSmartWalletActivation?: boolean
3537
onCancel?: () => Promise<void>
3638
onConfirm?: () => Promise<void>
3739
isUniswapX?: boolean
@@ -92,6 +94,7 @@ export function SwapDisplay({
9294
isUniswapX={isUniswapX}
9395
title={title}
9496
transactionGasFeeResult={transactionGasFeeResult}
97+
showSmartWalletActivation={showSmartWalletActivation}
9598
onCancel={onCancel}
9699
onConfirm={onConfirm}
97100
>

0 commit comments

Comments
 (0)