diff --git a/src/components/LegacyTokenDisplay.test.tsx b/src/components/LegacyTokenDisplay.test.tsx
index 866c30b1c37..cfcdd18a3a0 100644
--- a/src/components/LegacyTokenDisplay.test.tsx
+++ b/src/components/LegacyTokenDisplay.test.tsx
@@ -8,7 +8,6 @@ import { LocalCurrencyCode } from 'src/localCurrency/consts'
import { RootState } from 'src/redux/reducers'
import { Currency } from 'src/utils/currencies'
import { createMockStore, getElementText, RecursivePartial } from 'test/utils'
-import { getFeatureGate } from 'src/statsig'
import { NetworkId } from 'src/transactions/types'
import {
mockCusdTokenId,
@@ -91,16 +90,6 @@ describe('LegacyTokenDisplay', () => {
)
).toThrow()
})
- it('allows currency and tokenAddress to be empty when native tokens are permitted', () => {
- jest.mocked(getFeatureGate).mockReturnValueOnce(true)
- expect(() =>
- render(
-
-
-
- )
- ).not.toThrow()
- })
it('shows token amount when showLocalAmount is false', () => {
const { getByTestId } = render(
diff --git a/src/components/LegacyTokenDisplay.tsx b/src/components/LegacyTokenDisplay.tsx
index 4a479f87255..af254d6dea0 100644
--- a/src/components/LegacyTokenDisplay.tsx
+++ b/src/components/LegacyTokenDisplay.tsx
@@ -4,8 +4,6 @@ import { StyleProp, TextStyle } from 'react-native'
import { useTokenInfoByAddress, useTokenInfoWithAddressBySymbol } from 'src/tokens/hooks'
import { LocalAmount } from 'src/transactions/types'
import { Currency } from 'src/utils/currencies'
-import { getFeatureGate } from 'src/statsig'
-import { StatsigFeatureGates } from 'src/statsig/types'
import TokenDisplay from 'src/components/TokenDisplay'
interface Props {
@@ -36,15 +34,10 @@ function LegacyTokenDisplay({
style,
testID,
}: Props) {
- const showNativeTokens = getFeatureGate(StatsigFeatureGates.SHOW_NATIVE_TOKENS)
- if (!showNativeTokens && (tokenAddress ? currency : !currency)) {
+ if (tokenAddress ? currency : !currency) {
throw new Error(
'LegacyTokenDisplay must be passed either "currency" or "tokenAddress" and not both'
)
- } else if (tokenAddress && currency) {
- throw new Error(
- 'LegacyTokenDisplay must be passed tokenAddress, currency, or nethier, but not both'
- )
}
const tokenInfoFromAddress = useTokenInfoByAddress(tokenAddress)
diff --git a/src/components/LegacyTokenTotalLineItem.test.tsx b/src/components/LegacyTokenTotalLineItem.test.tsx
new file mode 100644
index 00000000000..eac56103477
--- /dev/null
+++ b/src/components/LegacyTokenTotalLineItem.test.tsx
@@ -0,0 +1,90 @@
+import { render } from '@testing-library/react-native'
+import BigNumber from 'bignumber.js'
+import * as React from 'react'
+import 'react-native'
+import { Provider } from 'react-redux'
+import LegacyTokenTotalLineItem from 'src/components/LegacyTokenTotalLineItem'
+import { LocalCurrencyCode } from 'src/localCurrency/consts'
+import { LocalAmount, NetworkId } from 'src/transactions/types'
+import { createMockStore, getElementText } from 'test/utils'
+import { mockCusdAddress, mockCusdTokenId } from 'test/values'
+
+const mockBtcAddress = '0xbtc'
+const mockBtcTokenId = `celo-alfajores:${mockBtcAddress}`
+
+const defaultAmount = new BigNumber(10)
+const defaultTokenAddress = mockCusdAddress
+
+// This component is primarily tested via TokenTotalLineItem.test.tsx
+describe('LegacyTokenTotalLineItem', () => {
+ function renderComponent({
+ amount = defaultAmount,
+ tokenAddress = defaultTokenAddress,
+ localAmount,
+ localCurrencyCode = LocalCurrencyCode.BRL,
+ usdToLocalRate = '1.5',
+ feeToAddInUsd = undefined,
+ hideSign = undefined,
+ }: {
+ amount?: BigNumber
+ tokenAddress?: string
+ localAmount?: LocalAmount
+ localCurrencyCode?: LocalCurrencyCode
+ usdToLocalRate?: string
+ feeToAddInUsd?: BigNumber
+ hideSign?: boolean
+ }) {
+ return render(
+
+
+
+ )
+ }
+
+ describe('When rendering normally', () => {
+ it('shows the right amounts', () => {
+ const { getByTestId } = renderComponent({})
+ expect(getElementText(getByTestId('TotalLineItem/Total'))).toEqual('R$15.00')
+ expect(getElementText(getByTestId('TotalLineItem/ExchangeRate'))).toEqual(
+ 'tokenExchanteRate, {"symbol":"cUSD"}R$1.50'
+ )
+ expect(getElementText(getByTestId('TotalLineItem/Subtotal'))).toEqual('10.00 cUSD')
+ })
+ })
+})
diff --git a/src/components/LegacyTokenTotalLineItem.tsx b/src/components/LegacyTokenTotalLineItem.tsx
new file mode 100644
index 00000000000..608f27e4b60
--- /dev/null
+++ b/src/components/LegacyTokenTotalLineItem.tsx
@@ -0,0 +1,38 @@
+import BigNumber from 'bignumber.js'
+import * as React from 'react'
+import { useTokenInfoByAddress } from 'src/tokens/hooks'
+import TokenTotalLineItem from 'src/components/TokenTotalLineItem'
+import { LocalAmount } from 'src/transactions/types'
+
+interface Props {
+ tokenAmount: BigNumber
+ tokenAddress?: string
+ localAmount?: LocalAmount
+ feeToAddInUsd?: BigNumber | undefined
+ hideSign?: boolean
+ title?: string | null
+}
+
+/**
+ * @deprecated Use TokenTotalLineItem instead
+ */
+export default function LegacyTokenTotalLineItem({
+ tokenAmount,
+ tokenAddress,
+ localAmount,
+ feeToAddInUsd,
+ hideSign,
+ title,
+}: Props) {
+ const tokenInfo = useTokenInfoByAddress(tokenAddress)
+ return (
+
+ )
+}
diff --git a/src/components/TokenTotalLineItem.test.tsx b/src/components/TokenTotalLineItem.test.tsx
index 22d3d7ddb9a..7973e07ac18 100644
--- a/src/components/TokenTotalLineItem.test.tsx
+++ b/src/components/TokenTotalLineItem.test.tsx
@@ -13,12 +13,12 @@ const mockBtcAddress = '0xbtc'
const mockBtcTokenId = `celo-alfajores:${mockBtcAddress}`
const defaultAmount = new BigNumber(10)
-const defaultTokenAddress = mockCusdAddress
+const defaultTokenId = mockCusdTokenId
describe('TokenTotalLineItem', () => {
function renderComponent({
amount = defaultAmount,
- tokenAddress = defaultTokenAddress,
+ tokenId = defaultTokenId,
localAmount,
localCurrencyCode = LocalCurrencyCode.BRL,
usdToLocalRate = '1.5',
@@ -26,7 +26,7 @@ describe('TokenTotalLineItem', () => {
hideSign = undefined,
}: {
amount?: BigNumber
- tokenAddress?: string
+ tokenId?: string
localAmount?: LocalAmount
localCurrencyCode?: LocalCurrencyCode
usdToLocalRate?: string
@@ -67,7 +67,7 @@ describe('TokenTotalLineItem', () => {
>
{
it('we show some significant values', () => {
const { getByTestId } = renderComponent({
amount: new BigNumber(0.000123456),
- tokenAddress: mockBtcAddress,
+ tokenId: mockBtcTokenId,
usdToLocalRate: '1',
})
expect(getElementText(getByTestId('TotalLineItem/Total'))).toEqual('R$8.02')
diff --git a/src/components/TokenTotalLineItem.tsx b/src/components/TokenTotalLineItem.tsx
index f3a6fc123ae..e1fbcce92ce 100644
--- a/src/components/TokenTotalLineItem.tsx
+++ b/src/components/TokenTotalLineItem.tsx
@@ -3,17 +3,17 @@ import * as React from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { StyleSheet, Text } from 'react-native'
import LineItemRow from 'src/components/LineItemRow'
-import LegacyTokenDisplay from 'src/components/LegacyTokenDisplay'
+import TokenDisplay from 'src/components/TokenDisplay'
import { LocalCurrencyCode, LocalCurrencySymbol } from 'src/localCurrency/consts'
import colors from 'src/styles/colors'
import fontStyles from 'src/styles/fonts'
-import { useTokenInfoByAddress } from 'src/tokens/hooks'
+import { useTokenInfo } from 'src/tokens/hooks'
import { LocalAmount } from 'src/transactions/types'
import { formatValueToDisplay } from 'src/components/TokenDisplay'
interface Props {
tokenAmount: BigNumber
- tokenAddress?: string
+ tokenId?: string
localAmount?: LocalAmount
feeToAddInUsd?: BigNumber | undefined
hideSign?: boolean
@@ -22,14 +22,14 @@ interface Props {
export default function TokenTotalLineItem({
tokenAmount,
- tokenAddress,
+ tokenId,
localAmount,
feeToAddInUsd,
hideSign,
title,
}: Props) {
const { t } = useTranslation()
- const tokenInfo = useTokenInfoByAddress(tokenAddress)
+ const tokenInfo = useTokenInfo(tokenId)
const feeInToken = tokenInfo?.priceUsd ? feeToAddInUsd?.dividedBy(tokenInfo.priceUsd) : undefined
return (
@@ -38,9 +38,9 @@ export default function TokenTotalLineItem({
title={title ?? t('total')}
textStyle={fontStyles.regular600}
amount={
-
+
)}
}
amount={
-
- {
jest.clearAllMocks()
storeWithUSD.clearActions()
storeWithPHP.clearActions()
- jest.mocked(getFeatureGate).mockImplementation((gate) => {
- return gate === StatsigFeatureGates.SHOW_NATIVE_TOKENS
- })
})
it.each([
- { currency: CiCoCurrency.cUSD, network: Network.Celo },
- { currency: CiCoCurrency.cEUR, network: Network.Celo },
- { currency: CiCoCurrency.ETH, network: Network.Ethereum },
- ])(`disables the next button if the $currency amount is 0`, ({ currency, network }) => {
+ { currency: CiCoCurrency.cUSD, tokenId: mockCusdTokenId, network: Network.Celo },
+ { currency: CiCoCurrency.cEUR, tokenId: mockCeurTokenId, network: Network.Celo },
+ { currency: CiCoCurrency.ETH, tokenId: mockEthTokenId, network: Network.Ethereum },
+ ])(`disables the next button if the $currency amount is 0`, ({ currency, network, tokenId }) => {
const mockScreenProps = getMockStackScreenProps(Screens.FiatExchangeAmount, {
currency,
+ tokenId,
flow: CICOFlow.CashIn,
network,
})
@@ -146,14 +144,30 @@ describe('FiatExchangeAmount cashIn', () => {
})
it.each([
- { currency: CiCoCurrency.cUSD, network: Network.Celo, store: storeWithUSD },
- { currency: CiCoCurrency.cEUR, network: Network.Celo, store: storeWithPHP },
- { currency: CiCoCurrency.ETH, network: Network.Ethereum, store: storeWithUSD },
+ {
+ currency: CiCoCurrency.cUSD,
+ tokenId: mockCusdTokenId,
+ network: Network.Celo,
+ store: storeWithUSD,
+ },
+ {
+ currency: CiCoCurrency.cEUR,
+ tokenId: mockCeurTokenId,
+ network: Network.Celo,
+ store: storeWithPHP,
+ },
+ {
+ currency: CiCoCurrency.ETH,
+ tokenId: mockEthTokenId,
+ network: Network.Ethereum,
+ store: storeWithUSD,
+ },
])(
`enables the next button if the $currency amount is greater than 0`,
- ({ currency, network, store }) => {
+ ({ currency, tokenId, network, store }) => {
const mockScreenProps = getMockStackScreenProps(Screens.FiatExchangeAmount, {
currency,
+ tokenId,
flow: CICOFlow.CashIn,
network,
})
@@ -171,6 +185,7 @@ describe('FiatExchangeAmount cashIn', () => {
it('renders correctly with USD as app currency', () => {
const mockScreenProps = getMockStackScreenProps(Screens.FiatExchangeAmount, {
currency: CiCoCurrency.cUSD,
+ tokenId: mockCusdTokenId,
flow: CICOFlow.CashIn,
network: Network.Celo,
})
@@ -185,6 +200,7 @@ describe('FiatExchangeAmount cashIn', () => {
it('renders correctly with EUR as app currency', () => {
const mockScreenProps = getMockStackScreenProps(Screens.FiatExchangeAmount, {
currency: CiCoCurrency.cUSD,
+ tokenId: mockCusdTokenId,
flow: CICOFlow.CashIn,
network: Network.Celo,
})
@@ -200,18 +216,21 @@ describe('FiatExchangeAmount cashIn', () => {
describe('FiatExchangeAmount cashOut', () => {
const mockScreenProps = getMockStackScreenProps(Screens.FiatExchangeAmount, {
currency: CiCoCurrency.cUSD,
+ tokenId: mockCusdTokenId,
flow: CICOFlow.CashOut,
network: Network.Celo,
})
const mockScreenPropsEuro = getMockStackScreenProps(Screens.FiatExchangeAmount, {
currency: CiCoCurrency.cEUR,
+ tokenId: mockCeurTokenId,
flow: CICOFlow.CashOut,
network: Network.Celo,
})
const mockScreenPropsCelo = getMockStackScreenProps(Screens.FiatExchangeAmount, {
currency: CiCoCurrency.CELO,
+ tokenId: mockCeloTokenId,
flow: CICOFlow.CashOut,
network: Network.Celo,
})
@@ -362,6 +381,7 @@ describe('FiatExchangeAmount cashOut', () => {
})
store.dispatch = jest.fn()
const screenProps = getMockStackScreenProps(Screens.FiatExchangeAmount, {
+ tokenId: mockCusdTokenId,
currency: CiCoCurrency.cUSD,
flow: CICOFlow.CashOut,
network: Network.Celo,
@@ -413,6 +433,7 @@ describe('FiatExchangeAmount cashOut', () => {
store.dispatch = jest.fn()
const screenProps = getMockStackScreenProps(Screens.FiatExchangeAmount, {
currency: CiCoCurrency.cUSD,
+ tokenId: mockCusdTokenId,
flow: CICOFlow.CashOut,
network: Network.Celo,
})
diff --git a/src/fiatExchanges/FiatExchangeAmount.tsx b/src/fiatExchanges/FiatExchangeAmount.tsx
index 6a2957950fd..9b9b1dc0d80 100644
--- a/src/fiatExchanges/FiatExchangeAmount.tsx
+++ b/src/fiatExchanges/FiatExchangeAmount.tsx
@@ -17,7 +17,7 @@ import Button, { BtnSizes, BtnTypes } from 'src/components/Button'
import Dialog from 'src/components/Dialog'
import KeyboardAwareScrollView from 'src/components/KeyboardAwareScrollView'
import KeyboardSpacer from 'src/components/KeyboardSpacer'
-import LegacyTokenDisplay from 'src/components/LegacyTokenDisplay'
+import TokenDisplay from 'src/components/TokenDisplay'
import LineItemRow from 'src/components/LineItemRow'
import { ALERT_BANNER_DURATION, DOLLAR_ADD_FUNDS_MAX_AMOUNT } from 'src/config'
import { useMaxSendAmount } from 'src/fees/hooks'
@@ -42,15 +42,12 @@ import { StatsigFeatureGates } from 'src/statsig/types'
import colors from 'src/styles/colors'
import fontStyles from 'src/styles/fonts'
import variables from 'src/styles/variables'
-import {
- useLocalToTokenAmount,
- useTokenInfoWithAddressBySymbol,
- useTokenToLocalAmount,
-} from 'src/tokens/hooks'
+import { useLocalToTokenAmount, useTokenInfo, useTokenToLocalAmount } from 'src/tokens/hooks'
import Logger from 'src/utils/Logger'
import { CiCoCurrency, currencyForAnalytics } from 'src/utils/currencies'
import { roundUp } from 'src/utils/formatting'
import { CICOFlow, isUserInputCrypto } from './utils'
+import networkConfig from 'src/web3/networkConfig'
const TAG = 'FiatExchangeAmount'
@@ -70,7 +67,7 @@ type Props = RouteProps
function FiatExchangeAmount({ route }: Props) {
const { t } = useTranslation()
- const { currency, flow, network } = route.params
+ const { currency, flow, network, tokenId } = route.params
const [showingInvalidAmountDialog, setShowingInvalidAmountDialog] = useState(false)
const closeInvalidAmountDialog = () => {
@@ -78,7 +75,7 @@ function FiatExchangeAmount({ route }: Props) {
}
const [inputAmount, setInputAmount] = useState('')
const parsedInputAmount = parseInputAmount(inputAmount, decimalSeparator)
- const { address } = useTokenInfoWithAddressBySymbol(currency) || {}
+ const { address } = useTokenInfo(tokenId) || {}
const inputConvertedToCrypto =
useLocalToTokenAmount(parsedInputAmount, address) || new BigNumber(0)
@@ -102,11 +99,10 @@ function FiatExchangeAmount({ route }: Props) {
const displayCurrencyKey = cicoCurrencyTranslationKeys[currency]
- const cUSDToken = useTokenInfoWithAddressBySymbol(CiCoCurrency.cUSD)!
+ const cUSDToken = useTokenInfo(networkConfig.currencyToTokenId[CiCoCurrency.cUSD])!
const localCurrencyMaxAmount =
useTokenToLocalAmount(new BigNumber(DOLLAR_ADD_FUNDS_MAX_AMOUNT), cUSDToken.address) ||
new BigNumber(0)
-
let overLocalLimitDisplayString = ''
if (localCurrencyCode !== LocalCurrencyCode.USD) {
overLocalLimitDisplayString = ` (${localCurrencySymbol}${roundUp(localCurrencyMaxAmount)})`
@@ -245,9 +241,9 @@ function FiatExchangeAmount({ route }: Props) {
<>
{`${t(displayCurrencyKey)} @ `}
{
-
@@ -255,9 +251,9 @@ function FiatExchangeAmount({ route }: Props) {
>
}
amount={
-
@@ -291,7 +287,7 @@ FiatExchangeAmount.navOptions = ({
}: {
route: RouteProp
}) => {
- const { currency, flow } = route.params
+ const { currency, flow, tokenId } = route.params
const inputIsCrypto = isUserInputCrypto(flow)
return {
...emptyHeader,
@@ -306,7 +302,7 @@ FiatExchangeAmount.navOptions = ({
currency,
}
)}
- currency={currency}
+ tokenId={tokenId}
showLocalAmount={!inputIsCrypto}
/>
),
@@ -315,14 +311,14 @@ FiatExchangeAmount.navOptions = ({
function FiatExchangeAmountHeader({
title,
- currency,
+ tokenId,
showLocalAmount,
}: {
title: string | React.ReactNode
- currency: CiCoCurrency
+ tokenId: string
showLocalAmount: boolean
}) {
- const tokenInfo = useTokenInfoWithAddressBySymbol(currency)
+ const tokenInfo = useTokenInfo(tokenId)
return (
({
@@ -44,6 +45,7 @@ describe('FiatExchangeCurrency', () => {
fireEvent.press(tree.getByText('next'))
expect(navigate).toHaveBeenCalledWith(Screens.FiatExchangeAmount, {
currency: 'cUSD',
+ tokenId: mockCusdTokenId,
flow: FiatExchangeFlow.CashIn,
network: Network.Celo,
})
@@ -61,6 +63,7 @@ describe('FiatExchangeCurrency', () => {
fireEvent.press(tree.getByText('next'))
expect(navigate).toHaveBeenCalledWith(Screens.FiatExchangeAmount, {
currency: 'cEUR',
+ tokenId: mockCeurTokenId,
flow: FiatExchangeFlow.CashIn,
network: Network.Celo,
})
@@ -77,6 +80,7 @@ describe('FiatExchangeCurrency', () => {
fireEvent.press(tree.getByTestId('radio/CELO'))
fireEvent.press(tree.getByText('next'))
expect(navigate).toHaveBeenCalledWith(Screens.FiatExchangeAmount, {
+ tokenId: mockCeloTokenId,
currency: 'CELO',
flow: FiatExchangeFlow.CashIn,
network: Network.Celo,
@@ -97,6 +101,7 @@ describe('FiatExchangeCurrency', () => {
fireEvent.press(tree.getByTestId('radio/ETH'))
fireEvent.press(tree.getByText('next'))
expect(navigate).toHaveBeenCalledWith(Screens.FiatExchangeAmount, {
+ tokenId: mockEthTokenId,
currency: 'ETH',
flow: FiatExchangeFlow.CashIn,
network: Network.Ethereum,
diff --git a/src/fiatExchanges/FiatExchangeCurrency.tsx b/src/fiatExchanges/FiatExchangeCurrency.tsx
index 632f2db022e..ad72b8a38b1 100644
--- a/src/fiatExchanges/FiatExchangeCurrency.tsx
+++ b/src/fiatExchanges/FiatExchangeCurrency.tsx
@@ -131,6 +131,7 @@ function FiatExchangeCurrency({ route, navigation }: Props) {
}
navigate(Screens.FiatExchangeAmount, {
currency: selectedCurrency,
+ tokenId: networkConfig.currencyToTokenId[selectedCurrency],
flow: flow === FiatExchangeFlow.CashIn ? CICOFlow.CashIn : CICOFlow.CashOut,
network: CiCoCurrencyNetworkMap[selectedCurrency],
})
diff --git a/src/firebase/notifications.test.ts b/src/firebase/notifications.test.ts
index b08d23369aa..58a9c79067f 100644
--- a/src/firebase/notifications.test.ts
+++ b/src/firebase/notifications.test.ts
@@ -136,6 +136,7 @@ describe(handleNotification, () => {
block: '42',
address: '0xtest',
amount: {
+ tokenId: 'celo-alfajores:0xCUSD',
value: '10',
tokenAddress: '0xCUSD',
},
diff --git a/src/firebase/notifications.ts b/src/firebase/notifications.ts
index d18ab183e8c..45080197f18 100644
--- a/src/firebase/notifications.ts
+++ b/src/firebase/notifications.ts
@@ -29,6 +29,7 @@ import { TokenTransactionTypeV2 } from 'src/transactions/types'
import Logger from 'src/utils/Logger'
import { call, put, select } from 'typed-redux-saga'
import networkConfig from 'src/web3/networkConfig'
+import { getTokenId } from 'src/tokens/utils'
const TAG = 'FirebaseNotifications'
@@ -70,6 +71,7 @@ function handlePaymentReceived(transferNotification: TransferNotificationData) {
block: transferNotification.blockNumber,
address,
amount: {
+ tokenId: getTokenId(networkConfig.defaultNetworkId, transferNotification.tokenAddress),
value: transferNotification.value,
tokenAddress: transferNotification.tokenAddress,
},
diff --git a/src/navigator/Headers.tsx b/src/navigator/Headers.tsx
index 3547e4c21ed..b66bc6cf862 100644
--- a/src/navigator/Headers.tsx
+++ b/src/navigator/Headers.tsx
@@ -6,6 +6,7 @@ import BackButton from 'src/components/BackButton'
import CancelButton from 'src/components/CancelButton'
import CurrencyDisplay from 'src/components/CurrencyDisplay'
import LegacyTokenDisplay from 'src/components/LegacyTokenDisplay'
+import TokenDisplay from 'src/components/TokenDisplay'
import i18n from 'src/i18n'
import BackChevronCentered from 'src/icons/BackChevronCentered'
import Times from 'src/icons/Times'
@@ -227,9 +228,9 @@ export function HeaderTitleWithTokenBalance({
}) {
const subTitle = tokenInfo ? (
-
diff --git a/src/navigator/types.tsx b/src/navigator/types.tsx
index 80cedade432..5065ea4d6db 100644
--- a/src/navigator/types.tsx
+++ b/src/navigator/types.tsx
@@ -103,6 +103,7 @@ export type StackParamList = {
}
[Screens.FiatExchangeAmount]: {
currency: CiCoCurrency
+ tokenId: string
flow: CICOFlow
network: Network
}
diff --git a/src/paymentRequest/PaymentRequestConfirmation.tsx b/src/paymentRequest/PaymentRequestConfirmation.tsx
index f3c4e31c9a8..83f54efb74c 100644
--- a/src/paymentRequest/PaymentRequestConfirmation.tsx
+++ b/src/paymentRequest/PaymentRequestConfirmation.tsx
@@ -13,7 +13,7 @@ import CommentTextInput from 'src/components/CommentTextInput'
import ContactCircle from 'src/components/ContactCircle'
import ReviewFrame from 'src/components/ReviewFrame'
import LegacyTokenDisplay from 'src/components/LegacyTokenDisplay'
-import TokenTotalLineItem from 'src/components/TokenTotalLineItem'
+import LegacyTokenTotalLineItem from 'src/components/LegacyTokenTotalLineItem'
import { emptyHeader } from 'src/navigator/Headers'
import { Screens } from 'src/navigator/Screens'
import { StackParamList } from 'src/navigator/types'
@@ -102,7 +102,10 @@ function PaymentRequestConfirmation({ route }: Props) {
const renderFooter = () => {
return (
-
+
)
}
diff --git a/src/redux/migrations.ts b/src/redux/migrations.ts
index 7d50b7f5051..488f5be19d3 100644
--- a/src/redux/migrations.ts
+++ b/src/redux/migrations.ts
@@ -1323,4 +1323,12 @@ export const migrations = {
...state,
app: _.omit(state.app, 'requireCPV'),
}),
+ 157: (state: any) => ({
+ ...state,
+ transactions: {
+ ...state.transactions,
+ standbyTransactions: [],
+ transactions: [],
+ },
+ }),
}
diff --git a/src/redux/store.test.ts b/src/redux/store.test.ts
index 68b1a3f8440..012350fe568 100644
--- a/src/redux/store.test.ts
+++ b/src/redux/store.test.ts
@@ -98,7 +98,7 @@ describe('store state', () => {
{
"_persist": {
"rehydrated": true,
- "version": 156,
+ "version": 157,
},
"account": {
"acceptedTerms": false,
diff --git a/src/redux/store.ts b/src/redux/store.ts
index eaee8758398..13f5324263c 100644
--- a/src/redux/store.ts
+++ b/src/redux/store.ts
@@ -23,7 +23,7 @@ const persistConfig: PersistConfig = {
key: 'root',
// default is -1, increment as we make migrations
// See https://github.com/valora-inc/wallet/tree/main/WALLET.md#redux-state-migration
- version: 156,
+ version: 157,
keyPrefix: `reduxStore-`, // the redux-persist default is `persist:` which doesn't work with some file systems.
storage: FSStorage(),
blacklist: ['networkInfo', 'alert', 'imports', 'keylessBackup'],
diff --git a/src/send/SendConfirmation.tsx b/src/send/SendConfirmation.tsx
index 3b033601c1c..19127392f4c 100644
--- a/src/send/SendConfirmation.tsx
+++ b/src/send/SendConfirmation.tsx
@@ -19,7 +19,7 @@ import ReviewFrame from 'src/components/ReviewFrame'
import ShortenedAddress from 'src/components/ShortenedAddress'
import TextButton from 'src/components/TextButton'
import LegacyTokenDisplay from 'src/components/LegacyTokenDisplay'
-import TokenTotalLineItem from 'src/components/TokenTotalLineItem'
+import LegacyTokenTotalLineItem from 'src/components/LegacyTokenTotalLineItem'
import Touchable from 'src/components/Touchable'
import { estimateFee, FeeType } from 'src/fees/reducer'
import { feeEstimatesSelector } from 'src/fees/selectors'
@@ -172,7 +172,7 @@ function SendConfirmation(props: Props) {
totalFee={totalFeeInUsd}
showLocalAmount={true}
/>
- {
status: TransactionStatus.Pending,
value: amount.negated().toString(),
tokenAddress: mockCusdAddress,
+ tokenId: mockCusdTokenId,
timestamp: Math.floor(Date.now() / 1000),
address: mockQRCodeRecipient.address,
})
diff --git a/src/send/saga.ts b/src/send/saga.ts
index 445d4544a94..cfb42e7a936 100644
--- a/src/send/saga.ts
+++ b/src/send/saga.ts
@@ -54,6 +54,7 @@ import { getConnectedUnlockedAccount } from 'src/web3/saga'
import { estimateGas } from 'src/web3/utils'
import { call, put, select, spawn, take, takeLeading } from 'typed-redux-saga'
import networkConfig from 'src/web3/networkConfig'
+import { getTokenId } from 'src/tokens/utils'
import * as utf8 from 'utf8'
const TAG = 'send/saga'
@@ -224,6 +225,7 @@ export function* buildAndSendPayment(
status: TransactionStatus.Pending,
value: amount.negated().toString(),
tokenAddress,
+ tokenId: getTokenId(networkConfig.defaultNetworkId, tokenAddress),
timestamp: Math.floor(Date.now() / 1000),
address: recipientAddress,
})
diff --git a/src/statsig/constants.ts b/src/statsig/constants.ts
index 0f83d044d73..466ac41befb 100644
--- a/src/statsig/constants.ts
+++ b/src/statsig/constants.ts
@@ -34,7 +34,6 @@ export const FeatureGates = {
[StatsigFeatureGates.SHOW_NOTIFICATION_CENTER]: false,
[StatsigFeatureGates.SHOW_CLOUD_ACCOUNT_BACKUP_SETUP]: false,
[StatsigFeatureGates.SHOW_CLOUD_ACCOUNT_BACKUP_RESTORE]: false,
- [StatsigFeatureGates.SHOW_NATIVE_TOKENS]: false,
[StatsigFeatureGates.USE_VIEM_FOR_SEND]: false,
}
diff --git a/src/statsig/types.ts b/src/statsig/types.ts
index 03af742ad85..54b47686785 100644
--- a/src/statsig/types.ts
+++ b/src/statsig/types.ts
@@ -30,7 +30,6 @@ export enum StatsigFeatureGates {
SHOW_NOTIFICATION_CENTER = 'show_notification_center',
SHOW_CLOUD_ACCOUNT_BACKUP_SETUP = 'show_cloud_account_backup_setup',
SHOW_CLOUD_ACCOUNT_BACKUP_RESTORE = 'show_cloud_account_backup_restore',
- SHOW_NATIVE_TOKENS = 'show_native_tokens',
USE_VIEM_FOR_SEND = 'use_viem_for_send',
}
diff --git a/src/tokens/TokenDetails.tsx b/src/tokens/TokenDetails.tsx
index 628104eb8d1..f47c31dadd2 100644
--- a/src/tokens/TokenDetails.tsx
+++ b/src/tokens/TokenDetails.tsx
@@ -152,6 +152,7 @@ function Actions({ token }: { token: TokenBalance }) {
if (isCicoToken(tokenSymbol)) {
navigate(Screens.FiatExchangeAmount, {
currency: tokenSymbol,
+ tokenId: token.tokenId,
flow,
network: Network.Celo,
})
diff --git a/src/tokens/hooks.ts b/src/tokens/hooks.ts
index 471bbc74fbf..2cc4ac42041 100644
--- a/src/tokens/hooks.ts
+++ b/src/tokens/hooks.ts
@@ -86,6 +86,12 @@ export function useTokensInfoUnavailable(networkIds: NetworkId[]) {
const totalBalance = useSelector(totalTokenBalanceSelectorWrapper(networkIds))
return totalBalance === null
}
+
+export function useTokensList() {
+ const networkIds = Object.values(networkConfig.networkToNetworkId)
+ return useSelector(tokensListSelectorWrapper(networkIds))
+}
+
export function useTokenPricesAreStale(networkIds: NetworkId[]) {
const tokens = useSelector(tokensListSelectorWrapper(networkIds))
// If no tokens then prices cannot be stale
@@ -170,7 +176,7 @@ export function useTokenInfoByCurrency(currency: Currency) {
export function useLocalToTokenAmount(
localAmount: BigNumber,
- tokenAddress?: string
+ tokenAddress?: string | null
): BigNumber | null {
const tokenInfo = useTokenInfoByAddress(tokenAddress)
const usdToLocalRate = useSelector(usdToLocalCurrencyRateSelector)
@@ -183,7 +189,7 @@ export function useLocalToTokenAmount(
export function useTokenToLocalAmount(
tokenAmount: BigNumber,
- tokenAddress?: string
+ tokenAddress?: string | null
): BigNumber | null {
const tokenInfo = useTokenInfoByAddress(tokenAddress)
const usdToLocalRate = useSelector(usdToLocalCurrencyRateSelector)
@@ -202,7 +208,7 @@ export function useAmountAsUsd(amount: BigNumber, tokenAddress: string) {
return amount.multipliedBy(tokenInfo.priceUsd)
}
-export function useUsdToTokenAmount(amount: BigNumber, tokenAddress?: string) {
+export function useUsdToTokenAmount(amount: BigNumber, tokenAddress?: string | null) {
const tokenInfo = useTokenInfoByAddress(tokenAddress)
if (!tokenInfo?.priceUsd) {
return null
diff --git a/src/tokens/utils.test.tsx b/src/tokens/utils.test.tsx
index a940deb4ade..44e268e7321 100644
--- a/src/tokens/utils.test.tsx
+++ b/src/tokens/utils.test.tsx
@@ -7,8 +7,11 @@ import {
getHigherBalanceCurrency,
isHistoricalPriceUpdated,
sortFirstStableThenCeloThenOthersByUsdBalance,
+ getTokenId,
} from 'src/tokens/utils'
import { Currency } from 'src/utils/currencies'
+import { NetworkId } from 'src/transactions/types'
+import networkConfig from 'src/web3/networkConfig'
import { ONE_DAY_IN_MILLIS, ONE_HOUR_IN_MILLIS } from 'src/utils/time'
import { mockPoofTokenId, mockTokenBalances } from 'test/values'
@@ -199,6 +202,25 @@ describe(convertTokenToLocalAmount, () => {
})
})
+describe(getTokenId, () => {
+ it('returns Celo native token correctly', () => {
+ const tokenId = getTokenId(NetworkId['celo-alfajores'], networkConfig.celoTokenAddress)
+ expect(tokenId).toEqual('celo-alfajores:native')
+ })
+ it('returns normal Celo token correctly', () => {
+ const tokenId = getTokenId(NetworkId['celo-alfajores'], '0xsomeaddress')
+ expect(tokenId).toEqual('celo-alfajores:0xsomeaddress')
+ })
+ it('returns Ethereum native token correctly', () => {
+ const tokenId = getTokenId(NetworkId['ethereum-sepolia'])
+ expect(tokenId).toEqual('ethereum-sepolia:native')
+ })
+ it('returns normal Ethereum token correctly', () => {
+ const tokenId = getTokenId(NetworkId['ethereum-sepolia'], '0xsomeaddress')
+ expect(tokenId).toEqual('ethereum-sepolia:0xsomeaddress')
+ })
+})
+
describe(isHistoricalPriceUpdated, () => {
const mockTokenBalance: TokenBalance = {
...mockTokenBalances[mockPoofTokenId],
diff --git a/src/tokens/utils.ts b/src/tokens/utils.ts
index 0db1ff052e7..57bd1eb0958 100644
--- a/src/tokens/utils.ts
+++ b/src/tokens/utils.ts
@@ -1,13 +1,14 @@
import BigNumber from 'bignumber.js'
+import { CurrencyTokens } from 'src/tokens/selectors'
+import { NetworkId, Network } from 'src/transactions/types'
+import { TokenBalance } from './slice'
import { TokenProperties } from 'src/analytics/Properties'
import { getDynamicConfigParams } from 'src/statsig'
import { DynamicConfigs } from 'src/statsig/constants'
+import networkConfig from 'src/web3/networkConfig'
import { StatsigDynamicConfigs } from 'src/statsig/types'
-import { CurrencyTokens } from 'src/tokens/selectors'
-import { NetworkId } from 'src/transactions/types'
import { CiCoCurrency, Currency } from 'src/utils/currencies'
import { ONE_DAY_IN_MILLIS, ONE_HOUR_IN_MILLIS } from 'src/utils/time'
-import { TokenBalance } from './slice'
export function getHigherBalanceCurrency(
currencies: Currency[],
@@ -125,6 +126,17 @@ export function getSupportedNetworkIdsForTokenBalances(): NetworkId[] {
.showBalances
}
+export function getTokenId(networkId: NetworkId, tokenAddress?: string): string {
+ if (
+ (networkId === networkConfig.networkToNetworkId[Network.Celo] &&
+ tokenAddress === networkConfig.celoTokenAddress) ||
+ !tokenAddress
+ ) {
+ return `${networkId}:native`
+ }
+ return `${networkId}:${tokenAddress}`
+}
+
export function showAssetDetailsScreen() {
// TODO(ACT-919): get from feature gate
return false
diff --git a/src/transactions/feed/SwapFeedItem.test.tsx b/src/transactions/feed/SwapFeedItem.test.tsx
index ba2db91514a..2c8c13515f2 100644
--- a/src/transactions/feed/SwapFeedItem.test.tsx
+++ b/src/transactions/feed/SwapFeedItem.test.tsx
@@ -11,7 +11,7 @@ import {
NetworkId,
} from 'src/transactions/types'
import { createMockStore, getElementText, RecursivePartial } from 'test/utils'
-import { mockCeurAddress, mockCusdAddress } from 'test/values'
+import { mockCeurTokenId, mockCusdTokenId } from 'test/values'
const MOCK_TX_HASH = '0x006b866d20452a24d1d90c7514422188cc7c5d873e2f1ed661ec3f810ad5331c'
@@ -77,11 +77,11 @@ describe('SwapFeedItem', () => {
it('renders correctly for cUSD to cEUR swap', async () => {
const { getByTestId } = renderScreen({
inAmount: {
- tokenAddress: mockCeurAddress,
+ tokenId: mockCeurTokenId,
value: 2.93,
},
outAmount: {
- tokenAddress: mockCusdAddress,
+ tokenId: mockCusdTokenId,
value: 2.87,
},
})
@@ -97,11 +97,11 @@ describe('SwapFeedItem', () => {
it('renders correctly for cEUR to cUSD swap', async () => {
const { getByTestId } = renderScreen({
inAmount: {
- tokenAddress: mockCusdAddress,
+ tokenId: mockCusdTokenId,
value: 17.87,
},
outAmount: {
- tokenAddress: mockCeurAddress,
+ tokenId: mockCeurTokenId,
value: 17.54,
},
})
diff --git a/src/transactions/feed/SwapFeedItem.tsx b/src/transactions/feed/SwapFeedItem.tsx
index a8cf56f90ae..88b054b7e36 100644
--- a/src/transactions/feed/SwapFeedItem.tsx
+++ b/src/transactions/feed/SwapFeedItem.tsx
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'
import { StyleSheet, Text, View } from 'react-native'
import { HomeEvents } from 'src/analytics/Events'
import ValoraAnalytics from 'src/analytics/ValoraAnalytics'
-import LegacyTokenDisplay from 'src/components/LegacyTokenDisplay'
+import TokenDisplay from 'src/components/TokenDisplay'
import Touchable from 'src/components/Touchable'
import SwapIcon from 'src/icons/SwapIcon'
import { navigate } from 'src/navigator/NavigationService'
@@ -11,7 +11,7 @@ import { Screens } from 'src/navigator/Screens'
import colors from 'src/styles/colors'
import fontStyles from 'src/styles/fonts'
import variables from 'src/styles/variables'
-import { useTokenInfoByAddress } from 'src/tokens/hooks'
+import { useTokenInfo } from 'src/tokens/hooks'
import { TokenExchange } from 'src/transactions/types'
interface Props {
@@ -20,8 +20,8 @@ interface Props {
function SwapFeedItem({ exchange }: Props) {
const { t } = useTranslation()
- const incomingTokenInfo = useTokenInfoByAddress(exchange.inAmount.tokenAddress)
- const outgoingTokenInfo = useTokenInfoByAddress(exchange.outAmount.tokenAddress)
+ const incomingTokenInfo = useTokenInfo(exchange.inAmount.tokenId)
+ const outgoingTokenInfo = useTokenInfo(exchange.outAmount.tokenId)
const handleTransferDetails = () => {
navigate(Screens.TransactionDetailsScreen, { transaction: exchange })
@@ -44,9 +44,9 @@ function SwapFeedItem({ exchange }: Props) {
-
- {
amount = {
value: 10,
tokenAddress: mockCusdAddress,
+ tokenId: mockCusdTokenId,
localAmount: {
currencyCode: 'EUR',
exchangeRate: '0.4',
@@ -107,10 +111,12 @@ describe('TransactionDetailsScreen', () => {
inAmount = {
value: 34,
tokenAddress: mockCeurAddress,
+ tokenId: mockCeurTokenId,
},
outAmount = {
value: 17,
tokenAddress: mockCusdAddress,
+ tokenId: mockCusdTokenId,
},
metadata = {},
fees = [],
@@ -145,6 +151,7 @@ describe('TransactionDetailsScreen', () => {
amount: {
value: '0.01',
tokenAddress: mockCeloAddress,
+ tokenId: mockCeloTokenId,
localAmount: {
value: '0.04',
currencyCode: 'EUR',
@@ -216,6 +223,7 @@ describe('TransactionDetailsScreen', () => {
amount: {
value: 0.1,
tokenAddress: mockCusdAddress,
+ tokenId: mockCusdTokenId,
},
},
],
diff --git a/src/transactions/feed/TransactionDetailsScreen.tsx b/src/transactions/feed/TransactionDetailsScreen.tsx
index 322772aea9f..5202c7ae8cb 100644
--- a/src/transactions/feed/TransactionDetailsScreen.tsx
+++ b/src/transactions/feed/TransactionDetailsScreen.tsx
@@ -10,7 +10,8 @@ import { Screens } from 'src/navigator/Screens'
import { StackParamList } from 'src/navigator/types'
import { coinbasePaySendersSelector, rewardsSendersSelector } from 'src/recipients/reducer'
import useSelector from 'src/redux/useSelector'
-import { tokensByCurrencySelector } from 'src/tokens/selectors'
+import { useTokenInfo } from 'src/tokens/hooks'
+import networkConfig from 'src/web3/networkConfig'
import TransferSentContent from 'src/transactions/feed/detailContent/TransferSentContent'
import {
TokenExchange,
@@ -28,8 +29,7 @@ type Props = NativeStackScreenProps ({
getFeatureGate: jest.fn(() => false),
@@ -31,6 +31,7 @@ const mockTransaction = (transactionHash: string): TokenTransaction => {
networkId: NetworkId['celo-alfajores'],
address: '0xd68360cce1f1ff696d898f58f03e0f1252f2ea33',
amount: {
+ tokenId: mockCusdTokenId,
tokenAddress: mockCusdAddress,
value: '0.1',
},
@@ -53,6 +54,7 @@ const MOCK_STANDBY_TRANSACTIONS: StandbyTransaction[] = [
status: TransactionStatus.Pending,
value: '0.5',
tokenAddress: mockCusdAddress,
+ tokenId: mockCusdTokenId,
comment: '',
timestamp: 1542300000,
address: '0xd68360cce1f1ff696d898f58f03e0f1252f2ea33',
diff --git a/src/transactions/feed/TransactionFeed.tsx b/src/transactions/feed/TransactionFeed.tsx
index b59f72389dc..3185e9be4dc 100644
--- a/src/transactions/feed/TransactionFeed.tsx
+++ b/src/transactions/feed/TransactionFeed.tsx
@@ -32,6 +32,7 @@ function mapStandbyTransactionToFeedTokenTransaction(tx: StandbyTransaction): Fe
block: '',
address: transferTx.address,
amount: {
+ tokenId: transferTx.tokenId,
value: transferTx.value,
tokenAddress: transferTx.tokenAddress,
},
diff --git a/src/transactions/feed/TransferFeedItem.test.tsx b/src/transactions/feed/TransferFeedItem.test.tsx
index 84bf99b26bf..bebd916b223 100644
--- a/src/transactions/feed/TransferFeedItem.test.tsx
+++ b/src/transactions/feed/TransferFeedItem.test.tsx
@@ -21,7 +21,9 @@ import {
import { createMockStore, getElementText, RecursivePartial } from 'test/utils'
import {
mockCeloAddress,
+ mockCeloTokenId,
mockCusdAddress,
+ mockCusdTokenId,
mockFiatConnectQuotes,
mockName,
mockTestTokenAddress,
@@ -61,6 +63,7 @@ describe('TransferFeedItem', () => {
type = TokenTransactionTypeV2.Sent,
amount = {
tokenAddress: mockCusdAddress,
+ tokenId: mockCusdTokenId,
value: 10,
},
metadata = {},
@@ -444,6 +447,7 @@ describe('TransferFeedItem', () => {
const { getByTestId } = renderScreen({
amount: {
tokenAddress: mockCusdAddress,
+ tokenId: mockCusdTokenId,
value: 10,
localAmount: {
currencyCode: LocalCurrencyCode.PHP,
@@ -465,6 +469,7 @@ describe('TransferFeedItem', () => {
const { getByTestId, queryByTestId } = renderScreen({
amount: {
tokenAddress: mockTestTokenAddress,
+ tokenId: mockTestTokenTokenId,
value: 10,
},
storeOverrides: {
@@ -495,6 +500,7 @@ describe('TransferFeedItem', () => {
const { getByTestId, queryByTestId } = renderScreen({
amount: {
tokenAddress: mockCeloAddress,
+ tokenId: mockCeloTokenId,
value: 10,
localAmount: {
currencyCode: 'EUR',
@@ -541,6 +547,7 @@ describe('TransferFeedItem', () => {
const { getByTestId } = renderScreen({
type: TokenTransactionTypeV2.Sent,
amount: {
+ tokenId: mockCusdTokenId,
tokenAddress: mockCusdAddress,
value: transferTotalCost,
},
diff --git a/src/transactions/feed/TransferFeedItem.tsx b/src/transactions/feed/TransferFeedItem.tsx
index c7b2da8b40d..431ee2c0db0 100644
--- a/src/transactions/feed/TransferFeedItem.tsx
+++ b/src/transactions/feed/TransferFeedItem.tsx
@@ -4,14 +4,14 @@ import { StyleSheet, Text, View } from 'react-native'
import { HomeEvents } from 'src/analytics/Events'
import ValoraAnalytics from 'src/analytics/ValoraAnalytics'
import ContactCircle from 'src/components/ContactCircle'
-import LegacyTokenDisplay from 'src/components/LegacyTokenDisplay'
+import TokenDisplay from 'src/components/TokenDisplay'
import Touchable from 'src/components/Touchable'
import { navigate } from 'src/navigator/NavigationService'
import { Screens } from 'src/navigator/Screens'
import colors from 'src/styles/colors'
import fontStyles from 'src/styles/fonts'
import variables from 'src/styles/variables'
-import { useTokenInfoByAddress } from 'src/tokens/hooks'
+import { useTokenInfo } from 'src/tokens/hooks'
import { FeedTokenProperties } from 'src/transactions/feed/TransactionFeed'
import { useTransferFeedDetails } from 'src/transactions/transferFeedUtils'
import { TokenTransfer } from 'src/transactions/types'
@@ -32,7 +32,7 @@ function TransferFeedItem({ transfer }: Props) {
ValoraAnalytics.track(HomeEvents.transaction_feed_item_select)
}
- const tokenInfo = useTokenInfoByAddress(amount.tokenAddress)
+ const tokenInfo = useTokenInfo(amount.tokenId)
const showTokenAmount = !amount.localAmount && !tokenInfo?.priceUsd
const { title, subtitle, recipient, customLocalAmount } = useTransferFeedDetails(transfer)
@@ -55,9 +55,9 @@ function TransferFeedItem({ transfer }: Props) {
-
{!showTokenAmount && (
- {t('learnMore')}
- token.address === exchange.outAmount.tokenAddress
+ (token) => token.tokenId === exchange.outAmount.tokenId
)?.symbol
const toTokenSymbol = tokensList.find(
- (token) => token.address === exchange.inAmount.tokenAddress
+ (token) => token.tokenId === exchange.inAmount.tokenId
)?.symbol
const onPressTxDetails = () => {
@@ -45,10 +44,10 @@ export default function SwapContent({ exchange }: Props) {
{t('swapTransactionDetailPage.swapTo')}
-
{t('swapTransactionDetailPage.swapFrom')}
-
{t('swapTransactionDetailPage.estimatedFee')}
- state.app.celoEducationUri)
- const isCeloTx = amount.tokenAddress === celoAddress
+ const isCeloTx = amount.tokenId === celoTokenId
const recipient = getRecipientFromAddress(address, info, metadata.title, metadata.image)
const openLearnMore = () => {
@@ -53,7 +53,7 @@ function TransferReceivedContent({ transfer }: { transfer: TokenTransfer }) {
{
return {
@@ -13,6 +13,7 @@ const mockFeedItem = (timestamp: number, comment: string): FeedTokenTransaction
amount: {
value: '5.05',
tokenAddress: mockCusdAddress,
+ tokenId: mockCusdTokenId,
localAmount: undefined,
},
fees: [],
diff --git a/src/viem/saga.ts b/src/viem/saga.ts
index 3a5b6ae3ecb..7d56fab6435 100644
--- a/src/viem/saga.ts
+++ b/src/viem/saga.ts
@@ -33,7 +33,7 @@ import networkConfig from 'src/web3/networkConfig'
import { unlockAccount } from 'src/web3/saga'
import { call, put } from 'typed-redux-saga'
import { SimulateContractReturnType, TransactionReceipt, getAddress } from 'viem'
-
+import { getTokenId } from 'src/tokens/utils'
const TAG = 'viem/saga'
/**
@@ -111,6 +111,7 @@ export function* sendPayment({
status: TransactionStatus.Pending,
value: amount.negated().toString(),
tokenAddress,
+ tokenId: getTokenId(networkConfig.defaultNetworkId, tokenAddress),
timestamp: Math.floor(Date.now() / 1000),
address: recipientAddress,
})
diff --git a/src/web3/networkConfig.ts b/src/web3/networkConfig.ts
index 27e0d6c5b4f..de142a0c2f2 100644
--- a/src/web3/networkConfig.ts
+++ b/src/web3/networkConfig.ts
@@ -11,6 +11,7 @@ import {
mainnet as ethereum,
sepolia as ethereumSepolia,
} from 'viem/chains'
+import { CiCoCurrency, Currency } from 'src/utils/currencies'
export enum Testnets {
alfajores = 'alfajores',
@@ -66,8 +67,30 @@ interface NetworkConfig {
viemChain: {
[key in Network]: ViemChain
}
+ currencyToTokenId: {
+ [key in CiCoCurrency | Currency]: string
+ }
+ celoTokenAddress: string
}
+const CELO_TOKEN_ADDRESS_STAGING = '0xf194afdf50b03e69bd7d057c1aa9e10c9954e4c9'
+const CELO_TOKEN_ADDRESS_MAINNET = '0x471ece3750da237f93b8e339c536989b8978a438'
+
+const CELO_TOKEN_ID_STAGING = `${NetworkId['celo-alfajores']}:native`
+const CELO_TOKEN_ID_MAINNET = `${NetworkId['celo-mainnet']}:native`
+
+const CUSD_TOKEN_ID_STAGING = `${NetworkId['celo-alfajores']}:0x874069fa1eb16d44d622f2e0ca25eea172369bc1`
+const CUSD_TOKEN_ID_MAINNET = `${NetworkId['celo-mainnet']}:0x765de816845861e75a25fca122bb6898b8b1282a`
+
+const CEUR_TOKEN_ID_STAGING = `${NetworkId['celo-alfajores']}:0x10c892a6ec43a53e45d0b916b4b7d383b1b78c0f`
+const CEUR_TOKEN_ID_MAINNET = `${NetworkId['celo-mainnet']}:0xd8763cba276a3738e6de85b4b3bf5fded6d6ca73`
+
+const CREAL_TOKEN_ID_STAGING = `${NetworkId['celo-alfajores']}:0xe4d517785d091d3c54818832db6094bcc2744545`
+const CREAL_TOKEN_ID_MAINNET = `${NetworkId['celo-mainnet']}:0xe8537a3d056da446677b9e9d6c5db704eaab4787`
+
+const ETH_TOKEN_ID_STAGING = `${NetworkId['ethereum-sepolia']}:native`
+const ETH_TOKEN_ID_MAINNET = `${NetworkId['ethereum-mainnet']}:native`
+
const CLOUD_FUNCTIONS_STAGING = 'https://api.alfajores.valora.xyz'
const CLOUD_FUNCTIONS_MAINNET = 'https://api.mainnet.valora.xyz'
@@ -236,6 +259,15 @@ const networkConfigs: { [testnet: string]: NetworkConfig } = {
[Network.Celo]: celoAlfajores,
[Network.Ethereum]: ethereumSepolia,
},
+ currencyToTokenId: {
+ [CiCoCurrency.CELO]: CELO_TOKEN_ID_STAGING,
+ [CiCoCurrency.cUSD]: CUSD_TOKEN_ID_STAGING,
+ [CiCoCurrency.cEUR]: CEUR_TOKEN_ID_STAGING,
+ [CiCoCurrency.cREAL]: CREAL_TOKEN_ID_STAGING,
+ [CiCoCurrency.ETH]: ETH_TOKEN_ID_STAGING,
+ [Currency.Celo]: CELO_TOKEN_ID_STAGING,
+ },
+ celoTokenAddress: CELO_TOKEN_ADDRESS_STAGING,
},
[Testnets.mainnet]: {
networkId: '42220',
@@ -295,6 +327,15 @@ const networkConfigs: { [testnet: string]: NetworkConfig } = {
[Network.Celo]: celo,
[Network.Ethereum]: ethereum,
},
+ currencyToTokenId: {
+ [CiCoCurrency.CELO]: CELO_TOKEN_ID_MAINNET,
+ [CiCoCurrency.cUSD]: CUSD_TOKEN_ID_MAINNET,
+ [CiCoCurrency.cEUR]: CEUR_TOKEN_ID_MAINNET,
+ [CiCoCurrency.cREAL]: CREAL_TOKEN_ID_MAINNET,
+ [CiCoCurrency.ETH]: ETH_TOKEN_ID_MAINNET,
+ [Currency.Celo]: CELO_TOKEN_ID_MAINNET,
+ },
+ celoTokenAddress: CELO_TOKEN_ADDRESS_MAINNET,
},
}
diff --git a/test/RootStateSchema.json b/test/RootStateSchema.json
index 8b041d9dcb5..4e0d14c894d 100644
--- a/test/RootStateSchema.json
+++ b/test/RootStateSchema.json
@@ -2725,6 +2725,9 @@
"tokenAddress": {
"type": "string"
},
+ "tokenId": {
+ "type": "string"
+ },
"type": {
"$ref": "#/definitions/TokenTransferTypeV2"
},
@@ -2739,6 +2742,7 @@
"networkId",
"status",
"timestamp",
+ "tokenId",
"type",
"value"
],
@@ -4580,11 +4584,15 @@
"tokenAddress": {
"type": "string"
},
+ "tokenId": {
+ "type": "string"
+ },
"value": {
"$ref": "#/definitions/BigNumber.Value"
}
},
"required": [
+ "tokenId",
"value"
],
"type": "object"
diff --git a/test/schemas.ts b/test/schemas.ts
index d1bffded4e8..e0bfe8d0b09 100644
--- a/test/schemas.ts
+++ b/test/schemas.ts
@@ -2657,6 +2657,19 @@ export const v156Schema = {
app: _.omit(v155Schema.app, 'requireCPV'),
}
+export const v157Schema = {
+ ...v156Schema,
+ _persist: {
+ ...v156Schema._persist,
+ version: 157,
+ },
+ transactions: {
+ ...v156Schema.transactions,
+ standbyTransactions: [],
+ transactions: [],
+ },
+}
+
export function getLatestSchema(): Partial {
- return v156Schema as Partial
+ return v157Schema as Partial
}
diff --git a/test/values.ts b/test/values.ts
index ddaca9d5118..c441df4c5e6 100644
--- a/test/values.ts
+++ b/test/values.ts
@@ -126,6 +126,7 @@ export const mockPoofTokenId = `celo-alfajores:${mockPoofAddress}`
export const mockTestTokenTokenId = `celo-alfajores:${mockTestTokenAddress}`
export const mockCrealTokenId = `celo-alfajores:${mockCrealAddress}`
export const mockWBTCTokenId = `celo-alfajores:${mockWBTCAddress}`
+export const mockEthTokenId = 'ethereum-sepolia:native'
export const mockQrCodeData2 = {
address: mockAccount2Invite,