diff --git a/package.json b/package.json index 6d51286ba1e..8fb563d13e6 100644 --- a/package.json +++ b/package.json @@ -342,6 +342,7 @@ "@types/qs": "6.9.7", "@types/react": "18.2.65", "@types/react-native-extra-dimensions-android": "1.2.3", + "@types/react-native-indicators": "0.16.6", "@types/react-test-renderer": "18.3.0", "@types/styled-components": "5.1.7", "@types/url-parse": "1.4.3", diff --git a/src/__swaps__/screens/Swap/components/AnimatedChainImage.android.tsx b/src/__swaps__/screens/Swap/components/AnimatedChainImage.android.tsx index f4d77a39815..49d30869f71 100644 --- a/src/__swaps__/screens/Swap/components/AnimatedChainImage.android.tsx +++ b/src/__swaps__/screens/Swap/components/AnimatedChainImage.android.tsx @@ -2,17 +2,17 @@ import React, { useMemo } from 'react'; import { Image, StyleSheet, View } from 'react-native'; +const ApechainBadge = require('@/assets/badges/apechain.png'); const ArbitrumBadge = require('@/assets/badges/arbitrum.png'); +const AvalancheBadge = require('@/assets/badges/avalanche.png'); const BaseBadge = require('@/assets/badges/base.png'); +const BlastBadge = require('@/assets/badges/blast.png'); const BscBadge = require('@/assets/badges/bsc.png'); +const DegenBadge = require('@/assets/badges/degen.png'); const EthereumBadge = require('@/assets/badges/ethereum.png'); const OptimismBadge = require('@/assets/badges/optimism.png'); const PolygonBadge = require('@/assets/badges/polygon.png'); const ZoraBadge = require('@/assets/badges/zora.png'); -const AvalancheBadge = require('@/assets/badges/avalanche.png'); -const BlastBadge = require('@/assets/badges/blast.png'); -const DegenBadge = require('@/assets/badges/degen.png'); -const ApechainBadge = require('@/assets/badges/apechainBadge.png'); import { ChainId } from '@/chains/types'; import { globalColors } from '@/design-system'; diff --git a/src/__swaps__/screens/Swap/components/AnimatedChainImage.ios.tsx b/src/__swaps__/screens/Swap/components/AnimatedChainImage.ios.tsx index 305806ab0ba..cad0369a89a 100644 --- a/src/__swaps__/screens/Swap/components/AnimatedChainImage.ios.tsx +++ b/src/__swaps__/screens/Swap/components/AnimatedChainImage.ios.tsx @@ -1,17 +1,6 @@ import React from 'react'; import { Image, StyleSheet, View } from 'react-native'; -import ArbitrumBadge from '@/assets/badges/arbitrum.png'; -import BaseBadge from '@/assets/badges/base.png'; -import BscBadge from '@/assets/badges/bsc.png'; -import EthereumBadge from '@/assets/badges/ethereum.png'; -import OptimismBadge from '@/assets/badges/optimism.png'; -import PolygonBadge from '@/assets/badges/polygon.png'; -import ZoraBadge from '@/assets/badges/zora.png'; -import AvalancheBadge from '@/assets/badges/avalanche.png'; -import BlastBadge from '@/assets/badges/blast.png'; -import DegenBadge from '@/assets/badges/degen.png'; -import ApechainBadge from '@/assets/badges/apechainBadge.png'; import { ChainId } from '@/chains/types'; import { useAnimatedProps, useDerivedValue } from 'react-native-reanimated'; import { AnimatedFasterImage } from '@/components/AnimatedComponents/AnimatedFasterImage'; @@ -22,6 +11,18 @@ import { PIXEL_RATIO } from '@/utils/deviceUtils'; import { useSwapContext } from '../providers/swap-provider'; import { BLANK_BASE64_PIXEL } from '@/components/DappBrowser/constants'; +import ApechainBadge from '@/assets/badges/apechain.png'; +import ArbitrumBadge from '@/assets/badges/arbitrum.png'; +import AvalancheBadge from '@/assets/badges/avalanche.png'; +import BaseBadge from '@/assets/badges/base.png'; +import BlastBadge from '@/assets/badges/blast.png'; +import BscBadge from '@/assets/badges/bsc.png'; +import DegenBadge from '@/assets/badges/degen.png'; +import EthereumBadge from '@/assets/badges/ethereum.png'; +import OptimismBadge from '@/assets/badges/optimism.png'; +import PolygonBadge from '@/assets/badges/polygon.png'; +import ZoraBadge from '@/assets/badges/zora.png'; + const networkBadges = { [ChainId.apechain]: Image.resolveAssetSource(ApechainBadge).uri, [ChainId.arbitrum]: Image.resolveAssetSource(ArbitrumBadge).uri, diff --git a/src/__swaps__/types/refraction.ts b/src/__swaps__/types/refraction.ts index edb3f6f13cb..802b8fc0f33 100644 --- a/src/__swaps__/types/refraction.ts +++ b/src/__swaps__/types/refraction.ts @@ -1,6 +1,6 @@ import { ZerionAsset } from '@/__swaps__/types/assets'; import { ChainId, ChainName } from '@/chains/types'; -import { PaginatedTransactionsApiResponse } from '@/resources/transactions/types'; +import { PaginatedTransactionsApiResponse } from '@/entities'; /** * Metadata for a message from the Zerion API. diff --git a/src/components/ActivityIndicator.js b/src/components/ActivityIndicator.tsx similarity index 66% rename from src/components/ActivityIndicator.js rename to src/components/ActivityIndicator.tsx index 0336e902e1a..d78faeb2e30 100644 --- a/src/components/ActivityIndicator.js +++ b/src/components/ActivityIndicator.tsx @@ -5,9 +5,15 @@ import { Centered } from './layout'; import styled from '@/styled-thing'; import { position } from '@/styles'; -const Container = styled(Centered)(({ size }) => position.sizeAsObject(Number(size))); +const Container = styled(Centered)(({ size }: { size: number }) => position.sizeAsObject(Number(size))); -export default function ActivityIndicator({ color, isInteraction = false, size = 25, ...props }) { +type ActivityIndicatorProps = { + color?: string; + isInteraction?: boolean; + size?: number; +}; + +export default function ActivityIndicator({ color, isInteraction = false, size = 25, ...props }: ActivityIndicatorProps) { const { colors } = useTheme(); return ( diff --git a/src/components/Divider.tsx b/src/components/Divider.tsx index 08a22f7c437..0776eefa36a 100644 --- a/src/components/Divider.tsx +++ b/src/components/Divider.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { magicMemo } from '../utils'; import styled from '@/styled-thing'; import { borders, position } from '@/styles'; -import { StyleProp, View, ViewProps, ViewStyle } from 'react-native'; +import { View } from 'react-native'; import { ThemeContextProps, useTheme } from '@/theme'; export const DividerSize = 2; diff --git a/src/components/activity-list/ActivityList.js b/src/components/activity-list/ActivityList.js deleted file mode 100644 index 877ae43aa21..00000000000 --- a/src/components/activity-list/ActivityList.js +++ /dev/null @@ -1,145 +0,0 @@ -import * as lang from '@/languages'; -import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { SectionList, StyleSheet, View } from 'react-native'; -import sectionListGetItemLayout from 'react-native-section-list-get-item-layout'; -import ActivityIndicator from '../ActivityIndicator'; -import Spinner from '../Spinner'; -import { ButtonPressAnimation } from '../animations'; -import { CoinRowHeight } from '../coin-row/CoinRow'; -import Text from '../text/Text'; -import ActivityListEmptyState from './ActivityListEmptyState'; -import ActivityListHeader from './ActivityListHeader'; -import styled from '@/styled-thing'; -import { useTheme } from '@/theme'; -import { useSectionListScrollToTopContext } from '@/navigation/SectionListScrollToTopContext'; -import { safeAreaInsetValues } from '@/utils'; -import { Network } from '@/chains/types'; - -const sx = StyleSheet.create({ - sectionHeader: { - paddingVertical: 18, - }, -}); - -const ActivityListHeaderHeight = 42; -const TRANSACTION_COIN_ROW_VERTICAL_PADDING = 7; - -const getItemLayout = sectionListGetItemLayout({ - getItemHeight: () => CoinRowHeight + TRANSACTION_COIN_ROW_VERTICAL_PADDING * 2, - getSectionHeaderHeight: () => ActivityListHeaderHeight, -}); - -const keyExtractor = ({ hash, timestamp, transactionDisplayDetails }) => - hash || (timestamp ? timestamp.ms : transactionDisplayDetails?.timestampInMs || 0); - -const renderSectionHeader = ({ section, colors }) => { - return ( - - - - ); -}; - -const LoadingSpinner = android ? Spinner : ActivityIndicator; - -const FooterWrapper = styled(ButtonPressAnimation)({ - alignItems: 'center', - height: 40, - justifyContent: 'center', - paddingBottom: 10, - width: '100%', -}); - -function ListFooterComponent({ label, onPress }) { - const [isLoading, setIsLoading] = useState(false); - const { colors } = useTheme(); - - useEffect(() => { - if (isLoading) { - onPress(); - setIsLoading(false); - } - }, [isLoading, setIsLoading, onPress]); - const onPressWrapper = () => { - setIsLoading(true); - }; - return ( - - {isLoading ? ( - - ) : ( - - {label} - - )} - - ); -} - -const ActivityList = ({ - hasPendingTransaction, - header, - nativeCurrency, - network, - nextPage, - remainingItemsLabel, - requests, - sections, - transactionsCount, -}) => { - const { setScrollToTopRef } = useSectionListScrollToTopContext(); - - const pendingTransactionsCount = useMemo(() => { - let currentPendingTransactionsCount = 0; - const pendingTxSection = sections[requests?.length ? 1 : 0]; - - if (pendingTxSection && pendingTxSection.title === lang.t(lang.l.transactions.pending_title)) { - currentPendingTransactionsCount = pendingTxSection.data.length; - } - return currentPendingTransactionsCount; - }, [sections, requests]); - - const { colors } = useTheme(); - const renderSectionHeaderWithTheme = useCallback(({ section }) => renderSectionHeader({ colors, section }), [colors]); - - const handleListRef = ref => { - if (!ref) return; - setScrollToTopRef(ref); - }; - - if (network === Network.mainnet) { - return ( - remainingItemsLabel && } - ref={handleListRef} - ListHeaderComponent={header} - alwaysBounceVertical={false} - contentContainerStyle={{ paddingBottom: !transactionsCount ? 0 : 90 }} - extraData={{ - hasPendingTransaction, - nativeCurrency, - pendingTransactionsCount, - }} - testID={'wallet-activity-list'} - ListEmptyComponent={} - getItemLayout={getItemLayout} - initialNumToRender={12} - keyExtractor={keyExtractor} - removeClippedSubviews - renderSectionHeader={renderSectionHeaderWithTheme} - scrollIndicatorInsets={{ - bottom: safeAreaInsetValues.bottom + 14, - }} - sections={sections} - /> - ); - } - - return ( - - {header} - - ); -}; - -export default ActivityList; diff --git a/src/components/activity-list/ActivityList.tsx b/src/components/activity-list/ActivityList.tsx new file mode 100644 index 00000000000..0542dab50ad --- /dev/null +++ b/src/components/activity-list/ActivityList.tsx @@ -0,0 +1,132 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import { SectionList, StyleSheet, View } from 'react-native'; +import sectionListGetItemLayout from 'react-native-section-list-get-item-layout'; +import ActivityIndicator from '../ActivityIndicator'; +import Spinner from '../Spinner'; +import { ButtonPressAnimation } from '../animations'; +import { CoinRowHeight } from '../coin-row/CoinRow'; +import Text from '../text/Text'; +import ActivityListEmptyState from './ActivityListEmptyState'; +import ActivityListHeader from './ActivityListHeader'; +import styled from '@/styled-thing'; +import { ThemeContextProps, useTheme } from '@/theme'; +import { useSectionListScrollToTopContext } from '@/navigation/SectionListScrollToTopContext'; +import { safeAreaInsetValues } from '@/utils'; +import { useAccountSettings, useAccountTransactions } from '@/hooks'; +import { usePendingTransactionsStore } from '@/state/pendingTransactions'; +import { TransactionSections, TransactionItemForSectionList } from '@/helpers/buildTransactionsSectionsSelector'; + +const sx = StyleSheet.create({ + sectionHeader: { + paddingVertical: 18, + }, +}); + +const ActivityListHeaderHeight = 42; +const TRANSACTION_COIN_ROW_VERTICAL_PADDING = 7; + +const getItemLayout = sectionListGetItemLayout({ + getItemHeight: () => CoinRowHeight + TRANSACTION_COIN_ROW_VERTICAL_PADDING * 2, + getSectionHeaderHeight: () => ActivityListHeaderHeight, +}); + +const keyExtractor = (data: TransactionSections['data'][number]) => { + if ('hash' in data) { + return (data.hash || data.timestamp ? data.timestamp?.toString() : performance.now().toString()) ?? performance.now().toString(); + } + return ( + (data.displayDetails?.timestampInMs ? data.displayDetails.timestampInMs.toString() : performance.now().toString()) ?? + performance.now().toString() + ); +}; + +const renderSectionHeader = ({ section, colors }: { section: TransactionSections; colors: ThemeContextProps['colors'] }) => { + return ( + + + + ); +}; + +const LoadingSpinner = android ? Spinner : ActivityIndicator; + +const FooterWrapper = styled(ButtonPressAnimation)({ + alignItems: 'center', + height: 40, + justifyContent: 'center', + paddingBottom: 10, + width: '100%', +}); + +function ListFooterComponent({ label, onPress }: { label: string; onPress: () => void }) { + const [isLoading, setIsLoading] = useState(false); + const { colors } = useTheme(); + + useEffect(() => { + if (isLoading) { + onPress(); + setIsLoading(false); + } + }, [isLoading, setIsLoading, onPress]); + const onPressWrapper = () => { + setIsLoading(true); + }; + return ( + + {isLoading ? ( + + ) : ( + + {label} + + )} + + ); +} + +const ActivityList = () => { + const { accountAddress, nativeCurrency } = useAccountSettings(); + + const { setScrollToTopRef } = useSectionListScrollToTopContext(); + const { sections, nextPage, transactionsCount, remainingItemsLabel } = useAccountTransactions(); + const pendingTransactions = usePendingTransactionsStore(state => state.pendingTransactions[accountAddress] || []); + + const { colors } = useTheme(); + const renderSectionHeaderWithTheme = useCallback( + ({ section }: { section: TransactionSections }) => renderSectionHeader({ colors, section }), + [colors] + ); + + const handleScrollToTopRef = (ref: SectionList | null) => { + if (!ref) return; + setScrollToTopRef(ref); + }; + + return ( + + ListFooterComponent={() => remainingItemsLabel && } + ref={handleScrollToTopRef} + alwaysBounceVertical={false} + contentContainerStyle={{ paddingBottom: !transactionsCount ? 0 : 90 }} + extraData={{ + hasPendingTransaction: pendingTransactions.length > 0, + nativeCurrency, + pendingTransactionsCount: pendingTransactions.length, + }} + testID={'wallet-activity-list'} + ListEmptyComponent={} + // @ts-expect-error - mismatch between react-native-section-list-get-item-layout and SectionList + getItemLayout={getItemLayout} + initialNumToRender={12} + keyExtractor={keyExtractor} + removeClippedSubviews + renderSectionHeader={renderSectionHeaderWithTheme} + scrollIndicatorInsets={{ + bottom: safeAreaInsetValues.bottom + 14, + }} + sections={sections} + /> + ); +}; + +export default ActivityList; diff --git a/src/components/activity-list/ActivityListEmptyState.js b/src/components/activity-list/ActivityListEmptyState.tsx similarity index 88% rename from src/components/activity-list/ActivityListEmptyState.js rename to src/components/activity-list/ActivityListEmptyState.tsx index f744450074a..552208f666c 100644 --- a/src/components/activity-list/ActivityListEmptyState.js +++ b/src/components/activity-list/ActivityListEmptyState.tsx @@ -16,7 +16,13 @@ const Container = styled(Column)({ width: 200, }); -const ActivityListEmptyState = ({ children, emoji, label }) => { +type ActivityListEmptyStateProps = { + children?: React.ReactNode; + emoji: string; + label: string; +}; + +const ActivityListEmptyState = ({ children, emoji, label }: ActivityListEmptyStateProps) => { const { top: topInset } = useSafeAreaInsets(); const { colors, isDarkMode } = useTheme(); diff --git a/src/components/activity-list/LoadingState.js b/src/components/activity-list/LoadingState.tsx similarity index 76% rename from src/components/activity-list/LoadingState.js rename to src/components/activity-list/LoadingState.tsx index 5eeb07a2b20..3fd4e4f51f2 100644 --- a/src/components/activity-list/LoadingState.js +++ b/src/components/activity-list/LoadingState.tsx @@ -3,7 +3,11 @@ import { AssetListItemSkeleton } from '../asset-list'; import { Column } from '../layout'; import { times } from '@/helpers/utilities'; -const LoadingState = ({ children }) => ( +type LoadingStateProps = { + children: React.ReactNode; +}; + +const LoadingState = ({ children }: LoadingStateProps) => ( {children} diff --git a/src/components/activity-list/index.js b/src/components/activity-list/index.ts similarity index 100% rename from src/components/activity-list/index.js rename to src/components/activity-list/index.ts diff --git a/src/components/cards/GasCard.tsx b/src/components/cards/GasCard.tsx index 665bc244201..4fb2bde4936 100644 --- a/src/components/cards/GasCard.tsx +++ b/src/components/cards/GasCard.tsx @@ -1,4 +1,3 @@ -// @ts-expect-error import AnimateNumber from '@bankify/react-native-animate-number'; import { useIsFocused } from '@react-navigation/native'; import * as i18n from '@/languages'; @@ -60,8 +59,7 @@ export const GasCard = () => { const isCurrentGweiLoaded = currentGwei && Number(currentGwei) > 0; const renderGweiText = useCallback( - // @ts-expect-error passed to an untyped JS component - animatedNumber => { + (animatedNumber: number) => { const priceText = animatedNumber === 0 ? isCurrentGweiLoaded diff --git a/src/components/coin-row/FastTransactionCoinRow.tsx b/src/components/coin-row/FastTransactionCoinRow.tsx index 58f724a9c6d..fdc2b5b8866 100644 --- a/src/components/coin-row/FastTransactionCoinRow.tsx +++ b/src/components/coin-row/FastTransactionCoinRow.tsx @@ -3,7 +3,7 @@ import { StyleSheet, View } from 'react-native'; import { ButtonPressAnimation } from '../animations'; import FastTransactionStatusBadge from './FastTransactionStatusBadge'; import { Bleed, Box, Inline, Text, globalColors, useForegroundColor } from '@/design-system'; -import { NativeCurrencyKey, RainbowTransaction } from '@/entities'; +import { NativeCurrencyKey, RainbowTransaction, TransactionStatus, TransactionType } from '@/entities'; import { ThemeContextProps } from '@/theme'; import { useNavigation } from '@/navigation'; import Routes from '@rainbow-me/routes'; @@ -12,7 +12,6 @@ import { CardSize } from '../unique-token/CardSize'; import { ChainBadge } from '../coin-icon'; import { ChainId } from '@/chains/types'; import { address } from '@/utils/abbreviations'; -import { TransactionType } from '@/resources/transactions/types'; import { convertAmountAndPriceToNativeDisplay, convertAmountToBalanceDisplay, @@ -54,7 +53,7 @@ const swapTypeValues = (changes: RainbowTransaction['changes'], status: RainbowT // NOTE: For pending txns let's use the change values instead of // the transaction balance change since that hasn't happened yet - if (status === 'pending') { + if (status === TransactionStatus.pending) { const valueOut = `${handleSignificantDecimals(convertRawAmountToDecimalFormat(tokenOut?.value?.toString() || '0', tokenOut?.asset.decimals || 18), tokenOut?.asset.decimals || 18)} ${tokenOut?.asset.symbol}`; const valueIn = `+${handleSignificantDecimals(convertRawAmountToDecimalFormat(tokenIn?.value?.toString() || '0', tokenIn?.asset.decimals || 18), tokenIn?.asset.decimals || 18)} ${tokenIn?.asset.symbol}`; @@ -143,8 +142,7 @@ export const ActivityTypeIcon = ({ transaction: Pick; color: string; }) => { - // if (status === 'pending') return null; - if (status === 'pending') { + if (status === TransactionStatus.pending) { return ; } diff --git a/src/components/coin-row/FastTransactionStatusBadge.tsx b/src/components/coin-row/FastTransactionStatusBadge.tsx index 56616000cba..fe390c7777d 100644 --- a/src/components/coin-row/FastTransactionStatusBadge.tsx +++ b/src/components/coin-row/FastTransactionStatusBadge.tsx @@ -1,7 +1,7 @@ -import React from 'react'; +import React, { useCallback } from 'react'; import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'; import { Text, useForegroundColor } from '@/design-system'; -import { RainbowTransaction } from '@/entities'; +import { RainbowTransaction, TransactionStatus } from '@/entities'; import { ThemeContextProps } from '@/theme'; import * as lang from '@/languages'; import { ActivityTypeIcon } from './FastTransactionCoinRow'; @@ -25,7 +25,7 @@ export default React.memo(function FastTransactionStatusBadge({ style?: StyleProp; }) { let statusColor = useForegroundColor('labelTertiary'); - if (transaction?.status === 'pending') { + if (transaction?.status === TransactionStatus.pending) { statusColor = colors.appleBlue; } else if (transaction?.status === 'failed') { statusColor = colors.red; @@ -37,8 +37,8 @@ export default React.memo(function FastTransactionStatusBadge({ - {/* @ts-ignore */} - {lang.t(lang.l.transactions.type[transaction?.title])} + {/* @ts-expect-error - some of these are dot.notation and some are strings */} + {lang.t(lang.l.transactions.type[transaction?.title])}{' '} ); diff --git a/src/components/gas/GasSpeedButton.js b/src/components/gas/GasSpeedButton.tsx similarity index 88% rename from src/components/gas/GasSpeedButton.js rename to src/components/gas/GasSpeedButton.tsx index 470415b39de..2506342a029 100644 --- a/src/components/gas/GasSpeedButton.js +++ b/src/components/gas/GasSpeedButton.tsx @@ -1,12 +1,11 @@ /* eslint-disable no-nested-ternary */ -/* eslint-disable no-undef */ import AnimateNumber from '@bankify/react-native-animate-number'; import lang from 'i18n-js'; -import { isEmpty, isNaN, isNil } from 'lodash'; +import { isEmpty, isNaN, isNil, noop } from 'lodash'; import makeColorMoreChill from 'make-color-more-chill'; import { AnimatePresence, MotiView } from 'moti'; -import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { InteractionManager, Keyboard } from 'react-native'; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { InteractionManager, Keyboard, View } from 'react-native'; import { Easing } from 'react-native-reanimated'; import { darkModeThemeColors } from '../../styles/colors'; import { ButtonPressAnimation } from '../animations'; @@ -29,9 +28,21 @@ import { ContextMenu } from '../context-menu'; import { EthCoinIcon } from '../coin-icon/EthCoinIcon'; import { ChainId } from '@/chains/types'; import { chainsGasSpeeds } from '@/chains'; +import { ThemeContextProps, useTheme } from '@/theme'; +import { OnPressMenuItemEventObject } from 'react-native-ios-context-menu'; +import { ParsedAddressAsset } from '@/entities'; const { GAS_EMOJIS, GAS_ICONS, GasSpeedOrder, CUSTOM, URGENT, NORMAL, FAST, getGasLabel } = gasUtils; +type WithThemeProps = { + borderColor: string; + color: string; + theme: ThemeContextProps; + marginBottom: number; + marginTop: number; + horizontalPadding: number; +}; + const CustomGasButton = styled(ButtonPressAnimation).attrs({ align: 'center', alignItems: 'center', @@ -40,7 +51,7 @@ const CustomGasButton = styled(ButtonPressAnimation).attrs({ justifyContent: 'center', scaleTo: 0.8, })({ - borderColor: ({ borderColor, color, theme: { colors } }) => borderColor || color || colors.appleBlue, + borderColor: ({ borderColor, color, theme: { colors } }: WithThemeProps) => borderColor || color || colors.appleBlue, borderRadius: 19, borderWidth: 2, ...padding.object(android ? 2 : 3, 0), @@ -69,7 +80,7 @@ const DoneCustomGas = styled(Text).attrs({ bottom: 0.5, }); -const ChainBadgeContainer = styled.View.attrs({ +const ChainBadgeContainer = styled(View).attrs({ hapticType: 'impactHeavy', scaleTo: 0.9, })({ @@ -89,16 +100,16 @@ const Container = styled(Column).attrs({ alignItems: 'center', hapticType: 'impactHeavy', justifyContent: 'center', -})(({ marginBottom, marginTop, horizontalPadding }) => ({ +})(({ marginBottom, marginTop, horizontalPadding }: WithThemeProps) => ({ ...margin.object(marginTop, 0, marginBottom), ...padding.object(0, horizontalPadding), width: '100%', })); -const Label = styled(Text).attrs(({ size }) => ({ +const Label = styled(Text).attrs(({ size }: { size: string }) => ({ lineHeight: 'normal', size: size || 'lmedium', -}))(({ weight }) => fontWithWidth(weight || fonts.weight.semibold)); +}))(({ weight }: { weight: string }) => fontWithWidth(weight || fonts.weight.semibold)); const GasSpeedPagerCentered = styled(Centered).attrs(() => ({ marginRight: 8, @@ -106,7 +117,7 @@ const GasSpeedPagerCentered = styled(Centered).attrs(() => ({ const TextContainer = styled(Column).attrs(() => ({}))({}); -const TransactionTimeLabel = ({ formatter, isLongWait, theme }) => { +const TransactionTimeLabel = ({ formatter, isLongWait, theme }: { formatter: () => string; isLongWait: boolean; theme: string }) => { const { colors } = useTheme(); let color = theme === 'dark' ? colors.alpha(darkModeThemeColors.blueGreyDark, 0.6) : colors.alpha(colors.blueGreyDark, 0.6); @@ -121,7 +132,7 @@ const TransactionTimeLabel = ({ formatter, isLongWait, theme }) => { ); }; -const shouldRoundGasDisplay = chainId => { +const shouldRoundGasDisplay = (chainId: ChainId) => { switch (chainId) { case ChainId.bsc: case ChainId.polygon: @@ -131,6 +142,24 @@ const shouldRoundGasDisplay = chainId => { } }; +type GasSpeedButtonProps = { + asset?: Partial; + chainId: ChainId; + horizontalPadding?: number; + fallbackColor?: string; + marginBottom?: number; + marginTop?: number; + speeds?: string[]; + testID?: string; + theme?: string; + canGoBack?: boolean; + showGasOptions?: boolean; + validateGasParams?: React.RefObject<(callback?: () => void) => void>; + flashbotTransaction?: boolean; + crossChainServiceTime?: number; + loading?: boolean; +}; + const GasSpeedButton = ({ asset, chainId, @@ -138,7 +167,7 @@ const GasSpeedButton = ({ fallbackColor, marginBottom = 20, marginTop = 18, - speeds = null, + speeds = [], testID = 'gas-speed-button', theme = 'dark', canGoBack = true, @@ -147,7 +176,7 @@ const GasSpeedButton = ({ flashbotTransaction = false, crossChainServiceTime = undefined, loading = false, -}) => { +}: GasSpeedButtonProps) => { const { colors } = useTheme(); const { navigate, goBack } = useNavigation(); const { nativeCurrencySymbol, nativeCurrency } = useAccountSettings(); @@ -159,7 +188,10 @@ const GasSpeedButton = ({ const { gasFeeParamsBySpeed, updateGasFeeOption, selectedGasFee, selectedGasFeeOption, currentBlockParams } = useGas(); const [gasPriceReady, setGasPriceReady] = useState(false); - const [shouldOpenCustomGasSheet, setShouldOpenCustomGasSheet] = useState({ + const [shouldOpenCustomGasSheet, setShouldOpenCustomGasSheet] = useState<{ + focusTo: string | null; + shouldOpen: boolean; + }>({ focusTo: null, shouldOpen: false, }); @@ -188,7 +220,7 @@ const GasSpeedButton = ({ ); const formatGasPrice = useCallback( - animatedValue => { + (animatedValue: string) => { if (animatedValue === null || loading || isNaN(animatedValue)) { return 0; } @@ -213,7 +245,7 @@ const GasSpeedButton = ({ [loading, gasPriceReady, isLegacyGasNetwork, nativeCurrencySymbol, nativeCurrency] ); - const openCustomOptionsRef = useRef(); + const openCustomOptionsRef = useRef(); const openCustomGasSheet = useCallback(() => { if (gasIsNotReady) return; @@ -222,14 +254,14 @@ const GasSpeedButton = ({ fallbackColor, flashbotTransaction, focusTo: shouldOpenCustomGasSheet.focusTo, - openCustomOptions: focusTo => openCustomOptionsRef.current(focusTo), + openCustomOptions: (focusTo: string) => openCustomOptionsRef?.current?.(focusTo), speeds: speeds ?? GasSpeedOrder, type: 'custom_gas', }); }, [gasIsNotReady, navigate, asset, shouldOpenCustomGasSheet.focusTo, flashbotTransaction, speeds, fallbackColor]); const openCustomOptions = useCallback( - focusTo => { + (focusTo: string) => { if (ios) { setShouldOpenCustomGasSheet({ focusTo, shouldOpen: true }); } else { @@ -242,7 +274,7 @@ const GasSpeedButton = ({ openCustomOptionsRef.current = openCustomOptions; const renderGasPriceText = useCallback( - animatedNumber => { + (animatedNumber: number) => { const priceText = animatedNumber === 0 || loading ? lang.t('swap.loading') : animatedNumber; return ( { + (selectedSpeed: string) => { if (selectedSpeed === CUSTOM) { if (ios) { InteractionManager.runAfterInteractions(() => { @@ -294,7 +326,7 @@ const GasSpeedButton = ({ } const estimatedTime = (selectedGasFee?.estimatedTime?.display || '').split(' '); - const [estimatedTimeValue = 0, estimatedTimeUnit = 'min'] = estimatedTime; + const [estimatedTimeValue = '0', estimatedTimeUnit = 'min'] = estimatedTime; const time = parseFloat(estimatedTimeValue).toFixed(0); const timeSymbol = estimatedTimeUnit === 'hr' ? '>' : '~'; @@ -329,14 +361,14 @@ const GasSpeedButton = ({ }, [chainId, crossChainServiceTime, inputCurrency, navigate, outputCurrency]); const handlePressMenuItem = useCallback( - ({ nativeEvent: { actionKey } }) => { + ({ nativeEvent: { actionKey } }: OnPressMenuItemEventObject) => { handlePressSpeedOption(actionKey); }, [handlePressSpeedOption] ); const handlePressActionSheet = useCallback( - buttonIndex => { + (buttonIndex: number) => { switch (buttonIndex) { case 0: handlePressSpeedOption(NORMAL); @@ -368,7 +400,8 @@ const GasSpeedButton = ({ const shouldRoundGwei = shouldRoundGasDisplay(chainId); const gweiDisplay = !shouldRoundGwei - ? gasFeeParamsBySpeed[gasOption]?.gasPrice?.display + ? // @ts-expect-error - legacy gas params has `gasPrice` + gasFeeParamsBySpeed[gasOption]?.gasPrice?.display : gasOption === 'custom' && selectedGasFeeOption !== 'custom' ? '' : greaterThan(estimatedGwei, totalGwei) @@ -411,9 +444,8 @@ const GasSpeedButton = ({ : colors.alpha(colors.blueGreyDark, 0.12) } dropdownEnabled={gasOptionsAvailable} + onPress={noop} label={label} - showGasOptions={showGasOptions} - showPager theme={theme} /> ); @@ -477,7 +509,7 @@ const GasSpeedButton = ({ // would make the expanded sheet come up with too much force // instead calling it from `useEffect` makes it appear smoothly useEffect(() => { - if (shouldOpenCustomGasSheet.shouldOpen && !prevShouldOpenCustomGasSheet.shouldOpen) { + if (shouldOpenCustomGasSheet.shouldOpen && !prevShouldOpenCustomGasSheet?.shouldOpen) { openCustomGasSheet(); setShouldOpenCustomGasSheet({ focusTo: null, shouldOpen: false }); } @@ -494,6 +526,7 @@ const GasSpeedButton = ({ ); ensCommitRegistrationName?: string; ensRegistration?: boolean; sourceAmount?: string; // for purchases @@ -86,9 +125,16 @@ export interface RainbowTransaction { explorerUrl?: string; } +export enum FlashbotsStatus { + PENDING = 'PENDING', + INCLUDED = 'INCLUDED', + FAILED = 'FAILED', + CANCELLED = 'CANCELLED', + UNKNOWN = 'UNKNOWN', +} + export type MinedTransaction = RainbowTransaction & { - status: 'confirmed' | 'failed'; - flashbotsStatus?: 'CANCELLED' | 'FAILED' | 'INCLUDED'; + status: TransactionStatus.confirmed | TransactionStatus.failed; blockNumber: number; minedAt: number; confirmations: number; @@ -144,3 +190,171 @@ export interface NewTransactionOrAddCashTransaction extends Omit; + +export type TransactionChanges = ( + | { + asset: ParsedAsset; + value: number | undefined; + direction: TransactionDirection; + address_from: string; + address_to: string; + price: number; + } + | undefined +)[]; +/** + * Metadata for a message from the Zerion API. + */ +export interface MessageMeta { + address?: string; + currency?: string; + cut_off?: number; + status?: string; + chain_id?: Network; // L2 + chain_ids?: ChainId[]; // v3 consolidated + chain_ids_with_errors?: ChainId[]; // v3 consolidated + asset_codes?: string; + next_page_cursor?: string; +} + +/** + * A message from the Zerion API indicating that assets were received. + */ +export interface AddressAssetsReceivedMessage { + payload?: { + assets?: { + asset: ZerionAsset; + quantity: string; + small_balances?: boolean; + }[]; + }; + meta?: MessageMeta; +} + +/** + * A message from the Zerion API indicating that transaction data was received. + */ +export interface TransactionsReceivedMessage { + payload?: { + transactions?: PaginatedTransactionsApiResponse[]; + }; + meta?: MessageMeta; +} + +/** + * A message from the Zerion API indicating that asset price data was received + */ +export interface AssetPricesReceivedMessage { + payload?: { + prices?: { + [id: string]: ZerionAsset; + }; + }; + meta?: MessageMeta; +} + +export type TxHash = `0x${string}`; + +export type PendingTransaction = RainbowTransaction & { + status: TransactionStatus.pending; +}; + +export const TransactionType = { + withoutChanges: ['cancel', 'contract_interaction', 'deployment', 'approve', 'revoke', 'speed_up'] as readonly string[], + withChanges: [ + 'sale', + 'bridge', + 'airdrop', + 'wrap', + 'unwrap', + 'bid', + 'burn', + 'send', + 'receive', + 'withdraw', + 'deposit', + 'mint', + 'swap', + 'borrow', + 'claim', + 'repay', + 'stake', + 'unstake', + 'purchase', + ] as readonly string[], +} as const; + +export type TransactionWithChangesType = (typeof TransactionType.withChanges)[number]; +export type TransactionWithoutChangesType = (typeof TransactionType.withoutChanges)[number]; + +export type TransactionType = TransactionWithChangesType | TransactionWithoutChangesType; + +export interface ExecuteRapResponse extends TransactionResponse { + errorMessage?: string; +} + +export type TransactionApiResponse = { + status: TransactionStatus; + id: TxHash; + hash: TxHash; + network: Network; + protocol?: string; + direction?: TransactionDirection; + address_from?: string; + address_to?: string; + // nonce will ALWAYS be -2 when the transaction is *not* from the wallet user + nonce: number; + changes: Array< + | { + asset: AddysAsset; + value: number | null; + direction: TransactionDirection; + address_from: string; + address_to: string; + price: number; + } + | undefined + >; + fee: { + value: number; + price: number; + + // Fee Details are only available on the tx by hash endpoint + // (won't be available on the consolidated txs list) + details?: { + type: 0 | 2; + type_label: 'legacy' | 'eip-1559'; + gas_price: number; + gas_limit: number; + gas_used: number; + max_fee: number; + max_priority_fee: number; + base_fee: number; + max_base_fee: number; + rollup_fee_details: { + l1_fee: number; + l1_fee_scalar: number; + l1_gas_price: number; + l1_gas_used: number; + l2_fee: number; + }; + }; + }; + block_confirmations?: number; // also only available on the tx by hash endpoint + meta: { + contract_name?: string; + contract_icon_url?: string; + type?: TransactionType; + action?: string; + asset?: AddysAsset; + quantity?: 'UNLIMITED' | string; + explorer_label?: string; + explorer_url?: string; + }; + block_number?: number; + mined_at?: number; +}; + +export type PaginatedTransactionsApiResponse = Omit & { + fee: Omit; +}; diff --git a/src/entities/transactions/transactionDirection.ts b/src/entities/transactions/transactionDirection.ts deleted file mode 100644 index 2b8f5350971..00000000000 --- a/src/entities/transactions/transactionDirection.ts +++ /dev/null @@ -1,11 +0,0 @@ -export enum TransactionDirection { - in = 'in', - out = 'out', - self = 'self', -} - -export default { - in: 'in', - out: 'out', - self: 'self', -}; diff --git a/src/entities/transactions/transactionStatus.ts b/src/entities/transactions/transactionStatus.ts deleted file mode 100644 index 0449bf04cfa..00000000000 --- a/src/entities/transactions/transactionStatus.ts +++ /dev/null @@ -1,61 +0,0 @@ -export enum TransactionStatus { - approved = 'approved', - approving = 'approving', - bridging = 'bridging', - bridged = 'bridged', - cancelled = 'cancelled', - cancelling = 'cancelling', - contract_interaction = 'contract interaction', - deposited = 'deposited', - depositing = 'depositing', - dropped = 'dropped', - failed = 'failed', - minted = 'minted', - minting = 'minting', - purchased = 'purchased', - purchasing = 'purchasing', - received = 'received', - receiving = 'receiving', - self = 'self', - selling = 'selling', - sold = 'sold', - sending = 'sending', - sent = 'sent', - speeding_up = 'speeding up', - swapped = 'swapped', - swapping = 'swapping', - unknown = 'unknown status', - withdrawing = 'withdrawing', - withdrew = 'withdrew', -} - -export default { - approved: 'approved', - approving: 'approving', - bridging: 'bridging', - bridged: 'bridged', - cancelled: 'cancelled', - cancelling: 'cancelling', - contract_interaction: 'contract interaction', - deposited: 'deposited', - depositing: 'depositing', - dropped: 'dropped', - failed: 'failed', - minted: 'minted', - minting: 'minting', - purchased: 'purchased', - purchasing: 'purchasing', - received: 'received', - receiving: 'receiving', - self: 'self', - selling: 'selling', - sold: 'sold', - sending: 'sending', - sent: 'sent', - speeding_up: 'speeding up', - swapped: 'swapped', - swapping: 'swapping', - unknown: 'unknown status', - withdrawing: 'withdrawing', - withdrew: 'withdrew', -}; diff --git a/src/entities/transactions/transactionType.ts b/src/entities/transactions/transactionType.ts deleted file mode 100644 index df443bb81cc..00000000000 --- a/src/entities/transactions/transactionType.ts +++ /dev/null @@ -1,24 +0,0 @@ -export const transactionTypes = { - withoutChanges: ['cancel', 'contract_interaction', 'deployment', 'approve', 'revoke', 'speed_up'], - withChanges: [ - 'sale', - 'bridge', - 'airdrop', - 'wrap', - 'unwrap', - 'bid', - 'burn', - 'send', - 'receive', - 'withdraw', - 'deposit', - 'mint', - 'swap', - 'borrow', - 'claim', - 'repay', - 'stake', - 'unstake', - 'purchase', - ], -} as const; diff --git a/src/entities/transactions/zerionTransaction.ts b/src/entities/transactions/zerionTransaction.ts index 1bd60d78b8d..5b8fba3d77c 100644 --- a/src/entities/transactions/zerionTransaction.ts +++ b/src/entities/transactions/zerionTransaction.ts @@ -1,7 +1,6 @@ -import { TransactionType } from '@/resources/transactions/types'; import { ProtocolType } from '../protocolTypes'; import { ZerionAsset } from '../tokens'; -import { TransactionDirection } from './transactionDirection'; +import { TransactionDirection, TransactionStatus, TransactionType } from '@/entities'; interface ZerionTransactionFee { price: number; @@ -14,12 +13,6 @@ interface ZerionTransactionMeta { asset?: ZerionAsset; } -enum ZerionTransactionStatus { - confirmed = 'confirmed', - failed = 'failed', - pending = 'pending', -} - export interface ZerionTransactionChange { address_from: string | null; address_to: string | null; @@ -43,6 +36,6 @@ export interface ZerionTransaction { mined_at: number; nonce: number | null; protocol: ProtocolType; - status: ZerionTransactionStatus; + status: TransactionStatus.pending | TransactionStatus.confirmed | TransactionStatus.failed; type: TransactionType; } diff --git a/src/handlers/transactions.ts b/src/handlers/transactions.ts index f2cf11f164e..304c75cae10 100644 --- a/src/handlers/transactions.ts +++ b/src/handlers/transactions.ts @@ -1,86 +1,16 @@ -import { Contract } from '@ethersproject/contracts'; -import { isEmpty } from 'lodash'; -import { web3Provider } from './web3'; -import { metadataClient } from '@/graphql'; -import { RainbowTransaction, TransactionStatus, ZerionTransaction } from '@/entities'; -import store from '@/redux/store'; -import { transactionSignaturesDataAddNewSignature } from '@/redux/transactionSignatures'; -import { SIGNATURE_REGISTRY_ADDRESS, signatureRegistryABI } from '@/references'; -import { ethereumUtils } from '@/utils'; -import { fetchWalletENSAvatars, fetchWalletNames } from '@/redux/wallets'; +import { FlashbotsStatus, RainbowTransaction, TransactionStatus } from '@/entities'; import { RainbowFetchClient } from '@/rainbow-fetch'; -import { IS_TEST } from '@/env'; -import { API_BASE_URL } from '@rainbow-me/swaps'; import { logger, RainbowError } from '@/logger'; const flashbotsApi = new RainbowFetchClient({ baseURL: 'https://protect.flashbots.net', }); -const rainbowSwapsApi = new RainbowFetchClient({ - baseURL: API_BASE_URL, -}); - -const parseSignatureToTitle = (signature: string) => { - const rawName = signature.match(/^([^)(]*)\((.*)\)([^)(]*)$/u); - let parsedName = ''; - - if (rawName) { - parsedName = - rawName[1].charAt(0).toUpperCase() + - rawName[1] - .slice(1) - .split(/(?=[A-Z])/u) - .join(' '); - } - return parsedName; -}; - -const timeoutPromise = new Promise((_, reject) => { - setTimeout(reject, 800); -}); - -export const getTransactionMethodName = async (transaction: ZerionTransaction) => { - try { - const { signatures } = store.getState().transactionSignatures; - // only being used on mainnet transactions, so we can use the default web3 provider - const txn = await web3Provider.getTransaction(transaction.hash); - const bytes = txn?.data?.substring(0, 10) || ''; - let signature = signatures[bytes] || ''; - if (signature) return signature; - try { - const data = await metadataClient.getContractFunction({ - chainID: 1, - hex: bytes, - }); - - if (data.contractFunction && !isEmpty(data?.contractFunction?.text)) { - signature = data.contractFunction.text; - } - // eslint-disable-next-line no-empty - } catch (e) {} - if (!signature) { - try { - const contract = new Contract(SIGNATURE_REGISTRY_ADDRESS, signatureRegistryABI, web3Provider!); - signature = await Promise.race([contract.entries(bytes), timeoutPromise]); - // eslint-disable-next-line no-empty - } catch (e) {} - } - const parsedSignature = parseSignatureToTitle(signature); - store.dispatch(transactionSignaturesDataAddNewSignature(parsedSignature, bytes)); - return parsedSignature; - } catch (e) { - return ''; - } -}; - -type FlashbotsStatus = 'PENDING' | 'INCLUDED' | 'FAILED' | 'CANCELLED' | 'UNKNOWN'; - export const getTransactionFlashbotStatus = async ( transaction: RainbowTransaction, txHash: string ): Promise<{ - flashbotsStatus: 'FAILED' | 'CANCELLED' | 'UNKNOWN'; + flashbotsStatus: FlashbotsStatus; status: 'failed'; minedAt: number; title: string; @@ -89,61 +19,22 @@ export const getTransactionFlashbotStatus = async ( const fbStatus = await flashbotsApi.get<{ status: FlashbotsStatus }>(`/tx/${txHash}`); const flashbotsStatus = fbStatus.data.status; // Make sure it wasn't dropped after 25 blocks or never made it - if (flashbotsStatus === 'FAILED' || flashbotsStatus === 'CANCELLED' || flashbotsStatus === 'UNKNOWN') { - const status = 'failed'; + if ( + flashbotsStatus === FlashbotsStatus.FAILED || + flashbotsStatus === FlashbotsStatus.CANCELLED || + flashbotsStatus === FlashbotsStatus.UNKNOWN + ) { + const status = TransactionStatus.failed; const minedAt = Math.floor(Date.now() / 1000); - const title = `${transaction.type}.failed`; + const title = `${transaction.type}.${status}`; return { flashbotsStatus, status, minedAt, title }; } } catch (e) { - // - } - return null; -}; -export const getTransactionSocketStatus = async (pendingTransaction: RainbowTransaction) => { - const { swap } = pendingTransaction; - const txHash = ethereumUtils.getHash(pendingTransaction); - let pending = true; - const minedAt: number | null = Math.floor(Date.now() / 1000); - let status = swap?.isBridge ? TransactionStatus.bridging : TransactionStatus.swapping; - try { - const socketStatus = await rainbowSwapsApi.get('/v1/bridge-status', { - params: { - txHash: txHash || '', - fromChainId: String(swap?.fromChainId), - toChainId: String(swap?.toChainId), - }, + logger.error(new RainbowError('[getTransactionFlashbotStatus]: Failed to get flashbots status'), { + error: e, + transaction, + txHash, }); - const socketResponse = socketStatus.data; - if (socketResponse.success) { - if (socketResponse?.result?.sourceTxStatus === 'COMPLETED') { - status = swap?.isBridge ? TransactionStatus.bridging : TransactionStatus.swapping; - } - if (socketResponse?.result?.DestinationTxStatus === 'COMPLETED') { - status = swap?.isBridge ? TransactionStatus.bridged : TransactionStatus.swapped; - pending = false; - } - if (socketResponse?.result?.DestinationTxStatus === 'FAILED' || socketResponse?.result?.sourceTxStatus === 'FAILED') { - status = TransactionStatus.failed; - pending = false; - } - } else if (socketResponse.error) { - logger.warn('[getTransactionSocketStatus]: transaction check failed', socketResponse.error); - status = TransactionStatus.failed; - pending = false; - } - } catch (e) { - logger.error(new RainbowError('[getTransactionSocketStatus]: transaction check caught')); - if (IS_TEST) { - status = swap?.isBridge ? TransactionStatus.bridged : TransactionStatus.swapped; - pending = false; - } } - - return { status, minedAt, pending }; -}; - -export const fetchWalletENSDataAfterRegistration = async () => { - await store.dispatch(fetchWalletENSAvatars()); - store.dispatch(fetchWalletNames()); + return null; }; diff --git a/src/helpers/buildTransactionsSectionsSelector.tsx b/src/helpers/buildTransactionsSectionsSelector.tsx index 86e76a100fb..0d39371a3ab 100644 --- a/src/helpers/buildTransactionsSectionsSelector.tsx +++ b/src/helpers/buildTransactionsSectionsSelector.tsx @@ -3,20 +3,37 @@ import { capitalize, groupBy, isEmpty } from 'lodash'; import React from 'react'; import { FastTransactionCoinRow, RequestCoinRow } from '../components/coin-row'; import { thisMonthTimestamp, thisYearTimestamp, todayTimestamp, yesterdayTimestamp } from './transactions'; -import { NativeCurrencyKey, RainbowTransaction, TransactionStatusTypes } from '@/entities'; +import { NativeCurrencyKey, RainbowTransaction, TransactionStatus } from '@/entities'; import * as i18n from '@/languages'; import { WalletconnectRequestData } from '@/redux/requests'; import { ThemeContextProps } from '@/theme'; import { Contact } from '@/redux/contacts'; -import { TransactionStatus } from '@/resources/transactions/types'; +import { SectionListData } from 'react-native'; -type RainbowTransactionWithContact = RainbowTransaction & { +export type RainbowTransactionWithContact = RainbowTransaction & { contact: Contact | null; }; +type Section = { + title: string; + data: T[]; + renderItem: ({ item }: { item: T }) => JSX.Element; +}; + +export type WalletconnectSection = Section; +export type TransactionSection = Section; + +export type TransactionSections = WalletconnectSection | TransactionSection; + +export type TransactionItemForSectionList = WalletconnectRequestData | RainbowTransactionWithContact; + +export type TransactionSectionsResult = { + sections: SectionListData[]; +}; + // bad news const groupTransactionByDate = ({ status, minedAt }: { status: TransactionStatus; minedAt: string }) => { - if (status === 'pending') { + if (status === TransactionStatus.pending) { return i18n.t(i18n.l.transactions.pending_title); } @@ -44,7 +61,7 @@ const addContactInfo = contact: Contact | null; } => { const { from, to, status } = txn; - const isSent = status === TransactionStatusTypes.sent; + const isSent = status === TransactionStatus.sent; const contactAddress = (isSent ? to : from) || ''; const contact = contacts?.[contactAddress?.toLowerCase()] ?? null; return { @@ -67,16 +84,12 @@ export const buildTransactionsSections = ({ theme: ThemeContextProps; transactions: RainbowTransaction[]; nativeCurrency: NativeCurrencyKey; -}) => { +}): TransactionSectionsResult => { if (!transactions) { return { sections: [] }; } - let sectionedTransactions: { - title: string; - data: RainbowTransactionWithContact[]; - renderItem: ({ item }: { item: RainbowTransactionWithContact }) => JSX.Element; - }[] = []; + let sectionedTransactions: TransactionSections[] = []; const transactionsWithContacts = transactions?.map(addContactInfo(contacts)); @@ -85,11 +98,7 @@ export const buildTransactionsSections = ({ const test = Object.keys(transactionsByDate); const filter = test.filter(key => key !== 'Dropped'); - const sectioned: { - title: string; - data: RainbowTransactionWithContact[]; - renderItem: ({ item }: { item: RainbowTransactionWithContact }) => JSX.Element; - }[] = filter.map((section: string) => { + const sectioned: TransactionSection[] = filter.map((section: string) => { const sectionData: RainbowTransactionWithContact[] = transactionsByDate[section].map(txn => { const typeTxn = txn as RainbowTransactionWithContact; const res = { @@ -119,18 +128,14 @@ export const buildTransactionsSections = ({ } } - // i18n - let requestsToApprove: any = []; if (!isEmpty(requests)) { - requestsToApprove = [ - { - data: requests, - renderItem: ({ item }: any) => , - title: i18n.t(i18n.l.walletconnect.requests), - }, - ]; + sectionedTransactions.unshift({ + data: requests, + renderItem: ({ item }: { item: WalletconnectRequestData }) => , + title: i18n.t(i18n.l.walletconnect.requests), + }); } return { - sections: requestsToApprove.concat(sectionedTransactions), + sections: sectionedTransactions as SectionListData[], }; }; diff --git a/src/hooks/useENSRegistrationActionHandler.ts b/src/hooks/useENSRegistrationActionHandler.ts index 494b915bf68..95337c4d4b9 100644 --- a/src/hooks/useENSRegistrationActionHandler.ts +++ b/src/hooks/useENSRegistrationActionHandler.ts @@ -8,7 +8,7 @@ import { coverMetadataAtom } from '../components/ens-registration/RegistrationCo import { ENSActionParameters, ENSRapActionType } from '@/raps/common'; import usePendingTransactions from './usePendingTransactions'; import { useAccountSettings, useENSRegistration, useWalletENSAvatar, useWallets } from '.'; -import { Records, RegistrationParameters } from '@/entities'; +import { PendingTransaction, Records, RegistrationParameters } from '@/entities'; import { fetchResolver } from '@/handlers/ens'; import { saveNameFromLabelhash } from '@/handlers/localstorage/ens'; import { uploadImage } from '@/handlers/pinata'; @@ -26,6 +26,7 @@ import { performanceTracking, Screens, TimeToSignOperation } from '@/state/perfo import { noop } from 'lodash'; import { logger, RainbowError } from '@/logger'; import { ChainId } from '@/chains/types'; +import { IS_IOS } from '@/env'; // Generic type for action functions type ActionFunction

= (...params: P) => Promise; @@ -171,13 +172,21 @@ const useENSRegistrationActionHandler: UseENSRegistrationActionHandler = ({ step const commitTransactionHash = registrationParameters?.commitTransactionHash; const tx = getPendingTransactionByHash(commitTransactionHash || ''); - commitTransactionHash && - tx && - navigate(ios ? Routes.SPEED_UP_AND_CANCEL_SHEET : Routes.SPEED_UP_AND_CANCEL_BOTTOM_SHEET, { - accentColor, - tx, - type: 'speed_up', - }); + if (commitTransactionHash && tx) { + if (IS_IOS) { + navigate(Routes.SPEED_UP_AND_CANCEL_SHEET, { + accentColor, + tx: tx as PendingTransaction, + type: 'speed_up', + }); + } else { + navigate(Routes.SPEED_UP_AND_CANCEL_BOTTOM_SHEET, { + accentColor, + tx: tx as PendingTransaction, + type: 'speed_up', + }); + } + } }, [getPendingTransactionByHash, navigate, registrationParameters?.commitTransactionHash] ); diff --git a/src/hooks/useGas.ts b/src/hooks/useGas.ts index cd822312924..3933239f905 100644 --- a/src/hooks/useGas.ts +++ b/src/hooks/useGas.ts @@ -137,7 +137,7 @@ export default function useGas({ nativeAsset }: { nativeAsset?: ParsedAddressAss const updateGasFeeOption = useCallback((option: string) => dispatch(gasUpdateGasFeeOption(option)), [dispatch]); const updateTxFee = useCallback( - (newGasLimit: any, overrideGasOption: any, l1GasFeeOptimism: any = null) => { + (newGasLimit: any, overrideGasOption?: any, l1GasFeeOptimism: any = null) => { dispatch(gasUpdateTxFee(newGasLimit, overrideGasOption, l1GasFeeOptimism)); }, [dispatch] diff --git a/src/hooks/useWatchPendingTxs.ts b/src/hooks/useWatchPendingTxs.ts index e2843208b8e..9d5c6fc825c 100644 --- a/src/hooks/useWatchPendingTxs.ts +++ b/src/hooks/useWatchPendingTxs.ts @@ -1,6 +1,6 @@ import { useCallback, useMemo } from 'react'; import useAccountSettings from './useAccountSettings'; -import { RainbowTransaction, MinedTransaction } from '@/entities/transactions/transaction'; +import { RainbowTransaction, MinedTransaction, TransactionStatus, FlashbotsStatus } from '@/entities'; import { userAssetsQueryKey } from '@/resources/assets/UserAssetsQuery'; import { userAssetsQueryKey as swapsUserAssetsQueryKey } from '@/__swaps__/screens/Swap/resources/assets/userAssets'; import { transactionFetchQuery } from '@/resources/transactions/transaction'; @@ -55,7 +55,7 @@ export const useWatchPendingTransactions = ({ address }: { address: string }) => ); const processFlashbotsTransaction = useCallback(async (tx: RainbowTransaction): Promise => { - const flashbotsTxStatus = await getTransactionFlashbotStatus(tx, tx.hash!); + const flashbotsTxStatus = await getTransactionFlashbotStatus(tx, tx.hash); if (flashbotsTxStatus) { const { flashbotsStatus, status, minedAt, title } = flashbotsTxStatus; @@ -65,7 +65,7 @@ export const useWatchPendingTransactions = ({ address }: { address: string }) => minedAt, title, flashbotsStatus, - } as RainbowTransaction; + } as MinedTransaction; } return tx; }, []); @@ -73,7 +73,7 @@ export const useWatchPendingTransactions = ({ address }: { address: string }) => const processSupportedNetworkTransaction = useCallback( async (tx: RainbowTransaction) => { const transaction = await transactionFetchQuery({ - hash: tx.hash!, + hash: tx.hash, chainId: tx.chainId, address, currency: nativeCurrency, @@ -94,11 +94,11 @@ export const useWatchPendingTransactions = ({ address }: { address: string }) => if (tx.chainId && tx.hash && address) { updatedTransaction = await processSupportedNetworkTransaction(updatedTransaction); // if flashbots tx and no blockNumber, check if it failed - if (!(tx as any).blockNumber && tx.flashbots) { + if (tx.flashbots && !('blockNumber' in tx)) { updatedTransaction = await processFlashbotsTransaction(updatedTransaction); } } else { - throw new Error('Pending transaction missing chain id'); + throw new Error('Pending transaction missing chainId, hash, or address'); } } catch (e) { logger.error(new RainbowError(`[useWatchPendingTransaction]: Failed to watch transaction`), { @@ -106,7 +106,7 @@ export const useWatchPendingTransactions = ({ address }: { address: string }) => }); } - if (updatedTransaction?.status !== 'pending') { + if (updatedTransaction?.status !== TransactionStatus.pending) { refreshAssets(tx); } return updatedTransaction; @@ -133,7 +133,7 @@ export const useWatchPendingTransactions = ({ address }: { address: string }) => return acc; } // if tx is flashbots and failed, we want to use the lowest nonce - if (tx.flashbots && (tx as any)?.flashbotsStatus === 'FAILED' && tx?.nonce) { + if (tx.flashbots && tx?.flashbotsStatus === FlashbotsStatus.FAILED && tx?.nonce) { // if we already have a failed flashbots tx, we want to use the lowest nonce if (flashbotsTxFailed && tx.nonce < acc.get(tx.chainId)) { acc.set(tx.chainId, tx.nonce); @@ -173,9 +173,12 @@ export const useWatchPendingTransactions = ({ address }: { address: string }) => processNonces(updatedPendingTransactions); - const { newPendingTransactions, minedTransactions } = updatedPendingTransactions.reduce( + const { newPendingTransactions, minedTransactions } = updatedPendingTransactions.reduce<{ + newPendingTransactions: RainbowTransaction[]; + minedTransactions: MinedTransaction[]; + }>( (acc, tx) => { - if (tx?.status === 'pending') { + if (tx?.status === TransactionStatus.pending) { acc.newPendingTransactions.push(tx); } else { acc.minedTransactions.push(tx as MinedTransaction); @@ -183,8 +186,8 @@ export const useWatchPendingTransactions = ({ address }: { address: string }) => return acc; }, { - newPendingTransactions: [] as RainbowTransaction[], - minedTransactions: [] as MinedTransaction[], + newPendingTransactions: [], + minedTransactions: [], } ); diff --git a/src/languages/en_US.json b/src/languages/en_US.json index eff69c44d9f..841dd103e34 100644 --- a/src/languages/en_US.json +++ b/src/languages/en_US.json @@ -2131,9 +2131,9 @@ "failed": "Send Failed" }, "receive": { - "pending": "", + "pending": "Receiving", "confirmed": "Received", - "failed": "" + "failed": "Receive Failed" }, "withdraw": { "pending": "Withdrawing", diff --git a/src/model/wallet.ts b/src/model/wallet.ts index c1d12fd303c..882ea85c53e 100644 --- a/src/model/wallet.ts +++ b/src/model/wallet.ts @@ -1,7 +1,7 @@ import { TransactionRequest } from '@ethersproject/abstract-provider'; import { arrayify } from '@ethersproject/bytes'; import { HDNode } from '@ethersproject/hdnode'; -import { Provider } from '@ethersproject/providers'; +import { Provider, StaticJsonRpcProvider } from '@ethersproject/providers'; import { Transaction } from '@ethersproject/transactions'; import { Wallet } from '@ethersproject/wallet'; import { signTypedData, SignTypedDataVersion, TypedMessage } from '@metamask/eth-sig-util'; @@ -74,7 +74,7 @@ interface WalletInitialized { interface TransactionRequestParam { transaction: TransactionRequest; existingWallet?: Signer; - provider?: Provider; + provider?: StaticJsonRpcProvider; } interface MessageTypeProperty { diff --git a/src/navigation/SectionListScrollToTopContext.tsx b/src/navigation/SectionListScrollToTopContext.tsx index 6ceb07b898c..158b95450da 100644 --- a/src/navigation/SectionListScrollToTopContext.tsx +++ b/src/navigation/SectionListScrollToTopContext.tsx @@ -1,20 +1,22 @@ import React, { createContext, useState } from 'react'; import { SectionList } from 'react-native'; -export const SectionListScrollToTopContext = createContext<{ +type SectionListScrollToTopContextType = { scrollToTop: () => void; - setScrollToTopRef: (ref: SectionList | null) => void; -}>({ + setScrollToTopRef: (ref: SectionList | null) => void; +}; + +export const SectionListScrollToTopContext = createContext>({ scrollToTop: () => {}, setScrollToTopRef: () => {}, }); -type ScrollToTopProviderProps = { +type ScrollToTopProviderProps = { children: React.ReactNode; }; -const SectionListScrollToTopProvider: React.FC = ({ children }) => { - const [scrollToTopRef, setScrollToTopRef] = useState(null); +function SectionListScrollToTopProvider({ children }: ScrollToTopProviderProps) { + const [scrollToTopRef, setScrollToTopRef] = useState | null>(null); const scrollToTop = () => { if (!scrollToTopRef?.props.sections.length) return; @@ -28,8 +30,10 @@ const SectionListScrollToTopProvider: React.FC = ({ ch return ( {children} ); -}; +} -export const useSectionListScrollToTopContext = () => React.useContext(SectionListScrollToTopContext); +export function useSectionListScrollToTopContext() { + return React.useContext(SectionListScrollToTopContext) as SectionListScrollToTopContextType; +} export default SectionListScrollToTopProvider; diff --git a/src/navigation/types.ts b/src/navigation/types.ts index 59420752554..bc501467c51 100644 --- a/src/navigation/types.ts +++ b/src/navigation/types.ts @@ -5,7 +5,7 @@ import Routes from '@/navigation/routesNames'; import { PortalSheetProps } from '@/screens/Portal'; import { REGISTRATION_MODES } from '@/helpers/ens'; import { CampaignCheckResult } from '@/components/remote-promo-sheet/checkForRemotePromoSheet'; -import { ParsedAddressAsset, UniqueAsset } from '@/entities'; +import { ParsedAddressAsset, PendingTransaction, UniqueAsset } from '@/entities'; import { Claimable } from '@/resources/addys/claimables/types'; import { WalletconnectApprovalSheetRouteParams, WalletconnectResultType } from '@/redux/walletconnect'; import { WalletConnectApprovalSheetType } from '@/helpers/walletConnectApprovalSheetTypes'; @@ -34,12 +34,12 @@ export type RootStackParamList = { }; [Routes.SPEED_UP_AND_CANCEL_BOTTOM_SHEET]: { accentColor?: string; - tx: Record; + tx: PendingTransaction; type: 'speed_up' | 'cancel'; }; [Routes.SPEED_UP_AND_CANCEL_SHEET]: { accentColor?: string; - tx: Record; + tx: PendingTransaction; type: 'speed_up' | 'cancel'; }; [Routes.BACKUP_SHEET]: { diff --git a/src/notifications/mapTransactionsType.ts b/src/notifications/mapTransactionsType.ts index 1b1f829b938..46c950d2b25 100644 --- a/src/notifications/mapTransactionsType.ts +++ b/src/notifications/mapTransactionsType.ts @@ -1,5 +1,5 @@ import { NotificationTransactionTypesType } from '@/notifications/types'; -import { TransactionType } from '@/resources/transactions/types'; +import { TransactionType } from '@/entities'; /** * Mapping of notification backend transaction types sent in notification diff --git a/src/parsers/index.ts b/src/parsers/index.ts index 705b2cde5c0..7b8d222d001 100644 --- a/src/parsers/index.ts +++ b/src/parsers/index.ts @@ -13,6 +13,5 @@ export { defaultGasParamsFormat, parseRainbowMeteorologyData, } from './gas'; -export { parseNewTransaction } from './newTransaction'; export { getRequestDisplayDetails } from './requests'; -export { getDescription } from './transactions'; +export { getDescription, convertNewTransactionToRainbowTransaction } from './transactions'; diff --git a/src/parsers/newTransaction.ts b/src/parsers/newTransaction.ts deleted file mode 100644 index 6111b7faa2b..00000000000 --- a/src/parsers/newTransaction.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { NativeCurrencyKey, NewTransactionOrAddCashTransaction, RainbowTransaction } from '@/entities'; -import { isL2Chain } from '@/handlers/web3'; -import { ETH_ADDRESS } from '@/references'; -import { convertAmountAndPriceToNativeDisplay, convertAmountToBalanceDisplay } from '@/helpers/utilities'; -import { ethereumUtils } from '@/utils'; - -/** - * @desc parse transactions from native prices - * @param {Object} [txDetails=null] - * @param {Object} [nativeCurrency=''] - * @return {String} - */ -export const parseNewTransaction = async ( - txDetails: NewTransactionOrAddCashTransaction, - nativeCurrency: NativeCurrencyKey -): Promise => { - let balance = null; - const { - amount, - asset, - data, - from, - flashbots, - ensCommitRegistrationName, - ensRegistration, - gasLimit, - gasPrice, - maxFeePerGas, - maxPriorityFeePerGas, - network, - chainId, - nft, - nonce, - hash, - protocol, - sourceAmount, - status, - to, - transferId, - type, - txTo, - value, - swap, - } = txDetails; - - if (amount && asset) { - balance = { - amount, - display: convertAmountToBalanceDisplay(amount, asset), - }; - } - - const assetPrice = asset?.price?.value ?? ethereumUtils.getAssetPrice(asset?.address); - - const native = - chainId && isL2Chain({ chainId }) - ? { amount: '', display: '' } - : convertAmountAndPriceToNativeDisplay(amount ?? 0, assetPrice, nativeCurrency); - - return { - address: asset?.address ?? ETH_ADDRESS, - chainId, - balance, - data, - ensCommitRegistrationName, - ensRegistration, - flashbots, - from, - gasLimit, - gasPrice, - hash, - maxFeePerGas, - maxPriorityFeePerGas, - minedAt: null, - name: asset?.name ?? null, - native, - network, - nft, - nonce, - protocol, - sourceAmount, - status, - symbol: asset?.symbol ?? null, - title: `${type}.${status}`, - to, - transferId, - txTo: txTo || to, - type, - value, - swap, - }; -}; diff --git a/src/parsers/transactions.ts b/src/parsers/transactions.ts index 9472f4d2d7f..e3aecd17c7f 100644 --- a/src/parsers/transactions.ts +++ b/src/parsers/transactions.ts @@ -1,6 +1,14 @@ -import { slice } from 'lodash'; -import { parseAllTxnsOnReceive } from '../config/debug'; -import { NativeCurrencyKey, RainbowTransaction, ZerionTransaction } from '@/entities'; +import { + NativeCurrencyKey, + RainbowTransaction, + TransactionDirection, + PaginatedTransactionsApiResponse, + TransactionApiResponse, + TransactionChanges, + TransactionStatus, + TransactionType, + TransactionWithChangesType, +} from '@/entities'; import { convertAmountAndPriceToNativeDisplay, @@ -12,17 +20,8 @@ import { import { NewTransaction, RainbowTransactionFee } from '@/entities/transactions/transaction'; import { parseAddressAsset, parseAsset } from '@/resources/assets/assets'; import { ParsedAsset } from '@/resources/assets/types'; -import { transactionTypes } from '@/entities/transactions/transactionType'; -import { - PaginatedTransactionsApiResponse, - TransactionApiResponse, - TransactionChanges, - TransactionType, - TransactionWithChangesType, -} from '@/resources/transactions/types'; -import { ChainId } from '@/chains/types'; -const LAST_TXN_HASH_BUFFER = 20; +import { ChainId } from '@/chains/types'; const TransactionOutTypes = [ 'burn', @@ -37,25 +36,11 @@ const TransactionOutTypes = [ 'revoke', 'deployment', 'contract_interaction', -] as const; +] as readonly string[]; -export const getDirection = (type: TransactionType) => { - // @ts-expect-error - Ts doesnt like the weird type structure here - if (TransactionOutTypes.includes(type as TransactionType)) return 'out'; - return 'in'; -}; - -const dataFromLastTxHash = (transactionData: ZerionTransaction[], transactions: RainbowTransaction[]): ZerionTransaction[] => { - if (__DEV__ && parseAllTxnsOnReceive) return transactionData; - const lastSuccessfulTxn = transactions.find(txn => !!txn.hash && txn.status !== 'pending'); - const lastTxHash = lastSuccessfulTxn?.hash; - if (lastTxHash) { - const lastTxnHashIndex = transactionData.findIndex(txn => lastTxHash.startsWith(txn.hash)); - if (lastTxnHashIndex > -1) { - return slice(transactionData, 0, lastTxnHashIndex + LAST_TXN_HASH_BUFFER); - } - } - return transactionData; +export const getDirection = (type: TransactionType): TransactionDirection => { + if (TransactionOutTypes.includes(type)) return TransactionDirection.OUT; + return TransactionDirection.IN; }; export const getAssetFromChanges = (changes: TransactionChanges, type: TransactionType) => { @@ -147,12 +132,12 @@ export const parseTransaction = async ( } as RainbowTransaction; }; -export const parseNewTransaction = (tx: NewTransaction): RainbowTransaction => { +export const convertNewTransactionToRainbowTransaction = (tx: NewTransaction): RainbowTransaction => { const asset = tx?.changes?.[0]?.asset || tx.asset; return { ...tx, - status: 'pending', + status: TransactionStatus.pending, data: tx.data, title: `${tx.type}.${tx.status}`, description: asset?.name, @@ -205,12 +190,9 @@ export const getDescription = (asset: ParsedAsset | undefined, type: Transaction export const isValidTransactionType = (type: string | undefined): type is TransactionType => !!type && - // @ts-expect-error - Ts doesnt like the weird type structure here - (transactionTypes.withChanges.includes(type as TransactionType) || - // @ts-expect-error - Ts doesnt like the weird type structure here - transactionTypes.withoutChanges.includes(type as TransactionType) || + (TransactionType.withChanges.includes(type as TransactionType) || + TransactionType.withoutChanges.includes(type as TransactionType) || type === ('sale' as TransactionType)); export const transactionTypeShouldHaveChanges = (type: TransactionType): type is TransactionWithChangesType => - // @ts-expect-error - Ts doesnt like the weird type structure here - transactionTypes.withChanges.includes(type); + TransactionType.withChanges.includes(type); diff --git a/src/raps/actions/claimBridge.ts b/src/raps/actions/claimBridge.ts index b4ed75e4635..e410d7c1565 100644 --- a/src/raps/actions/claimBridge.ts +++ b/src/raps/actions/claimBridge.ts @@ -1,10 +1,16 @@ -import { NewTransaction, ParsedAddressAsset, TransactionGasParamAmounts } from '@/entities'; +import { + NewTransaction, + ParsedAddressAsset, + TransactionDirection, + TransactionGasParamAmounts, + TransactionStatus, + TxHash, +} from '@/entities'; import { getProvider } from '@/handlers/web3'; import { add, addBuffer, greaterThan, lessThan, multiply, subtract } from '@/helpers/utilities'; import { RainbowError } from '@/logger'; import store from '@/redux/store'; import { REFERRER_CLAIM } from '@/references'; -import { TxHash } from '@/resources/transactions/types'; import { addNewTransaction } from '@/state/pendingTransactions'; import ethereumUtils from '@/utils/ethereumUtils'; import { AddressZero } from '@ethersproject/constants'; @@ -54,7 +60,7 @@ export async function claimBridge({ parameters, wallet, baseNonce }: ActionProps const provider = getProvider({ chainId: ChainId.optimism }); const l1GasFeeOptimism = await ethereumUtils.calculateL1FeeOptimism( - // @ts-ignore + // @ts-expect-error - TODO: fix improper arguments here { data: bridgeQuote.data, from: bridgeQuote.from, @@ -177,29 +183,29 @@ export async function claimBridge({ parameters, wallet, baseNonce }: ActionProps asset: typedAssetToBuy, changes: [ { - direction: 'out', + direction: TransactionDirection.OUT, asset: typedAssetToSell, value: bridgeQuote.sellAmount.toString(), }, { - direction: 'in', + direction: TransactionDirection.IN, asset: typedAssetToBuy, value: bridgeQuote.buyAmount.toString(), }, ], - from: bridgeQuote.from as Address, + from: bridgeQuote.from, to: bridgeQuote.to as Address, hash: swap.hash as TxHash, network: chainsName[parameters.chainId], nonce: swap.nonce, - status: 'pending', + status: TransactionStatus.pending, type: 'bridge', flashbots: false, ...gasParams, } satisfies NewTransaction; addNewTransaction({ - address: bridgeQuote.from as Address, + address: bridgeQuote.from, chainId: parameters.chainId, transaction, }); diff --git a/src/raps/actions/crosschainSwap.ts b/src/raps/actions/crosschainSwap.ts index c3744368916..04ba753930a 100644 --- a/src/raps/actions/crosschainSwap.ts +++ b/src/raps/actions/crosschainSwap.ts @@ -5,8 +5,7 @@ import { estimateGasWithPadding, getProvider } from '@/handlers/web3'; import { REFERRER, gasUnits, ReferrerType } from '@/references'; import { ChainId } from '@/chains/types'; -import { NewTransaction } from '@/entities/transactions'; -import { TxHash } from '@/resources/transactions/types'; +import { NewTransaction, TransactionDirection, TransactionStatus, TxHash } from '@/entities'; import { addNewTransaction } from '@/state/pendingTransactions'; import { RainbowError, logger } from '@/logger'; @@ -21,7 +20,7 @@ import { overrideWithFastSpeedIfNeeded, } from '../utils'; import { TokenColors } from '@/graphql/__generated__/metadata'; -import { ParsedAsset } from '@/resources/assets/types'; +import { AddysNetworkDetails, ParsedAsset } from '@/resources/assets/types'; import { ExtendedAnimatedAssetWithColors } from '@/__swaps__/types/assets'; import { Screens, TimeToSignOperation, performanceTracking } from '@/state/performance/performance'; import { swapsStore } from '@/state/swaps/swapsStore'; @@ -182,43 +181,42 @@ export const crosschainSwap = async ({ } : parameters.assetToSell.price; + const assetToBuy = { + ...parameters.assetToBuy, + network: chainsName[parameters.assetToBuy.chainId], + networks: parameters.assetToBuy.networks as Record, + colors: parameters.assetToBuy.colors as TokenColors, + price: nativePriceForAssetToBuy, + } satisfies ParsedAsset; + + const assetToSell = { + ...parameters.assetToSell, + network: chainsName[parameters.assetToSell.chainId], + networks: parameters.assetToSell.networks as Record, + colors: parameters.assetToSell.colors as TokenColors, + price: nativePriceForAssetToSell, + } satisfies ParsedAsset; + const transaction = { chainId, data: parameters.quote.data, - from: parameters.quote.from as Address, + from: parameters.quote.from, to: parameters.quote.to as Address, value: parameters.quote.value?.toString(), - asset: { - ...parameters.assetToBuy, - network: chainsName[parameters.assetToBuy.chainId], - colors: parameters.assetToBuy.colors as TokenColors, - price: nativePriceForAssetToBuy, - } as ParsedAsset, + asset: assetToBuy, changes: [ { - direction: 'out', - // TODO: MARK - Replace this once we migrate network => chainId - // asset: parameters.assetToSell, + direction: TransactionDirection.OUT, asset: { - ...parameters.assetToSell, - network: chainsName[parameters.assetToSell.chainId], - chainId: parameters.assetToSell.chainId, - colors: parameters.assetToSell.colors as TokenColors, - price: nativePriceForAssetToSell, + ...assetToSell, native: undefined, }, value: quote.sellAmount.toString(), }, { - direction: 'in', - // TODO: MARK - Replace this once we migrate network => chainId - // asset: parameters.assetToBuy, + direction: TransactionDirection.IN, asset: { - ...parameters.assetToBuy, - network: chainsName[parameters.assetToBuy.chainId], - chainId: parameters.assetToBuy.chainId, - colors: parameters.assetToBuy.colors as TokenColors, - price: nativePriceForAssetToBuy, + ...assetToBuy, native: undefined, }, value: quote.buyAmountMinusFees.toString(), @@ -228,14 +226,14 @@ export const crosschainSwap = async ({ hash: swap.hash as TxHash, network: chainsName[parameters.chainId], nonce: swap.nonce, - status: 'pending', + status: TransactionStatus.pending, type: 'swap', flashbots: parameters.flashbots, ...gasParamsToUse, } satisfies NewTransaction; addNewTransaction({ - address: parameters.quote.from as Address, + address: parameters.quote.from, chainId, transaction, }); diff --git a/src/raps/actions/ens.ts b/src/raps/actions/ens.ts index 11d3d1b2f3f..d0466d77149 100644 --- a/src/raps/actions/ens.ts +++ b/src/raps/actions/ens.ts @@ -1,9 +1,8 @@ import { Signer } from '@ethersproject/abstract-signer'; -import { captureException } from '@sentry/react-native'; import { IS_TESTING } from 'react-native-dotenv'; import { ENSActionParameters, ENSRap, ENSRapActionType, RapENSAction, RapENSActionParameters } from '@/raps/common'; import { analytics } from '@/analytics'; -import { ENSRegistrationRecords, NewTransaction, TransactionGasParamAmounts } from '@/entities'; +import { ENSRegistrationRecords, NewTransaction, TransactionGasParamAmounts, TransactionStatus } from '@/entities'; import { estimateENSTransactionGasLimit, formatRecordsForTransaction } from '@/handlers/ens'; import { toHex } from '@/handlers/web3'; import { ENSRegistrationTransactionType, getENSExecutionDetails, REGISTRATION_MODES } from '@/helpers/ens'; @@ -462,7 +461,7 @@ const ensAction = async ( logger.debug(`[raps/ens]: [${actionName}] response`, { data: tx }); - const newTransaction: NewTransaction = { + const newTransaction = { chainId: ChainId.mainnet, data: tx.data, ensCommitRegistrationName: type === ENSRegistrationTransactionType.COMMIT ? name : undefined, @@ -480,8 +479,8 @@ const ensAction = async ( to: tx?.to, value: toHex(tx.value), network: Network.mainnet, - status: 'pending', - }; + status: TransactionStatus.pending, + } satisfies NewTransaction; logger.debug(`[raps/ens]: [${actionName}] adding new txn`, { data: newTransaction }); diff --git a/src/raps/actions/swap.ts b/src/raps/actions/swap.ts index 696bae0d8a7..d04d5cd254f 100644 --- a/src/raps/actions/swap.ts +++ b/src/raps/actions/swap.ts @@ -18,8 +18,7 @@ import { Address } from 'viem'; import { metadataPOSTClient } from '@/graphql'; import { ChainId } from '@/chains/types'; -import { NewTransaction } from '@/entities/transactions'; -import { TxHash } from '@/resources/transactions/types'; +import { NewTransaction, TxHash, TransactionStatus, TransactionDirection } from '@/entities'; import { add } from '@/helpers/utilities'; import { addNewTransaction } from '@/state/pendingTransactions'; import { RainbowError, logger } from '@/logger'; @@ -40,7 +39,7 @@ import { import { populateApprove } from './unlock'; import { TokenColors } from '@/graphql/__generated__/metadata'; import { swapMetadataStorage } from '../common'; -import { ParsedAsset } from '@/resources/assets/types'; +import { AddysNetworkDetails, ParsedAsset } from '@/resources/assets/types'; import { ExtendedAnimatedAssetWithColors } from '@/__swaps__/types/assets'; import { Screens, TimeToSignOperation, performanceTracking } from '@/state/performance/performance'; import { swapsStore } from '@/state/swaps/swapsStore'; @@ -313,43 +312,42 @@ export const swap = async ({ } : parameters.assetToSell.price; + const assetToBuy = { + ...parameters.assetToBuy, + network: chainsName[parameters.assetToBuy.chainId], + networks: parameters.assetToBuy.networks as Record, + colors: parameters.assetToBuy.colors as TokenColors, + price: nativePriceForAssetToBuy, + } satisfies ParsedAsset; + + const assetToSell = { + ...parameters.assetToSell, + network: chainsName[parameters.assetToSell.chainId], + networks: parameters.assetToSell.networks as Record, + colors: parameters.assetToSell.colors as TokenColors, + price: nativePriceForAssetToSell, + } satisfies ParsedAsset; + const transaction = { chainId: parameters.chainId, - data: swap.data, - from: swap.from as Address, - to: swap.to as Address, - value: quote.value?.toString(), - // TODO: MARK - Replace this once we migrate network => chainId - // asset: parameters.assetToBuy, - asset: { - ...parameters.assetToBuy, - network: chainsName[parameters.assetToBuy.chainId], - colors: parameters.assetToBuy.colors as TokenColors, - price: nativePriceForAssetToBuy, - } as ParsedAsset, + data: parameters.quote.data, + from: parameters.quote.from, + to: parameters.quote.to as Address, + value: parameters.quote.value?.toString(), + asset: assetToBuy, changes: [ { - direction: 'out', - // TODO: MARK - Replace this once we migrate network => chainId - // asset: parameters.assetToSell, + direction: TransactionDirection.OUT, asset: { - ...parameters.assetToSell, - network: chainsName[parameters.assetToSell.chainId], - colors: parameters.assetToSell.colors as TokenColors, - price: nativePriceForAssetToSell, + ...assetToSell, native: undefined, }, value: quote.sellAmount.toString(), }, { - direction: 'in', - // TODO: MARK - Replace this once we migrate network => chainId - // asset: parameters.assetToBuy, + direction: TransactionDirection.IN, asset: { - ...parameters.assetToBuy, - network: chainsName[parameters.assetToBuy.chainId], - colors: parameters.assetToBuy.colors as TokenColors, - price: nativePriceForAssetToBuy, + ...assetToBuy, native: undefined, }, value: quote.buyAmountMinusFees.toString(), @@ -359,7 +357,7 @@ export const swap = async ({ hash: swap.hash as TxHash, network: chainsName[parameters.chainId], nonce: swap.nonce, - status: 'pending', + status: TransactionStatus.pending, type: 'swap', swap: { type: SwapType.normal, @@ -380,7 +378,7 @@ export const swap = async ({ } addNewTransaction({ - address: parameters.quote.from as Address, + address: parameters.quote.from, chainId: parameters.chainId, transaction, }); diff --git a/src/raps/actions/unlock.ts b/src/raps/actions/unlock.ts index ad04789165e..af0bce33217 100644 --- a/src/raps/actions/unlock.ts +++ b/src/raps/actions/unlock.ts @@ -7,8 +7,7 @@ import { Address, erc20Abi, erc721Abi } from 'viem'; import { ChainId } from '@/chains/types'; import { TransactionGasParams, TransactionLegacyGasParams } from '@/__swaps__/types/gas'; -import { NewTransaction } from '@/entities/transactions'; -import { TxHash } from '@/resources/transactions/types'; +import { NewTransaction, TransactionStatus, TxHash } from '@/entities'; import { addNewTransaction } from '@/state/pendingTransactions'; import { RainbowError, logger } from '@/logger'; @@ -283,7 +282,7 @@ export const unlock = async ({ network: chainsName[chainId], chainId: approval.chainId, nonce: approval.nonce, - status: 'pending', + status: TransactionStatus.pending, type: 'approve', approvalAmount: 'UNLIMITED', ...gasParams, diff --git a/src/rapsV2/actions/claimTransactionClaimableAction.ts b/src/rapsV2/actions/claimTransactionClaimableAction.ts index b2d94597cd0..7874b9e295b 100644 --- a/src/rapsV2/actions/claimTransactionClaimableAction.ts +++ b/src/rapsV2/actions/claimTransactionClaimableAction.ts @@ -3,7 +3,7 @@ import { sendTransaction } from '@/model/wallet'; import { getProvider } from '@/handlers/web3'; import { RainbowError } from '@/logger'; import { addNewTransaction } from '@/state/pendingTransactions'; -import { NewTransaction } from '@/entities'; +import { NewTransaction, TransactionStatus } from '@/entities'; import { chainsName } from '@/chains'; export async function claimTransactionClaimable({ parameters, wallet }: ActionProps<'claimTransactionClaimableAction'>) { @@ -24,7 +24,7 @@ export async function claimTransactionClaimable({ parameters, wallet }: ActionPr chainId: result.result.chainId, hash: result.result.hash, network: chainsName[result.result.chainId], - status: 'pending', + status: TransactionStatus.pending, type: 'claim', nonce: result.result.nonce, asset, diff --git a/src/resources/transactions/consolidatedTransactions.ts b/src/resources/transactions/consolidatedTransactions.ts index 7801e8e9d88..616af75da8e 100644 --- a/src/resources/transactions/consolidatedTransactions.ts +++ b/src/resources/transactions/consolidatedTransactions.ts @@ -1,7 +1,6 @@ import { useInfiniteQuery } from '@tanstack/react-query'; import { InfiniteQueryConfig, QueryConfig, QueryFunctionArgs, createQueryKey, queryClient } from '@/react-query'; -import { NativeCurrencyKey, RainbowTransaction } from '@/entities'; -import { TransactionApiResponse, TransactionsReceivedMessage } from './types'; +import { NativeCurrencyKey, RainbowTransaction, TransactionApiResponse, TransactionsReceivedMessage } from '@/entities'; import { RainbowError, logger } from '@/logger'; import { rainbowFetch } from '@/rainbow-fetch'; import { ADDYS_API_KEY } from 'react-native-dotenv'; diff --git a/src/resources/transactions/transaction.ts b/src/resources/transactions/transaction.ts index d8f181084a8..da7cde08be7 100644 --- a/src/resources/transactions/transaction.ts +++ b/src/resources/transactions/transaction.ts @@ -1,4 +1,4 @@ -import { NativeCurrencyKey, RainbowTransaction } from '@/entities'; +import { NativeCurrencyKey, RainbowTransaction, TransactionApiResponse } from '@/entities'; import { createQueryKey, queryClient, QueryFunctionArgs, QueryFunctionResult } from '@/react-query'; import { useQuery } from '@tanstack/react-query'; import { consolidatedTransactionsQueryFunction, consolidatedTransactionsQueryKey } from './consolidatedTransactions'; @@ -7,7 +7,6 @@ import { rainbowFetch } from '@/rainbow-fetch'; import { ADDYS_API_KEY } from 'react-native-dotenv'; import { parseTransaction } from '@/parsers/transactions'; import { RainbowError, logger } from '@/logger'; -import { TransactionApiResponse } from './types'; import { ChainId } from '@/chains/types'; import { SUPPORTED_MAINNET_CHAIN_IDS } from '@/chains'; diff --git a/src/resources/transactions/types.ts b/src/resources/transactions/types.ts deleted file mode 100644 index e0ec0868b2b..00000000000 --- a/src/resources/transactions/types.ts +++ /dev/null @@ -1,249 +0,0 @@ -import { TransactionResponse } from '@ethersproject/providers'; - -import { ZerionAsset } from '@/entities/tokens'; -import { LegacyTransactionGasParams, TransactionGasParams } from '@/entities/gas'; -import { Network } from '@/chains/types'; -import { AddysAsset, ParsedAsset } from '../assets/types'; - -type ChainId = number; - -export type TransactionStatus = 'pending' | 'confirmed' | 'failed'; - -export type TransactionChanges = ( - | { - asset: ParsedAsset; - value: number | undefined; - direction: TransactionDirection; - address_from: string; - address_to: string; - price: number; - } - | undefined -)[]; -/** - * Metadata for a message from the Zerion API. - */ -export interface MessageMeta { - address?: string; - currency?: string; - cut_off?: number; - status?: string; - chain_id?: Network; // L2 - chain_ids?: ChainId[]; // v3 consolidated - chain_ids_with_errors?: ChainId[]; // v3 consolidated - asset_codes?: string; - next_page_cursor?: string; -} - -/** - * A message from the Zerion API indicating that assets were received. - */ -export interface AddressAssetsReceivedMessage { - payload?: { - assets?: { - asset: ZerionAsset; - quantity: string; - small_balances?: boolean; - }[]; - }; - meta?: MessageMeta; -} - -/** - * A message from the Zerion API indicating that transaction data was received. - */ -export interface TransactionsReceivedMessage { - payload?: { - transactions?: PaginatedTransactionsApiResponse[]; - }; - meta?: MessageMeta; -} - -/** - * A message from the Zerion API indicating that asset price data was received - */ -export interface AssetPricesReceivedMessage { - payload?: { - prices?: { - [id: string]: ZerionAsset; - }; - }; - meta?: MessageMeta; -} - -export type TxHash = `0x${string}`; - -type BaseTransaction = { - hash: TxHash; - nonce: number; // -2 when not from the wallet user - from: string; - to?: string; // it may not have a to if it's a contract deployment (covalent) - data?: string; - network: Network; - - changes?: Array< - | { - asset: ParsedAsset; - direction: TransactionDirection; - address_from?: string; - address_to?: string; - value?: number | string; - price?: number | string; - } - | undefined - >; - direction?: TransactionDirection; - flashbots?: boolean; - - value?: string; // network asset amount sent with the tx (like eth or matic) - fee?: string; - native?: { - // fee and value but in the user prefered currency terms (USD, EUR, etc) - value?: string; - fee?: string; - }; - - type: TransactionType; - protocol?: string; - title: string; - description?: string; - - asset?: AddysAsset; // this is the relevant tx asset, like the asset being sold/approved/withdrawn etc - approvalAmount?: 'UNLIMITED' | (string & object); - contract?: { - name: string; - iconUrl?: string; - }; - - feeType?: 'legacy' | 'eip-1559'; - gasPrice?: string; - gasLimit?: string; - baseFee?: string; -} & Partial; - -export type PendingTransaction = BaseTransaction & { - status: 'pending'; -}; - -type MinedTransaction = BaseTransaction & { - status: 'confirmed' | 'failed'; - flashbotsStatus?: 'CANCELLED' | 'FAILED' | 'INCLUDED'; - blockNumber: number; - minedAt: number; - confirmations: number; - gasUsed: string; -}; - -type NewTransaction = Omit & { - changes?: Array< - | { - direction: TransactionDirection; - asset: AddysAsset; // becomes a user asset when the transaction is parsed - value?: number | string; - price?: number | string; - } - | undefined - >; -}; - -const transactionTypes = { - withoutChanges: ['cancel', 'contract_interaction', 'deployment', 'approve', 'revoke', 'speed_up'], - withChanges: [ - 'sale', - 'bridge', - 'airdrop', - 'wrap', - 'unwrap', - 'bid', - 'burn', - 'send', - 'receive', - 'withdraw', - 'deposit', - 'mint', - 'swap', - 'borrow', - 'claim', - 'repay', - 'stake', - 'unstake', - 'purchase', - ], -} as const; - -export type TransactionWithChangesType = (typeof transactionTypes.withChanges)[number]; -export type TransactionWithoutChangesType = (typeof transactionTypes.withoutChanges)[number]; - -export type TransactionType = TransactionWithChangesType | TransactionWithoutChangesType; - -export type TransactionDirection = 'in' | 'out' | 'self'; - -export interface ExecuteRapResponse extends TransactionResponse { - errorMessage?: string; -} - -export type TransactionApiResponse = { - status: TransactionStatus; - id: TxHash; - hash: TxHash; - network: Network; - protocol?: string; - direction?: TransactionDirection; - address_from?: string; - address_to?: string; - // nonce will ALWAYS be -2 when the transaction is *not* from the wallet user - nonce: number; - changes: Array< - | { - asset: AddysAsset; - value: number | null; - direction: TransactionDirection; - address_from: string; - address_to: string; - price: number; - } - | undefined - >; - fee: { - value: number; - price: number; - - // Fee Details are only available on the tx by hash endpoint - // (won't be available on the consolidated txs list) - details?: { - type: 0 | 2; - type_label: 'legacy' | 'eip-1559'; - gas_price: number; - gas_limit: number; - gas_used: number; - max_fee: number; - max_priority_fee: number; - base_fee: number; - max_base_fee: number; - rollup_fee_details: { - l1_fee: number; - l1_fee_scalar: number; - l1_gas_price: number; - l1_gas_used: number; - l2_fee: number; - }; - }; - }; - block_confirmations?: number; // also only available on the tx by hash endpoint - meta: { - contract_name?: string; - contract_icon_url?: string; - type?: TransactionType; - action?: string; - asset?: AddysAsset; - quantity?: 'UNLIMITED' | string; - explorer_label?: string; - explorer_url?: string; - }; - block_number?: number; - mined_at?: number; -}; - -export type PaginatedTransactionsApiResponse = Omit & { - fee: Omit; -}; diff --git a/src/screens/ENSConfirmRegisterSheet.tsx b/src/screens/ENSConfirmRegisterSheet.tsx index d5986d728d5..7db4480e300 100644 --- a/src/screens/ENSConfirmRegisterSheet.tsx +++ b/src/screens/ENSConfirmRegisterSheet.tsx @@ -81,7 +81,6 @@ function TransactionActionRow({ - {/* @ts-expect-error JavaScript component */} {isLoading && ( - {/* @ts-expect-error JavaScript component */} )} diff --git a/src/screens/ExchangeModal.tsx b/src/screens/ExchangeModal.tsx index 5925bd822d7..2f8aa2c28df 100644 --- a/src/screens/ExchangeModal.tsx +++ b/src/screens/ExchangeModal.tsx @@ -905,7 +905,6 @@ export function ExchangeModal({ fromDiscover, ignoreInitialTypeCheck, testID, ty marginBottom={0} marginTop={0} testID={`${testID}-gas`} - // @ts-expect-error - invalid prop type but fixed in the next PR crossChainServiceTime={getCrosschainSwapServiceTime(tradeDetails as CrosschainQuote)} /> diff --git a/src/screens/NFTSingleOfferSheet/index.tsx b/src/screens/NFTSingleOfferSheet/index.tsx index 22e2b6701c4..c5370caa023 100644 --- a/src/screens/NFTSingleOfferSheet/index.tsx +++ b/src/screens/NFTSingleOfferSheet/index.tsx @@ -27,7 +27,7 @@ import ConditionalWrap from 'conditional-wrap'; import Routes from '@/navigation/routesNames'; import { useLegacyNFTs } from '@/resources/nfts'; import { useAccountSettings, useGas, useWallets } from '@/hooks'; -import { NewTransaction } from '@/entities'; +import { NewTransaction, TransactionDirection, TransactionStatus } from '@/entities'; import { analyticsV2 } from '@/analytics'; import { BigNumber } from '@ethersproject/bignumber'; import { HoldToAuthorizeButton } from '@/components/buttons'; @@ -324,7 +324,7 @@ export function NFTSingleOfferSheet() { }; if (step.id === 'sale') { tx = { - status: 'pending', + status: TransactionStatus.pending, chainId: offerChainId, to: item.data?.to, from: item.data?.from, @@ -339,12 +339,12 @@ export function NFTSingleOfferSheet() { }, changes: [ { - direction: 'out', + direction: TransactionDirection.OUT, asset, value: 1, }, { - direction: 'in', + direction: TransactionDirection.IN, asset: { ...offer.paymentToken, network: offer.network as Network, @@ -358,7 +358,7 @@ export function NFTSingleOfferSheet() { }; } else if (step.id === 'nft-approval') { tx = { - status: 'pending', + status: TransactionStatus.pending, chainId: offerChainId, to: item.data?.to, from: item.data?.from, diff --git a/src/screens/ProfileScreen.js b/src/screens/ProfileScreen.tsx similarity index 64% rename from src/screens/ProfileScreen.js rename to src/screens/ProfileScreen.tsx index bede588182e..63b32a3e6a6 100644 --- a/src/screens/ProfileScreen.js +++ b/src/screens/ProfileScreen.tsx @@ -1,10 +1,9 @@ -import { useIsFocused } from '@react-navigation/native'; -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback } from 'react'; import { ActivityList } from '../components/activity-list'; import { Page } from '../components/layout'; import { useNavigation } from '../navigation/Navigation'; import { ButtonPressAnimation } from '@/components/animations'; -import { useAccountProfile, useAccountSettings, useAccountTransactions, useRequests } from '@/hooks'; +import { useAccountProfile, useAccountSettings, useAccountTransactions } from '@/hooks'; import Routes from '@/navigation/routesNames'; import styled from '@/styled-thing'; import { position } from '@/styles'; @@ -13,34 +12,18 @@ import ImageAvatar from '@/components/contacts/ImageAvatar'; import { ContactAvatar } from '@/components/contacts'; import { usePendingTransactionWatcher } from '@/hooks/usePendingTransactionWatcher'; -const ACTIVITY_LIST_INITIALIZATION_DELAY = 5000; - const ProfileScreenPage = styled(Page)({ ...position.sizeAsObject('100%'), flex: 1, }); export default function ProfileScreen() { - const [activityListInitialized, setActivityListInitialized] = useState(false); - const isFocused = useIsFocused(); const { navigate } = useNavigation(); - const accountTransactions = useAccountTransactions(activityListInitialized, isFocused); - - const { isLoadingTransactions: isLoading, sections, transactionsCount } = accountTransactions; - const { pendingRequestCount } = useRequests(); - const { network, accountAddress } = useAccountSettings(); + const { accountAddress } = useAccountSettings(); const { accountSymbol, accountColor, accountImage } = useAccountProfile(); usePendingTransactionWatcher({ address: accountAddress }); - const isEmpty = !transactionsCount && !pendingRequestCount; - - useEffect(() => { - setTimeout(() => { - setActivityListInitialized(true); - }, ACTIVITY_LIST_INITIALIZATION_DELAY); - }, []); - const onChangeWallet = useCallback(() => { navigate(Routes.CHANGE_WALLET_SHEET); }, [navigate]); @@ -61,7 +44,7 @@ export default function ProfileScreen() { } /> - + ); } diff --git a/src/screens/SendSheet.tsx b/src/screens/SendSheet.tsx index 5d824eb8dc7..3988e2c7dc4 100644 --- a/src/screens/SendSheet.tsx +++ b/src/screens/SendSheet.tsx @@ -12,7 +12,7 @@ import { getDefaultCheckboxes } from './SendConfirmationSheet'; import { WrappedAlert as Alert } from '@/helpers/alert'; import { analytics } from '@/analytics'; import { PROFILES, useExperimentalFlag } from '@/config'; -import { AssetTypes, NewTransaction, ParsedAddressAsset, UniqueAsset } from '@/entities'; +import { AssetTypes, NewTransaction, ParsedAddressAsset, TransactionStatus, UniqueAsset } from '@/entities'; import { isNativeAsset } from '@/handlers/assets'; import { debouncedFetchSuggestions } from '@/handlers/ens'; import { @@ -574,7 +574,7 @@ export default function SendSheet() { txDetails.chainId = currentChainId; txDetails.txTo = signableTransaction.to; txDetails.type = 'send'; - txDetails.status = 'pending'; + txDetails.status = TransactionStatus.pending; addNewTransaction({ address: accountAddress, chainId: currentChainId, diff --git a/src/screens/SignTransactionSheet.tsx b/src/screens/SignTransactionSheet.tsx index 9a92af35bf9..68af545cb21 100644 --- a/src/screens/SignTransactionSheet.tsx +++ b/src/screens/SignTransactionSheet.tsx @@ -8,7 +8,7 @@ import { Transaction } from '@ethersproject/transactions'; import { ChainImage } from '@/components/coin-icon/ChainImage'; import { SheetActionButton } from '@/components/sheet'; import { Bleed, Box, Columns, Inline, Inset, Stack, Text, globalColors, useBackgroundColor, useForegroundColor } from '@/design-system'; -import { NewTransaction } from '@/entities'; +import { NewTransaction, TransactionStatus } from '@/entities'; import { useNavigation } from '@/navigation'; import { useTheme } from '@/theme'; @@ -377,10 +377,10 @@ export const SignTransactionSheet = () => { let txSavedInCurrentWallet = false; const displayDetails = transactionDetails.displayDetails; - let txDetails: NewTransaction | null = null; + let txDetails: NewTransaction | undefined; if (sendInsteadOfSign && sendResult?.hash) { txDetails = { - status: 'pending', + status: TransactionStatus.pending, chainId, asset: displayDetails?.request?.asset || nativeAsset, contract: { @@ -398,6 +398,7 @@ export const SignTransactionSheet = () => { type: 'contract_interaction', ...gasParams, }; + if (accountInfo.address?.toLowerCase() === txDetails.from?.toLowerCase()) { addNewTransaction({ transaction: txDetails, @@ -427,17 +428,19 @@ export const SignTransactionSheet = () => { closeScreen(false); // When the tx is sent from a different wallet, // we need to switch to that wallet before saving the tx + InteractionManager.runAfterInteractions(async () => { + if (!txSavedInCurrentWallet && !!txDetails) { + if (txDetails?.from) { + await switchToWalletWithAddress(txDetails?.from as string); + } - if (!txSavedInCurrentWallet && !isNil(txDetails)) { - InteractionManager.runAfterInteractions(async () => { - await switchToWalletWithAddress(txDetails?.from as string); addNewTransaction({ - transaction: txDetails as NewTransaction, + transaction: txDetails, chainId, address: txDetails?.from as string, }); - }); - } + } + }); } else { logger.error(new RainbowError(`[SignTransactionSheet]: Tx failure - ${formattedDappUrl}`), { dappName: transactionDetails?.dappName, diff --git a/src/screens/SpeedUpAndCancelSheet.js b/src/screens/SpeedUpAndCancelSheet.tsx similarity index 76% rename from src/screens/SpeedUpAndCancelSheet.js rename to src/screens/SpeedUpAndCancelSheet.tsx index ecdce4e9c1b..352df10fd8e 100644 --- a/src/screens/SpeedUpAndCancelSheet.js +++ b/src/screens/SpeedUpAndCancelSheet.tsx @@ -1,10 +1,10 @@ -import { useRoute } from '@react-navigation/native'; +import { RouteProp, useRoute } from '@react-navigation/native'; import { BigNumber } from 'bignumber.js'; import lang from 'i18n-js'; import { isEmpty } from 'lodash'; import Routes from '@/navigation/routesNames'; -import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import { ActivityIndicator } from 'react-native'; +import React, { ComponentProps, Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { ActivityIndicator, View } from 'react-native'; import Animated, { useSharedValue, withSpring } from 'react-native-reanimated'; import { useDispatch } from 'react-redux'; import Divider from '@/components/Divider'; @@ -15,7 +15,7 @@ import { SheetActionButton, SheetActionButtonRow, SheetHandleFixedToTop, SheetKe import { Emoji, Text } from '../components/text'; import { WrappedAlert as Alert } from '@/helpers/alert'; import { removeRegistrationByName, saveCommitRegistrationParameters } from '@/redux/ensRegistration'; -import { GasFeeTypes } from '@/entities'; +import { GasFeeType, GasFeeTypes, LegacyTransactionGasParamAmounts, TransactionGasParamAmounts, TransactionStatus } from '@/entities'; import { getFlashbotsProvider, getProvider, isL2Chain, toHex } from '@/handlers/web3'; import { greaterThan } from '@/helpers/utilities'; import { useAccountSettings, useDimensions, useGas, useWallets } from '@/hooks'; @@ -32,6 +32,11 @@ import { updateTransaction } from '@/state/pendingTransactions'; import { logger, RainbowError } from '@/logger'; import { supportedFlashbotsChainIds } from '@/chains'; import { ChainId } from '@/chains/types'; +import { ThemeContextProps, useTheme } from '@/theme'; +import { BigNumberish } from '@ethersproject/bignumber'; +import { RootStackParamList } from '@/navigation/types'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { BytesLike } from '@ethersproject/bytes'; const { CUSTOM, URGENT } = gasUtils; @@ -41,9 +46,15 @@ const springConfig = { stiffness: 1000, }; +type WithThemeContextProps = { + deviceHeight: number; + height: number; + theme: ThemeContextProps; +}; + const Container = styled(Centered).attrs({ direction: 'column', -})(({ deviceHeight, height }) => ({ +})(({ deviceHeight, height }: WithThemeContextProps) => ({ ...(height && { height: height + deviceHeight, }), @@ -55,21 +66,21 @@ const CenteredSheet = styled(Centered)({ borderTopRightRadius: 39, }); -const ExtendedSheetBackground = styled.View({ - backgroundColor: ({ theme: { colors } }) => colors.white, +const ExtendedSheetBackground = styled(View)({ + backgroundColor: ({ theme: { colors } }: WithThemeContextProps) => colors.white, bottom: -800, height: 1000, position: 'absolute', width: '100%', }); -const LoadingSpinner = styled(android ? Spinner : ActivityIndicator).attrs(({ theme: { colors } }) => ({ +const LoadingSpinner = styled(android ? Spinner : ActivityIndicator).attrs(({ theme: { colors } }: WithThemeContextProps) => ({ color: colors.alpha(colors.blueGreyDark, 0.3), size: 'large', }))({}); const AnimatedContainer = Animated.createAnimatedComponent(Container); -const AnimatedSheet = Animated.createAnimatedComponent(CenteredSheet); +const AnimatedSheet = Animated.createAnimatedComponent>(CenteredSheet); const GasSpeedButtonContainer = styled(Row).attrs({ justify: 'center', @@ -90,8 +101,8 @@ const text = { [SPEED_UP]: i18n.t(i18n.l.wallet.transaction.speed_up.speed_up_text), }; -const calcGasParamRetryValue = prevWeiValue => { - const prevWeiValueBN = new BigNumber(prevWeiValue); +const calcGasParamRetryValue = (prevWeiValue: BigNumberish) => { + const prevWeiValueBN = new BigNumber(prevWeiValue.toString()); const newWeiValueBN = prevWeiValueBN.times(new BigNumber('110')).dividedBy(new BigNumber('100')); @@ -110,45 +121,49 @@ export default function SpeedUpAndCancelSheet() { const speedUrgentSelected = useRef(false); const { params: { type, tx, accentColor }, - } = useRoute(); + } = useRoute>(); const [ready, setReady] = useState(false); - const [txType, setTxType] = useState(); - const [minGasPrice, setMinGasPrice] = useState(calcGasParamRetryValue(tx.gasPrice)); - const [minMaxPriorityFeePerGas, setMinMaxPriorityFeePerGas] = useState(calcGasParamRetryValue(tx.maxPriorityFeePerGas)); - const [minMaxFeePerGas, setMinMaxFeePerGas] = useState(calcGasParamRetryValue(tx.maxFeePerGas)); + const [txType, setTxType] = useState(); + const [minGasPrice, setMinGasPrice] = useState(tx?.gasPrice ? calcGasParamRetryValue(tx.gasPrice) : undefined); + const [minMaxPriorityFeePerGas, setMinMaxPriorityFeePerGas] = useState( + tx?.maxPriorityFeePerGas ? calcGasParamRetryValue(tx.maxPriorityFeePerGas) : undefined + ); + const [minMaxFeePerGas, setMinMaxFeePerGas] = useState(tx?.maxFeePerGas ? calcGasParamRetryValue(tx.maxFeePerGas) : undefined); const fetchedTx = useRef(false); - const [currentChainId, setCurrentChainId] = useState(null); - const [currentProvider, setCurrentProvider] = useState(null); - const [data, setData] = useState(null); - const [gasLimit, setGasLimit] = useState(null); - const [nonce, setNonce] = useState(null); - const [to, setTo] = useState(tx.to); - const [value, setValue] = useState(null); + const [currentChainId, setCurrentChainId] = useState(ChainId.mainnet); + const [currentProvider, setCurrentProvider] = useState(getProvider({ chainId: ChainId.mainnet })); + const [data, setData] = useState(); + const [gasLimit, setGasLimit] = useState(); + const [nonce, setNonce] = useState(); + const [to, setTo] = useState(tx?.to ?? undefined); + const [value, setValue] = useState(); const isL2 = isL2Chain({ chainId: tx?.chainId }); const getNewTransactionGasParams = useCallback(() => { const gasParams = parseGasParamsForTransaction(selectedGasFee); if (txType === GasFeeTypes.eip1559) { - const rawMaxPriorityFeePerGas = gasParams.maxPriorityFeePerGas; - const rawMaxFeePerGas = gasParams.maxFeePerGas; + const rawMaxPriorityFeePerGas = (gasParams as TransactionGasParamAmounts).maxPriorityFeePerGas; + const rawMaxFeePerGas = (gasParams as TransactionGasParamAmounts).maxFeePerGas; - const maxPriorityFeePerGas = greaterThan(rawMaxPriorityFeePerGas, minMaxPriorityFeePerGas) + const maxPriorityFeePerGas = greaterThan(rawMaxPriorityFeePerGas, minMaxPriorityFeePerGas ?? 0) ? toHex(rawMaxPriorityFeePerGas) - : toHex(minMaxPriorityFeePerGas); + : toHex(minMaxPriorityFeePerGas ?? 0); - const maxFeePerGas = greaterThan(rawMaxFeePerGas, minMaxFeePerGas) ? toHex(rawMaxFeePerGas) : toHex(minMaxFeePerGas); + const maxFeePerGas = greaterThan(rawMaxFeePerGas, minMaxFeePerGas ?? 0) ? toHex(rawMaxFeePerGas) : toHex(minMaxFeePerGas ?? 0); return { maxFeePerGas, maxPriorityFeePerGas }; } else { - const rawGasPrice = gasParams.gasPrice; + const rawGasPrice = (gasParams as LegacyTransactionGasParamAmounts).gasPrice; return { - gasPrice: greaterThan(rawGasPrice, minGasPrice) ? toHex(rawGasPrice) : toHex(minGasPrice), + gasPrice: greaterThan(rawGasPrice, minGasPrice ?? 0) ? toHex(rawGasPrice) : toHex(minGasPrice ?? 0), }; } }, [txType, selectedGasFee, minMaxPriorityFeePerGas, minMaxFeePerGas, minGasPrice]); const cancelCommitTransactionHash = useCallback(() => { - dispatch(removeRegistrationByName(tx?.ensCommitRegistrationName)); + if (tx?.ensCommitRegistrationName) { + dispatch(removeRegistrationByName(tx?.ensCommitRegistrationName)); + } }, [dispatch, tx?.ensCommitRegistrationName]); const handleCancellation = useCallback(async () => { @@ -167,10 +182,12 @@ export default function SpeedUpAndCancelSheet() { if (tx?.ensCommitRegistrationName) { cancelCommitTransactionHash(); } - const updatedTx = { ...tx }; + const updatedTx = { ...tx, nonce: tx.nonce ?? 0 }; // Update the hash on the copy of the original tx - updatedTx.hash = res.result?.hash; - updatedTx.status = 'pending'; + if (res?.result?.hash) { + updatedTx.hash = res.result.hash; + } + updatedTx.status = TransactionStatus.pending; updatedTx.type = 'cancel'; updateTransaction({ address: accountAddress, @@ -209,7 +226,7 @@ export default function SpeedUpAndCancelSheet() { }, [handleCancellation, isHardwareWallet, navigate]); const saveCommitTransactionHash = useCallback( - hash => { + (hash: string) => { dispatch( saveCommitRegistrationParameters({ commitTransactionHash: hash, @@ -237,13 +254,15 @@ export default function SpeedUpAndCancelSheet() { transaction: fasterTxPayload, }); - if (tx?.ensCommitRegistrationName && res.result?.hash) { - saveCommitTransactionHash(res?.result?.hash); + if (tx?.ensCommitRegistrationName && res?.result?.hash) { + saveCommitTransactionHash(res.result.hash); } - const updatedTx = { ...tx }; + const updatedTx = { ...tx, nonce: tx.nonce ?? 0 }; // Update the hash on the copy of the original tx - updatedTx.hash = res?.result?.hash; - updatedTx.status = 'pending'; + if (res?.result?.hash) { + updatedTx.hash = res.result.hash; + } + updatedTx.status = TransactionStatus.pending; updatedTx.type = 'speed_up'; updateTransaction({ @@ -328,26 +347,39 @@ export default function SpeedUpAndCancelSheet() { if (currentChainId && currentProvider && !fetchedTx.current) { try { fetchedTx.current = true; - const hexGasLimit = toHex(tx?.gasLimit?.toString() || '0x'); - const hexValue = toHex(tx?.value?.toString() || '0x'); - const hexData = tx?.data; + + if (tx.value) { + setValue(toHex(tx?.value?.toString())); + } + + if (tx.to) { + setTo(tx.to); + } + + // NOTE: If we don't have a supplied gas limit, we don't need to set it. + if (tx?.gasLimit) { + setGasLimit(toHex(tx?.gasLimit?.toString())); + } setReady(true); - setNonce(tx.nonce); - setValue(hexValue); - setData(hexData); - setTo(tx.to); - setGasLimit(hexGasLimit); + setNonce(tx.nonce ?? 0); + setData(tx?.data); if (!isL2) { setTxType(GasFeeTypes.eip1559); - const hexMaxPriorityFeePerGas = toHex(tx.maxPriorityFeePerGas.toString()); - setMinMaxPriorityFeePerGas(calcGasParamRetryValue(hexMaxPriorityFeePerGas)); - const hexMaxFeePerGas = toHex(tx.maxFeePerGas.toString()); - setMinMaxFeePerGas(calcGasParamRetryValue(hexMaxFeePerGas)); + if (tx.maxPriorityFeePerGas) { + const hexMaxPriorityFeePerGas = toHex(tx.maxPriorityFeePerGas.toString()); + setMinMaxPriorityFeePerGas(calcGasParamRetryValue(hexMaxPriorityFeePerGas)); + } + if (tx.maxFeePerGas) { + const hexMaxFeePerGas = toHex(tx.maxFeePerGas.toString()); + setMinMaxFeePerGas(calcGasParamRetryValue(hexMaxFeePerGas)); + } } else { setTxType(GasFeeTypes.legacy); - const hexGasPrice = toHex(tx.gasPrice.toString()); - setMinGasPrice(calcGasParamRetryValue(hexGasPrice)); + if (tx.gasPrice) { + const hexGasPrice = toHex(tx.gasPrice.toString()); + setMinGasPrice(calcGasParamRetryValue(hexGasPrice)); + } } } catch (e) { logger.error(new RainbowError(`[SpeedUpAndCancelSheet]: error fetching tx info: ${e}`), { @@ -374,8 +406,8 @@ export default function SpeedUpAndCancelSheet() { useEffect(() => { if (!isEmpty(gasFeeParamsBySpeed) && !calculatingGasLimit.current) { calculatingGasLimit.current = true; - if (greaterThan(minMaxPriorityFeePerGas, gasFeeParamsBySpeed?.fast?.maxPriorityFeePerGas?.amount)) { - dispatch(updateGasFeeForSpeed(gasUtils.FAST, minMaxPriorityFeePerGas)); + if (greaterThan(minMaxPriorityFeePerGas ?? 0, gasFeeParamsBySpeed?.fast?.maxPriorityFeePerGas?.amount)) { + dispatch(updateGasFeeForSpeed(gasUtils.FAST, (minMaxPriorityFeePerGas || 0).toString())); } const gasLimitForNewTx = type === CANCEL_TX ? ethUnits.basic_tx : tx.gasLimit; updateTxFee(gasLimitForNewTx); @@ -396,7 +428,7 @@ export default function SpeedUpAndCancelSheet() { const { colors, isDarkMode } = useTheme(); const speeds = useMemo(() => { - const defaultSpeeds = [URGENT]; + const defaultSpeeds: string[] = [URGENT]; if (!isL2) { defaultSpeeds.push(CUSTOM); } diff --git a/src/screens/mints/MintSheet.tsx b/src/screens/mints/MintSheet.tsx index 3d97ee5e44d..09c628a8865 100644 --- a/src/screens/mints/MintSheet.tsx +++ b/src/screens/mints/MintSheet.tsx @@ -26,7 +26,7 @@ import { ButtonPressAnimation } from '@/components/animations'; import { useFocusEffect, useRoute } from '@react-navigation/native'; import { ReservoirCollection } from '@/graphql/__generated__/arcDev'; import { format } from 'date-fns'; -import { NewTransaction } from '@/entities'; +import { NewTransaction, TransactionStatus } from '@/entities'; import * as i18n from '@/languages'; import { analyticsV2 } from '@/analytics'; import { event } from '@/analytics/event'; @@ -408,7 +408,7 @@ const MintSheet = () => { const tx: NewTransaction = { chainId, - status: 'pending', + status: TransactionStatus.pending, to: item.data?.to, from: item.data?.from, hash: item.txHashes[0].txHash, diff --git a/src/screens/transaction-details/components/TransactionDetailsStatusActionsAndTimestampSection.tsx b/src/screens/transaction-details/components/TransactionDetailsStatusActionsAndTimestampSection.tsx index d3df660b79d..728f6d2947b 100644 --- a/src/screens/transaction-details/components/TransactionDetailsStatusActionsAndTimestampSection.tsx +++ b/src/screens/transaction-details/components/TransactionDetailsStatusActionsAndTimestampSection.tsx @@ -1,8 +1,7 @@ import React, { useCallback, useMemo } from 'react'; -import { RainbowTransaction, TransactionStatusTypes } from '@/entities'; +import { PendingTransaction, RainbowTransaction, TransactionStatus } from '@/entities'; import { Box, Stack, Text } from '@/design-system'; import { formatTransactionDetailsDate } from '@/screens/transaction-details/helpers/formatTransactionDetailsDate'; -import { capitalize } from 'lodash'; import { getIconColorAndGradientForTransactionStatus } from '@/screens/transaction-details/helpers/getIconColorAndGradientForTransactionStatus'; import RadialGradient from 'react-native-radial-gradient'; import { useTheme } from '@/theme'; @@ -33,7 +32,7 @@ export const TransactionDetailsStatusActionsAndTimestampSection: React.FC const isOutgoing = from?.toLowerCase() === accountAddress?.toLowerCase(); const canBeResubmitted = isOutgoing && !minedAt; - const canBeCancelled = canBeResubmitted && status !== TransactionStatusTypes.cancelling; + const canBeCancelled = canBeResubmitted && status !== TransactionStatus.cancelling; const menuConfig = useMemo( () => ({ @@ -77,13 +76,13 @@ export const TransactionDetailsStatusActionsAndTimestampSection: React.FC switch (actionKey) { case 'speedUp': navigate(Routes.SPEED_UP_AND_CANCEL_SHEET, { - tx: transaction, + tx: transaction as PendingTransaction, type: 'speed_up', }); return; case 'cancel': navigate(Routes.SPEED_UP_AND_CANCEL_SHEET, { - tx: transaction, + tx: transaction as PendingTransaction, type: 'cancel', }); return; diff --git a/src/screens/transaction-details/components/TransactionMasthead.tsx b/src/screens/transaction-details/components/TransactionMasthead.tsx index 3ec25d33e5f..6516a3179d0 100644 --- a/src/screens/transaction-details/components/TransactionMasthead.tsx +++ b/src/screens/transaction-details/components/TransactionMasthead.tsx @@ -25,7 +25,7 @@ import { ContactAvatar } from '@/components/contacts'; import { isLowerCaseMatch } from '@/utils'; import { useSelector } from 'react-redux'; import { AppState } from '@/redux/store'; -import { useContacts, useUserAccounts } from '@/hooks'; +import { useAccountSettings, useContacts, useUserAccounts } from '@/hooks'; import { useTiming } from 'react-native-redash'; import Animated, { Easing, interpolate, useAnimatedStyle } from 'react-native-reanimated'; import { removeFirstEmojiFromString, returnStringFirstEmoji } from '@/helpers/emojiHandler'; @@ -79,9 +79,8 @@ function CurrencyTile({ address?: string; onAddressCopied: () => void; }) { - const accountAddress = useSelector((state: AppState) => state.settings.accountAddress); + const { accountAddress } = useAccountSettings(); const theme = useTheme(); - const { contacts } = useContacts(); const { userAccounts, watchedAccounts } = useUserAccounts(); diff --git a/src/screens/transaction-details/helpers/checkForPendingSwap.ts b/src/screens/transaction-details/helpers/checkForPendingSwap.ts index e780eedd2b7..240a546cee7 100644 --- a/src/screens/transaction-details/helpers/checkForPendingSwap.ts +++ b/src/screens/transaction-details/helpers/checkForPendingSwap.ts @@ -1,5 +1,5 @@ -import { RainbowTransaction } from '@/entities'; +import { RainbowTransaction, TransactionStatus } from '@/entities'; export const checkForPendingSwap = (transaction: RainbowTransaction) => { - return ['swap', 'wrap', 'unwrap'].includes(transaction.type) && transaction.status === 'pending'; + return ['swap', 'wrap', 'unwrap'].includes(transaction.type) && transaction.status === TransactionStatus.pending; }; diff --git a/src/screens/transaction-details/helpers/getIconColorAndGradientForTransactionStatus.ts b/src/screens/transaction-details/helpers/getIconColorAndGradientForTransactionStatus.ts index 8e514e77c82..98f7bb235d7 100644 --- a/src/screens/transaction-details/helpers/getIconColorAndGradientForTransactionStatus.ts +++ b/src/screens/transaction-details/helpers/getIconColorAndGradientForTransactionStatus.ts @@ -1,4 +1,4 @@ -import { TransactionStatus } from '@/resources/transactions/types'; +import { TransactionStatus } from '@/entities'; import { ThemeContextProps } from '@/theme'; export function getIconColorAndGradientForTransactionStatus( @@ -9,14 +9,13 @@ export function getIconColorAndGradientForTransactionStatus( color: 'red' | 'blue' | 'labelSecondary'; gradient: string[]; } { - if (status === 'pending') { + if (status === TransactionStatus.pending) { return { icon: '􀖇', color: 'labelSecondary', gradient: colors.gradients.transparentToLightGrey, }; - } - if (status === 'failed') { + } else if (status === TransactionStatus.failed) { return { icon: '􀆄', color: 'red', diff --git a/src/state/pendingTransactions/index.ts b/src/state/pendingTransactions/index.ts index e877464fdf0..34896c3d006 100644 --- a/src/state/pendingTransactions/index.ts +++ b/src/state/pendingTransactions/index.ts @@ -1,7 +1,7 @@ import { RainbowTransaction, NewTransaction } from '@/entities/transactions'; import { createStore } from '../internal/createStore'; import create from 'zustand'; -import { parseNewTransaction } from '@/parsers/transactions'; +import { convertNewTransactionToRainbowTransaction } from '@/parsers/transactions'; import { nonceStore } from '../nonces'; import { ChainId } from '@/chains/types'; @@ -79,7 +79,7 @@ export const addNewTransaction = ({ }) => { const { addPendingTransaction } = pendingTransactionsStore.getState(); const { setNonce } = nonceStore.getState(); - const parsedTransaction = parseNewTransaction(transaction); + const parsedTransaction = convertNewTransactionToRainbowTransaction(transaction); addPendingTransaction({ address, pendingTransaction: parsedTransaction }); setNonce({ address, @@ -99,7 +99,7 @@ export const updateTransaction = ({ }) => { const { updatePendingTransaction } = pendingTransactionsStore.getState(); const { setNonce } = nonceStore.getState(); - const parsedTransaction = parseNewTransaction(transaction); + const parsedTransaction = convertNewTransactionToRainbowTransaction(transaction); updatePendingTransaction({ address, pendingTransaction: parsedTransaction }); setNonce({ address, diff --git a/src/utils/gas.ts b/src/utils/gas.ts index c50c6331c6f..d090582a62b 100644 --- a/src/utils/gas.ts +++ b/src/utils/gas.ts @@ -20,7 +20,9 @@ const NO_TREND = 'notrend'; const GasSpeedOrder = [NORMAL, FAST, URGENT, CUSTOM]; const GasTrends = { FALLING, NO_TREND, RISING, STABLE, SURGING }; -const GAS_ICONS = { +const GAS_ICONS: { + [key in (typeof GasSpeedOrder)[number]]: string; +} = { [CUSTOM]: 'gear', [FAST]: 'rocket', [NORMAL]: 'stopwatch', @@ -54,7 +56,9 @@ const SWAP_GAS_ICONS: SwapGasIcons = { }, }; -const GAS_EMOJIS = { +const GAS_EMOJIS: { + [key in (typeof GasSpeedOrder)[number]]: string; +} = { [CUSTOM]: '⚙️', [FAST]: '🚀', [NORMAL]: IS_IOS ? '⏱' : '🕘', diff --git a/types/@bankify/react-native-animate-number.d.ts b/types/@bankify/react-native-animate-number.d.ts new file mode 100644 index 00000000000..7ffa96a56ff --- /dev/null +++ b/types/@bankify/react-native-animate-number.d.ts @@ -0,0 +1 @@ +declare module '@bankify/react-native-animate-number'; diff --git a/yarn.lock b/yarn.lock index 6c19cae78bd..bd4226b8d26 100644 --- a/yarn.lock +++ b/yarn.lock @@ -62,6 +62,16 @@ __metadata: languageName: node linkType: hard +"@babel/code-frame@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/code-frame@npm:7.25.7" + dependencies: + "@babel/highlight": "npm:^7.25.7" + picocolors: "npm:^1.0.0" + checksum: 10c0/14825c298bdec914caf3d24d1383b6d4cd6b030714686004992f4fc251831ecf432236652896f99d5d341f17170ae9a07b58d8d7b15aa0df8cfa1c5a7d5474bc + languageName: node + linkType: hard + "@babel/compat-data@npm:^7.17.7, @babel/compat-data@npm:^7.20.5, @babel/compat-data@npm:^7.22.0, @babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.24.8": version: 7.24.9 resolution: "@babel/compat-data@npm:7.24.9" @@ -69,6 +79,13 @@ __metadata: languageName: node linkType: hard +"@babel/compat-data@npm:^7.25.7": + version: 7.25.8 + resolution: "@babel/compat-data@npm:7.25.8" + checksum: 10c0/8b81c17580e5fb4cbb6a3c52079f8c283fc59c0c6bd2fe14cfcf9c44b32d2eaab71b02c5633e2c679f5896f73f8ac4036ba2e67a4c806e8f428e4b11f526d7f4 + languageName: node + linkType: hard + "@babel/core@npm:7.22.0": version: 7.22.0 resolution: "@babel/core@npm:7.22.0" @@ -164,6 +181,18 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/generator@npm:7.25.7" + dependencies: + "@babel/types": "npm:^7.25.7" + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.25" + jsesc: "npm:^3.0.2" + checksum: 10c0/c03a26c79864d60d04ce36b649c3fa0d6fd7b2bf6a22e22854a0457aa09206508392dd73ee40e7bc8d50b3602f9ff068afa47770cda091d332e7db1ca382ee96 + languageName: node + linkType: hard + "@babel/helper-annotate-as-pure@npm:^7.0.0, @babel/helper-annotate-as-pure@npm:^7.22.5, @babel/helper-annotate-as-pure@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-annotate-as-pure@npm:7.24.7" @@ -173,6 +202,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-annotate-as-pure@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-annotate-as-pure@npm:7.25.7" + dependencies: + "@babel/types": "npm:^7.25.7" + checksum: 10c0/2f020b0fa9d336b5778485cc2de3141561ec436a7591b685457a5bcdae4ce41d9ddee68169c95504e0789e5a4327e73b8b7e72e5b60e82e96d730c4d19255248 + languageName: node + linkType: hard + "@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.24.7" @@ -206,6 +244,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-compilation-targets@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-compilation-targets@npm:7.25.7" + dependencies: + "@babel/compat-data": "npm:^7.25.7" + "@babel/helper-validator-option": "npm:^7.25.7" + browserslist: "npm:^4.24.0" + lru-cache: "npm:^5.1.1" + semver: "npm:^6.3.1" + checksum: 10c0/705be7e5274a3fdade68e3e2cf42e2b600316ab52794e13b91299a16f16c926f15886b6e9d6df20eb943ccc1cdba5a363d4766f8d01e47b8e6f4e01175f5e66c + languageName: node + linkType: hard + "@babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.24.7, @babel/helper-create-class-features-plugin@npm:^7.24.8": version: 7.24.8 resolution: "@babel/helper-create-class-features-plugin@npm:7.24.8" @@ -225,6 +276,23 @@ __metadata: languageName: node linkType: hard +"@babel/helper-create-class-features-plugin@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-create-class-features-plugin@npm:7.25.7" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.25.7" + "@babel/helper-member-expression-to-functions": "npm:^7.25.7" + "@babel/helper-optimise-call-expression": "npm:^7.25.7" + "@babel/helper-replace-supers": "npm:^7.25.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/405c3c1a137acda1206380a96993cf2cfd808b3bee1c11c4af47ee0f03a20858497aa53394d6adc5431793c543be5e02010620e871a5ab39d938ae90a54b50f2 + languageName: node + linkType: hard + "@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-create-regexp-features-plugin@npm:7.24.7" @@ -337,6 +405,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-member-expression-to-functions@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-member-expression-to-functions@npm:7.25.7" + dependencies: + "@babel/traverse": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" + checksum: 10c0/1e948162ab48d84593a7c6ec9570d14c906146f1697144fc369c59dbeb00e4a062da67dd06cb0d8f98a044cd8389002dcf2ab6f5613d99c35748307846ec63fc + languageName: node + linkType: hard + "@babel/helper-module-imports@npm:^7.0.0, @babel/helper-module-imports@npm:^7.0.0-beta.49, @babel/helper-module-imports@npm:^7.18.6, @babel/helper-module-imports@npm:^7.22.5, @babel/helper-module-imports@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-module-imports@npm:7.24.7" @@ -371,6 +449,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-optimise-call-expression@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-optimise-call-expression@npm:7.25.7" + dependencies: + "@babel/types": "npm:^7.25.7" + checksum: 10c0/19b4cc7e77811b1fedca4928dbc14026afef913c2ba4142e5e110ebdcb5c3b2efc0f0fbee9f362c23a194674147b9d627adea71c289b9be08b9067bc0085308b + languageName: node + linkType: hard + "@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.16.7, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.18.9, @babel/helper-plugin-utils@npm:^7.20.2, @babel/helper-plugin-utils@npm:^7.21.5, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.24.8, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": version: 7.24.8 resolution: "@babel/helper-plugin-utils@npm:7.24.8" @@ -378,6 +465,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-plugin-utils@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-plugin-utils@npm:7.25.7" + checksum: 10c0/241f8cf3c5b7700e91cab7cfe5b432a3c710ae3cd5bb96dc554da536a6d25f5b9f000cc0c0917501ceb4f76ba92599ee3beb25e10adaf96be59f8df89a842faf + languageName: node + linkType: hard + "@babel/helper-remap-async-to-generator@npm:^7.18.9": version: 7.25.0 resolution: "@babel/helper-remap-async-to-generator@npm:7.25.0" @@ -404,6 +498,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-remap-async-to-generator@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-remap-async-to-generator@npm:7.25.7" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.25.7" + "@babel/helper-wrap-function": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/972d84876adce6ab61c87a2df47e1afc790b73cff0d1767d0a1c5d9f7aa5e91d8c581a272b66b2051a26cfbb167d8a780564705e488e3ce1f477f1c15059bc5f + languageName: node + linkType: hard + "@babel/helper-replace-supers@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-replace-supers@npm:7.24.7" @@ -430,6 +537,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-replace-supers@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-replace-supers@npm:7.25.7" + dependencies: + "@babel/helper-member-expression-to-functions": "npm:^7.25.7" + "@babel/helper-optimise-call-expression": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/761d64ee74429f7326a6aa65e2cd5bfcb8de9e3bc3f1efb14b8f610d2410f003b0fca52778dc801d49ff8fbc90b057e8f51b27c62b0b05c95eaf23140ca1287b + languageName: node + linkType: hard + "@babel/helper-simple-access@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-simple-access@npm:7.24.7" @@ -459,6 +579,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.25.7" + dependencies: + "@babel/traverse": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" + checksum: 10c0/5804adb893849a9d8cfb548e3812566a81d95cb0c9a10d66b52912d13f488e577c33063bf19bc06ac70e6333162a7370d67ba1a1c3544d37fb50d5f4a00db4de + languageName: node + linkType: hard + "@babel/helper-split-export-declaration@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-split-export-declaration@npm:7.24.7" @@ -503,6 +633,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-option@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-validator-option@npm:7.25.7" + checksum: 10c0/12ed418c8e3ed9ed44c8c80d823f4e42d399b5eb2e423adccb975e31a31a008cd3b5d8eab688b31f740caff4a1bb28fe06ea2fa7d635aee34cc0ad6995d50f0a + languageName: node + linkType: hard + "@babel/helper-wrap-function@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-wrap-function@npm:7.24.7" @@ -526,6 +663,17 @@ __metadata: languageName: node linkType: hard +"@babel/helper-wrap-function@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-wrap-function@npm:7.25.7" + dependencies: + "@babel/template": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" + checksum: 10c0/b5d412f72697f4a4ce4cb9784fbaf82501c63cf95066c0eadd3179e3439cbbf0aa5fa4858d93590083671943cd357aeb87286958df34aa56fdf8a4c9dea39755 + languageName: node + linkType: hard + "@babel/helpers@npm:^7.22.0, @babel/helpers@npm:^7.24.8": version: 7.24.8 resolution: "@babel/helpers@npm:7.24.8" @@ -548,6 +696,18 @@ __metadata: languageName: node linkType: hard +"@babel/highlight@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/highlight@npm:7.25.7" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.25.7" + chalk: "npm:^2.4.2" + js-tokens: "npm:^4.0.0" + picocolors: "npm:^1.0.0" + checksum: 10c0/1f5894fdb0a0af6101fb2822369b2eeeae32cbeae2ef73ff73fc6a0a4a20471565cd9cfa589f54ed69df66adeca7c57266031ca9134b7bd244d023a488d419aa + languageName: node + linkType: hard + "@babel/parser@npm:7.22.0": version: 7.22.0 resolution: "@babel/parser@npm:7.22.0" @@ -577,6 +737,17 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.25.7": + version: 7.25.8 + resolution: "@babel/parser@npm:7.25.8" + dependencies: + "@babel/types": "npm:^7.25.8" + bin: + parser: ./bin/babel-parser.js + checksum: 10c0/a1a13845b7e8dda4c970791814a4bbf60004969882f18f470e260ad822d2e1f8941948f851e9335895563610f240fa6c98481ce8019865e469502bbf21daafa4 + languageName: node + linkType: hard + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.24.7": version: 7.24.7 resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.24.7" @@ -1063,6 +1234,19 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-async-generator-functions@npm:^7.24.3": + version: 7.25.8 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.25.8" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-remap-async-to-generator": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/1698d0757d3dc895047120346cdbe6d539dae4a7bb930caf958c3623e89c850d378d1ebd971a1a8b4cba39c8f001cd9c25a1d6f430099022ab1e87aeddb5dd88 + languageName: node + linkType: hard + "@babel/plugin-transform-async-to-generator@npm:^7.20.0, @babel/plugin-transform-async-to-generator@npm:^7.20.7, @babel/plugin-transform-async-to-generator@npm:^7.24.7": version: 7.24.7 resolution: "@babel/plugin-transform-async-to-generator@npm:7.24.7" @@ -1110,6 +1294,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-class-properties@npm:^7.24.1": + version: 7.25.7 + resolution: "@babel/plugin-transform-class-properties@npm:7.25.7" + dependencies: + "@babel/helper-create-class-features-plugin": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/1f41e6934b20ad3e05df63959cff9bc600ff3119153b9acbbd44c1731e7df04866397e6e17799173f4c53cdee6115e155632859aee20bf47ec7dcef3f2168a47 + languageName: node + linkType: hard + "@babel/plugin-transform-class-static-block@npm:^7.22.0, @babel/plugin-transform-class-static-block@npm:^7.24.7": version: 7.24.7 resolution: "@babel/plugin-transform-class-static-block@npm:7.24.7" @@ -1251,6 +1447,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-for-of@npm:^7.0.0": + version: 7.25.7 + resolution: "@babel/plugin-transform-for-of@npm:7.25.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/08a37a1742368a422d095c998ed76f60f6bf3f9cc060033be121d803fd2dddc08fe543e48ee49c022bdc9ed80893ca79d084958d83d30684178b088774754277 + languageName: node + linkType: hard + "@babel/plugin-transform-for-of@npm:^7.21.5, @babel/plugin-transform-for-of@npm:^7.24.7": version: 7.24.7 resolution: "@babel/plugin-transform-for-of@npm:7.24.7" @@ -1311,6 +1519,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-logical-assignment-operators@npm:^7.24.1": + version: 7.25.8 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.25.8" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.25.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/9adc2634c94b283b682fbf71bbec553bd8448196213491a0ef9ea167993c9c36dcb2fbefbd834e113cfed843a67290131bc99e463f8702043c3f4e3a99bb807e + languageName: node + linkType: hard + "@babel/plugin-transform-member-expression-literals@npm:^7.18.6, @babel/plugin-transform-member-expression-literals@npm:^7.24.7": version: 7.24.7 resolution: "@babel/plugin-transform-member-expression-literals@npm:7.24.7" @@ -1408,6 +1627,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.24.1": + version: 7.25.8 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.25.8" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.25.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/3cb7c44cffccae42e104755acb31b4f00bc27d8c88102ae6f30dca508832f98fa5b746bead0fc7c0c6ddcf83f336829be4b64245c6c7ce26b3ef591937ec54a4 + languageName: node + linkType: hard + "@babel/plugin-transform-numeric-separator@npm:^7.22.0, @babel/plugin-transform-numeric-separator@npm:^7.24.7": version: 7.24.7 resolution: "@babel/plugin-transform-numeric-separator@npm:7.24.7" @@ -1420,6 +1650,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-numeric-separator@npm:^7.24.1": + version: 7.25.8 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.25.8" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.25.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/d23b3ebc50513f24510791ac2cad43e3c6ea08579f54dccfd4ed5e5d5084f02da0576ea42ea999fb51e1f94f42857cac96a1a29ac6728fc262fbe87ec966dc18 + languageName: node + linkType: hard + "@babel/plugin-transform-object-rest-spread@npm:^7.12.13, @babel/plugin-transform-object-rest-spread@npm:^7.22.0, @babel/plugin-transform-object-rest-spread@npm:^7.24.7": version: 7.24.7 resolution: "@babel/plugin-transform-object-rest-spread@npm:7.24.7" @@ -1434,6 +1675,19 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-object-rest-spread@npm:^7.24.5": + version: 7.25.8 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.25.8" + dependencies: + "@babel/helper-compilation-targets": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/plugin-transform-parameters": "npm:^7.25.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/058d5f5bb61068997fb78855011dd175d441da84717640852bbfd12a5919acf8d8c5a14c1debfe87d230f3f4c47c22fcad3d7fa1acd72e5e48b2fff93b6c1dd9 + languageName: node + linkType: hard + "@babel/plugin-transform-object-super@npm:^7.18.6, @babel/plugin-transform-object-super@npm:^7.24.7": version: 7.24.7 resolution: "@babel/plugin-transform-object-super@npm:7.24.7" @@ -1458,6 +1712,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-optional-catch-binding@npm:^7.24.1": + version: 7.25.8 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.25.8" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.25.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/f4360e62ca4aa998db31548d0ef06836d958bcb29dee58f5c62d0c29b6b2bff1b54871195bd032825fe3dd79a4fd8275e165148c8d4b57694bcf72135c8f7d24 + languageName: node + linkType: hard + "@babel/plugin-transform-optional-chaining@npm:^7.0.0-0, @babel/plugin-transform-optional-chaining@npm:^7.22.0, @babel/plugin-transform-optional-chaining@npm:^7.24.7, @babel/plugin-transform-optional-chaining@npm:^7.24.8": version: 7.24.8 resolution: "@babel/plugin-transform-optional-chaining@npm:7.24.8" @@ -1471,6 +1736,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-optional-chaining@npm:^7.24.5": + version: 7.25.8 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.25.8" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/a1cdbfc249619fa6b37e57f81600701281629d86a57e616b0c2b29816d0c43114a2296ce089564afd3aa7870c8aad62e907658ffef2c110662af14ee23d5247f + languageName: node + linkType: hard + "@babel/plugin-transform-parameters@npm:^7.0.0, @babel/plugin-transform-parameters@npm:^7.20.7, @babel/plugin-transform-parameters@npm:^7.22.0, @babel/plugin-transform-parameters@npm:^7.22.15, @babel/plugin-transform-parameters@npm:^7.24.7": version: 7.24.7 resolution: "@babel/plugin-transform-parameters@npm:7.24.7" @@ -1482,6 +1759,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-parameters@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-parameters@npm:7.25.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.25.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/b40ba70278842ce1e800d7ab400df730994941550da547ef453780023bd61a9b8acf4b9fb8419c1b5bcbe09819a1146ff59369db11db07eb71870bef86a12422 + languageName: node + linkType: hard + "@babel/plugin-transform-private-methods@npm:^7.22.0, @babel/plugin-transform-private-methods@npm:^7.22.5, @babel/plugin-transform-private-methods@npm:^7.24.7": version: 7.24.7 resolution: "@babel/plugin-transform-private-methods@npm:7.24.7" @@ -1617,6 +1905,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-regenerator@npm:^7.20.0": + version: 7.25.7 + resolution: "@babel/plugin-transform-regenerator@npm:7.25.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.25.7" + regenerator-transform: "npm:^0.15.2" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/7ee3a57c4050bc908ef7ac392d810826b294970a7182f4ec34a8ca93dbe36deb21bc862616d46a6f3d881d6b5749930e1679e875b638a00866d844a4250df212 + languageName: node + linkType: hard + "@babel/plugin-transform-regenerator@npm:^7.21.5, @babel/plugin-transform-regenerator@npm:^7.24.7": version: 7.24.7 resolution: "@babel/plugin-transform-regenerator@npm:7.24.7" @@ -2112,6 +2412,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/template@npm:7.25.7" + dependencies: + "@babel/code-frame": "npm:^7.25.7" + "@babel/parser": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" + checksum: 10c0/8ae9e36e4330ee83d4832531d1d9bec7dc2ef6a2a8afa1ef1229506fd60667abcb17f306d1c3d7e582251270597022990c845d5d69e7add70a5aea66720decb9 + languageName: node + linkType: hard + "@babel/traverse@npm:^7.1.6, @babel/traverse@npm:^7.2.3, @babel/traverse@npm:^7.20.0, @babel/traverse@npm:^7.22.0, @babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.24.8, @babel/traverse@npm:^7.4.5": version: 7.24.8 resolution: "@babel/traverse@npm:7.24.8" @@ -2145,6 +2456,21 @@ __metadata: languageName: node linkType: hard +"@babel/traverse@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/traverse@npm:7.25.7" + dependencies: + "@babel/code-frame": "npm:^7.25.7" + "@babel/generator": "npm:^7.25.7" + "@babel/parser": "npm:^7.25.7" + "@babel/template": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" + debug: "npm:^4.3.1" + globals: "npm:^11.1.0" + checksum: 10c0/75d73e52c507a7a7a4c7971d6bf4f8f26fdd094e0d3a0193d77edf6a5efa36fc3db91ec5cc48e8b94e6eb5d5ad21af0a1040e71309172851209415fd105efb1a + languageName: node + linkType: hard + "@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.1.6, @babel/types@npm:^7.18.9, @babel/types@npm:^7.20.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.0, @babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.24.9, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": version: 7.24.9 resolution: "@babel/types@npm:7.24.9" @@ -2189,6 +2515,17 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.25.7, @babel/types@npm:^7.25.8": + version: 7.25.8 + resolution: "@babel/types@npm:7.25.8" + dependencies: + "@babel/helper-string-parser": "npm:^7.25.7" + "@babel/helper-validator-identifier": "npm:^7.25.7" + to-fast-properties: "npm:^2.0.0" + checksum: 10c0/55ca2d6df6426c98db2769ce884ce5e9de83a512ea2dd7bcf56c811984dc14351cacf42932a723630c5afcff2455809323decd645820762182f10b7b5252b59f + languageName: node + linkType: hard + "@bankify/react-native-animate-number@npm:0.2.1": version: 0.2.1 resolution: "@bankify/react-native-animate-number@npm:0.2.1" @@ -5496,6 +5833,18 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-clean@npm:14.1.0": + version: 14.1.0 + resolution: "@react-native-community/cli-clean@npm:14.1.0" + dependencies: + "@react-native-community/cli-tools": "npm:14.1.0" + chalk: "npm:^4.1.2" + execa: "npm:^5.0.0" + fast-glob: "npm:^3.3.2" + checksum: 10c0/57ed359c11b5f58da61ca22213394d56db815538d0df459a99017fb38450d35b6ef5c0ccc997c48c34160fc08898147593d7cd1e8ab78b3cea988020d0d6ce88 + languageName: node + linkType: hard + "@react-native-community/cli-config@npm:13.6.9": version: 13.6.9 resolution: "@react-native-community/cli-config@npm:13.6.9" @@ -5510,6 +5859,20 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-config@npm:14.1.0": + version: 14.1.0 + resolution: "@react-native-community/cli-config@npm:14.1.0" + dependencies: + "@react-native-community/cli-tools": "npm:14.1.0" + chalk: "npm:^4.1.2" + cosmiconfig: "npm:^9.0.0" + deepmerge: "npm:^4.3.0" + fast-glob: "npm:^3.3.2" + joi: "npm:^17.2.1" + checksum: 10c0/3e4ebea0eb17e52c42e5d60eb9219c84f2cf8d804bc083ae483ffae504bf0c6077c5e859c72311caa319f0dc8d2fc4b69c4230ee3aba5e9f2c1c0461c9c538ea + languageName: node + linkType: hard + "@react-native-community/cli-debugger-ui@npm:13.6.9": version: 13.6.9 resolution: "@react-native-community/cli-debugger-ui@npm:13.6.9" @@ -5519,6 +5882,15 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-debugger-ui@npm:14.1.0": + version: 14.1.0 + resolution: "@react-native-community/cli-debugger-ui@npm:14.1.0" + dependencies: + serve-static: "npm:^1.13.1" + checksum: 10c0/e673412c042ed2c40e06b59e85c9964303384d69547b13a7e093ad53a8ddc9a9df4cf0ba647b645601e362bb37c2d8bd8616097e6e880c4da04df1dd1f22d87e + languageName: node + linkType: hard + "@react-native-community/cli-doctor@npm:13.6.9": version: 13.6.9 resolution: "@react-native-community/cli-doctor@npm:13.6.9" @@ -5544,6 +5916,30 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-doctor@npm:14.1.0": + version: 14.1.0 + resolution: "@react-native-community/cli-doctor@npm:14.1.0" + dependencies: + "@react-native-community/cli-config": "npm:14.1.0" + "@react-native-community/cli-platform-android": "npm:14.1.0" + "@react-native-community/cli-platform-apple": "npm:14.1.0" + "@react-native-community/cli-platform-ios": "npm:14.1.0" + "@react-native-community/cli-tools": "npm:14.1.0" + chalk: "npm:^4.1.2" + command-exists: "npm:^1.2.8" + deepmerge: "npm:^4.3.0" + envinfo: "npm:^7.13.0" + execa: "npm:^5.0.0" + node-stream-zip: "npm:^1.9.1" + ora: "npm:^5.4.1" + semver: "npm:^7.5.2" + strip-ansi: "npm:^5.2.0" + wcwidth: "npm:^1.0.1" + yaml: "npm:^2.2.1" + checksum: 10c0/4293e05195deb6d5e920317874c27dd0f7a39da0f7c5152f7e72187d92b1915d576929d069c3e92869d474a1ae36d2a77b9e298b378019519b112384308f5240 + languageName: node + linkType: hard + "@react-native-community/cli-hermes@npm:13.6.9": version: 13.6.9 resolution: "@react-native-community/cli-hermes@npm:13.6.9" @@ -5570,6 +5966,20 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-platform-android@npm:14.1.0": + version: 14.1.0 + resolution: "@react-native-community/cli-platform-android@npm:14.1.0" + dependencies: + "@react-native-community/cli-tools": "npm:14.1.0" + chalk: "npm:^4.1.2" + execa: "npm:^5.0.0" + fast-glob: "npm:^3.3.2" + fast-xml-parser: "npm:^4.4.1" + logkitty: "npm:^0.7.1" + checksum: 10c0/634b0303e783c0e481b03af0a4223bf70b98d09fdada69b10a820d9d637ba76f1674451be13aaf78bbb9a094e7a2cd59cc7b840b5a4ea73ba9b8a32e7480f778 + languageName: node + linkType: hard + "@react-native-community/cli-platform-apple@npm:13.6.9": version: 13.6.9 resolution: "@react-native-community/cli-platform-apple@npm:13.6.9" @@ -5584,6 +5994,20 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-platform-apple@npm:14.1.0": + version: 14.1.0 + resolution: "@react-native-community/cli-platform-apple@npm:14.1.0" + dependencies: + "@react-native-community/cli-tools": "npm:14.1.0" + chalk: "npm:^4.1.2" + execa: "npm:^5.0.0" + fast-glob: "npm:^3.3.2" + fast-xml-parser: "npm:^4.4.1" + ora: "npm:^5.4.1" + checksum: 10c0/04c15a024b99a17a0f7fe75dcf2c454d541021950e4fbff494a2ced11654ee9f2a49944f5a6d1c0329abd33a0a95c3f5b58a11d3790968c93f9f1dc769c517a3 + languageName: node + linkType: hard + "@react-native-community/cli-platform-ios@npm:13.6.9": version: 13.6.9 resolution: "@react-native-community/cli-platform-ios@npm:13.6.9" @@ -5593,6 +6017,15 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-platform-ios@npm:14.1.0": + version: 14.1.0 + resolution: "@react-native-community/cli-platform-ios@npm:14.1.0" + dependencies: + "@react-native-community/cli-platform-apple": "npm:14.1.0" + checksum: 10c0/67f89496fe4405dc055ab478e9331ca8c34687f2983bb421188834e1ef9877c1e47fb420f58eb6d4df3088cd64454eb6b3af1c9c02c771f654443fae3033d515 + languageName: node + linkType: hard + "@react-native-community/cli-server-api@npm:13.6.9": version: 13.6.9 resolution: "@react-native-community/cli-server-api@npm:13.6.9" @@ -5610,6 +6043,23 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-server-api@npm:14.1.0": + version: 14.1.0 + resolution: "@react-native-community/cli-server-api@npm:14.1.0" + dependencies: + "@react-native-community/cli-debugger-ui": "npm:14.1.0" + "@react-native-community/cli-tools": "npm:14.1.0" + compression: "npm:^1.7.1" + connect: "npm:^3.6.5" + errorhandler: "npm:^1.5.1" + nocache: "npm:^3.0.1" + pretty-format: "npm:^26.6.2" + serve-static: "npm:^1.13.1" + ws: "npm:^6.2.3" + checksum: 10c0/e79ba3311b70661bdabfdfa4d5f6a4737081140332093811ea67cee38ac15b835e829830e996a105842cf166fa0dc4c9d697fff34c8f48ca69490b40651b21ac + languageName: node + linkType: hard + "@react-native-community/cli-tools@npm:13.6.9": version: 13.6.9 resolution: "@react-native-community/cli-tools@npm:13.6.9" @@ -5629,6 +6079,24 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-tools@npm:14.1.0": + version: 14.1.0 + resolution: "@react-native-community/cli-tools@npm:14.1.0" + dependencies: + appdirsjs: "npm:^1.2.4" + chalk: "npm:^4.1.2" + execa: "npm:^5.0.0" + find-up: "npm:^5.0.0" + mime: "npm:^2.4.1" + open: "npm:^6.2.0" + ora: "npm:^5.4.1" + semver: "npm:^7.5.2" + shell-quote: "npm:^1.7.3" + sudo-prompt: "npm:^9.0.0" + checksum: 10c0/982fff928966f44db88bb1e2b968cf9908b4156570bd2a8f71d087c9b64c3840e92db4e5217d3c787b1ffd57c3fd1c79aab5f81611e8862f75e22c4e49b7b322 + languageName: node + linkType: hard + "@react-native-community/cli-types@npm:13.6.9": version: 13.6.9 resolution: "@react-native-community/cli-types@npm:13.6.9" @@ -5638,6 +6106,15 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli-types@npm:14.1.0": + version: 14.1.0 + resolution: "@react-native-community/cli-types@npm:14.1.0" + dependencies: + joi: "npm:^17.2.1" + checksum: 10c0/bb7acced460cc73b3c849f07df52794c4be7845669adb97834b0b715c325266bec9cfefd89b4ac8d31a464073790d99bc624f1454d3579630a36dd9502033b36 + languageName: node + linkType: hard + "@react-native-community/cli@npm:13.6.9": version: 13.6.9 resolution: "@react-native-community/cli@npm:13.6.9" @@ -5665,6 +6142,32 @@ __metadata: languageName: node linkType: hard +"@react-native-community/cli@npm:14.1.0": + version: 14.1.0 + resolution: "@react-native-community/cli@npm:14.1.0" + dependencies: + "@react-native-community/cli-clean": "npm:14.1.0" + "@react-native-community/cli-config": "npm:14.1.0" + "@react-native-community/cli-debugger-ui": "npm:14.1.0" + "@react-native-community/cli-doctor": "npm:14.1.0" + "@react-native-community/cli-server-api": "npm:14.1.0" + "@react-native-community/cli-tools": "npm:14.1.0" + "@react-native-community/cli-types": "npm:14.1.0" + chalk: "npm:^4.1.2" + commander: "npm:^9.4.1" + deepmerge: "npm:^4.3.0" + execa: "npm:^5.0.0" + find-up: "npm:^5.0.0" + fs-extra: "npm:^8.1.0" + graceful-fs: "npm:^4.1.3" + prompts: "npm:^2.4.2" + semver: "npm:^7.5.2" + bin: + rnc-cli: build/bin.js + checksum: 10c0/6f9cbba7d0f8c851333efc286fb469c59c61c7b5ce79dcfa4d6a4b205e917e99d0df0174db73b9f37b4160935b73d523cfd34b82e5171f8cca16b1e52d2525c4 + languageName: node + linkType: hard + "@react-native-community/netinfo@npm:9.0.0": version: 9.0.0 resolution: "@react-native-community/netinfo@npm:9.0.0" @@ -5741,6 +6244,13 @@ __metadata: languageName: node linkType: hard +"@react-native/assets-registry@npm:0.75.4": + version: 0.75.4 + resolution: "@react-native/assets-registry@npm:0.75.4" + checksum: 10c0/5669e8700cb8b1bed8878dc6d6a869a54c7157f60dc88b85556db48cabc65414b87f01995244dc5532009cc860adfa1f86b57415c810fe10806f8fc085b3673f + languageName: node + linkType: hard + "@react-native/babel-plugin-codegen@npm:0.74.83": version: 0.74.83 resolution: "@react-native/babel-plugin-codegen@npm:0.74.83" @@ -5768,6 +6278,15 @@ __metadata: languageName: node linkType: hard +"@react-native/babel-plugin-codegen@npm:0.75.4": + version: 0.75.4 + resolution: "@react-native/babel-plugin-codegen@npm:0.75.4" + dependencies: + "@react-native/codegen": "npm:0.75.4" + checksum: 10c0/ceac60a2a33a7e75e9c2f0045d738516769128d0358de35091d1ef23bbb5a391a2f7937781532c61f427e18a76038566dc804d46bdd0d68314619920e23153b0 + languageName: node + linkType: hard + "@react-native/babel-preset@npm:0.74.83": version: 0.74.83 resolution: "@react-native/babel-preset@npm:0.74.83" @@ -5927,6 +6446,61 @@ __metadata: languageName: node linkType: hard +"@react-native/babel-preset@npm:0.75.4": + version: 0.75.4 + resolution: "@react-native/babel-preset@npm:0.75.4" + dependencies: + "@babel/core": "npm:^7.20.0" + "@babel/plugin-proposal-export-default-from": "npm:^7.0.0" + "@babel/plugin-syntax-dynamic-import": "npm:^7.8.0" + "@babel/plugin-syntax-export-default-from": "npm:^7.0.0" + "@babel/plugin-syntax-flow": "npm:^7.18.0" + "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.0.0" + "@babel/plugin-syntax-optional-chaining": "npm:^7.0.0" + "@babel/plugin-transform-arrow-functions": "npm:^7.0.0" + "@babel/plugin-transform-async-generator-functions": "npm:^7.24.3" + "@babel/plugin-transform-async-to-generator": "npm:^7.20.0" + "@babel/plugin-transform-block-scoping": "npm:^7.0.0" + "@babel/plugin-transform-class-properties": "npm:^7.24.1" + "@babel/plugin-transform-classes": "npm:^7.0.0" + "@babel/plugin-transform-computed-properties": "npm:^7.0.0" + "@babel/plugin-transform-destructuring": "npm:^7.20.0" + "@babel/plugin-transform-flow-strip-types": "npm:^7.20.0" + "@babel/plugin-transform-for-of": "npm:^7.0.0" + "@babel/plugin-transform-function-name": "npm:^7.0.0" + "@babel/plugin-transform-literals": "npm:^7.0.0" + "@babel/plugin-transform-logical-assignment-operators": "npm:^7.24.1" + "@babel/plugin-transform-modules-commonjs": "npm:^7.0.0" + "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.0.0" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.24.1" + "@babel/plugin-transform-numeric-separator": "npm:^7.24.1" + "@babel/plugin-transform-object-rest-spread": "npm:^7.24.5" + "@babel/plugin-transform-optional-catch-binding": "npm:^7.24.1" + "@babel/plugin-transform-optional-chaining": "npm:^7.24.5" + "@babel/plugin-transform-parameters": "npm:^7.0.0" + "@babel/plugin-transform-private-methods": "npm:^7.22.5" + "@babel/plugin-transform-private-property-in-object": "npm:^7.22.11" + "@babel/plugin-transform-react-display-name": "npm:^7.0.0" + "@babel/plugin-transform-react-jsx": "npm:^7.0.0" + "@babel/plugin-transform-react-jsx-self": "npm:^7.0.0" + "@babel/plugin-transform-react-jsx-source": "npm:^7.0.0" + "@babel/plugin-transform-regenerator": "npm:^7.20.0" + "@babel/plugin-transform-runtime": "npm:^7.0.0" + "@babel/plugin-transform-shorthand-properties": "npm:^7.0.0" + "@babel/plugin-transform-spread": "npm:^7.0.0" + "@babel/plugin-transform-sticky-regex": "npm:^7.0.0" + "@babel/plugin-transform-typescript": "npm:^7.5.0" + "@babel/plugin-transform-unicode-regex": "npm:^7.0.0" + "@babel/template": "npm:^7.0.0" + "@react-native/babel-plugin-codegen": "npm:0.75.4" + babel-plugin-transform-flow-enums: "npm:^0.0.2" + react-refresh: "npm:^0.14.0" + peerDependencies: + "@babel/core": "*" + checksum: 10c0/adf81e70813abd82c3ff2b0bccef100667ca33c197aa473aafec0e88d1e9c4d6d05f6f90004947f36fa1a199e9a4b9afa8c7876e9b6614e55881475c80b6bf28 + languageName: node + linkType: hard + "@react-native/codegen@npm:0.74.83": version: 0.74.83 resolution: "@react-native/codegen@npm:0.74.83" @@ -5978,6 +6552,24 @@ __metadata: languageName: node linkType: hard +"@react-native/codegen@npm:0.75.4": + version: 0.75.4 + resolution: "@react-native/codegen@npm:0.75.4" + dependencies: + "@babel/parser": "npm:^7.20.0" + glob: "npm:^7.1.1" + hermes-parser: "npm:0.22.0" + invariant: "npm:^2.2.4" + jscodeshift: "npm:^0.14.0" + mkdirp: "npm:^0.5.1" + nullthrows: "npm:^1.1.1" + yargs: "npm:^17.6.2" + peerDependencies: + "@babel/preset-env": ^7.1.6 + checksum: 10c0/49149c2b07c2c142abe0eb6459face50f7ffa5d7b0db29075ea5243b6e6c546087968c4e80b789a9a39d0bf9050495f0d620b1d3544d8b4bed2682b3d8f48bc2 + languageName: node + linkType: hard + "@react-native/community-cli-plugin@npm:0.74.85": version: 0.74.85 resolution: "@react-native/community-cli-plugin@npm:0.74.85" @@ -5998,6 +6590,25 @@ __metadata: languageName: node linkType: hard +"@react-native/community-cli-plugin@npm:0.75.4": + version: 0.75.4 + resolution: "@react-native/community-cli-plugin@npm:0.75.4" + dependencies: + "@react-native-community/cli-server-api": "npm:14.1.0" + "@react-native-community/cli-tools": "npm:14.1.0" + "@react-native/dev-middleware": "npm:0.75.4" + "@react-native/metro-babel-transformer": "npm:0.75.4" + chalk: "npm:^4.0.0" + execa: "npm:^5.1.1" + metro: "npm:^0.80.3" + metro-config: "npm:^0.80.3" + metro-core: "npm:^0.80.3" + node-fetch: "npm:^2.2.0" + readline: "npm:^1.3.0" + checksum: 10c0/f51cc82a6ef722a3c1866181823a3047c78b80fb40c33f47420b31ee155a42a4683fe53e3221f4d5f3d3ba471c8575db5dbb2efbbce74341df2eb8c7aa2b9aa9 + languageName: node + linkType: hard + "@react-native/debugger-frontend@npm:0.74.85": version: 0.74.85 resolution: "@react-native/debugger-frontend@npm:0.74.85" @@ -6005,6 +6616,13 @@ __metadata: languageName: node linkType: hard +"@react-native/debugger-frontend@npm:0.75.4": + version: 0.75.4 + resolution: "@react-native/debugger-frontend@npm:0.75.4" + checksum: 10c0/189ba0711a59bf1a23b0a72c0f2485b7a634089c09912af429e93ab2849c228350d42d0b29570feb70417e9eaab41bcd5e20c7bf0c7a9a8949d62d9e19c26a4f + languageName: node + linkType: hard + "@react-native/dev-middleware@npm:0.74.85": version: 0.74.85 resolution: "@react-native/dev-middleware@npm:0.74.85" @@ -6026,6 +6644,26 @@ __metadata: languageName: node linkType: hard +"@react-native/dev-middleware@npm:0.75.4": + version: 0.75.4 + resolution: "@react-native/dev-middleware@npm:0.75.4" + dependencies: + "@isaacs/ttlcache": "npm:^1.4.1" + "@react-native/debugger-frontend": "npm:0.75.4" + chrome-launcher: "npm:^0.15.2" + chromium-edge-launcher: "npm:^0.2.0" + connect: "npm:^3.6.5" + debug: "npm:^2.2.0" + node-fetch: "npm:^2.2.0" + nullthrows: "npm:^1.1.1" + open: "npm:^7.0.3" + selfsigned: "npm:^2.4.1" + serve-static: "npm:^1.13.1" + ws: "npm:^6.2.2" + checksum: 10c0/edeb979f4acf7102b92ffc9c6ec47f9221fd044ff00a42e8d3af06d79f09635e6e5fd7bb6b686c87bc8d09c5d62265f3d89f137f659ce708b258c5775e8b1e16 + languageName: node + linkType: hard + "@react-native/gradle-plugin@npm:0.74.85": version: 0.74.85 resolution: "@react-native/gradle-plugin@npm:0.74.85" @@ -6033,6 +6671,13 @@ __metadata: languageName: node linkType: hard +"@react-native/gradle-plugin@npm:0.75.4": + version: 0.75.4 + resolution: "@react-native/gradle-plugin@npm:0.75.4" + checksum: 10c0/0a0fd65c6c1fad34f5ff82db5ccd99401cfd5ff476efcad069dc16b6daecd685d2fe73a7c4bcb912a69574ddd723d53cdca3cc4da6b34ffd9a9a33e3cf436e6e + languageName: node + linkType: hard + "@react-native/js-polyfills@npm:0.74.83": version: 0.74.83 resolution: "@react-native/js-polyfills@npm:0.74.83" @@ -6047,6 +6692,13 @@ __metadata: languageName: node linkType: hard +"@react-native/js-polyfills@npm:0.75.4": + version: 0.75.4 + resolution: "@react-native/js-polyfills@npm:0.75.4" + checksum: 10c0/46c0c455e805d07ab6d55a162fdfbcacab6e0ae5d83e93f146556b780f05e28839156c28f5ba838232e598d41893297d015823b7f154b2ac9db3af757d4b6c71 + languageName: node + linkType: hard + "@react-native/metro-babel-transformer@npm:0.74.83": version: 0.74.83 resolution: "@react-native/metro-babel-transformer@npm:0.74.83" @@ -6075,6 +6727,20 @@ __metadata: languageName: node linkType: hard +"@react-native/metro-babel-transformer@npm:0.75.4": + version: 0.75.4 + resolution: "@react-native/metro-babel-transformer@npm:0.75.4" + dependencies: + "@babel/core": "npm:^7.20.0" + "@react-native/babel-preset": "npm:0.75.4" + hermes-parser: "npm:0.22.0" + nullthrows: "npm:^1.1.1" + peerDependencies: + "@babel/core": "*" + checksum: 10c0/455f21645e0e9a32e4400a423b896b12503a64a6feca7edea2c9d27608963cc4d283c41156a48b31b15d8662f645c9f1d16cdb449a1b1096bdc90985edf17027 + languageName: node + linkType: hard + "@react-native/metro-config@npm:0.74.83": version: 0.74.83 resolution: "@react-native/metro-config@npm:0.74.83" @@ -6101,6 +6767,13 @@ __metadata: languageName: node linkType: hard +"@react-native/normalize-colors@npm:0.75.4": + version: 0.75.4 + resolution: "@react-native/normalize-colors@npm:0.75.4" + checksum: 10c0/b8224cf53f6baff67c50156766e1d01807058ac8efe3e114c97acab4d83bdad446ee05e80ce294dc0f62761dd54a473fd27be2e9bc5544dc09db263238d34b45 + languageName: node + linkType: hard + "@react-native/typescript-config@npm:0.74.83": version: 0.74.83 resolution: "@react-native/typescript-config@npm:0.74.83" @@ -6125,6 +6798,23 @@ __metadata: languageName: node linkType: hard +"@react-native/virtualized-lists@npm:0.75.4": + version: 0.75.4 + resolution: "@react-native/virtualized-lists@npm:0.75.4" + dependencies: + invariant: "npm:^2.2.4" + nullthrows: "npm:^1.1.1" + peerDependencies: + "@types/react": ^18.2.6 + react: "*" + react-native: "*" + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/816c4df3ecbca2ab03e8f5dc5047bfd49160f9ab8879d9cc6bb420f764a4d58bef208a2e198edee33cbeae21cf1a8a71738fc9f8b1e3f43e036ac4fad673bddc + languageName: node + linkType: hard + "@react-native/virtualized-lists@npm:^0.72.4": version: 0.72.8 resolution: "@react-native/virtualized-lists@npm:0.72.8" @@ -7608,6 +8298,16 @@ __metadata: languageName: node linkType: hard +"@types/react-native-indicators@npm:0.16.6": + version: 0.16.6 + resolution: "@types/react-native-indicators@npm:0.16.6" + dependencies: + "@types/react": "npm:*" + react-native: "npm:*" + checksum: 10c0/057d4f68be6143e44cfed622728c66f577b4fae48034da9922475cf81b895077e0ee325c76b10f4361bd17a6eb71cabcf2c8bc61413e30767a498bfb3c80fee0 + languageName: node + linkType: hard + "@types/react-native@npm:*": version: 0.72.8 resolution: "@types/react-native@npm:0.72.8" @@ -9044,6 +9744,7 @@ __metadata: "@types/qs": "npm:6.9.7" "@types/react": "npm:18.2.65" "@types/react-native-extra-dimensions-android": "npm:1.2.3" + "@types/react-native-indicators": "npm:0.16.6" "@types/react-redux": "npm:7.1.9" "@types/react-test-renderer": "npm:18.3.0" "@types/styled-components": "npm:5.1.7" @@ -10916,6 +11617,20 @@ __metadata: languageName: node linkType: hard +"browserslist@npm:^4.24.0": + version: 4.24.0 + resolution: "browserslist@npm:4.24.0" + dependencies: + caniuse-lite: "npm:^1.0.30001663" + electron-to-chromium: "npm:^1.5.28" + node-releases: "npm:^2.0.18" + update-browserslist-db: "npm:^1.1.0" + bin: + browserslist: cli.js + checksum: 10c0/95e76ad522753c4c470427f6e3c8a4bb5478ff448841e22b3d3e53f89ecaf17b6984666d6c7e715c370f1e7fa0cf684f42e34e554236a8b2fab38ea76b9e4c52 + languageName: node + linkType: hard + "bs-logger@npm:0.x": version: 0.2.6 resolution: "bs-logger@npm:0.2.6" @@ -11279,6 +11994,13 @@ __metadata: languageName: node linkType: hard +"caniuse-lite@npm:^1.0.30001663": + version: 1.0.30001667 + resolution: "caniuse-lite@npm:1.0.30001667" + checksum: 10c0/6bc8555a47603e1e76eaef9b185d6fdeeca7d9c20a283f7c32c971eb1b52ea3a80e6ec086920f088f06abe619240f1023a2d3a08b5b1f2f11df1475695e9f71c + languageName: node + linkType: hard + "canvaskit-wasm@npm:0.39.1": version: 0.39.1 resolution: "canvaskit-wasm@npm:0.39.1" @@ -11477,6 +12199,20 @@ __metadata: languageName: node linkType: hard +"chromium-edge-launcher@npm:^0.2.0": + version: 0.2.0 + resolution: "chromium-edge-launcher@npm:0.2.0" + dependencies: + "@types/node": "npm:*" + escape-string-regexp: "npm:^4.0.0" + is-wsl: "npm:^2.2.0" + lighthouse-logger: "npm:^1.0.0" + mkdirp: "npm:^1.0.4" + rimraf: "npm:^3.0.2" + checksum: 10c0/880972816dd9b95c0eb77d1f707569667a8cce7cc29fe9c8d199c47fdfbe4971e9da3e5a29f61c4ecec29437ac7cebbbb5afc30bec96306579d1121e7340606a + languageName: node + linkType: hard + "ci-info@npm:^2.0.0": version: 2.0.0 resolution: "ci-info@npm:2.0.0" @@ -12157,6 +12893,23 @@ __metadata: languageName: node linkType: hard +"cosmiconfig@npm:^9.0.0": + version: 9.0.0 + resolution: "cosmiconfig@npm:9.0.0" + dependencies: + env-paths: "npm:^2.2.1" + import-fresh: "npm:^3.3.0" + js-yaml: "npm:^4.1.0" + parse-json: "npm:^5.2.0" + peerDependencies: + typescript: ">=4.9.5" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/1c1703be4f02a250b1d6ca3267e408ce16abfe8364193891afc94c2d5c060b69611fdc8d97af74b7e6d5d1aac0ab2fb94d6b079573146bc2d756c2484ce5f0ee + languageName: node + linkType: hard + "crc-32@npm:^1.2.0": version: 1.2.2 resolution: "crc-32@npm:1.2.2" @@ -13460,6 +14213,13 @@ __metadata: languageName: node linkType: hard +"electron-to-chromium@npm:^1.5.28": + version: 1.5.35 + resolution: "electron-to-chromium@npm:1.5.35" + checksum: 10c0/49f7921dbdee725284898728a0ba4a786ab27a145a871057b7085f5643df51d7be3ece5374a105cc621417abb1bca780365a058a0531083d0252347b75cf0f3f + languageName: node + linkType: hard + "elliptic@npm:6.5.4": version: 6.5.4 resolution: "elliptic@npm:6.5.4" @@ -13668,14 +14428,14 @@ __metadata: languageName: node linkType: hard -"env-paths@npm:^2.2.0": +"env-paths@npm:^2.2.0, env-paths@npm:^2.2.1": version: 2.2.1 resolution: "env-paths@npm:2.2.1" checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 languageName: node linkType: hard -"envinfo@npm:^7.10.0": +"envinfo@npm:^7.10.0, envinfo@npm:^7.13.0": version: 7.14.0 resolution: "envinfo@npm:7.14.0" bin: @@ -14946,7 +15706,7 @@ __metadata: languageName: node linkType: hard -"fast-xml-parser@npm:^4.0.12, fast-xml-parser@npm:^4.2.4": +"fast-xml-parser@npm:^4.0.12, fast-xml-parser@npm:^4.2.4, fast-xml-parser@npm:^4.4.1": version: 4.5.0 resolution: "fast-xml-parser@npm:4.5.0" dependencies: @@ -16416,6 +17176,13 @@ __metadata: languageName: node linkType: hard +"hermes-estree@npm:0.22.0": + version: 0.22.0 + resolution: "hermes-estree@npm:0.22.0" + checksum: 10c0/4e39ea6b7032568c2d314268e0cbe807b0d004fa397886d8416b1b695bfa477bd4571617b03f24845228e747554491f4bfb13bbb0e289659d7c57ea02273c050 + languageName: node + linkType: hard + "hermes-parser@npm:0.19.1": version: 0.19.1 resolution: "hermes-parser@npm:0.19.1" @@ -16434,6 +17201,15 @@ __metadata: languageName: node linkType: hard +"hermes-parser@npm:0.22.0": + version: 0.22.0 + resolution: "hermes-parser@npm:0.22.0" + dependencies: + hermes-estree: "npm:0.22.0" + checksum: 10c0/095fad12ccd21ed151494c61b5b900abde78d89579e34c1748a526eed0f64657bee2cd3f30ae270881092d8f244e3386266b78496b866428b7d215fa13daef1e + languageName: node + linkType: hard + "hermes-profile-transformer@npm:^0.0.6": version: 0.0.6 resolution: "hermes-profile-transformer@npm:0.0.6" @@ -16760,7 +17536,7 @@ __metadata: languageName: node linkType: hard -"import-fresh@npm:^3.0.0, import-fresh@npm:^3.2.1": +"import-fresh@npm:^3.0.0, import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0": version: 3.3.0 resolution: "import-fresh@npm:3.3.0" dependencies: @@ -18432,6 +19208,15 @@ __metadata: languageName: node linkType: hard +"jsesc@npm:^3.0.2": + version: 3.0.2 + resolution: "jsesc@npm:3.0.2" + bin: + jsesc: bin/jsesc + checksum: 10c0/ef22148f9e793180b14d8a145ee6f9f60f301abf443288117b4b6c53d0ecd58354898dc506ccbb553a5f7827965cd38bc5fb726575aae93c5e8915e2de8290e1 + languageName: node + linkType: hard + "jsesc@npm:~0.5.0": version: 0.5.0 resolution: "jsesc@npm:0.5.0" @@ -20872,6 +21657,13 @@ __metadata: languageName: node linkType: hard +"node-releases@npm:^2.0.18": + version: 2.0.18 + resolution: "node-releases@npm:2.0.18" + checksum: 10c0/786ac9db9d7226339e1dc84bbb42007cb054a346bd9257e6aa154d294f01bc6a6cddb1348fa099f079be6580acbb470e3c048effd5f719325abd0179e566fd27 + languageName: node + linkType: hard + "node-source-walk@npm:^4.0.0, node-source-walk@npm:^4.2.0, node-source-walk@npm:^4.2.2": version: 4.3.0 resolution: "node-source-walk@npm:4.3.0" @@ -23551,6 +24343,61 @@ react-native-safe-area-view@rainbow-me/react-native-safe-area-view: languageName: node linkType: hard +"react-native@npm:*": + version: 0.75.4 + resolution: "react-native@npm:0.75.4" + dependencies: + "@jest/create-cache-key-function": "npm:^29.6.3" + "@react-native-community/cli": "npm:14.1.0" + "@react-native-community/cli-platform-android": "npm:14.1.0" + "@react-native-community/cli-platform-ios": "npm:14.1.0" + "@react-native/assets-registry": "npm:0.75.4" + "@react-native/codegen": "npm:0.75.4" + "@react-native/community-cli-plugin": "npm:0.75.4" + "@react-native/gradle-plugin": "npm:0.75.4" + "@react-native/js-polyfills": "npm:0.75.4" + "@react-native/normalize-colors": "npm:0.75.4" + "@react-native/virtualized-lists": "npm:0.75.4" + abort-controller: "npm:^3.0.0" + anser: "npm:^1.4.9" + ansi-regex: "npm:^5.0.0" + base64-js: "npm:^1.5.1" + chalk: "npm:^4.0.0" + commander: "npm:^9.4.1" + event-target-shim: "npm:^5.0.1" + flow-enums-runtime: "npm:^0.0.6" + glob: "npm:^7.1.1" + invariant: "npm:^2.2.4" + jest-environment-node: "npm:^29.6.3" + jsc-android: "npm:^250231.0.0" + memoize-one: "npm:^5.0.0" + metro-runtime: "npm:^0.80.3" + metro-source-map: "npm:^0.80.3" + mkdirp: "npm:^0.5.1" + nullthrows: "npm:^1.1.1" + pretty-format: "npm:^26.5.2" + promise: "npm:^8.3.0" + react-devtools-core: "npm:^5.3.1" + react-refresh: "npm:^0.14.0" + regenerator-runtime: "npm:^0.13.2" + scheduler: "npm:0.24.0-canary-efb381bbf-20230505" + semver: "npm:^7.1.3" + stacktrace-parser: "npm:^0.1.10" + whatwg-fetch: "npm:^3.0.0" + ws: "npm:^6.2.2" + yargs: "npm:^17.6.2" + peerDependencies: + "@types/react": ^18.2.6 + react: ^18.2.0 + peerDependenciesMeta: + "@types/react": + optional: true + bin: + react-native: cli.js + checksum: 10c0/e368c7257cb16e3501975c2cf7d1168b3878724e83042d21ea796f91363892a2c0fcafc85864322ec241ed89c1e62fdaa2688265a84da335b6e66d76406b7a71 + languageName: node + linkType: hard + "react-native@npm:0.74.3": version: 0.74.3 resolution: "react-native@npm:0.74.3" @@ -24837,7 +25684,7 @@ react-native-safe-area-view@rainbow-me/react-native-safe-area-view: languageName: node linkType: hard -"semver@npm:^7.0.0, semver@npm:^7.2.1, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": +"semver@npm:^7.0.0, semver@npm:^7.1.3, semver@npm:^7.2.1, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": version: 7.6.3 resolution: "semver@npm:7.6.3" bin: @@ -28287,7 +29134,7 @@ react-native-safe-area-view@rainbow-me/react-native-safe-area-view: languageName: node linkType: hard -"ws@npm:^6.2.2": +"ws@npm:^6.2.2, ws@npm:^6.2.3": version: 6.2.3 resolution: "ws@npm:6.2.3" dependencies: