Skip to content

[pull] main from MetaMask:main#37

Merged
pull[bot] merged 5 commits into
Reality2byte:mainfrom
MetaMask:main
Aug 1, 2025
Merged

[pull] main from MetaMask:main#37
pull[bot] merged 5 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Aug 1, 2025

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.3)

Can you help keep this open source service alive? 💖 Please sponsor : )

andrepimenta and others added 5 commits August 1, 2025 13:31
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

This PR implements
[Worklets](https://github.com/margelo/react-native-worklets-core).
Worklets are small JavaScript functions that can be executed on a
separate JavaScript Thread so they don't clog the main JS Thread.
Perfect for heavy computations and processing.



## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->


https://github.com/user-attachments/assets/ba3be2b7-71b8-4840-8a22-5407fa54a088

### **After**

<!-- [screenshots/recordings] -->


https://github.com/user-attachments/assets/500036ce-252d-48d9-8148-4672618567bf

## **How to use RN Worklets (Threads)**
# runAsync

Purpose: runAsync is used to execute code on a different thread without
blocking the main JS thread.

When to use: Use it to offload functions to a background thread.

Example:

```
import { Worklets } from 'react-native-worklets-core';
...
const fibonacci = (num: number): number => {
  'worklet'
  if (num <= 1) return num;
  let prev = 0, curr = 1;
  for (let i = 2; i <= num; i++) {
    let next = prev + curr;
    prev = curr;
    curr = next;
  }
  return curr;
}

const context = Worklets.defaultContext
const result = await context.runAsync(() => {
  'worklet'
  return fibonacci(50)
})
console.log(`Fibonacci of 50 is ${result}`)
```

# runOnJS
Purpose: runOnJS is used to call a JavaScript function from within a
worklet. Since worklets run on a separate thread, they cannot directly
call JavaScript functions. runOnJS bridges this gap by allowing you to
invoke JavaScript functions on the JavaScript thread.

When to use: Use it when you need to communicate from the worklet thread
back to the JavaScript thread.

Example:
```
import { runOnJS } from 'react-native-worklets-core';
...
const [age, setAge] = useState(30)

function something() {
  'worklet'
  Worklets.runOnJS(() => setAge(50))
}
```

# useWorklet

Purpose: useWorklet is a hook that allows you to define a worklet
function directly within your React component. It ensures that the
function is properly marked as a worklet and can run on the worklet
thread.

When to use: Use this hook when you need to define a function that will
execute on the worklet thread.

Example:
```
import { useWorklet } from 'react-native-worklets-core';

function MyComponent() {
  const myWorklet = useWorklet(() => {
    'worklet';
    console.log('This is running on the worklet thread');
  }, []);

  return (
    <Button title="Run Worklet" onPress={() => myWorklet()} />
  );
}
```

# useRunOnJS
Purpose: useRunOnJS is a hook that allows you to define a JavaScript
function that can be safely called from a worklet. It ensures that the
function is properly wrapped to run on the JavaScript thread when
invoked from the worklet thread.

When to use: Use this hook when you need to call a JavaScript function
from a worklet.

```
import { useRunOnJS } from 'react-native-worklets-core';

function App() {
  const sayHello = useRunOnJS(() => {
    console.log("hello from JS!")
  }, [])

  const worklet = useWorklet('default', () => {
    'worklet'
    console.log("hello from worklet!")
    sayHello()
  }, [sayHello])

  return (
    <Button title="Run Worklet" onPress={() => worklet()} />
  );
}

```

# useSharedValue
Purpose:
useSharedValue is a hook that creates a SharedValue instance, which can
be read from and written to by both the JavaScript thread and the
worklet thread simultaneously.

For arrays and objects, useSharedValue creates a C++-based proxy
implementation, ensuring that all read and write operations on these
data structures are thread-safe.

When to use:
Use useSharedValue when you need to share state between the JavaScript
thread and the worklet thread.

Example:
```
function App() {
  const something = useSharedValue(5)
  const worklet = useWorklet('default', () => {
    'worklet'
    something.value = Math.random()
  }, [something])
}
```

# Separate Threads/Contexts (Worklets.createContext)
Purpose:
Worklets.createContext is a method that allows you to create a separate
thread (context) for running worklets.

Each thread created with createContext operates in isolation, ensuring
that tasks in one thread do not interfere with tasks in another.

When to use:
Use Worklets.createContext when you need to offload heavy computations
or background tasks to multiple separate threads.

```
const context1 = Worklets.createContext('my-new-thread-1')
const context2 = Worklets.createContext('my-new-thread-2')
context1.runAsync(() => {
  'worklet'
  console.log("Hello from context #1!")
  context2.runAsync(() => {
    'worklet'
    console.log("Hello from context #2!")
  })
})
```


# Worklet Examples

WorkletExampleComponent.tsx
```
import React, { useState } from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import { useRunOnJS, useSharedValue, useWorklet } from 'react-native-worklets-core';

const WorkletExampleComponent = () => {

    const sharedValue = useSharedValue(0);

    const [result, setResult] = useState(0);

    const setResultFromWorklet = useRunOnJS(() => {
        console.log("Calling main JS from worklet!")
        setResult(sharedValue.value)
    }, [])

    const heavyComputationWorklet = useWorklet('default', () => {
        'worklet'
        console.log("Calling worklet!")
        let result = 0;
        for (let i = 0; i < 10000000; i++) {
            result += Math.random();
        }
        sharedValue.value += result;
        setResultFromWorklet()
    }, [sharedValue, setResultFromWorklet])

    const mainJSFunction = () => {
        console.log("hello from main JS function!", sharedValue.value)
        heavyComputationWorklet()
    }

    return (
        <View style={styles.container}>
            <Text style={styles.title}>Worklet Hooks Example</Text>

            <View style={styles.infoBox}>

                <TouchableOpacity style={styles.tertiaryButton} onPress={mainJSFunction}>
                    <Text style={styles.buttonText}>Heavy Computation</Text>
                </TouchableOpacity>
            </View>

            <View style={styles.infoBox}>
                <Text style={styles.messageText}>Result: {result}</Text>
            </View>

            <View style={styles.descriptionBox}>
                <Text style={styles.descriptionText}>
                    This component demonstrates:
                    {'\n'}• useSharedValue: Shared counter between threads
                    {'\n'}• useWorklet: Functions running on worklet thread
                    {'\n'}• useRunOnJS: Safe JS calls from worklets
                </Text>
            </View>
        </View>
    );
};

const styles = StyleSheet.create({
    container: {
        padding: 16,
        backgroundColor: '#fff',
    },
    title: {
        fontSize: 24,
        fontWeight: 'bold',
        textAlign: 'center',
        marginBottom: 16,
    },
    infoBox: {
        marginBottom: 24,
        padding: 16,
        backgroundColor: '#f5f5f5',
        borderRadius: 8,
    },
    counterText: {
        fontSize: 16,
        fontWeight: '600',
        marginBottom: 8,
    },
    messageText: {
        fontSize: 14,
        color: '#666',
    },
    buttonContainer: {
        gap: 12,
    },
    primaryButton: {
        backgroundColor: '#007AFF',
        padding: 16,
        borderRadius: 8,
        alignItems: 'center',
    },
    secondaryButton: {
        backgroundColor: '#34C759',
        padding: 16,
        borderRadius: 8,
        alignItems: 'center',
    },
    tertiaryButton: {
        backgroundColor: '#FF9500',
        padding: 16,
        borderRadius: 8,
        alignItems: 'center',
    },
    buttonText: {
        color: '#fff',
        fontSize: 16,
        fontWeight: '600',
    },
    descriptionBox: {
        padding: 16,
        backgroundColor: '#f0f0f0',
        borderRadius: 8,
    },
    descriptionText: {
        fontSize: 12,
        color: '#666',
        lineHeight: 18,
    },
});

export default WorkletExampleComponent;
```

WorkletExampleFunctions.ts
```
import { Worklets } from 'react-native-worklets-core';

// Example 1: Heavy computation using runAsync
const fibonacci = (num: number): number => {
  'worklet';
  if (num <= 1) return num;
  let prev = 0, curr = 1;
  for (let i = 2; i <= num; i++) {
    let next = prev + curr;
    prev = curr;
    curr = next;
  }
  return curr;
};

export const calculateFibonacci = async (num: number): Promise<number> => {
  const context = Worklets.defaultContext;
  const result = await context.runAsync(() => {
    'worklet';
    return fibonacci(num);
  });
  return result;
};

// Example 2: Array processing on worklet thread
export const processLargeArray = async (data: number[]): Promise<number[]> => {
  const context = Worklets.defaultContext;
  
  return await context.runAsync(() => {
    'worklet';
    // Heavy array processing that would block the UI thread
    return data
      .map(x => x * 2)
      .filter(x => x > 10)
      .map(x => Math.sqrt(x))
      .sort((a, b) => b - a);
  });
};

// Example 3: Using separate contexts for parallel processing
export const parallelProcessing = async (
  data1: number[],
  data2: number[]
): Promise<{result1: number, result2: number}> => {
  const context1 = Worklets.createContext('worker-1');
  const context2 = Worklets.createContext('worker-2');
  
  // Process both arrays in parallel on different threads
  const [result1, result2] = await Promise.all([
    context1.runAsync(() => {
      'worklet';
      console.log('Processing on worker-1');
      return data1.reduce((sum, val) => sum + Math.pow(val, 2), 0);
    }),
    context2.runAsync(() => {
      'worklet';
      console.log('Processing on worker-2');
      return data2.reduce((sum, val) => sum + Math.pow(val, 3), 0);
    })
  ]);
  
  return { result1, result2 };
}; 
```

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---------

Co-authored-by: Cal Leung <cal.leung@consensys.net>
…n yml (#17784)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
* git force with lease instead of git force
* remove unnecessary permissions 
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

This PR updates parsing of the utm params to match the recommended way
listed in
[#2213](https://github.com/MetaMask/mobile-planning/issues/2213)

## **Related issues**

Fixes: [#2213](https://github.com/MetaMask/mobile-planning/issues/2213)

## **Manual testing steps**

- Use deeplink for testing -
https://link.metamask.io/home?utm_source=facebook&utm_medium=social&utm_campaign=summer_sale
- Install this branch on iOS simulator
- Create new wallet and unlock wallet
- Background wallet
- Open deeplink in simulator via `xcrun simctl openurl booted
https://link.metamask.io/home\?utm_source\=facebook\&utm_medium\=social\&utm_campaign\=summer_sale`
- Notice that deeplink interstitial shows
- Background and foreground app
- Notice that dev log shows `TRACK event saved {"event": "App Opened",
"properties": {"anonymous": false, "attributionId": "", "utm_campaign":
"summer_sale", "utm_content": "", "utm_medium": "social", "utm_source":
"facebook", "utm_term": ""}, "type": "track"}`, which includes parsed
utm params

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---------

Co-authored-by: Cal-L <cleun007@gmail.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This branch contains ongoing work for adding Snaps E2E tests.

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---------

Co-authored-by: Guillaume Roux <guillaumeroux123@gmail.com>
Co-authored-by: Frederik Bolding <frederik.bolding@gmail.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
React Native DevTools network tab is unstable on Android and it only
works on iOS. As an alternative, Reactotron is implemented to view API
calls on Android (also works on iOS)

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes: MetaMask/mobile-planning#2245

## **Manual testing steps**

1. Install desktop Reactotron `brew install --cask reactotron`
2. Open Reactotron and refresh simulator (maybe need to rebuild)
3. Should see API calls in Timeline tab in Reactotron 
4. If no connection is made on Android, run `adb reverse tcp:9090
tcp:9090`

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**
![React Native
DevTool](https://github.com/user-attachments/assets/bb40c273-c12c-4a4e-9fb3-6921ce8ecca0)

### **After**

![Reactotron](https://github.com/user-attachments/assets/0685744a-e5c5-48b6-9bd4-3f0e8a93a587)

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
@pull pull Bot locked and limited conversation to collaborators Aug 1, 2025
@pull pull Bot added the ⤵️ pull label Aug 1, 2025
@pull pull Bot merged commit 8b099cf into Reality2byte:main Aug 1, 2025
1 of 35 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants