Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
15 changes: 15 additions & 0 deletions .depcheckrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,18 @@ ignores:

# Used in Yarn plugin for preview builds
- '@yarnpkg/core'

# Babel plugins referenced in babel.config.js by their short name (without
# the `babel-plugin-` prefix). Babel resolves them correctly at build time
# but depcheck doesn't recognize the indirect reference. See babel.config.js
# line 65 comment for details.
- 'babel-plugin-react-compiler' # used as 'react-compiler' (line 68)
- 'babel-plugin-transform-inline-environment-variables' # used as 'transform-inline-environment-variables' (line 81)
- 'babel-plugin-transform-remove-console' # used as 'transform-remove-console' (line 166, production env)

# Listed as a direct dep in package.json but no longer referenced in
# babel.config.js (we use babel-preset-expo) or anywhere in our source.
# It's still available transitively via babel-preset-expo + Metro, so
# removing the direct declaration should be a no-op — left for a follow-up
# cleanup once the RN 0.81 upgrade has settled to avoid surprises.
- '@react-native/babel-preset'
5 changes: 5 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,12 @@ app/components/UI/TemplateRenderer @MetaMask/confirmations @MetaMask/core-plat
app/components/UI/Stake @MetaMask/earn
app/core/Engine/controllers/earn-controller @MetaMask/earn
app/core/Engine/messengers/earn-controller-messenger @MetaMask/earn
app/core/Engine/controllers/chomp-api-service-init* @MetaMask/earn
app/core/Engine/controllers/money-account-upgrade-controller-init* @MetaMask/earn
app/core/Engine/messengers/chomp-api-service-messenger* @MetaMask/earn
app/core/Engine/messengers/money-account-upgrade-controller-messenger* @MetaMask/earn
app/selectors/earnController @MetaMask/earn
app/selectors/featureFlagController/chompApi/ @MetaMask/earn
**/Earn/** @MetaMask/earn
**/earn/** @MetaMask/earn
**/Money/** @MetaMask/earn
Expand Down
21 changes: 17 additions & 4 deletions .github/workflows/build-android-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ jobs:
exit 1
fi

# TEMPORARY: `${{ github.run_id }}` makes every key unique per workflow
# run so we always get a fresh build during the RN 0.81 upgrade — the
# `yarn fingerprint:generate` heuristic doesn't track every native input
# being changed (yarn patches, MainApplication, Podfile shims, etc.) so
# the branch cache can serve a stale .apk and only the JS gets repacked.
# Remove the trailing `-${{ github.run_id }}` from each `key:` below
# once the upgrade is settled and fingerprint covers the touched paths.
- name: Restore APKs matching fingerprint from branch cache
if: ${{ inputs.runner_provider != 'namespace' }}
id: apk-cache-restore
Expand All @@ -132,7 +139,7 @@ jobs:
# - "Restore APKs matching fingerprint from main cache"
# - "Restore Gradle dependencies from branch cache"
# - "Restore Gradle dependencies from main cache"
key: android-apk-${{ github.ref_name }}-${{ inputs.build_type }}-${{ env.CACHE_GENERATION }}-${{ steps.generate-fingerprint.outputs.fingerprint }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
key: android-apk-${{ github.ref_name }}-${{ inputs.build_type }}-${{ env.CACHE_GENERATION }}-${{ steps.generate-fingerprint.outputs.fingerprint }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}-${{ github.run_id }}

- name: Restore APKs matching fingerprint from main cache
if: ${{ inputs.runner_provider != 'namespace' && steps.apk-cache-restore.outputs.cache-hit != 'true' && github.ref_name != 'main' }}
Expand All @@ -149,7 +156,7 @@ jobs:
# - "Restore APKs matching fingerprint from main cache"
# - "Restore Gradle dependencies from branch cache"
# - "Restore Gradle dependencies from main cache"
key: android-apk-main-${{ inputs.build_type }}-${{ env.CACHE_GENERATION }}-${{ steps.generate-fingerprint.outputs.fingerprint }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
key: android-apk-main-${{ inputs.build_type }}-${{ env.CACHE_GENERATION }}-${{ steps.generate-fingerprint.outputs.fingerprint }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}-${{ github.run_id }}

- name: Restore Gradle dependencies from branch cache
id: gradle-cache-restore
Expand All @@ -168,7 +175,7 @@ jobs:
# - "Restore APKs matching fingerprint from main cache"
# - "Restore Gradle dependencies from branch cache"
# - "Restore Gradle dependencies from main cache"
key: gradle-${{ github.ref_name }}-${{ env.GRADLE_CACHE_VERSION }}-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
key: gradle-${{ github.ref_name }}-${{ env.GRADLE_CACHE_VERSION }}-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}-${{ github.run_id }}

- name: Restore Gradle dependencies from main cache
# This will only restore the cache, not update it
Expand All @@ -186,7 +193,7 @@ jobs:
# - "Restore APKs matching fingerprint from main cache"
# - "Restore Gradle dependencies from branch cache"
# - "Restore Gradle dependencies from main cache"
key: gradle-main-${{ env.GRADLE_CACHE_VERSION }}-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
key: gradle-main-${{ env.GRADLE_CACHE_VERSION }}-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}-${{ github.run_id }}

- name: Build Android E2E APKs
if: ${{ inputs.runner_provider == 'namespace' || (steps.apk-cache-restore.outputs.cache-hit != 'true' && steps.apk-cache-restore-main.outputs.cache-hit != 'true') }}
Expand All @@ -208,6 +215,12 @@ jobs:
NODE_OPTIONS: '--max-old-space-size=4096'
# Limit Metro workers to prevent OOM (each worker uses ~3GB)
METRO_MAX_WORKERS: '4'
# React Native 0.81's ReactAndroid/build.gradle.kts requests CMake 3.30.5
# via `System.getenv("CMAKE_VERSION") ?: "3.30.5"`. The self-hosted runner
# only ships CMake 3.22.1 in /opt/android-sdk/cmake/ and AGP cannot auto-
# download missing components, causing CXX1300. RN's CMakeLists.txt files
# only require >= 3.13, so 3.22.1 is fully sufficient.
CMAKE_VERSION: '3.22.1'
BRIDGE_USE_DEV_APIS: 'true'
RAMP_INTERNAL_BUILD: 'true'
SEEDLESS_ONBOARDING_ENABLED: 'true'
Expand Down
19 changes: 13 additions & 6 deletions .github/workflows/build-ios-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ jobs:
sourcemap-uploaded: ${{ steps.upload-sourcemap.outcome == 'success' }}
env:
# Bump these to bust the respective caches and force a full rebuild
XCODE_CACHE_VERSION: 1
IOS_APP_CACHE_VERSION: 2
XCODE_CACHE_VERSION: 4
IOS_APP_CACHE_VERSION: 5
RCT_NO_LAUNCH_PACKAGER: 1
XCODE_BUILD_SETTINGS: 'COMPILER_INDEX_STORE_ENABLE=NO'
GITHUB_CI: 'true' # This ensures it's available during pod install
Expand Down Expand Up @@ -75,6 +75,13 @@ jobs:
- name: Checkout repo
uses: actions/checkout@v6

# TEMPORARY: `${{ github.run_id }}` makes every key unique per workflow
# run so we always get a fresh build during the RN 0.81 upgrade — the
# `yarn fingerprint:generate` heuristic doesn't track every native input
# being changed (yarn patches, AppDelegate, Podfile shims, etc.) so the
# branch cache can serve a stale .app and only the JS gets repacked.
# Remove the trailing `-${{ github.run_id }}` from each `key:` below
# once the upgrade is settled and fingerprint covers the touched paths.
- name: Restore Xcode derived data from branch cache
id: xcode-restore-cache
# This action automatically updates the cache at the end of the workflow
Expand All @@ -83,7 +90,7 @@ jobs:
path: |
~/Library/Developer/Xcode/DerivedData
ios/build
key: ${{ runner.os }}-xcode-${{ github.ref_name }}-${{ env.XCODE_CACHE_VERSION }}-${{ hashFiles('ios/**/*.{h,m,mm,swift}', 'ios/**/Podfile.lock', 'yarn.lock') }}
key: ${{ runner.os }}-xcode-${{ github.ref_name }}-${{ env.XCODE_CACHE_VERSION }}-${{ hashFiles('ios/**/*.{h,m,mm,swift}', 'ios/**/Podfile.lock', 'yarn.lock') }}-${{ github.run_id }}

