Skip to content

Commit

Permalink
[CHORE]: Remove transaction inconsistencies and improve type safety (#…
Browse files Browse the repository at this point in the history
…6137)

* lots of typescript improvements

* lots of deduping of types and consolidation of files

* more cleanup and move to enums for flashbots

* good lord

* Update src/entities/transactions/transaction.ts

* Update src/raps/references.ts

* fix issue with ref old txn types

* Update src/screens/transaction-details/components/TransactionMasthead.tsx

* code review changes

* alpabetize images and tslint fix

* some minor changes to provider and parsers
  • Loading branch information
walmat authored Oct 10, 2024
1 parent 51c1d0a commit 3ac1661
Show file tree
Hide file tree
Showing 61 changed files with 1,653 additions and 1,106 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
23 changes: 12 additions & 11 deletions src/__swaps__/screens/Swap/components/AnimatedChainImage.ios.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/__swaps__/types/refraction.ts
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<Container size={size} {...props}>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Divider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
145 changes: 0 additions & 145 deletions src/components/activity-list/ActivityList.js

This file was deleted.

132 changes: 132 additions & 0 deletions src/components/activity-list/ActivityList.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<View style={[sx.sectionHeader, { backgroundColor: colors.white }]}>
<ActivityListHeader {...section} />
</View>
);
};

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 (
<FooterWrapper onPress={onPressWrapper}>
{isLoading ? (
<LoadingSpinner />
) : (
<Text align="center" color={colors.alpha(colors.blueGreyDark, 0.3)} lineHeight="loose" size="smedium" weight="bold">
{label}
</Text>
)}
</FooterWrapper>
);
}

const ActivityList = () => {
const { accountAddress, nativeCurrency } = useAccountSettings();

const { setScrollToTopRef } = useSectionListScrollToTopContext<TransactionItemForSectionList, TransactionSections>();
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<TransactionItemForSectionList, TransactionSections> | null) => {
if (!ref) return;
setScrollToTopRef(ref);
};

return (
<SectionList<TransactionItemForSectionList, TransactionSections>
ListFooterComponent={() => remainingItemsLabel && <ListFooterComponent label={remainingItemsLabel} onPress={nextPage} />}
ref={handleScrollToTopRef}
alwaysBounceVertical={false}
contentContainerStyle={{ paddingBottom: !transactionsCount ? 0 : 90 }}
extraData={{
hasPendingTransaction: pendingTransactions.length > 0,
nativeCurrency,
pendingTransactionsCount: pendingTransactions.length,
}}
testID={'wallet-activity-list'}
ListEmptyComponent={<ActivityListEmptyState />}
// @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;
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
Loading

0 comments on commit 3ac1661

Please sign in to comment.