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,