- name: Restore Xcode derived data from main cache
if: ${{ steps.xcode-restore-cache.outputs.cache-hit != 'true' && github.ref_name != 'main' }}
Expand All @@ -94,7 +101,7 @@ jobs:
path: |
~/Library/Developer/Xcode/DerivedData
ios/build
key: ${{ runner.os }}-xcode-main-${{ env.XCODE_CACHE_VERSION }}-${{ hashFiles('ios/**/*.{h,m,mm,swift}', 'ios/**/Podfile.lock', 'yarn.lock') }}
key: ${{ runner.os }}-xcode-main-${{ env.XCODE_CACHE_VERSION }}-${{ hashFiles('ios/**/*.{h,m,mm,swift}', 'ios/**/Podfile.lock', 'yarn.lock') }}-${{ github.run_id }}

- name: Restore .metamask folder (Foundry download cache for install:foundryup)
uses: actions/cache@v4
Expand Down Expand Up @@ -154,7 +161,7 @@ jobs:
with:
path: |
ios/build/Build/Products/Release-iphonesimulator/MetaMask.app
key: ios-app-${{ github.ref_name }}-v${{ env.IOS_APP_CACHE_VERSION }}-${{ steps.generate-fingerprint.outputs.fingerprint }}
key: ios-app-${{ github.ref_name }}-v${{ env.IOS_APP_CACHE_VERSION }}-${{ steps.generate-fingerprint.outputs.fingerprint }}-${{ github.run_id }}

