Skip to content

Commit

Permalink
fix: support set custom nonce to zero (#10729)
Browse files Browse the repository at this point in the history
<!--
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 PR adds support for setting the custom nonce to zero and addressing
an issue reported by Customer Support.

**Context**
Reported by: CS
Problem: Users are unable to set the custom nonce to 0 on mobile
devices. The lowest value currently allowed is 1, which prevents users
from replacing transactions stuck at nonce 0.
Behavior: When attempting to set the nonce to 0, either through manual
input or by pasting, the input initially appears to accept the value,
but on submission, the nonce is automatically adjusted to the next
available value, bypassing 0 entirely.

<!--
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?
-->

## **Related issues**

Fixes: #10703

## **Manual testing steps**

1. Start a send transaction
2. Try to edit the nonce to 0

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

[Screencast from 21-08-2024
14:47:22.webm](https://github.com/user-attachments/assets/0daa47f0-bdb7-4260-b352-bc4e2e6f6fdc)


<!-- [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**

- [ ] 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.
  • Loading branch information
vinistevam authored and devin-ai-integration[bot] committed Sep 9, 2024
1 parent f055ed8 commit f6af44c
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 74 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`CustomNonceModal should render correctly 1`] = `
exports[`CustomNonceModal renders correctly 1`] = `
<ReactNativeModal
animationIn="slideInUp"
animationInTiming={600}
Expand All @@ -18,13 +18,13 @@ exports[`CustomNonceModal should render correctly 1`] = `
hasBackdrop={true}
hideModalContentWhileAnimating={false}
isVisible={true}
onBackButtonPress={[Function]}
onBackdropPress={[Function]}
onBackButtonPress={[MockFunction]}
onBackdropPress={[MockFunction]}
onModalHide={[Function]}
onModalShow={[Function]}
onModalWillHide={[Function]}
onModalWillShow={[Function]}
onSwipeComplete={[Function]}
onSwipeComplete={[MockFunction]}
panResponderThreshold={4}
propagateSwipe={true}
scrollHorizontal={false}
Expand Down Expand Up @@ -128,7 +128,7 @@ exports[`CustomNonceModal should render correctly 1`] = `
"width": 80,
}
}
value="28"
value="26"
/>
</View>
<Text
Expand Down Expand Up @@ -166,6 +166,7 @@ exports[`CustomNonceModal should render correctly 1`] = `
"padding": 4,
}
}
testID="decrement-nonce"
>
<Icon
allowFontScaling={false}
Expand All @@ -185,6 +186,7 @@ exports[`CustomNonceModal should render correctly 1`] = `
"padding": 4,
}
}
testID="increment-nonce"
>
<Icon
allowFontScaling={false}
Expand All @@ -205,48 +207,6 @@ exports[`CustomNonceModal should render correctly 1`] = `
}
}
>
<View
style={
{
"backgroundColor": "#bf52081a",
"borderColor": "#bf5208",
"borderRadius": 8,
"borderWidth": 1,
"display": "flex",
"flexDirection": "row",
"marginBottom": 16,
"marginTop": 10,
"padding": 16,
}
}
>
<Icon
allowFontScaling={false}
color="#bf5208"
name="exclamation-circle"
size={16}
style={
{
"flex": 0,
"marginTop": 6,
"paddingRight": 14,
}
}
/>
<Text
style={
{
"color": "#141618",
"flex": 1,
"fontSize": 12,
"lineHeight": 16,
"width": "100%",
}
}
>
Warning: You may encounter issues with future transactions if you continue. Use with caution.
</Text>
</View>
<Text
bold={true}
style={
Expand Down Expand Up @@ -294,7 +254,7 @@ exports[`CustomNonceModal should render correctly 1`] = `
"opacity": 0.6,
}
}
onPress={[Function]}
onPress={[MockFunction]}
styleDisabled={
{
"opacity": 0.6,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,12 @@ const CustomModalNonce = ({ proposedNonce, nonceValue, close, save }) => {
const { colors, themeAppearance } = useTheme();
const styles = createStyles(colors);

const incrementDecrementNonce = (decrement) => {
let newValue = nonce;
newValue = decrement ? --newValue : ++newValue;
onChangeText(newValue > 1 ? newValue : 1);
const incrementDecrementNonce = (isDecrement) => {
const currentNonce = Number(nonce);
const updatedValue = isDecrement ? currentNonce - 1 : currentNonce + 1;
const clampedValue = Math.max(updatedValue, 0);

onChangeText(clampedValue);
};

const saveAndClose = () => {
Expand Down Expand Up @@ -192,6 +194,7 @@ const CustomModalNonce = ({ proposedNonce, nonceValue, close, save }) => {
<TouchableOpacity
style={styles.incrementHit}
onPress={() => incrementDecrementNonce(true)}
testID={'decrement-nonce'}
>
<EvilIcons
name="minus"
Expand All @@ -202,6 +205,7 @@ const CustomModalNonce = ({ proposedNonce, nonceValue, close, save }) => {
<TouchableOpacity
style={styles.incrementHit}
onPress={() => incrementDecrementNonce(false)}
testID={'increment-nonce'}
>
<EvilIcons
name="plus"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,68 @@ import React from 'react';
import { shallow } from 'enzyme';
import CustomNonceModal from '.';

const PROPOSED_NONCE = 26;
const saveMock = jest.fn();
const closeMock = jest.fn();
const createWrapper = () =>
shallow(
<CustomNonceModal
save={saveMock}
close={closeMock}
proposedNonce={PROPOSED_NONCE}
nonceValue={PROPOSED_NONCE}
/>,
);
describe('CustomNonceModal', () => {
const proposedNonce = 26;
const customNonce = 28;
it('should render correctly', () => {
const noop = () => ({});
const wrapper = shallow(
<CustomNonceModal
save={noop}
close={noop}
proposedNonce={proposedNonce}
nonceValue={customNonce}
/>,
);
it('renders correctly', () => {
const wrapper = createWrapper();
expect(wrapper).toMatchSnapshot();
});

it('should handle only numeric inputs', () => {
const saveMock = jest.fn();
const closeMock = jest.fn();
it('handles only numeric inputs', () => {
const wrapper = createWrapper();
const nonceTextInput = wrapper.find('TextInput');
nonceTextInput.simulate('changeText', '30c');
expect(wrapper.find('TextInput').prop('value')).toBe(
String(PROPOSED_NONCE),
);
nonceTextInput.simulate('changeText', '30');
expect(wrapper.find('TextInput').prop('value')).toBe('30');
});

it('increments nonce correctly', () => {
const wrapper = createWrapper();
const incrementButton = wrapper.find({ testID: 'increment-nonce' });

incrementButton.simulate('press');
expect(wrapper.find('TextInput').prop('value')).toBe(
String(PROPOSED_NONCE + 1),
);
});

it('decrements nonce correctly', () => {
const wrapper = shallow(
<CustomNonceModal
save={saveMock}
close={closeMock}
proposedNonce={proposedNonce}
nonceValue={proposedNonce}
proposedNonce={PROPOSED_NONCE}
nonceValue={PROPOSED_NONCE}
/>,
);
const nonceTextInput = wrapper.find('TextInput');
nonceTextInput.simulate('changeText', '30c');
expect(wrapper.find('TextInput').prop('value')).toBe(String(proposedNonce));
nonceTextInput.simulate('changeText', '30');
expect(wrapper.find('TextInput').prop('value')).toBe('30');
const decrementButton = wrapper.find({ testID: 'decrement-nonce' });

decrementButton.simulate('press');
expect(wrapper.find('TextInput').prop('value')).toBe(
String(PROPOSED_NONCE - 1),
);
});

it('does not decrement the nonce value below 0 when the current nonce is 0', () => {
const wrapper = createWrapper();
wrapper.setProps({ proposedNonce: 0, nonceValue: 0 });
const decrementButton = wrapper.find({ testID: 'decrement-nonce' });

decrementButton.simulate('press');
expect(wrapper.find('TextInput').prop('value')).toBe(String(0));
});
});

0 comments on commit f6af44c

Please sign in to comment.