Skip to content

Commit acedf4b

Browse files
authored
CP-13626: Fusion Refunded UI (#3655)
1 parent b74dbea commit acedf4b

File tree

34 files changed

+931
-194
lines changed

34 files changed

+931
-194
lines changed

packages/core-mobile/app/new/common/utils/createZustandStore.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { create } from 'zustand'
22
import { persist, PersistOptions } from 'zustand/middleware'
3-
import { zustandMMKVStorage } from 'utils/mmkv/storages'
3+
import { zustandPersistStorage } from 'utils/mmkv/storages'
44

55
/**
66
* A lightweight utility for creating isolated Zustand stores that behave like `useState`
@@ -64,7 +64,7 @@ export function createZustandStore<T>(
6464
...options.persist,
6565
storage:
6666
options.persist.storage ??
67-
(zustandMMKVStorage as unknown as NonNullable<
67+
(zustandPersistStorage as unknown as NonNullable<
6868
PersistOptions<StoreState<T>, { value: T }>['storage']
6969
>),
7070
partialize:

packages/core-mobile/app/new/features/accountSettings/store.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
import { Platform } from 'react-native'
99
import { ZustandStorageKeys } from 'resources/Constants'
1010
import AnalyticsService from 'services/analytics/AnalyticsService'
11-
import { zustandMMKVStorage } from 'utils/mmkv/storages'
11+
import { zustandPersistStorage } from 'utils/mmkv/storages'
1212
import { isDebugOrInternalBuild } from 'utils/Utils'
1313
import { create } from 'zustand'
1414
import { persist } from 'zustand/middleware'
@@ -49,7 +49,7 @@ export const recentAccountsStore = create<RecentAccountsState>()(
4949
}),
5050
{
5151
name: ZustandStorageKeys.RECENT_ACCOUNTS,
52-
storage: zustandMMKVStorage,
52+
storage: zustandPersistStorage,
5353
// eslint-disable-next-line @typescript-eslint/no-explicit-any
5454
migrate: (persistedState: any) => {
5555
// Check if this is legacy data with recentAccountIndexes

packages/core-mobile/app/new/features/activity/store.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { AvatarType } from '@avalabs/k2-alpine'
22
import { createZustandStore } from 'common/utils/createZustandStore'
33
import { ZustandStorageKeys } from 'resources/Constants'
4-
import { zustandMMKVStorage } from 'utils/mmkv/storages'
4+
import { zustandPersistStorage } from 'utils/mmkv/storages'
55
import { create } from 'zustand'
66
import { persist } from 'zustand/middleware'
77
import { ActivityNetworkFilter } from './hooks/useActivityFilterAndSearch'
@@ -27,7 +27,9 @@ export const activityStore = create<ActivityState>()(
2727
}),
2828
{
2929
name: ZustandStorageKeys.ACTIVITY,
30-
storage: zustandMMKVStorage,
30+
storage: zustandPersistStorage,
31+
// TODO use correct type
32+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
3133
migrate: (persistedState: any) => {
3234
// Check if this is legacy data with recentAccountIndexes
3335
if (

packages/core-mobile/app/new/features/appReview/store.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ZustandStorageKeys } from 'resources/Constants'
2-
import { zustandMMKVStorage } from 'utils/mmkv/storages'
2+
import { zustandPersistStorage } from 'utils/mmkv/storages'
33
import { create } from 'zustand'
44
import { persist } from 'zustand/middleware'
55
import { getAppReviewConfig } from 'features/appReview/config'
@@ -70,7 +70,7 @@ export const appReviewStore = create<AppReviewState>()(
7070
}),
7171
{
7272
name: ZustandStorageKeys.APP_REVIEW,
73-
storage: zustandMMKVStorage,
73+
storage: zustandPersistStorage,
7474
version: 1
7575
}
7676
)

packages/core-mobile/app/new/features/ledger/store.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ZustandStorageKeys } from 'resources/Constants'
22
import { LedgerDerivationPathType, LedgerDevice } from 'services/ledger/types'
3-
import { zustandMMKVStorage } from 'utils/mmkv/storages'
3+
import { zustandPersistStorage } from 'utils/mmkv/storages'
44
import { create } from 'zustand'
55
import { persist } from 'zustand/middleware'
66
import { Network } from '@avalabs/core-chains-sdk'
@@ -87,7 +87,7 @@ export const ledgerWalletMapStore = create<LedgerWalletMapState>()(
8787
}),
8888
{
8989
name: ZustandStorageKeys.LEDGER_WALLET_MAP,
90-
storage: zustandMMKVStorage
90+
storage: zustandPersistStorage
9191
}
9292
)
9393
)

packages/core-mobile/app/new/features/notifications/components/FusionTransferItem.tsx

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,15 @@ import { TokenUnit } from '@avalabs/core-utils-sdk'
44
import { useNetworks } from 'hooks/networks/useNetworks'
55
import { FusionTransfer } from 'features/swap/types'
66
import { mapTransferToSwapStatus } from '../utils'
7+
import { NotificationSwapStatus } from '../types'
78
import NotificationListItem from './NotificationListItem'
89
import { SwapIcon } from './SwapIcon'
9-
import { RetrySwapButton } from './RetrySwapButton'
10+
11+
const SUBTITLE_MAP = {
12+
[NotificationSwapStatus.Completed]: 'Completed',
13+
[NotificationSwapStatus.Failed]: 'Failed',
14+
[NotificationSwapStatus.Refunded]: undefined
15+
} as const
1016

1117
type FusionTransferItemProps = {
1218
item: FusionTransfer
@@ -58,43 +64,51 @@ export const FusionTransferItem: FC<FusionTransferItemProps> = ({
5864
}
5965
}, [item.transfer])
6066

61-
const shouldBePlural = useMemo(() => {
62-
return !!fromAmount?.gt(1)
63-
}, [fromAmount])
64-
6567
const title = useMemo(() => {
68+
if (
69+
status === NotificationSwapStatus.Refunded &&
70+
'refund' in item.transfer
71+
) {
72+
const { refund } = item.transfer
73+
if (refund.asset) {
74+
const refundUnit = new TokenUnit(
75+
refund.amount,
76+
refund.asset.decimals,
77+
refund.asset.symbol
78+
)
79+
return `${refundUnit.toDisplay()} ${
80+
refund.asset.symbol
81+
} refunded to your wallet`
82+
}
83+
}
6684
const from = fromAmount
6785
? `${fromAmount.toDisplay()} ${fromSymbol}`
6886
: fromSymbol
6987
const to = toAmount ? `${toAmount.toDisplay()} ${toSymbol}` : toSymbol
70-
return status === 'failed'
71-
? `${from} swapped for ${to}`
72-
: status === 'completed'
73-
? `${from} ${shouldBePlural ? 'were' : 'was'} swapped for ${to}`
74-
: `Swapping ${fromSymbol} to ${toSymbol} in progress...`
75-
}, [fromAmount, fromSymbol, shouldBePlural, toAmount, toSymbol, status])
88+
return status === NotificationSwapStatus.InProgress
89+
? `Swapping ${fromSymbol} to ${toSymbol} in progress...`
90+
: `${from} swapped for ${to}`
91+
}, [fromAmount, fromSymbol, toAmount, toSymbol, status, item.transfer])
7692

7793
const subtitle =
78-
status === 'completed'
79-
? 'Completed'
80-
: status === 'failed'
81-
? 'Failed'
94+
status in SUBTITLE_MAP
95+
? SUBTITLE_MAP[status as keyof typeof SUBTITLE_MAP]
8296
: 'Tap for more details'
8397

84-
const accessoryType =
85-
status === 'completed' || status === 'failed' ? 'none' : 'chevron'
98+
const accessoryType = 'chevron'
8699

87100
const renderSubtitle = useCallback(() => {
101+
if (!subtitle) return null
88102
return (
89103
<Text
90104
variant="body2"
91105
sx={{
92106
lineHeight: 15,
93107
fontWeight: 500,
94108
color:
95-
status === 'completed'
109+
status === NotificationSwapStatus.Completed
96110
? '$textSuccess'
97-
: status === 'failed'
111+
: status === NotificationSwapStatus.Failed
98112
? '$textDanger'
99113
: '$textSecondary'
100114
}}
@@ -110,11 +124,10 @@ export const FusionTransferItem: FC<FusionTransferItemProps> = ({
110124
title={title}
111125
subtitle={renderSubtitle()}
112126
icon={<SwapIcon status={status} networkLogoUri={fromNetworkLogoUri} />}
113-
timestamp={status === 'failed' ? undefined : item.timestamp}
127+
timestamp={item.timestamp}
114128
showSeparator={showSeparator}
115129
accessoryType={accessoryType}
116130
testID={testID}
117-
rightAccessory={<RetrySwapButton status={status} item={item} />}
118131
/>
119132
)
120133
}

packages/core-mobile/app/new/features/notifications/components/RetrySwapButton.tsx

Lines changed: 0 additions & 33 deletions
This file was deleted.

packages/core-mobile/app/new/features/notifications/components/SwapIcon.tsx

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,44 @@ type SwapIconProps = {
1313

1414
/**
1515
* Icon shown on the left of each swap item:
16-
* - completed → grey circle with Compare arrows (→←) + optional network badge
17-
* - failed → grey circle with Compare arrows (→←) + optional network badge
16+
* - completed → grey circle with Compare arrows (→←) + optional network badge
17+
* - failed → grey circle with Compare arrows (→←) + optional network badge
18+
* - refunded → grey circle with Restart icon + optional network badge
1819
* - in_progress → grey circle with a continuously spinning sync icon + optional network badge
1920
*/
2021
export const SwapIcon: FC<SwapIconProps> = ({ status, networkLogoUri }) => {
2122
const {
2223
theme: { colors }
2324
} = useTheme()
2425

25-
if (status === 'completed' || status === 'failed') {
26+
if (status === NotificationSwapStatus.Refunded) {
27+
return (
28+
<View sx={{ width: ICON_SIZE }}>
29+
<View
30+
sx={{
31+
width: ICON_SIZE,
32+
height: ICON_SIZE,
33+
borderRadius: ICON_SIZE / 2,
34+
backgroundColor: '$surfaceSecondary',
35+
justifyContent: 'center',
36+
alignItems: 'center'
37+
}}>
38+
<Icons.Custom.Restart color={colors.$textPrimary} />
39+
</View>
40+
{networkLogoUri && (
41+
<NetworkBadge
42+
logoUri={networkLogoUri}
43+
borderColor={colors.$surfacePrimary}
44+
/>
45+
)}
46+
</View>
47+
)
48+
}
49+
50+
if (
51+
status === NotificationSwapStatus.Completed ||
52+
status === NotificationSwapStatus.Failed
53+
) {
2654
return (
2755
<View sx={{ width: ICON_SIZE }}>
2856
<View

0 commit comments

Comments
 (0)