- name: Restore iOS app matching fingerprint from main cache
if: ${{ steps.cache-restore.outputs.cache-hit != 'true' && github.ref_name != 'main' }}
Expand All @@ -164,7 +171,7 @@ jobs:
with:
path: |
ios/build/Build/Products/Release-iphonesimulator/MetaMask.app
key: ios-app-main-v${{ env.IOS_APP_CACHE_VERSION }}-${{ steps.generate-fingerprint.outputs.fingerprint }}
key: ios-app-main-v${{ env.IOS_APP_CACHE_VERSION }}-${{ steps.generate-fingerprint.outputs.fingerprint }}-${{ github.run_id }}

# Build the iOS E2E app for simulator
- name: Build iOS E2E App
Expand Down
18 changes: 17 additions & 1 deletion .github/workflows/run-e2e-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ on:
type: number
default: 1
test-timeout-minutes:
# Hard cap on the `Run E2E tests` step — when it elapses, GitHub kills the whole suite.
description: 'The timeout in minutes for the test command'
required: false
type: number
default: 30
default: 40
build_type:
description: 'The type of build to perform'
required: false
Expand Down Expand Up @@ -210,6 +211,21 @@ jobs:
fi

chmod +x "$APP_PATH/$BUNDLE_EXEC"

# actions/upload-artifact strips execute permissions from ALL files, not just the
# main binary. Framework dylibs and binaries inside Frameworks/ also need +x or
# SpringBoard (SBMainWorkspace) will refuse to launch the app with:
# FBSOpenApplicationServiceErrorDomain code=1: denied by service delegate
if [ -d "$APP_PATH/Frameworks" ]; then
find "$APP_PATH/Frameworks" -type d -name "*.framework" | while IFS= read -r fw; do
binary="$fw/$(basename "$fw" .framework)"
if [ -f "$binary" ]; then
chmod +x "$binary"
fi
done
find "$APP_PATH/Frameworks" -type f -name "*.dylib" -exec chmod +x {} \;
fi
echo "✅ Restored execute permissions on main binary and all framework binaries"
shell: bash

