Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:rainbow-me/rainbow into brody/li…
Browse files Browse the repository at this point in the history
…nt-test-3

* 'develop' of github.com:rainbow-me/rainbow:
  Bring in flashbots functionality for networks that support it (#5800)
  Swaps: logic, data flow, and performance fixes (#5787)
  remove limit from token to buy list (#5795)
  [e2e] Brody/e2e parallel (#5786)
  • Loading branch information
BrodyHughes committed Jun 1, 2024
2 parents fb364af + c9a2e63 commit 691d08b
Show file tree
Hide file tree
Showing 75 changed files with 2,521 additions and 1,772 deletions.
10 changes: 10 additions & 0 deletions .detoxrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ module.exports = {
screenshot: 'failing',
},
},
behavior: {
cleanup: {
shutdownDevice: false,
},
},
},
'ios.sim.debug': {
app: 'ios.debug',
Expand All @@ -64,6 +69,11 @@ module.exports = {
screenshot: 'failing',
},
},
behavior: {
cleanup: {
shutdownDevice: false,
},
},
},
'android.emu.release': {
app: 'android.release',
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/macstadium-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ jobs:
run: rm -rf ./artifacts/

- name: Build the app in release mode
run: ./node_modules/.bin/detox build --configuration ios.sim.release
run: ./node_modules/.bin/detox build --configuration ios.sim.release | xcpretty --color

- name: Run iOS e2e tests with retry
# change the '5' here to how many times you want the tests to rerun on failure
run: ./scripts/run-retry-tests.sh 5
run: ./scripts/run-retry-tests.sh 3

- name: Upload Test Artifacts
if: failure()
Expand Down
1 change: 1 addition & 0 deletions e2e/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export async function importWalletFlow() {
await authenticatePin('1234');
}
await device.enableSynchronization();
await delayTime('very-long');
await checkIfVisible('wallet-screen');
}

Expand Down
2 changes: 0 additions & 2 deletions e2e/jest.e2e.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ const { pathsToModuleNameMapper } = require('ts-jest');
const { compilerOptions } = require('../tsconfig');

module.exports = {
maxWorkers: 1,
bail: 1,
setupFilesAfterEnv: ['./init.js'],
testEnvironment: './environment',

Expand Down
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@
"clean:packager": "watchman watch-del-all && rm -rf $TMPDIR/react-* && rm -rf $TMPDIR/metro-* && rm -rf $TMPDIR/haste-map-*",
"clean:node": "rm -rf node_modules",
"nuke": "./scripts/nuke.sh",
"detox:android": "detox build -c android.emu.debug && detox test -R 1 -c android.emu.debug --loglevel verbose",
"detox:android:release": "detox build -c android.emu.release && detox test -R 1 -c android.emu.release",
"detox:ios": "detox build -c ios.sim.debug | xcpretty --color && detox test -R 1 -c ios.sim.debug --bail",
"detox:ios:release": "detox build -c ios.sim.release && detox test -R 1 -c ios.sim.release --bail",
"detox:android": "detox build -c android.emu.debug && detox test -c android.emu.debug --loglevel verbose",
"detox:android:release": "detox build -c android.emu.release && detox test -c android.emu.release",
"detox:ios:tests": "detox test -c ios.sim.debug --maxWorkers 2 -- --bail 1",
"detox:ios": "detox build -c ios.sim.debug | xcpretty --color && yarn detox:ios:tests",
"detox:ios:release": "detox build -c ios.sim.release && detox test -c ios.sim.release --maxWorkers 2 -- --bail 1",
"ds:install": "yarn install --cwd src/design-system/docs",
"ds": "cd src/design-system/docs && yarn dev",
"fast": "yarn setup && yarn install-pods-fast",
Expand Down
2 changes: 1 addition & 1 deletion scripts/run-retry-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ count=0

until (( count >= max_retries ))
do
./node_modules/.bin/detox test --configuration ios.sim.release --forceExit
./node_modules/.bin/detox test -c ios.sim.release --maxWorkers 2 -- --forceExit --bail 1
ret_val=$?
if [ $ret_val -eq 0 ]; then
exit 0
Expand Down
13 changes: 13 additions & 0 deletions src/__swaps__/safe-math/SafeMath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ const toStringWorklet = (value: string | number): string => {
return typeof value === 'number' ? value.toString() : value;
};

// Converts a numeric string to a scaled integer string, preserving the specified decimal places
export function toScaledIntegerWorklet(num: string, decimalPlaces = 18): string {
'worklet';
if (!isNumberStringWorklet(num)) {
throw new Error('Argument must be a numeric string');
}
const [bigIntNum, numDecimalPlaces] = removeDecimalWorklet(num);
const scaleFactor = BigInt(10) ** BigInt(decimalPlaces - numDecimalPlaces);
const scaledIntegerBigInt = bigIntNum * scaleFactor;

return scaledIntegerBigInt.toString();
}

// Sum function
export function sumWorklet(num1: string | number, num2: string | number): string {
'worklet';
Expand Down
11 changes: 11 additions & 0 deletions src/__swaps__/safe-math/__tests__/SafeMath.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
subWorklet,
sumWorklet,
toFixedWorklet,
toScaledIntegerWorklet,
} from '../SafeMath';

const RESULTS = {
Expand All @@ -29,12 +30,14 @@ const RESULTS = {
toFixed: '1243425.35',
ceil: '1243426',
floor: '1243425',
toScaledInteger: '57464009350560633',
};

const VALUE_A = '1243425.345';
const VALUE_B = '3819.24';
const VALUE_C = '2';
const VALUE_D = '1243425.745';
const VALUE_E = '0.057464009350560633';
const NEGATIVE_VALUE = '-2412.12';
const ZERO = '0';
const ONE = '1';
Expand Down Expand Up @@ -190,6 +193,10 @@ describe('SafeMath', () => {
expect(roundWorklet(Number(VALUE_A))).toBe(RESULTS.floor);
expect(roundWorklet(Number(VALUE_D))).toBe(RESULTS.ceil);
});

test('toScaledIntegerWorklet', () => {
expect(toScaledIntegerWorklet(VALUE_E, 18)).toBe(RESULTS.toScaledInteger);
});
});

describe('BigNumber', () => {
Expand Down Expand Up @@ -243,4 +250,8 @@ describe('BigNumber', () => {
expect(new BigNumber(VALUE_B).lte(VALUE_A)).toBe(true);
expect(new BigNumber(VALUE_A).lte(VALUE_A)).toBe(true);
});

test('toScaledInteger', () => {
expect(new BigNumber(VALUE_E).shiftedBy(18).toFixed(0)).toBe(RESULTS.toScaledInteger);
});
});
160 changes: 130 additions & 30 deletions src/__swaps__/screens/Swap/Swap.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import React, { useCallback, useEffect } from 'react';
import { StyleSheet, StatusBar } from 'react-native';
import Animated from 'react-native-reanimated';
import Animated, { runOnJS, useAnimatedReaction } from 'react-native-reanimated';
import { ScreenCornerRadius } from 'react-native-screen-corner-radius';

import { IS_ANDROID } from '@/env';
Expand All @@ -19,8 +19,13 @@ import { SwapNavbar } from '@/__swaps__/screens/Swap/components/SwapNavbar';
import { SliderAndKeyboard } from '@/__swaps__/screens/Swap/components/SliderAndKeyboard';
import { SwapBottomPanel } from '@/__swaps__/screens/Swap/components/SwapBottomPanel';
import { SwapWarning } from './components/SwapWarning';
import { useSwapContext } from './providers/swap-provider';
import { UserAssetsSync } from './components/UserAssetsSync';
import { SwapProvider, useSwapContext } from './providers/swap-provider';
import { useSwapsStore } from '@/state/swaps/swapsStore';
import { userAssetsStore } from '@/state/assets/userAssets';
import { parseSearchAsset } from '@/__swaps__/utils/assets';
import { SwapAssetType } from '@/__swaps__/types/swap';
import { ChainId } from '@/__swaps__/types/chains';
import { useDelayedMount } from '@/hooks/useDelayedMount';

/** README
* This prototype is largely driven by Reanimated and Gesture Handler, which
Expand Down Expand Up @@ -60,38 +65,133 @@ import { UserAssetsSync } from './components/UserAssetsSync';
*/

export function SwapScreen() {
const { AnimatedSwapStyles } = useSwapContext();
return (
<SwapSheetGestureBlocker>
<Box as={Page} style={styles.rootViewBackground} testID="swap-screen" width="full">
<SwapBackground />
<Box alignItems="center" height="full" paddingTop={{ custom: safeAreaInsetValues.top + (navbarHeight - 12) + 29 }} width="full">
<SwapInputAsset />
<FlipButton />
<SwapOutputAsset />
<Box as={Animated.View} width="full" position="absolute" bottom="0px" style={AnimatedSwapStyles.hideWhenInputsExpanded}>
<SliderAndKeyboard />
<SwapBottomPanel />
</Box>
<Box
as={Animated.View}
alignItems="center"
justifyContent="center"
style={[styles.swapWarningAndExchangeWrapper, AnimatedSwapStyles.hideWhileReviewingOrConfiguringGas]}
>
<ExchangeRateBubble />
<SwapWarning />
<SwapProvider>
<MountAndUnmountHandlers />
<SwapSheetGestureBlocker>
<Box as={Page} style={styles.rootViewBackground} testID="swap-screen" width="full">
<SwapBackground />
<Box alignItems="center" height="full" paddingTop={{ custom: safeAreaInsetValues.top + (navbarHeight - 12) + 29 }} width="full">
<SwapInputAsset />
<FlipButton />
<SwapOutputAsset />
<SliderAndKeyboardAndBottomControls />
<ExchangeRateBubbleAndWarning />
</Box>
<SwapNavbar />
</Box>
<SwapNavbar />

{/* NOTE: The components below render null and are solely for keeping react-query and Zustand in sync */}
<UserAssetsSync />
</Box>
</SwapSheetGestureBlocker>
</SwapSheetGestureBlocker>
<WalletAddressObserver />
</SwapProvider>
);
}

const MountAndUnmountHandlers = () => {
useMountSignal();
useCleanupOnUnmount();

return null;
};

const useMountSignal = () => {
useEffect(() => {
useSwapsStore.setState({ isSwapsOpen: true });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
};

const useCleanupOnUnmount = () => {
useEffect(() => {
return () => {
const highestValueAsset = userAssetsStore.getState().getHighestValueAsset();
const parsedAsset = highestValueAsset
? parseSearchAsset({
assetWithPrice: undefined,
searchAsset: highestValueAsset,
userAsset: highestValueAsset,
})
: null;

useSwapsStore.setState({
inputAsset: parsedAsset,
isSwapsOpen: false,
outputAsset: null,
outputSearchQuery: '',
quote: null,
selectedOutputChainId: parsedAsset?.chainId ?? ChainId.mainnet,
});

userAssetsStore.setState({ filter: 'all', inputSearchQuery: '' });
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
};

const WalletAddressObserver = () => {
const currentWalletAddress = userAssetsStore(state => state.associatedWalletAddress);
const { setAsset } = useSwapContext();

const setNewInputAsset = useCallback(() => {
const newHighestValueAsset = userAssetsStore.getState().getHighestValueAsset();

if (userAssetsStore.getState().filter !== 'all') {
userAssetsStore.setState({ filter: 'all' });
}

setAsset({
type: SwapAssetType.inputAsset,
asset: newHighestValueAsset,
});

if (userAssetsStore.getState().userAssets.size === 0) {
setAsset({
type: SwapAssetType.outputAsset,
asset: null,
});
}
}, [setAsset]);

useAnimatedReaction(
() => currentWalletAddress,
(current, previous) => {
const didWalletAddressChange = previous && current !== previous;

if (didWalletAddressChange) {
runOnJS(setNewInputAsset)();
}
}
);

return null;
};

const SliderAndKeyboardAndBottomControls = () => {
const shouldMount = useDelayedMount();
const { AnimatedSwapStyles } = useSwapContext();

return shouldMount ? (
<Box as={Animated.View} width="full" position="absolute" bottom="0px" style={AnimatedSwapStyles.hideWhenInputsExpanded}>
<SliderAndKeyboard />
<SwapBottomPanel />
</Box>
) : null;
};

const ExchangeRateBubbleAndWarning = () => {
const { AnimatedSwapStyles } = useSwapContext();
return (
<Box
as={Animated.View}
alignItems="center"
justifyContent="center"
style={[styles.swapWarningAndExchangeWrapper, AnimatedSwapStyles.hideWhileReviewingOrConfiguringGas]}
>
<ExchangeRateBubble />
<SwapWarning />
</Box>
);
};

export const styles = StyleSheet.create({
rootViewBackground: {
borderRadius: IS_ANDROID ? 20 : ScreenCornerRadius,
Expand Down
9 changes: 5 additions & 4 deletions src/__swaps__/screens/Swap/components/AnimatedChainImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,10 @@ export function AnimatedChainImage({
});

return (
<View style={[sx.badge, { bottom: 0, borderRadius: size / 2, width: size, height: size }]}>
{/* @ts-expect-error source prop is missing */}
<AnimatedFasterImage style={{ borderRadius: size / 2, width: size, height: size }} animatedProps={animatedIconSource} />
<View style={[sx.badge, { borderRadius: size / 2, height: size, width: size }]}>
{/* ⚠️ TODO: This works but we should figure out how to type this correctly to avoid this error */}
{/* @ts-expect-error: Doesn't pick up that it's getting a source prop via animatedProps */}
<AnimatedFasterImage style={{ height: size, width: size }} animatedProps={animatedIconSource} />
</View>
);
}
Expand All @@ -118,7 +119,7 @@ const sx = StyleSheet.create({
height: 4,
width: 0,
},
shadowRadius: 6,
shadowOpacity: 0.2,
shadowRadius: 6,
},
});
Loading

0 comments on commit 691d08b

Please sign in to comment.