wallet-stack 1.0.0-alpha.128 → 1.0.0-alpha.129
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/analytics/Properties.tsx +1 -0
- package/src/fiatExchanges/ExternalExchanges.tsx +3 -2
- package/src/fiatExchanges/Spend.tsx +3 -2
- package/src/fiatconnect/LinkAccountScreen.tsx +3 -2
- package/src/fiatconnect/ReviewScreen.tsx +3 -2
- package/src/fiatconnect/TransferStatusScreen.tsx +4 -3
- package/src/keylessBackup/KeylessBackupIntro.tsx +3 -2
- package/src/navigator/types.tsx +1 -0
- package/src/nfts/NftsLoadError.tsx +3 -2
- package/src/send/EnterAmount.tsx +4 -0
- package/src/send/SendEnterAmount.test.tsx +108 -1
- package/src/send/SendEnterAmount.tsx +18 -9
- package/src/send/useSendFilterChips.ts +46 -0
- package/src/statsig/constants.ts +6 -0
- package/src/statsig/types.ts +1 -0
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { NativeStackScreenProps } from '@react-navigation/native-stack'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
import { useTranslation } from 'react-i18next'
|
|
4
|
-
import {
|
|
4
|
+
import { ScrollView, StyleSheet, Text, View } from 'react-native'
|
|
5
|
+
import { SafeAreaView } from 'react-native-safe-area-context'
|
|
5
6
|
import { FiatExchangeEvents } from 'src/analytics/Events'
|
|
6
7
|
import AppAnalytics from 'src/analytics/AppAnalytics'
|
|
7
8
|
import BackButton from 'src/components/BackButton'
|
|
@@ -55,7 +56,7 @@ function ExternalExchanges({ route }: Props) {
|
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
return (
|
|
58
|
-
<SafeAreaView style={styles.container}>
|
|
59
|
+
<SafeAreaView style={styles.container} edges={['bottom']}>
|
|
59
60
|
<Text style={styles.pleaseSelectExchange}>
|
|
60
61
|
{t('youCanTransferOut', {
|
|
61
62
|
digitalAsset: tokenInfo?.symbol,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { NativeStackScreenProps } from '@react-navigation/native-stack'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
import { useTranslation } from 'react-i18next'
|
|
4
|
-
import {
|
|
4
|
+
import { ScrollView, StyleSheet, Text, View } from 'react-native'
|
|
5
|
+
import { SafeAreaView } from 'react-native-safe-area-context'
|
|
5
6
|
import AppAnalytics from 'src/analytics/AppAnalytics'
|
|
6
7
|
import { FiatExchangeEvents } from 'src/analytics/Events'
|
|
7
8
|
import BackButton from 'src/components/BackButton'
|
|
@@ -54,7 +55,7 @@ function Spend(props: Props) {
|
|
|
54
55
|
|
|
55
56
|
return (
|
|
56
57
|
<ScrollView style={styles.container}>
|
|
57
|
-
<SafeAreaView>
|
|
58
|
+
<SafeAreaView edges={['bottom']}>
|
|
58
59
|
<Text style={styles.pleaseSelectProvider}>{t('useBalanceWithMerchants')}</Text>
|
|
59
60
|
<View>
|
|
60
61
|
{merchants
|
|
@@ -3,7 +3,8 @@ import { RouteProp } from '@react-navigation/native'
|
|
|
3
3
|
import { NativeStackScreenProps } from '@react-navigation/native-stack'
|
|
4
4
|
import React from 'react'
|
|
5
5
|
import { Trans, useTranslation } from 'react-i18next'
|
|
6
|
-
import {
|
|
6
|
+
import { StyleSheet, Text } from 'react-native'
|
|
7
|
+
import { SafeAreaView } from 'react-native-safe-area-context'
|
|
7
8
|
import AppAnalytics from 'src/analytics/AppAnalytics'
|
|
8
9
|
import { FiatExchangeEvents } from 'src/analytics/Events'
|
|
9
10
|
import BackButton from 'src/components/BackButton'
|
|
@@ -105,7 +106,7 @@ function LinkAccountSection(props: {
|
|
|
105
106
|
}
|
|
106
107
|
|
|
107
108
|
return (
|
|
108
|
-
<SafeAreaView style={styles.content}>
|
|
109
|
+
<SafeAreaView style={styles.content} edges={['bottom']}>
|
|
109
110
|
<Text style={styles.title}>{t(bodyTitle)}</Text>
|
|
110
111
|
<Text testID="descriptionText" style={styles.description}>
|
|
111
112
|
<Trans i18nKey={description} values={{ providerName: quote.getProviderName() }}>
|
|
@@ -5,7 +5,8 @@ import BigNumber from 'bignumber.js'
|
|
|
5
5
|
import React, { useEffect, useLayoutEffect, useMemo, useState } from 'react'
|
|
6
6
|
import { useAsync } from 'react-async-hook'
|
|
7
7
|
import { useTranslation } from 'react-i18next'
|
|
8
|
-
import { ActivityIndicator, BackHandler,
|
|
8
|
+
import { ActivityIndicator, BackHandler, StyleSheet, Text, View } from 'react-native'
|
|
9
|
+
import { SafeAreaView } from 'react-native-safe-area-context'
|
|
9
10
|
import AppAnalytics from 'src/analytics/AppAnalytics'
|
|
10
11
|
import { FiatExchangeEvents } from 'src/analytics/Events'
|
|
11
12
|
import BackButton from 'src/components/BackButton'
|
|
@@ -251,7 +252,7 @@ export default function FiatConnectReviewScreen({ route, navigation }: Props) {
|
|
|
251
252
|
}
|
|
252
253
|
|
|
253
254
|
return (
|
|
254
|
-
<SafeAreaView style={styles.content}>
|
|
255
|
+
<SafeAreaView style={styles.content} edges={['bottom']}>
|
|
255
256
|
<Dialog
|
|
256
257
|
testID="expiredQuoteDialog"
|
|
257
258
|
isVisible={showingExpiredQuoteDialog}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { NativeStackScreenProps } from '@react-navigation/native-stack'
|
|
2
2
|
import React, { useEffect, useState, type JSX } from 'react'
|
|
3
3
|
import { useTranslation } from 'react-i18next'
|
|
4
|
-
import { ActivityIndicator,
|
|
4
|
+
import { ActivityIndicator, StyleSheet, Text, View } from 'react-native'
|
|
5
|
+
import { SafeAreaView } from 'react-native-safe-area-context'
|
|
5
6
|
import AppAnalytics from 'src/analytics/AppAnalytics'
|
|
6
7
|
import { FiatExchangeEvents } from 'src/analytics/Events'
|
|
7
8
|
import BackButton from 'src/components/BackButton'
|
|
@@ -269,7 +270,7 @@ export default function FiatConnectTransferStatusScreen({ route, navigation }: P
|
|
|
269
270
|
),
|
|
270
271
|
})
|
|
271
272
|
return (
|
|
272
|
-
<SafeAreaView style={styles.content}>
|
|
273
|
+
<SafeAreaView style={styles.content} edges={['bottom']}>
|
|
273
274
|
<FailureSection flow={flow} normalizedQuote={normalizedQuote} fiatAccount={fiatAccount} />
|
|
274
275
|
</SafeAreaView>
|
|
275
276
|
)
|
|
@@ -282,7 +283,7 @@ export default function FiatConnectTransferStatusScreen({ route, navigation }: P
|
|
|
282
283
|
// intentionally falls thru since TxProcessing and Completed use the same component
|
|
283
284
|
case SendingTransferStatus.TxProcessing:
|
|
284
285
|
return (
|
|
285
|
-
<SafeAreaView style={styles.content}>
|
|
286
|
+
<SafeAreaView style={styles.content} edges={['bottom']}>
|
|
286
287
|
<SuccessOrProcessingSection
|
|
287
288
|
status={fiatConnectTransfer.status}
|
|
288
289
|
flow={flow}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { NativeStackScreenProps } from '@react-navigation/native-stack'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
import { Trans, useTranslation } from 'react-i18next'
|
|
4
|
-
import {
|
|
4
|
+
import { ScrollView, StyleSheet, Text, View } from 'react-native'
|
|
5
|
+
import { SafeAreaView } from 'react-native-safe-area-context'
|
|
5
6
|
import AppAnalytics from 'src/analytics/AppAnalytics'
|
|
6
7
|
import { KeylessBackupEvents } from 'src/analytics/Events'
|
|
7
8
|
import BackButton from 'src/components/BackButton'
|
|
@@ -33,7 +34,7 @@ function KeylessBackupIntro({ route }: Props) {
|
|
|
33
34
|
const { t } = useTranslation()
|
|
34
35
|
|
|
35
36
|
return (
|
|
36
|
-
<SafeAreaView style={styles.container}>
|
|
37
|
+
<SafeAreaView style={styles.container} edges={['bottom']}>
|
|
37
38
|
<ScrollView style={styles.scrollContainer}>
|
|
38
39
|
{isSetup && <Text style={styles.title}>{t('keylessBackupIntro.setup.title')}</Text>}
|
|
39
40
|
<Text
|
package/src/navigator/types.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useEffect } from 'react'
|
|
2
2
|
import { Trans, useTranslation } from 'react-i18next'
|
|
3
|
-
import {
|
|
3
|
+
import { ScrollView, StyleSheet, Text, View } from 'react-native'
|
|
4
|
+
import { SafeAreaView } from 'react-native-safe-area-context'
|
|
4
5
|
import AppAnalytics from 'src/analytics/AppAnalytics'
|
|
5
6
|
import { NftEvents } from 'src/analytics/Events'
|
|
6
7
|
import Touchable from 'src/components/Touchable'
|
|
@@ -31,7 +32,7 @@ export default function NftsLoadError({ testID }: Props) {
|
|
|
31
32
|
}, [])
|
|
32
33
|
|
|
33
34
|
return (
|
|
34
|
-
<SafeAreaView style={styles.safeArea} testID={testID}>
|
|
35
|
+
<SafeAreaView style={styles.safeArea} testID={testID} edges={['bottom']}>
|
|
35
36
|
<ScrollView
|
|
36
37
|
contentContainerStyle={styles.contentContainerStyle}
|
|
37
38
|
style={styles.scrollContainer}
|
package/src/send/EnterAmount.tsx
CHANGED
|
@@ -10,6 +10,7 @@ import BackButton from 'src/components/BackButton'
|
|
|
10
10
|
import { BottomSheetModalRefType } from 'src/components/BottomSheet'
|
|
11
11
|
import Button, { BtnSizes } from 'src/components/Button'
|
|
12
12
|
import FeeInfoBottomSheet from 'src/components/FeeInfoBottomSheet'
|
|
13
|
+
import { FilterChip } from 'src/components/FilterChipsCarousel'
|
|
13
14
|
import InLineNotification, { NotificationVariant } from 'src/components/InLineNotification'
|
|
14
15
|
import KeyboardAwareScrollView from 'src/components/KeyboardAwareScrollView'
|
|
15
16
|
import { ReviewDetailsItem } from 'src/components/ReviewTransaction'
|
|
@@ -66,6 +67,7 @@ interface Props {
|
|
|
66
67
|
children?: React.ReactNode
|
|
67
68
|
ProceedComponent: ComponentType<ProceedComponentProps>
|
|
68
69
|
disableBalanceCheck?: boolean
|
|
70
|
+
filterChips?: FilterChip<TokenBalance>[]
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
export const SendProceed = ({
|
|
@@ -107,6 +109,7 @@ export default function EnterAmount({
|
|
|
107
109
|
children,
|
|
108
110
|
ProceedComponent,
|
|
109
111
|
disableBalanceCheck = false,
|
|
112
|
+
filterChips,
|
|
110
113
|
}: Props) {
|
|
111
114
|
const { t } = useTranslation()
|
|
112
115
|
const insets = useSafeAreaInsets()
|
|
@@ -325,6 +328,7 @@ export default function EnterAmount({
|
|
|
325
328
|
tokens={tokens}
|
|
326
329
|
title={t('sendEnterAmountScreen.selectToken')}
|
|
327
330
|
titleStyle={styles.title}
|
|
331
|
+
filterChips={filterChips}
|
|
328
332
|
/>
|
|
329
333
|
</SafeAreaView>
|
|
330
334
|
)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fireEvent, render, waitFor } from '@testing-library/react-native'
|
|
1
|
+
import { fireEvent, render, waitFor, within } from '@testing-library/react-native'
|
|
2
2
|
import BigNumber from 'bignumber.js'
|
|
3
3
|
import React from 'react'
|
|
4
4
|
import { Provider } from 'react-redux'
|
|
@@ -10,6 +10,7 @@ import { Screens } from 'src/navigator/Screens'
|
|
|
10
10
|
import { RecipientType } from 'src/recipients/recipient'
|
|
11
11
|
import SendEnterAmount from 'src/send/SendEnterAmount'
|
|
12
12
|
import { usePrepareSendTransactions } from 'src/send/usePrepareSendTransactions'
|
|
13
|
+
import { getDynamicConfigParams } from 'src/statsig'
|
|
13
14
|
import { getSerializablePreparedTransactionsPossible } from 'src/viem/preparedTransactionSerialization'
|
|
14
15
|
import { PreparedTransactionsPossible } from 'src/viem/prepareTransactions'
|
|
15
16
|
import MockedNavigator from 'test/MockedNavigator'
|
|
@@ -29,6 +30,10 @@ import {
|
|
|
29
30
|
jest.mock('src/statsig')
|
|
30
31
|
jest.mock('src/send/usePrepareSendTransactions')
|
|
31
32
|
|
|
33
|
+
jest.mocked(getDynamicConfigParams).mockReturnValue({
|
|
34
|
+
miniPayTokenIds: [],
|
|
35
|
+
})
|
|
36
|
+
|
|
32
37
|
const mockPrepareTransactionsResultPossible: PreparedTransactionsPossible = {
|
|
33
38
|
type: 'possible',
|
|
34
39
|
transactions: [
|
|
@@ -164,6 +169,7 @@ describe('SendEnterAmount', () => {
|
|
|
164
169
|
underlyingTokenAddress: mockCeloAddress,
|
|
165
170
|
underlyingTokenSymbol: 'CELO',
|
|
166
171
|
amountEnteredIn: 'token',
|
|
172
|
+
isMiniPayRecipient: false,
|
|
167
173
|
})
|
|
168
174
|
expect(navigate).toHaveBeenCalledWith(Screens.SendConfirmation, {
|
|
169
175
|
origin: params.origin,
|
|
@@ -232,4 +238,105 @@ describe('SendEnterAmount', () => {
|
|
|
232
238
|
expect(getByTestId('SendEnterAmount/TokenSelect')).toHaveTextContent('cUSD', { exact: false })
|
|
233
239
|
expect(getByTestId('SendEnterAmount/TokenSelect')).toBeDisabled()
|
|
234
240
|
})
|
|
241
|
+
|
|
242
|
+
describe('MiniPay filter', () => {
|
|
243
|
+
const miniPayTokenIds = [mockCusdTokenId, mockUSDCTokenId]
|
|
244
|
+
|
|
245
|
+
beforeEach(() => {
|
|
246
|
+
jest.mocked(getDynamicConfigParams).mockReturnValue({
|
|
247
|
+
miniPayTokenIds,
|
|
248
|
+
})
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
it('should show MiniPay chip pre-selected and only MiniPay tokens when isMiniPayRecipient is true', () => {
|
|
252
|
+
const { getAllByTestId, getByText } = render(
|
|
253
|
+
<Provider store={store}>
|
|
254
|
+
<MockedNavigator
|
|
255
|
+
component={SendEnterAmount}
|
|
256
|
+
params={{ ...params, isMiniPayRecipient: true }}
|
|
257
|
+
/>
|
|
258
|
+
</Provider>
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
expect(getByText('MiniPay')).toBeTruthy()
|
|
262
|
+
|
|
263
|
+
const tokenBottomSheet = getAllByTestId('TokenBottomSheet')[0]
|
|
264
|
+
const tokens = within(tokenBottomSheet).getAllByTestId('TokenBalanceItem')
|
|
265
|
+
// only cUSD visible (USDC is on a different network and filtered by selector)
|
|
266
|
+
expect(tokens).toHaveLength(1)
|
|
267
|
+
expect(tokens[0]).toHaveTextContent('cUSD', { exact: false })
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
it('should select default token from MiniPay list', () => {
|
|
271
|
+
const { getByTestId } = render(
|
|
272
|
+
<Provider store={store}>
|
|
273
|
+
<MockedNavigator
|
|
274
|
+
component={SendEnterAmount}
|
|
275
|
+
params={{ ...params, isMiniPayRecipient: true }}
|
|
276
|
+
/>
|
|
277
|
+
</Provider>
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
// cUSD is the only MiniPay token with balance, not CELO (which is excluded)
|
|
281
|
+
expect(getByTestId('SendEnterAmount/TokenSelect')).toHaveTextContent('cUSD', { exact: false })
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
it('should show all tokens when MiniPay chip is toggled off', () => {
|
|
285
|
+
const { getAllByTestId, getByText } = render(
|
|
286
|
+
<Provider store={store}>
|
|
287
|
+
<MockedNavigator
|
|
288
|
+
component={SendEnterAmount}
|
|
289
|
+
params={{ ...params, isMiniPayRecipient: true }}
|
|
290
|
+
/>
|
|
291
|
+
</Provider>
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
fireEvent.press(getByText('MiniPay'))
|
|
295
|
+
|
|
296
|
+
const tokenBottomSheet = getAllByTestId('TokenBottomSheet')[0]
|
|
297
|
+
const tokens = within(tokenBottomSheet).getAllByTestId('TokenBalanceItem')
|
|
298
|
+
expect(tokens).toHaveLength(3)
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
it('should not show MiniPay chip when isMiniPayRecipient is not set', () => {
|
|
302
|
+
const { queryByText } = render(
|
|
303
|
+
<Provider store={store}>
|
|
304
|
+
<MockedNavigator component={SendEnterAmount} params={params} />
|
|
305
|
+
</Provider>
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
expect(queryByText('MiniPay')).toBeFalsy()
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
it('should include isMiniPayRecipient in send_amount_continue analytics', async () => {
|
|
312
|
+
jest.mocked(usePrepareSendTransactions).mockReturnValue({
|
|
313
|
+
prepareTransactionsResult: mockPrepareTransactionsResultPossible,
|
|
314
|
+
prepareTransactionLoading: false,
|
|
315
|
+
refreshPreparedTransactions: jest.fn(),
|
|
316
|
+
clearPreparedTransactions: jest.fn(),
|
|
317
|
+
prepareTransactionError: undefined,
|
|
318
|
+
})
|
|
319
|
+
const { getByTestId, getByText } = render(
|
|
320
|
+
<Provider store={store}>
|
|
321
|
+
<MockedNavigator
|
|
322
|
+
component={SendEnterAmount}
|
|
323
|
+
params={{ ...params, isMiniPayRecipient: true }}
|
|
324
|
+
/>
|
|
325
|
+
</Provider>
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
fireEvent.changeText(getByTestId('SendEnterAmount/TokenAmountInput'), '8')
|
|
329
|
+
|
|
330
|
+
await waitFor(() => expect(getByText('review')).not.toBeDisabled())
|
|
331
|
+
fireEvent.press(getByText('review'))
|
|
332
|
+
|
|
333
|
+
await waitFor(() => expect(AppAnalytics.track).toHaveBeenCalledTimes(1))
|
|
334
|
+
expect(AppAnalytics.track).toHaveBeenCalledWith(
|
|
335
|
+
SendEvents.send_amount_continue,
|
|
336
|
+
expect.objectContaining({
|
|
337
|
+
isMiniPayRecipient: true,
|
|
338
|
+
})
|
|
339
|
+
)
|
|
340
|
+
})
|
|
341
|
+
})
|
|
235
342
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NativeStackScreenProps } from '@react-navigation/native-stack'
|
|
2
2
|
import BigNumber from 'bignumber.js'
|
|
3
|
-
import React
|
|
3
|
+
import React from 'react'
|
|
4
4
|
import AppAnalytics from 'src/analytics/AppAnalytics'
|
|
5
5
|
import { SendEvents } from 'src/analytics/Events'
|
|
6
6
|
import { getLocalCurrencyCode, usdToLocalCurrencyRateSelector } from 'src/localCurrency/selectors'
|
|
@@ -11,6 +11,7 @@ import { useSelector } from 'src/redux/hooks'
|
|
|
11
11
|
import EnterAmount, { ProceedArgs, SendProceed } from 'src/send/EnterAmount'
|
|
12
12
|
import { lastUsedTokenIdSelector } from 'src/send/selectors'
|
|
13
13
|
import { usePrepareSendTransactions } from 'src/send/usePrepareSendTransactions'
|
|
14
|
+
import useSendFilterChips from 'src/send/useSendFilterChips'
|
|
14
15
|
import { sortedTokensWithBalanceOrShowZeroBalanceSelector } from 'src/tokens/selectors'
|
|
15
16
|
import { TokenBalance } from 'src/tokens/slice'
|
|
16
17
|
import Logger from 'src/utils/Logger'
|
|
@@ -22,18 +23,24 @@ type Props = NativeStackScreenProps<StackParamList, Screens.SendEnterAmount>
|
|
|
22
23
|
const TAG = 'SendEnterAmount'
|
|
23
24
|
|
|
24
25
|
function SendEnterAmount({ route }: Props) {
|
|
25
|
-
const {
|
|
26
|
+
const {
|
|
27
|
+
defaultTokenIdOverride,
|
|
28
|
+
origin,
|
|
29
|
+
recipient,
|
|
30
|
+
isFromScan,
|
|
31
|
+
forceTokenId,
|
|
32
|
+
isMiniPayRecipient,
|
|
33
|
+
} = route.params
|
|
26
34
|
// explicitly allow zero state tokens to be shown for exploration purposes for
|
|
27
35
|
// new users with no balance
|
|
28
36
|
const tokens = useSelector(sortedTokensWithBalanceOrShowZeroBalanceSelector)
|
|
29
37
|
const lastUsedTokenId = useSelector(lastUsedTokenIdSelector)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}, [tokens, defaultTokenIdOverride, lastUsedTokenId])
|
|
38
|
+
const { filterChips, defaultToken } = useSendFilterChips({
|
|
39
|
+
isMiniPayRecipient,
|
|
40
|
+
tokens,
|
|
41
|
+
defaultTokenIdOverride,
|
|
42
|
+
lastUsedTokenId,
|
|
43
|
+
})
|
|
37
44
|
|
|
38
45
|
const localCurrencyCode = useSelector(getLocalCurrencyCode)
|
|
39
46
|
const localCurrencyExchangeRate = useSelector(usdToLocalCurrencyRateSelector)
|
|
@@ -72,6 +79,7 @@ function SendEnterAmount({ route }: Props) {
|
|
|
72
79
|
amountEnteredIn,
|
|
73
80
|
tokenId: token.tokenId,
|
|
74
81
|
networkId: token.networkId,
|
|
82
|
+
isMiniPayRecipient: isMiniPayRecipient ?? false,
|
|
75
83
|
})
|
|
76
84
|
}
|
|
77
85
|
|
|
@@ -116,6 +124,7 @@ function SendEnterAmount({ route }: Props) {
|
|
|
116
124
|
tokenSelectionDisabled={!!forceTokenId}
|
|
117
125
|
onPressProceed={handleReviewSend}
|
|
118
126
|
ProceedComponent={SendProceed}
|
|
127
|
+
filterChips={filterChips}
|
|
119
128
|
/>
|
|
120
129
|
)
|
|
121
130
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { BooleanFilterChip } from 'src/components/FilterChipsCarousel'
|
|
2
|
+
import { getDynamicConfigParams } from 'src/statsig'
|
|
3
|
+
import { DynamicConfigs } from 'src/statsig/constants'
|
|
4
|
+
import { StatsigDynamicConfigs } from 'src/statsig/types'
|
|
5
|
+
import { TokenBalance } from 'src/tokens/slice'
|
|
6
|
+
|
|
7
|
+
export default function useSendFilterChips({
|
|
8
|
+
isMiniPayRecipient,
|
|
9
|
+
tokens,
|
|
10
|
+
defaultTokenIdOverride,
|
|
11
|
+
lastUsedTokenId,
|
|
12
|
+
}: {
|
|
13
|
+
isMiniPayRecipient?: boolean
|
|
14
|
+
tokens: TokenBalance[]
|
|
15
|
+
defaultTokenIdOverride?: string
|
|
16
|
+
lastUsedTokenId?: string | null
|
|
17
|
+
}): {
|
|
18
|
+
filterChips: BooleanFilterChip<TokenBalance>[]
|
|
19
|
+
defaultToken: TokenBalance | undefined
|
|
20
|
+
} {
|
|
21
|
+
const { miniPayTokenIds: configTokenIds } = getDynamicConfigParams(
|
|
22
|
+
DynamicConfigs[StatsigDynamicConfigs.SEND_CONFIG]
|
|
23
|
+
)
|
|
24
|
+
const miniPayTokenIds = isMiniPayRecipient && configTokenIds.length > 0 ? configTokenIds : null
|
|
25
|
+
|
|
26
|
+
const filterChips: BooleanFilterChip<TokenBalance>[] = miniPayTokenIds
|
|
27
|
+
? [
|
|
28
|
+
{
|
|
29
|
+
id: 'minipay',
|
|
30
|
+
name: 'MiniPay',
|
|
31
|
+
filterFn: (token: TokenBalance) => miniPayTokenIds.includes(token.tokenId),
|
|
32
|
+
isSelected: true,
|
|
33
|
+
},
|
|
34
|
+
]
|
|
35
|
+
: []
|
|
36
|
+
|
|
37
|
+
const eligibleTokens = miniPayTokenIds
|
|
38
|
+
? tokens.filter((token) => miniPayTokenIds.includes(token.tokenId))
|
|
39
|
+
: tokens
|
|
40
|
+
const defaultToken =
|
|
41
|
+
eligibleTokens.find((token) => token.tokenId === defaultTokenIdOverride) ??
|
|
42
|
+
eligibleTokens.find((token) => token.tokenId === lastUsedTokenId) ??
|
|
43
|
+
eligibleTokens[0]
|
|
44
|
+
|
|
45
|
+
return { filterChips, defaultToken }
|
|
46
|
+
}
|
package/src/statsig/constants.ts
CHANGED
|
@@ -164,6 +164,12 @@ export const DynamicConfigs = {
|
|
|
164
164
|
inviteRewardsVersion: 'none',
|
|
165
165
|
},
|
|
166
166
|
},
|
|
167
|
+
[StatsigDynamicConfigs.SEND_CONFIG]: {
|
|
168
|
+
configName: StatsigDynamicConfigs.SEND_CONFIG,
|
|
169
|
+
defaultValues: {
|
|
170
|
+
miniPayTokenIds: [] as string[],
|
|
171
|
+
},
|
|
172
|
+
},
|
|
167
173
|
} satisfies {
|
|
168
174
|
[key in StatsigDynamicConfigs]: {
|
|
169
175
|
configName: key
|
package/src/statsig/types.ts
CHANGED