# On re-run (run_attempt > 1), download previous test results to identify failed tests
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

# claude code worktrees (agent-local, not shipped)
.claude/worktrees/
# claude code per-user settings (agent-local, not shipped)
.claude/settings.local.json

# osx
.DS_Store
Expand Down Expand Up @@ -46,6 +48,7 @@ android/app/gradle*
android/app/_build*
android/libs
.cxx/
.kotlin/

# if we ever want to add google services
android/app/google-services.json
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# @metamask/react-native-acm@1.2.0 was authored against an older RN where:
# - ReactContextBaseJavaModule.getCurrentActivity() was a Java method, so Kotlin
# auto-exposed it as the synthetic property `currentActivity`.
# - ActivityEventListener.onNewIntent took a nullable `Intent?` parameter.
#
# In React Native 0.81 both classes were rewritten in Kotlin source. Because
# `getCurrentActivity()` is now declared as `fun getCurrentActivity()` (not as a
# property), Kotlin does NOT expose `currentActivity` as a synthetic accessor —
# callers must use the explicit method form. Additionally, `onNewIntent` is now
# `fun onNewIntent(intent: Intent)` (non-nullable). Without this patch the
# package fails to compile on RN 0.81 with:
# - "Unresolved reference 'currentActivity'." (3 sites)
# - "'onNewIntent' overrides nothing. Potential signatures for overriding:
# fun onNewIntent(intent: Intent): Unit"
#
# When @metamask/react-native-acm publishes an RN 0.81-compatible release, this
# patch (and the resolution in package.json) can be removed.
diff --git a/android/src/main/java/com/googleacm/GoogleAcmModule.kt b/android/src/main/java/com/googleacm/GoogleAcmModule.kt
index 395a46ebdcc45bc3afd596903e7926525ebe5874..0495944fb891b0999624b50801c11a313e8adee1 100644
--- a/android/src/main/java/com/googleacm/GoogleAcmModule.kt
+++ b/android/src/main/java/com/googleacm/GoogleAcmModule.kt
@@ -65,7 +65,7 @@ class GoogleAcmModule(reactContext: ReactApplicationContext) :
requestObject: ReadableMap,
promise: Promise
) {
- val activity: Activity? = currentActivity
+ val activity: Activity? = getCurrentActivity()
if (activity == null) {
promise.reject("E_NO_ACTIVITY", "Current activity is null, cannot launch UI.")
return
@@ -133,7 +133,7 @@ class GoogleAcmModule(reactContext: ReactApplicationContext) :
}

private suspend fun tryLegacySignIn(serverClientId: String): ReadableMap? {
- val activity = currentActivity
+ val activity = getCurrentActivity()
?: throw Exception("No activity available for legacy sign-in")

val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
@@ -188,7 +188,7 @@ class GoogleAcmModule(reactContext: ReactApplicationContext) :
}
}

- override fun onNewIntent(intent: Intent?) { }
+ override fun onNewIntent(intent: Intent) { }

