Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
b6e494c
bump semver 7.58.1
sethkfman Nov 5, 2025
39c63c1
[skip ci] Bump version number to 2949
metamaskbot Nov 5, 2025
1146422
Merge branch 'stable' into release/7.58.1
joaoloureirop Nov 6, 2025
ca57ba1
chore: increase bundle size check value to 50 (#22254)
joaoloureirop Nov 6, 2025
22b9eda
chore(runway): cherry-pick fix(card): delegation issues (#22249)
runway-github[bot] Nov 6, 2025
74c304c
chore(runway): cherry-pick fix(card): Onboarding UI issues (#22263)
runway-github[bot] Nov 6, 2025
2b99cc8
chore(runway): cherry-pick fix(card): add temporary fix for crashing …
runway-github[bot] Nov 6, 2025
3806dbe
fix: cp-75.8.1 remove selected network reference from bridge getBridg…
micaelae Nov 6, 2025
c376d31
chore(runway): cherry-pick fix: Android In-App Browser Crash (#22269)
runway-github[bot] Nov 6, 2025
5e04a23
chore(runway): cherry-pick refactor(card): sonarcloud maintainability…
runway-github[bot] Nov 6, 2025
f7fcec1
[skip ci] Bump version number to 2957
metamaskbot Nov 6, 2025
4ede6c5
chore: update release/7.58.1 changelog (#22309)
joaoloureirop Nov 7, 2025
68783d7
chore: update changelog
joaoloureirop Nov 7, 2025
275bcb7
chore(runway): bump version to 7.58.2 (#22345)
runway-github[bot] Nov 7, 2025
590669f
chore: Suppress CI error (#22280)
smilingkylan Nov 7, 2025
c3d5f80
chore(runway): cherry-pick fix: cp-7.58.2 update close position calcu…
nickewansmith Nov 10, 2025
ac429d4
chore(runway): cherry-pick fix(card): UI issues on Authentication/Del…
runway-github[bot] Nov 10, 2025
fc8dd22
chore(runway): cherry-pick fix(card): cp-7.58.2 CardHome and Spending…
runway-github[bot] Nov 11, 2025
9b54d80
chore(runway): cherry-pick fix: pressability measureAsyncOnUI only ru…
runway-github[bot] Nov 11, 2025
189163a
[skip ci] Bump version number to 3001
metamaskbot Nov 11, 2025
db02608
chore(runway): cherry-pick fix(card): cp-7.58.2 delegation issues (#2…
runway-github[bot] Nov 11, 2025
2ce63c0
[skip ci] Bump version number to 3004
metamaskbot Nov 11, 2025
e8d447d
chore: update v7.58.2 changelog
joaoloureirop Nov 11, 2025
e7fea4d
Release 7.58.2 (#22329)
joaoloureirop Nov 12, 2025
e3a5282
chore(predict): Adds correct no search results found empty state (#22…
kevinbluer Nov 13, 2025
f6976b3
fix(card): cp-7.59.0 wrong zero balances on SelectAsset BottomSheet (…
Brunonascdev Nov 13, 2025
a15b575
fix(perps): race condition sometime preventing loading hip-3 position…
abretonc7s Nov 13, 2025
206c5c6
feat: predict claim gas station (#22553)
matthewwalsh0 Nov 13, 2025
26b7dd2
chore: enable predict for non-evm networks (#22657)
caieu Nov 13, 2025
df409db
feat: updated transaction details for predict claim and withdraw (#22…
matthewwalsh0 Nov 13, 2025
849cd16
chore(predict): change spacing in about tab (#22656)
caieu Nov 13, 2025
3a12477
Merge origin/main into stable-sync
joaoloureirop Nov 13, 2025
a9721ca
feat(perps): remove current pill on chart (#22599)
abretonc7s Nov 13, 2025
8123358
chore: sync stable to main for version 7.60.0 (#22671)
sethkfman Nov 13, 2025
9551d05
feat(perps): single line hip3 hours warning (#22513)
abretonc7s Nov 13, 2025
6b4dbaa
fix(predict): only show rewards if enabled for account (#22672)
matallui Nov 13, 2025
4eb25f2
feat(perps): update error screens for improved messaging (#22617)
abretonc7s Nov 13, 2025
a7e247c
feat: Add all entry points for Predict feed (#22659)
andrepimenta Nov 13, 2025
e3dd7bd
fix(predict): hide unrealized pnl if the user has 0 positions (#22678)
matallui Nov 13, 2025
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
28 changes: 27 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [7.58.2]

### Fixed

- fix(card): cp-7.58.2 delegation issues ([#22476](https://github.com/MetaMask/metamask-mobile/pull/22476)
- fix: pressability measureAsyncOnUI only running on Android cp-7.58.2 ([#22464](https://github.com/MetaMask/metamask-mobile/pull/22464)
- fix(card): cp-7.58.2 CardHome and SpendingLimit UI issues ([#22448](https://github.com/MetaMask/metamask-mobile/pull/22448)
- fix(card): UI issues on Authentication/Delegation ([#22433](https://github.com/MetaMask/metamask-mobile/pull/22433)
- fix: cp-7.58.2 update close position calculation with funding fees and live data ([#22344](https://github.com/MetaMask/metamask-mobile/pull/22344)

## [7.58.1]

### Fixed

- fix: Android In-App Browser Crash ([#22269](https://github.com/MetaMask/metamask-mobile/pull/22269))
- fix: cp-75.8.1 remove selected network reference from bridge getBridgeERC20Allowance handler ([#22230](https://github.com/MetaMask/metamask-mobile/pull/22230))
- fix(card): add temporary fix for crashing KYC webview on Android ([#22238](https://github.com/MetaMask/metamask-mobile/pull/22238))
- fix(card): Onboarding UI issues ([#22263](https://github.com/MetaMask/metamask-mobile/pull/22263))
- fix(card): delegation issues ([#22249](https://github.com/MetaMask/metamask-mobile/pull/22249))

### Changed

- refactor(card): sonarcloud maintainability issues ([#22268](https://github.com/MetaMask/metamask-mobile/pull/22268))

## [7.58.0]

### Added
Expand Down Expand Up @@ -8783,7 +8807,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [#957](https://github.com/MetaMask/metamask-mobile/pull/957): fix timeouts (#957)
- [#954](https://github.com/MetaMask/metamask-mobile/pull/954): Bugfix: onboarding navigation (#954)

[Unreleased]: https://github.com/MetaMask/metamask-mobile/compare/v7.58.0...HEAD
[Unreleased]: https://github.com/MetaMask/metamask-mobile/compare/v7.58.2...HEAD
[7.58.2]: https://github.com/MetaMask/metamask-mobile/compare/v7.58.1...v7.58.2
[7.58.1]: https://github.com/MetaMask/metamask-mobile/compare/v7.58.0...v7.58.1
[7.58.0]: https://github.com/MetaMask/metamask-mobile/compare/v7.57.2...v7.58.0
[7.57.2]: https://github.com/MetaMask/metamask-mobile/compare/v7.57.1...v7.57.2
[7.57.1]: https://github.com/MetaMask/metamask-mobile/compare/v7.57.0...v7.57.1
Expand Down
4 changes: 2 additions & 2 deletions app/components/Nav/Main/MainNavigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -942,8 +942,8 @@ const MainNavigator = () => {
// Get feature flag state for conditional Predict screen registration
const predictEnabledFlag = useSelector(selectPredictEnabledFlag);
const isPredictEnabled = useMemo(
() => predictEnabledFlag && isEvmSelected,
[predictEnabledFlag, isEvmSelected],
() => predictEnabledFlag,
[predictEnabledFlag],
);
const { enabled: isSendRedesignEnabled } = useSelector(
selectSendRedesignFlags,
Expand Down
6 changes: 3 additions & 3 deletions app/components/UI/Card/hooks/useAssetBalances.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ describe('useAssetBalances', () => {
mockUseTokensWithBalance.mockReturnValue([
{
address: mockEvmToken.address?.toLowerCase() || '',
chainId: mockEvmToken.caipChainId,
chainId: '0xe708', // Use hex format, not CAIP format
balance: '250.75',
balanceFiat: '$250.75',
symbol: 'USDC',
Expand Down Expand Up @@ -449,7 +449,7 @@ describe('useAssetBalances', () => {
mockUseTokensWithBalance.mockReturnValue([
{
address: mockNotEnabledToken.address?.toLowerCase() || '',
chainId: mockNotEnabledToken.caipChainId,
chainId: '0xe708', // Use hex format, not CAIP format
balance: '200.75',
balanceFiat: '$200.75',
symbol: 'DAI',
Expand Down Expand Up @@ -559,7 +559,7 @@ describe('useAssetBalances', () => {
mockUseTokensWithBalance.mockReturnValue([
{
address: mockEvmToken.address?.toLowerCase() || '',
chainId: mockEvmToken.caipChainId,
chainId: '0xe708', // Use hex format, not CAIP format
balance: '125.50',
balanceFiat: '$125.50',
symbol: 'USDC',
Expand Down
9 changes: 8 additions & 1 deletion app/components/UI/Card/hooks/useAssetBalances.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export const useAssetBalances = (
}
}
});

return map;
});

Expand Down Expand Up @@ -114,6 +115,7 @@ export const useAssetBalances = (
}
}
});

return map;
});

Expand Down Expand Up @@ -487,8 +489,13 @@ export const useAssetBalances = (
: safeFormatChainIdToHex(token.caipChainId);

// Find the token in tokensWithBalance
// Note: tokensWithBalance uses hex chainId (e.g., "0xe708") while token has CAIP chainId (e.g., "eip155:59144")
// We need to use assetChainId which is already normalized to the correct format
// Also need case-insensitive address comparison since tokensWithBalance may have checksum addresses
const filteredToken = tokensWithBalance.find(
(t) => t.address === assetAddress && t.chainId === token.caipChainId,
(t) =>
t.address?.toLowerCase() === assetAddress?.toLowerCase() &&
t.chainId === assetChainId,
);

// Get wallet asset as fallback
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jest.mock('../../../../../component-library/components/Icons/Icon', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
default: ({ name, ...props }: any) => <View {...props} testID={name} />,
IconName: {
Details: 'Details',
Warning: 'Warning',
},
IconColor: {
Muted: 'Muted',
Expand Down Expand Up @@ -146,7 +146,6 @@ describe('PerpsConnectionErrorView', () => {
);

expect(getByText('perps.errors.connectionFailed.title')).toBeTruthy();
expect(getByText('perps.errors.connectionFailed.description')).toBeTruthy();
expect(getByText('perps.errors.connectionFailed.retry')).toBeTruthy();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ const PerpsConnectionErrorView: React.FC<PerpsConnectionErrorViewProps> = ({
<View style={styles.container}>
<View style={styles.errorContainer}>
<Icon
name={IconName.Details}
name={IconName.Warning}
color={IconColor.Muted}
size={IconSize.Xl}
style={styles.errorIcon}
Expand All @@ -99,14 +99,6 @@ const PerpsConnectionErrorView: React.FC<PerpsConnectionErrorViewProps> = ({
{strings('perps.errors.connectionFailed.title')}
</Text>

<Text
variant={TextVariant.BodyMD}
color={TextColor.Muted}
style={styles.errorMessage}
>
{strings('perps.errors.connectionFailed.description')}
</Text>

{/* Only show debug details in development */}
{shouldShowDebugDetails && (
<Text
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ describe('PerpsErrorState', () => {
expect(
getByText(strings('perps.errors.connectionFailed.title')),
).toBeTruthy();
expect(
getByText(strings('perps.errors.connectionFailed.description')),
).toBeTruthy();

const retryButton = getByText(
strings('perps.errors.connectionFailed.retry'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ const PerpsErrorState: React.FC<PerpsErrorStateProps> = ({
switch (errorType) {
case PerpsErrorType.CONNECTION_FAILED:
return {
icon: IconName.Wifi,
icon: IconName.Warning,
title: strings('perps.errors.connectionFailed.title'),
description: strings('perps.errors.connectionFailed.description'),
description: undefined,
primaryAction: {
label: strings('perps.errors.connectionFailed.retry'),
onPress: onRetry,
Expand Down Expand Up @@ -97,13 +97,15 @@ const PerpsErrorState: React.FC<PerpsErrorStateProps> = ({
>
{errorContent.title}
</Text>
<Text
variant={TextVariant.BodyMD}
color={TextColor.Muted}
style={styles.description}
>
{errorContent.description}
</Text>
{errorContent.description && (
<Text
variant={TextVariant.BodyMD}
color={TextColor.Muted}
style={styles.description}
>
{errorContent.description}
</Text>
)}
{errorContent.primaryAction?.onPress && (
<Button
variant={ButtonVariants.Primary}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ describe('PerpsMarketHoursBanner', () => {
);

expect(
getByText('Expect more volatility outside of regular market hours'),
getByText('Expect more volatility outside of market hours'),
).toBeTruthy();
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const PerpsWatchlistMarkets: React.FC<PerpsWatchlistMarketsProps> = ({
({ item }: { item: PerpsMarketData }) => (
<PerpsMarketRowItem
market={item}
showBadge={false}
onPress={() => handleMarketPress(item)}
/>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,9 +569,9 @@ export const createTradingViewChartTemplate = (
price: parseFloat(currentPrice),
color: '#FFF', // White
lineWidth: 1,
lineStyle: 0, // Solid line
lineStyle: 2, // Dashed line
axisLabelVisible: true,
title: 'Current'
title: ''
});
// Store reference for future removal
window.priceLines.currentPrice = priceLine;
Expand Down Expand Up @@ -711,25 +711,25 @@ export const createTradingViewChartTemplate = (
price: window.originalPriceLineData.currentPrice.price,
color: '#FFF',
lineWidth: 1,
lineStyle: 0,
lineStyle: 2,
axisLabelVisible: true,
title: 'Current'
title: ''
});
} catch (error) {
// Silent error handling
}
}

// Recreate current price line from stored data
if (window.originalPriceLineData.currentPrice) {
try {
window.priceLines.currentPrice = window.candlestickSeries.createPriceLine({
price: window.originalPriceLineData.currentPrice.price,
color: '#FFF',
lineWidth: 1,
lineStyle: 0,
lineStyle: 2,
axisLabelVisible: true,
title: 'Current'
title: ''
});
} catch (error) {
// Silent error handling
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3676,6 +3676,13 @@ export class HyperLiquidProvider implements IPerpsProvider {
this.ensureClientsInitialized();
this.clientService.ensureInitialized();

// CRITICAL: Build asset mapping on first call to ensure DEX discovery
// This must happen BEFORE any WebSocket subscriptions receive data
// Otherwise HIP-3 positions will be filtered out due to empty discoveredDexNames
if (this.coinToAssetId.size === 0) {
await this.buildAssetMapping();
}

// Path 1: Symbol filtering - group by DEX and fetch in parallel
if (params?.symbols && params.symbols.length > 0) {
DevLogger.log(
Expand Down
4 changes: 2 additions & 2 deletions app/components/UI/Perps/hooks/usePerpsMarkets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export interface UsePerpsMarketsOptions {
skipInitialFetch?: boolean;
/**
* Show markets with zero or invalid volume
* @default false
* @default __DEV__ (true in development, false in production)
*/
showZeroVolume?: boolean;
}
Expand Down Expand Up @@ -112,7 +112,7 @@ export const usePerpsMarkets = (
enablePolling = false,
pollingInterval = 60000, // 1 minute default
skipInitialFetch = false,
showZeroVolume = false,
showZeroVolume = __DEV__, // Show zero-volume markets in development mode
} = options;

const streamManager = usePerpsStream();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export class HyperLiquidSubscriptionService {
this.walletService = walletService;
this.hip3Enabled = hip3Enabled ?? false;
this.enabledDexs = enabledDexs ?? [];
this.discoveredDexNames = enabledDexs ?? [];
this.allowlistMarkets = allowlistMarkets ?? [];
this.blocklistMarkets = blocklistMarkets ?? [];
}
Expand Down
4 changes: 2 additions & 2 deletions app/components/UI/Perps/utils/marketDataTransform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ describe('marketDataTransform', () => {
expect(result[0].marketType).toBe('commodity');
});

it('handles unmapped HIP-3 DEX with marketSource but no marketType', () => {
it('handles unmapped HIP-3 DEX - defaults to equity marketType', () => {
const unknownDexAsset = {
name: 'unknown:ASSET1',
maxLeverage: 10,
Expand All @@ -376,7 +376,7 @@ describe('marketDataTransform', () => {
expect(result).toHaveLength(1);
expect(result[0].symbol).toBe('unknown:ASSET1');
expect(result[0].marketSource).toBe('unknown');
expect(result[0].marketType).toBeUndefined();
expect(result[0].marketType).toBe('equity');
});

it('handles main DEX assets with no marketSource or marketType', () => {
Expand Down
13 changes: 9 additions & 4 deletions app/components/UI/Perps/utils/marketDataTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,16 +224,21 @@ export function transformMarketData(
fundingRate = fundingData.predictedFundingRate;
}

// Extract DEX and determine market type for badge display
// Extract DEX and base symbol for display
// e.g., "flx:TSLA" → { dex: "flx", symbol: "TSLA" }
const { dex } = parseAssetName(symbol);
const marketSource = dex || undefined;

// Simple per-asset lookup from feature flag (e.g., 'xyz:GOLD' → 'commodity')
const marketType: MarketType | undefined = assetMarketTypes?.[symbol];
// Determine market type:
// 1. Check explicit mapping (e.g., 'xyz:GOLD' → 'commodity')
// 2. Default HIP-3 DEX markets to 'equity' (stocks) if not mapped
// 3. Main DEX markets remain undefined (crypto)
const marketType: MarketType | undefined =
assetMarketTypes?.[symbol] || (dex ? 'equity' : undefined);

return {
symbol,
name: symbol, // HyperLiquid uses symbol as name
name: symbol,
maxLeverage: `${asset.maxLeverage}x`,
price: isNaN(currentPrice)
? PERPS_CONSTANTS.FALLBACK_PRICE_DISPLAY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ const styleSheet = () =>
width: '100%',
padding: 16,
},
emptySearchContainer: {
justifyContent: 'center',
alignItems: 'center',
width: '100%',
marginTop: 42,
padding: 16,
},
marketListContainer: {
flex: 1,
width: '100%',
Expand Down
Loading
Loading