From a96fb2af57322de1255805dfe07b6fa51ecfedf4 Mon Sep 17 00:00:00 2001 From: Kristof Csillag Date: Fri, 16 Feb 2024 02:16:56 +0100 Subject: [PATCH] Add support for using different tokens on ParaTimes Up to now, we assumed that the native token on each ParaTime is always the same as the native token on the network. Unfortunately this is not always true, so now we have to make it possible to use different tokens on paratimes. --- .../RuntimeTransactionDetailPage/index.tsx | 5 +++-- .../pages/RuntimeTransactionsPage/index.tsx | 4 ++-- .../SearchResultsPage/SearchResultsList.tsx | 7 ++++--- .../__tests__/SearchResultsList.test.tsx | 9 +++++---- src/coin-gecko/api.ts | 15 ++++++++------ src/config.ts | 20 ++++++++++++++++++- src/oasis-nexus/api.ts | 10 +++++----- 7 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/app/pages/RuntimeTransactionDetailPage/index.tsx b/src/app/pages/RuntimeTransactionDetailPage/index.tsx index 29e820fd67..5687cd23c6 100644 --- a/src/app/pages/RuntimeTransactionDetailPage/index.tsx +++ b/src/app/pages/RuntimeTransactionDetailPage/index.tsx @@ -26,7 +26,8 @@ import { TransactionLink } from '../../components/Transactions/TransactionLink' import { TransactionEvents } from '../../components/Transactions/TransactionEvents' import { useRequiredScopeParam } from '../../hooks/useScopeParam' import { DashboardLink } from '../ParatimeDashboardPage/DashboardLink' -import { getNameForTicker, getTickerForNetwork, Ticker } from '../../../types/ticker' +import { getNameForTicker, Ticker } from '../../../types/ticker' +import { getTickerForScope } from '../../../config' import { TokenPriceInfo, useTokenPrice } from '../../../coin-gecko/api' import { CurrentFiatValue } from './CurrentFiatValue' import { AddressSwitch, AddressSwitchOption } from '../../components/AddressSwitch' @@ -102,7 +103,7 @@ export const RuntimeTransactionDetailPage: FC = () => { data?.data, ) - const tokenPriceInfo = useTokenPrice(getTickerForNetwork(scope.network)) + const tokenPriceInfo = useTokenPrice(getTickerForScope(scope)) if (!transaction && !isLoading) { throw AppErrors.NotFoundTxHash diff --git a/src/app/pages/RuntimeTransactionsPage/index.tsx b/src/app/pages/RuntimeTransactionsPage/index.tsx index 4419d2f352..6b9ab1666b 100644 --- a/src/app/pages/RuntimeTransactionsPage/index.tsx +++ b/src/app/pages/RuntimeTransactionsPage/index.tsx @@ -15,7 +15,7 @@ import { TableLayout, TableLayoutButton } from '../../components/TableLayoutButt import { RuntimeTransactionDetailView } from '../RuntimeTransactionDetailPage' import { useRequiredScopeParam } from '../../hooks/useScopeParam' import { useTokenPrice } from '../../../coin-gecko/api' -import { getTickerForNetwork } from '../../../types/ticker' +import { getTickerForScope } from '../../../config' import { VerticalList } from '../../components/VerticalList' const limit = NUMBER_OF_ITEMS_ON_SEPARATE_PAGE @@ -35,7 +35,7 @@ export const RuntimeTransactionsPage: FC = () => { // we should call useGetConsensusTransactions() } - const tokenPriceInfo = useTokenPrice(getTickerForNetwork(scope.network)) + const tokenPriceInfo = useTokenPrice(getTickerForScope(scope)) useEffect(() => { if (!isMobile) { diff --git a/src/app/pages/SearchResultsPage/SearchResultsList.tsx b/src/app/pages/SearchResultsPage/SearchResultsList.tsx index 4eb4945fd3..2da0f092b5 100644 --- a/src/app/pages/SearchResultsPage/SearchResultsList.tsx +++ b/src/app/pages/SearchResultsPage/SearchResultsList.tsx @@ -21,6 +21,7 @@ import { AllTokenPrices } from '../../../coin-gecko/api' import { ResultListFrame } from './ResultListFrame' import { TokenDetails } from '../../components/Tokens/TokenDetails' import { ProposalDetailView } from '../ProposalDetailsPage' +import { getTickerForScope } from '../../../config' /** * Component for displaying a list of search results @@ -70,7 +71,7 @@ export const SearchResultsList: FC<{ )} @@ -86,7 +87,7 @@ export const SearchResultsList: FC<{ isLoading={false} isError={false} account={item} - tokenPriceInfo={tokenPrices[item.network]} + tokenPriceInfo={tokenPrices[getTickerForScope(item)]} showLayer={true} /> )} @@ -102,7 +103,7 @@ export const SearchResultsList: FC<{ isLoading={false} isError={false} account={item} - tokenPriceInfo={tokenPrices[item.network]} + tokenPriceInfo={tokenPrices[getTickerForScope(item)]} showLayer={true} /> )} diff --git a/src/app/pages/SearchResultsPage/__tests__/SearchResultsList.test.tsx b/src/app/pages/SearchResultsPage/__tests__/SearchResultsList.test.tsx index e726877c43..cf9ef0771f 100644 --- a/src/app/pages/SearchResultsPage/__tests__/SearchResultsList.test.tsx +++ b/src/app/pages/SearchResultsPage/__tests__/SearchResultsList.test.tsx @@ -8,6 +8,7 @@ import { } from '../../../utils/test-fixtures' import { Network } from '../../../../types/network' import { SearchResultsList } from '../SearchResultsList' +import { Ticker } from '../../../../types/ticker' describe('SearchResultsView', () => { beforeEach(() => { @@ -24,13 +25,13 @@ describe('SearchResultsView', () => { { title="test search" networkForTheme={Network.mainnet} tokenPrices={{ - [Network.mainnet]: { + [Ticker.ROSE]: { isLoading: false, isFree: false, price: 1, hasUsedCoinGecko: true, }, - [Network.testnet]: { + [Ticker.TEST]: { isLoading: false, isFree: true, hasUsedCoinGecko: false, diff --git a/src/coin-gecko/api.ts b/src/coin-gecko/api.ts index 7e160aad64..9e6afb431f 100644 --- a/src/coin-gecko/api.ts +++ b/src/coin-gecko/api.ts @@ -1,8 +1,8 @@ import axios from 'axios' import type { AxiosResponse, AxiosError } from 'axios' import { useQuery } from '@tanstack/react-query' -import { getTickerForNetwork, NativeTicker, Ticker } from '../types/ticker' -import { Network } from '../types/network' +import { NativeTicker, Ticker } from '../types/ticker' +import { getTickerForScope } from '../config' import { RouteUtils } from '../app/utils/route-utils' import { exhaustedTypeWarning } from '../types/errors' @@ -78,12 +78,15 @@ export const useTokenPrice = (ticker: NativeTicker): TokenPriceInfo => { } } -export type AllTokenPrices = Record +export type AllTokenPrices = Record export const useAllTokenPrices = (): AllTokenPrices => { const results = {} as any - // The list of networks will never change on the run, so we can do this - // eslint-disable-next-line react-hooks/rules-of-hooks - RouteUtils.getEnabledNetworks().forEach(net => (results[net] = useTokenPrice(getTickerForNetwork(net)))) + RouteUtils.getEnabledScopes().forEach(scope => { + const ticker = getTickerForScope(scope) + // The list of networks will never change on the run, so we can do this + // eslint-disable-next-line react-hooks/rules-of-hooks + results[ticker] = useTokenPrice(ticker) + }) return results } diff --git a/src/config.ts b/src/config.ts index fa6ce54c40..751d3356a1 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,5 +1,7 @@ // eslint-disable-next-line no-restricted-imports -import { Layer } from './oasis-nexus/generated/api' // We get this from the generated code to avoid circular imports +import { Layer } from './oasis-nexus/generated/api' +import { getTickerForNetwork, NativeTicker, Ticker } from './types/ticker' +import { SearchScope } from './types/searchScope' // We get this from the generated code to avoid circular imports export const consensusDecimals = 9 @@ -8,6 +10,13 @@ type LayerNetwork = { address: string | undefined blockGasLimit: number | undefined runtimeId: string | undefined + + /** + * What do we call the native ticker on this layer? + * + * (If not given, the network's default token will be used.) + */ + ticker?: NativeTicker } type LayerConfig = { @@ -164,3 +173,12 @@ const stableDeploys = [...deploys.production, deploys.staging] export const isStableDeploy = stableDeploys.some(url => window.location.origin === url) export const getAppTitle = () => process.env.REACT_APP_META_TITLE + +export const getTickerForScope = ({ network, layer }: SearchScope): NativeTicker => { + const networkDefault = getTickerForNetwork(network) + + if (layer !== Layer.consensus) { + return paraTimesConfig[layer][network].ticker ?? networkDefault + } + return networkDefault +} diff --git a/src/oasis-nexus/api.ts b/src/oasis-nexus/api.ts index 68595930f8..feef24e4a0 100644 --- a/src/oasis-nexus/api.ts +++ b/src/oasis-nexus/api.ts @@ -1,7 +1,7 @@ /** @file Wrappers around generated API */ import axios, { AxiosResponse } from 'axios' -import { consensusDecimals, paraTimesConfig } from '../config' +import { consensusDecimals, getTickerForScope, paraTimesConfig } from '../config' import * as generated from './generated/api' import { QueryKey, UseQueryOptions, UseQueryResult } from '@tanstack/react-query' import { @@ -176,7 +176,7 @@ export const useGetRuntimeTransactions: typeof generated.useGetRuntimeTransactio params?, options?, ) => { - const ticker = getTickerForNetwork(network) + const ticker = getTickerForScope({ network, layer: runtime }) return generated.useGetRuntimeTransactions(network, runtime, params, { ...options, request: { @@ -248,7 +248,7 @@ export const useGetRuntimeTransactionsTxHash: typeof generated.useGetRuntimeTran ) => { // Sometimes we will call this with an undefined txHash, so we must be careful here. const actualHash = txHash?.startsWith('0x') ? txHash.substring(2) : txHash - const ticker = getTickerForNetwork(network) + const ticker = getTickerForScope({ network, layer: runtime }) return generated.useGetRuntimeTransactionsTxHash(network, runtime, actualHash, { ...options, request: { @@ -317,7 +317,7 @@ export const useGetRuntimeAccountsAddress: typeof generated.useGetRuntimeAccount const oasisAddress = useTransformToOasisAddress(address) - const ticker = getTickerForNetwork(network) + const ticker = getTickerForScope({ network, layer: runtime }) const query = generated.useGetRuntimeAccountsAddress(network, runtime, oasisAddress!, { ...options, query: { @@ -752,7 +752,7 @@ export const useGetRuntimeEvents: typeof generated.useGetRuntimeEvents = ( event.body.amount.Amount, paraTimesConfig[runtime].decimals, ), - Denomination: getTickerForNetwork(network), + Denomination: getTickerForScope({ network, layer: runtime }), } : event.body.amount, },