private fun handleLegacySignInResult(resultCode: Int, data: Intent?): ReadableMap? {
if (resultCode != Activity.RESULT_OK) {
@@ -278,7 +278,7 @@ class GoogleAcmModule(reactContext: ReactApplicationContext) :
}

suspend fun handleSignOut() {
- val activity: Activity? = currentActivity
+ val activity: Activity? = getCurrentActivity()
if (activity == null) {
throw Exception("Current activity is null, cannot sign out.")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
diff --git a/Button.js b/Button.js
index 46dc1e06fa389a3660f6ce67c0d2eaead3e2782d..7f92ea9421bd90ba858ad9f81c7f4c1008a2553e 100644
--- a/Button.js
+++ b/Button.js
@@ -11,18 +11,23 @@ import {
import coalesceNonElementChildren from './coalesceNonElementChildren';

const systemButtonOpacity = 0.2;
+const touchableOpacityPropTypes = TouchableOpacity.propTypes || {};
+const textPropTypes = Text.propTypes || {};
+const viewStylePropType = (ViewPropTypes && ViewPropTypes.style) || PropTypes.any;
+const textStylePropType = textPropTypes.style || PropTypes.any;
+const allowFontScalingPropType = textPropTypes.allowFontScaling || PropTypes.bool;

export default class Button extends Component {
static propTypes = {
- ...TouchableOpacity.propTypes,
+ ...touchableOpacityPropTypes,
accessibilityLabel: PropTypes.string,
- allowFontScaling: Text.propTypes.allowFontScaling,
- containerStyle: ViewPropTypes.style,
- disabledContainerStyle: ViewPropTypes.style,
+ allowFontScaling: allowFontScalingPropType,
+ containerStyle: viewStylePropType,
+ disabledContainerStyle: viewStylePropType,
disabled: PropTypes.bool,
- style: Text.propTypes.style,
- styleDisabled: Text.propTypes.style,
- childGroupStyle: ViewPropTypes.style,
+ style: textStylePropType,
+ styleDisabled: textStylePropType,
+ childGroupStyle: viewStylePropType,
};

render() {
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
diff --git a/android/build.gradle b/android/build.gradle
index 0d066bd15543931e4029146f627a5902f244d4ee..db6528a8db0b21634c3eb0ca7aabc2405b89818c 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -1,12 +1,12 @@
apply plugin: 'com.android.library'

android {
- compileSdkVersion 28
- buildToolsVersion "28.0.3"
+ compileSdkVersion 36
+ buildToolsVersion "36.0.0"

defaultConfig {
minSdkVersion 21
- targetSdkVersion 28
+ targetSdkVersion 36
versionCode 1
versionName "1.0"
ndk {
diff --git a/android/src/main/java/com/reactnativepayments/ReactNativePaymentsModule.java b/android/src/main/java/com/reactnativepayments/ReactNativePaymentsModule.java
index f26dd586ec397f5259c00ba147974a58825a03fe..e671afcc3faf5368e7987e2d9b8d1797d4249a29 100644
--- a/android/src/main/java/com/reactnativepayments/ReactNativePaymentsModule.java
+++ b/android/src/main/java/com/reactnativepayments/ReactNativePaymentsModule.java
@@ -13,7 +13,6 @@ import androidx.annotation.RequiresPermission;
import android.util.Log;

import com.facebook.react.bridge.Callback;
-import com.facebook.react.bridge.ReactBridge;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.google.android.gms.common.api.GoogleApiClient;
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
diff --git a/package.json b/package.json
index 6b9ca814f3e2b4630e81371235f6ad942d5eac3f..1d7129b41beb19c53b3fbe277b9670ff72b30d6d 100644
--- a/package.json
+++ b/package.json
@@ -95,6 +95,14 @@
"jsSrcsDir": "./src",
"android": {
"javaPackageName": "com.reactnativecommunity.webview"
+ },
+ "ios": {
+ "componentProvider": {
+ "RNCWebView": "RNCWebView"
+ },
+ "modulesProvider": {
+ "RNCWebViewModule": "RNCWebViewModule"
+ }
}
},
"packageManager": "yarn@1.22.19"
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
diff --git a/ios/ReactNativePageView.h b/ios/ReactNativePageView.h
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000001 100644
--- a/ios/ReactNativePageView.h
+++ b/ios/ReactNativePageView.h
@@ -1,3 +1,4 @@
#import <React/RCTShadowView.h>
+#import <React/RCTEventDispatcher.h>
#import <React/UIView+React.h>
#import <UIKit/UIKit.h>
Loading
Loading