Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
983b54e
chore: set OTA_VERSION to v7.78.1 for OTA hotfix (release/7.78.1-ota)
metamaskbot May 27, 2026
59d702b
cherry-pick: fix(perps): investigate Failed to execute 'dispatchEvent…
joaoloureirop May 27, 2026
a3715bb
[skip ci] Bump version number to 5196
metamaskbot May 27, 2026
5e3d695
Revert "[skip ci] Bump version number to 5196"
joaoloureirop May 27, 2026
265546c
ota fingerprint hack
joaoloureirop May 27, 2026
a0eebce
modify fingerprint hack
joaoloureirop May 27, 2026
896867a
modify fingerprint hack again
joaoloureirop May 27, 2026
da5beef
release: update changelog for 7.78.1 (hotfix - no test plan) (#30700)
joaoloureirop May 29, 2026
f327cc0
remove fingerprint hack
joaoloureirop May 29, 2026
4e43423
Merge branch 'stable' into release/7.78.1-ota
joaoloureirop May 29, 2026
6c60682
release: 7.78.1 (OTA) (#30695)
joaoloureirop May 29, 2026
a4da13e
Merge origin/main into stable-main-7.78.0
metamaskbot May 29, 2026
3e5edf7
chore: bump axios 16.1 (#30815)
tommasini May 29, 2026
46270d3
chore(release): sync stable to main for version 7.78.0 (#30807)
metamaskbotv2[bot] May 29, 2026
9031898
chore(ci): add bitrise.yml to fix release automation (#30825)
joaoloureirop May 29, 2026
dbd8678
feat(predict): add predictHomeRedesign feature flag and selector (#30…
MarioAslau May 29, 2026
ae601d9
fix(engagement): latch startup marketing consent prompt (#30808)
samir-acle May 29, 2026
f6df783
chore(pure black): elevate MMDS BottomSheet surfaces via useElevatedS…
vinnyhoward May 29, 2026
c6cc0b9
ci: remove OTA tag creation step (#30813)
weitingsun May 29, 2026
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
73 changes: 13 additions & 60 deletions .github/workflows/auto-rc-ota-build-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
#
# Auto RC OTA / build core (reusable)
#
# Shared logic for the Auto RC flow (build-rc-auto.yml): detect an OTA_VERSION bump and either
# dispatch push-eas-update.yml, or fall through to build.yml.
# Shared logic for the Auto RC flow (build-rc-auto.yml): detect whether the push is an
# OTA_VERSION bump and, if so, skip the native build (OTA-only changes are published
# separately). Otherwise fall through to a native build.yml build (and TestFlight for iOS).
#
# Runway's manual entry workflows no longer use this file — they call the dedicated OTA-only or
# build-only workflows (runway-ota-*.yml, runway-*-builds.yml) directly. Kept here to preserve
# automatic OTA-vs-build detection on every push to a release branch.
# This workflow does not push OTA updates — OTA publishing is handled outside this flow.
#
# Runway's manual entry workflows do not use this file — they call the dedicated OTA-only or
# build-only workflows (runway-ota-*.yml, runway-*-builds.yml) directly.
#
##############################################################################################
name: Auto RC OTA Build Core
Expand All @@ -16,7 +18,7 @@ on:
workflow_call:
inputs:
platform:
description: 'Target platform passed to push-eas-update and build.yml (android or ios)'
description: 'Target platform passed to build.yml (android or ios)'
required: true
type: string
source_branch:
Expand All @@ -26,41 +28,30 @@ on:
required: false
type: string
default: ''
ota_channel:
description: 'push-eas-update channel input (e.g. rc, production)'
required: false
type: string
default: rc
build_name:
description: 'build.yml build_name (e.g. main-rc, main-prod)'
required: false
type: string
default: main-rc
create_production_ota_tag:
description: 'If true, create OTA release tag after production trigger-ota (callers: *production* only)'
required: false
type: boolean
default: false
environment:
description: 'Build environment / track passed to upload-to-testflight (e.g. rc, prod)'
required: false
type: string
default: 'rc'
outputs:
semantic_version:
description: 'package.json version at the built commit (empty when OTA path taken)'
description: 'package.json version at the built commit (empty when OTA bump skips the build)'
value: ${{ jobs.trigger-build.outputs.semantic_version }}
ios_version_code:
description: 'iOS CURRENT_PROJECT_VERSION at the built commit (empty when OTA path taken)'
description: 'iOS CURRENT_PROJECT_VERSION at the built commit (empty when OTA bump skips the build)'
value: ${{ jobs.trigger-build.outputs.ios_version_code }}
android_version_code:
description: 'Android versionCode at the built commit (empty when OTA path taken)'
description: 'Android versionCode at the built commit (empty when OTA bump skips the build)'
value: ${{ jobs.trigger-build.outputs.android_version_code }}

permissions:
contents: write
pull-requests: read
actions: write
contents: read
pull-requests: read # required by runway-ota-resolve-context.yml
id-token: write # required by build.yml

jobs:
Expand All @@ -71,34 +62,6 @@ jobs:
source_branch: ${{ inputs.source_branch }}
secrets: inherit

validate-ota-pr:
name: Validate PR for OTA
needs: resolve-context
if: needs.resolve-context.outputs.ota_bump == 'true'
runs-on: ubuntu-latest
steps:
- name: Validate PR number
run: |
if [[ -z "${{ needs.resolve-context.outputs.pr_number }}" ]]; then
echo "::error::No PR found for this branch. OTA update requires a PR number."
echo "::error::If you ran the workflow manually (workflow_dispatch), select your release branch in the 'Use workflow from' dropdown (e.g. release/7.71.0), not main."
exit 1
fi
echo "Using PR #${{ needs.resolve-context.outputs.pr_number }}"

trigger-ota:
name: Trigger OTA update
needs: [resolve-context, validate-ota-pr]
if: needs.resolve-context.outputs.ota_bump == 'true'
uses: ./.github/workflows/push-eas-update.yml
with:
pr_number: ${{ needs.resolve-context.outputs.pr_number }}
base_branch: ${{ needs.resolve-context.outputs.base_ref }}
message: ${{ needs.resolve-context.outputs.ota_version }}
channel: ${{ inputs.ota_channel }}
platform: ${{ inputs.platform }}
secrets: inherit

trigger-build:
name: Trigger build mobile app
needs: resolve-context
Expand All @@ -111,16 +74,6 @@ jobs:
upload_to_sentry: true
secrets: inherit

create-ota-production-tag:
name: Create OTA production release tag
needs: [resolve-context, trigger-ota]
if: ${{ inputs.create_production_ota_tag == true }}
uses: ./.github/workflows/runway-create-ota-production-tag.yml
with:
tag_name: ${{ needs.resolve-context.outputs.ota_version }}
checkout_ref: ${{ inputs.source_branch || github.ref_name }}
secrets: inherit

upload-ios-testflight:
name: Upload iOS to TestFlight
needs: [trigger-build]
Expand Down
69 changes: 0 additions & 69 deletions .github/workflows/runway-create-ota-production-tag.yml

This file was deleted.

16 changes: 3 additions & 13 deletions .github/workflows/runway-ota-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
#
# Runway OTA Production
#
# Triggered from Runway to push an OTA update to the production channel (iOS + Android) and
# create the corresponding `v<OTA_VERSION>` release tag.
# Triggered from Runway to push an OTA update to the production channel (iOS + Android).
#
# This workflow does not build binaries and does not bump the build version — the release PR is
# expected to bump OTA_VERSION (app/constants/ota.ts) before dispatch.
Expand All @@ -16,13 +15,13 @@ on:
inputs:
source_branch:
description: >-
Optional branch, tag, or SHA for OTA publish + tag creation.
Optional branch, tag, or SHA for OTA publish.
Empty uses the branch selected in the "Use workflow from" UI.
required: false
type: string

permissions:
contents: write # required to push the v<OTA_VERSION> tag
contents: read
pull-requests: read
id-token: write # required by push-eas-update.yml

Expand Down Expand Up @@ -59,12 +58,3 @@ jobs:
channel: production
platform: all
secrets: inherit

create-ota-production-tag:
name: Create OTA production release tag
needs: [resolve-context, push-ota]
uses: ./.github/workflows/runway-create-ota-production-tag.yml
with:
tag_name: ${{ needs.resolve-context.outputs.ota_version }}
checkout_ref: ${{ inputs.source_branch || github.ref_name }}
secrets: inherit
9 changes: 6 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Uncategorized
## [7.78.1]

### Fixed

- chore(deps): bump the `@metamask/tron-wallet-snap` to `^1.25.6` (#30200)
- Fixed a crash caused by CloseEvent dispatch on WebSocket failing instanceof validation (#30612)

## [7.78.0]

Expand Down Expand Up @@ -11561,7 +11563,8 @@ 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.78.0...HEAD
[Unreleased]: https://github.com/MetaMask/metamask-mobile/compare/v7.78.1...HEAD
[7.78.1]: https://github.com/MetaMask/metamask-mobile/compare/v7.78.0...v7.78.1
[7.78.0]: https://github.com/MetaMask/metamask-mobile/compare/v7.77.2...v7.78.0
[7.77.2]: https://github.com/MetaMask/metamask-mobile/compare/v7.77.1...v7.77.2
[7.77.1]: https://github.com/MetaMask/metamask-mobile/compare/v7.77.0...v7.77.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { RootState } from '../../../../../reducers';
import { BridgeToken } from '../../types';
import { formatTokenBalance } from '../../utils';
import { BatchSellDestinationTokenSelectorModalSelectorsIDs } from './BatchSellDestinationTokenSelectorModal.testIds';
import { useElevatedSurface } from '../../../../../util/theme/themeUtils';

const getTokenKey = (token: BridgeToken) => `${token.chainId}:${token.address}`;

Expand Down Expand Up @@ -86,6 +87,7 @@ export function BatchSellDestinationTokenSelectorModal() {
chainIds:
destinationChainIds ?? (sourceChainId ? [sourceChainId] : undefined),
});
const surfaceClass = useElevatedSurface();

const handleClose = useCallback(() => {
sheetRef.current?.onCloseBottomSheet();
Expand All @@ -104,6 +106,7 @@ export function BatchSellDestinationTokenSelectorModal() {
ref={sheetRef}
goBack={navigation.goBack}
testID={BatchSellDestinationTokenSelectorModalSelectorsIDs.SHEET}
twClassName={surfaceClass}
>
<BottomSheetHeader
onClose={handleClose}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { useBatchSellHasSufficientGas } from '../../hooks/useBatchSellHasSuffici
import type { BridgeToken } from '../../types';
import { BatchSellQuoteDetails } from '../BatchSellQuoteDetailsModal';
import { BatchSellFinalReviewModalSelectorsIDs } from './BatchSellFinalReviewModal.testIds';
import { useElevatedSurface } from '../../../../../util/theme/themeUtils';

const MAX_VISIBLE_SOURCE_TOKEN_AVATARS = 5;
const SOURCE_TOKEN_AVATAR_OVERLAP = 12;
Expand Down Expand Up @@ -289,6 +290,7 @@ export function BatchSellFinalReviewModal() {
isGasless: batchSellQuoteData.isGasless,
networkFee: batchSellQuoteData.networkFee,
});
const surfaceClass = useElevatedSurface();
const [isTokenDetailsExpanded, setIsTokenDetailsExpanded] = useState(true);
const finalReviewQuoteData = useMemo(
() =>
Expand Down Expand Up @@ -362,6 +364,7 @@ export function BatchSellFinalReviewModal() {
<BottomSheet
testID={BatchSellFinalReviewModalSelectorsIDs.SHEET}
goBack={navigation.goBack}
twClassName={surfaceClass}
>
<BottomSheetHeader
onClose={navigation.goBack}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { strings } from '../../../../../../locales/i18n';
import { useParams } from '../../../../../util/navigation/navUtils';
import { BatchSellMinimumReceivedInfoModalSelectorsIDs } from './BatchSellMinimumReceivedInfoModal.testIds';
import { BatchSellMinimumReceivedInfoModalParams } from './BatchSellMinimumReceivedInfoModal.types';
import { useElevatedSurface } from '../../../../../util/theme/themeUtils';

export function BatchSellMinimumReceivedInfoModal() {
const navigation =
Expand All @@ -23,11 +24,13 @@ export function BatchSellMinimumReceivedInfoModal() {
const handleBack = sourceModal
? () => navigation.replace(sourceModal.screen, sourceModal.params)
: undefined;
const surfaceClass = useElevatedSurface();

return (
<BottomSheet
testID={BatchSellMinimumReceivedInfoModalSelectorsIDs.SHEET}
goBack={navigation.goBack}
twClassName={surfaceClass}
>
<BottomSheetHeader
onBack={handleBack}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { strings } from '../../../../../../locales/i18n';
import { useParams } from '../../../../../util/navigation/navUtils';
import { BatchSellNetworkFeeInfoModalSelectorsIDs } from './BatchSellNetworkFeeInfoModal.testIds';
import { BatchSellNetworkFeeInfoModalParams } from './BatchSellNetworkFeeInfoModal.types';
import { useElevatedSurface } from '../../../../../util/theme/themeUtils';

export function BatchSellNetworkFeeInfoModal() {
const navigation =
Expand All @@ -23,11 +24,13 @@ export function BatchSellNetworkFeeInfoModal() {
const handleBack = sourceModal
? () => navigation.replace(sourceModal.screen, sourceModal.params)
: undefined;
const surfaceClass = useElevatedSurface();

return (
<BottomSheet
testID={BatchSellNetworkFeeInfoModalSelectorsIDs.SHEET}
goBack={navigation.goBack}
twClassName={surfaceClass}
>
<BottomSheetHeader
onBack={handleBack}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ import {
import { BatchSellQuoteDetails } from './BatchSellQuoteDetails';
import { BatchSellQuoteDetailsModalSelectorsIDs } from './BatchSellQuoteDetailsModal.testIds';
import { strings } from '../../../../../../locales/i18n';
import { useElevatedSurface } from '../../../../../util/theme/themeUtils';

export function BatchSellQuoteDetailsModal() {
const navigation =
useNavigation<StackNavigationProp<Record<string, object | undefined>>>();
const sourceTokens = useSelector(selectBatchSellSourceTokens);
const surfaceClass = useElevatedSurface();
const batchSellQuoteData = useBatchSellQuoteData({
shouldUpdateBatchSellTrades: false,
});
Expand All @@ -48,6 +50,7 @@ export function BatchSellQuoteDetailsModal() {
<BottomSheet
testID={BatchSellQuoteDetailsModalSelectorsIDs.SHEET}
goBack={navigation.goBack}
twClassName={surfaceClass}
>
<BottomSheetHeader
onClose={navigation.goBack}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
useSwapBridgeNavigation,
} from '../../hooks/useSwapBridgeNavigation';
import { HighRateAlertModalSelectorsIDs } from './HighRateAlertModal.testIds';
import { useElevatedSurface } from '../../../../../util/theme/themeUtils';

export interface HighRateAlertModalParams {
sourceToken: BridgeToken;
Expand All @@ -33,6 +34,7 @@ export function HighRateAlertModal() {
location: SwapBridgeNavigationLocation.MainView,
sourcePage: 'BatchSell',
});
const surfaceClass = useElevatedSurface();

const handleClose = useCallback(() => {
sheetRef.current?.onCloseBottomSheet();
Expand All @@ -49,6 +51,7 @@ export function HighRateAlertModal() {
ref={sheetRef}
goBack={goBack}
testID={HighRateAlertModalSelectorsIDs.SHEET}
twClassName={surfaceClass}
>
<BottomSheetHeader
onClose={handleClose}
Expand Down
Loading
Loading