diff --git a/.changelog/1245.feature.md b/.changelog/1245.feature.md new file mode 100644 index 0000000000..5716493c19 --- /dev/null +++ b/.changelog/1245.feature.md @@ -0,0 +1 @@ +Add Pontus-X as a hidden layer diff --git a/src/app/components/Search/search-utils.ts b/src/app/components/Search/search-utils.ts index 32ae1e3834..79d013ef17 100644 --- a/src/app/components/Search/search-utils.ts +++ b/src/app/components/Search/search-utils.ts @@ -33,6 +33,7 @@ export const searchSuggestionTerms = { suggestedTokenFragment: 'mock', }, cipher: undefined, + pontusx: undefined, consensus: undefined, }, testnet: { @@ -49,6 +50,13 @@ export const searchSuggestionTerms = { suggestedTokenFragment: 'USD', }, cipher: undefined, + pontusx: { + // TODO: provide proper suggestions + suggestedBlock: '4260', + suggestedTransaction: '0xd9b5c08be1cb74229abedd9b3e1afb8b43228085a6abf72993db415959ab6b35', + suggestedAccount: '0xfA3AC9f65C9D75EE3978ab76c6a1105f03156204', + suggestedTokenFragment: 'USD', + }, consensus: undefined, }, } satisfies SpecifiedPerEnabledLayer diff --git a/src/app/pages/HomePage/Graph/Graph/graph-utils.ts b/src/app/pages/HomePage/Graph/Graph/graph-utils.ts index 0f138c90b3..a658da6eaa 100644 --- a/src/app/pages/HomePage/Graph/Graph/graph-utils.ts +++ b/src/app/pages/HomePage/Graph/Graph/graph-utils.ts @@ -27,6 +27,10 @@ export abstract class GraphUtils { x: 1.2 * width, y: 0.7 * height, } + case Layer.pontusx: + // TODO: update this if/when we want to display this layer + // We meed this case here since this switch/case is declared to be exhaustive. + return initialValue case Layer.sapphire: return { scale: 2.4, diff --git a/src/app/pages/HomePage/Graph/Graph/index.tsx b/src/app/pages/HomePage/Graph/Graph/index.tsx index c4f49642af..0def0bfe0b 100644 --- a/src/app/pages/HomePage/Graph/Graph/index.tsx +++ b/src/app/pages/HomePage/Graph/Graph/index.tsx @@ -293,7 +293,7 @@ const GraphCmp: ForwardRefRenderFunction = ( return !RouteUtils.getEnabledLayersForNetwork(network).includes(Layer) } - const disabledMap: Record = { + const disabledMap: Partial> = { [Layer.emerald]: isLayerDisabled(Layer.emerald), [Layer.consensus]: isLayerDisabled(Layer.consensus), [Layer.cipher]: isLayerDisabled(Layer.cipher), diff --git a/src/app/pages/HomePage/Graph/GraphTooltipMobile/index.tsx b/src/app/pages/HomePage/Graph/GraphTooltipMobile/index.tsx index fafd6fec8f..c84160e8b2 100644 --- a/src/app/pages/HomePage/Graph/GraphTooltipMobile/index.tsx +++ b/src/app/pages/HomePage/Graph/GraphTooltipMobile/index.tsx @@ -140,7 +140,7 @@ const layerTooltipBodyCaption = (t: TFunction, layer: Layer, enabled: boolean, o : t('common.paraTimeOnline') } -const useLayerTooltipMap = (network: Network): Record => { +const useLayerTooltipMap = (network: Network): Partial> => { const isSapphireEnabled = RouteUtils.getEnabledLayersForNetwork(network).includes(Layer.sapphire) const isEmeraldEnabled = RouteUtils.getEnabledLayersForNetwork(network).includes(Layer.emerald) const isCipherEnabled = RouteUtils.getEnabledLayersForNetwork(network).includes(Layer.cipher) @@ -270,7 +270,9 @@ export const GraphTooltipMobile: FC = ({ network, layer const navigate = useNavigate() const { t } = useTranslation() const { isMobile } = useScreenSize() - const { body, disabled, failing } = useLayerTooltipMap(network)[layer] + const tooltip = useLayerTooltipMap(network)[layer] + if (!tooltip) return + const { body, disabled, failing } = tooltip const navigateTo = () => { if (disabled) { diff --git a/src/app/pages/ParatimeDashboardPage/LearningMaterials.tsx b/src/app/pages/ParatimeDashboardPage/LearningMaterials.tsx index eaf42f13ec..118f70e5e2 100644 --- a/src/app/pages/ParatimeDashboardPage/LearningMaterials.tsx +++ b/src/app/pages/ParatimeDashboardPage/LearningMaterials.tsx @@ -62,6 +62,7 @@ const getContent = (t: TFunction) => { }, }, [Layer.cipher]: undefined, + [Layer.pontusx]: undefined, }, [Network.testnet]: { [Layer.emerald]: { @@ -99,8 +100,9 @@ const getContent = (t: TFunction) => { }, }, [Layer.cipher]: undefined, + [Layer.pontusx]: undefined, }, - } satisfies SpecifiedPerEnabledRuntime + } satisfies SpecifiedPerEnabledRuntime } export const LearningMaterials: FC<{ scope: SearchScope }> = ({ scope }) => { diff --git a/src/app/pages/SearchResultsPage/GlobalSearchResultsView.tsx b/src/app/pages/SearchResultsPage/GlobalSearchResultsView.tsx index 94a18fab5b..223480793b 100644 --- a/src/app/pages/SearchResultsPage/GlobalSearchResultsView.tsx +++ b/src/app/pages/SearchResultsPage/GlobalSearchResultsView.tsx @@ -16,7 +16,7 @@ import { } from '../../../types/network' import { HideMoreResults, ShowMoreResults } from './notifications' import { getThemesForNetworks } from '../../../styles/theme' -import { orderByLayer } from '../../../types/layers' +import { isNotOnHiddenLayer, orderByLayer } from '../../../types/layers' import { useRedirectIfSingleResult } from './useRedirectIfSingleResult' export const GlobalSearchResultsView: FC<{ @@ -33,7 +33,7 @@ export const GlobalSearchResultsView: FC<{ const otherNetworks = RouteUtils.getEnabledNetworks().filter(isNotMainnet) const notificationTheme = themes[Network.testnet] const mainnetResults = searchResults.filter(isOnMainnet).sort(orderByLayer) - const otherResults = searchResults.filter(isNotOnMainnet).sort(orderByLayer) + const otherResults = searchResults.filter(isNotOnMainnet).filter(isNotOnHiddenLayer).sort(orderByLayer) return ( <> diff --git a/src/app/utils/content.tsx b/src/app/utils/content.tsx index 0a56350483..e714209987 100644 --- a/src/app/utils/content.tsx +++ b/src/app/utils/content.tsx @@ -9,6 +9,7 @@ export const getLayerLabels = (t: TFunction): Record => ({ [Layer.emerald]: t('common.emerald'), [Layer.sapphire]: t('common.sapphire'), [Layer.cipher]: t('common.cipher'), + [Layer.pontusx]: t('common.pontusx'), [Layer.consensus]: t('common.consensus'), }) diff --git a/src/app/utils/externalLinks.ts b/src/app/utils/externalLinks.ts index 2e6d10de57..42a9f7a3f3 100644 --- a/src/app/utils/externalLinks.ts +++ b/src/app/utils/externalLinks.ts @@ -48,6 +48,7 @@ export const faucet = { [Layer.consensus]: faucetUrl, [Layer.emerald]: `${faucetParaTimeBaseUrl}emerald`, [Layer.sapphire]: `${faucetParaTimeBaseUrl}sapphire`, + [Layer.pontusx]: `${faucetParaTimeBaseUrl}pontusx`, [Layer.cipher]: `${faucetParaTimeBaseUrl}cipher`, } diff --git a/src/app/utils/route-utils.ts b/src/app/utils/route-utils.ts index 1bc292cb6f..b8f1916c1e 100644 --- a/src/app/utils/route-utils.ts +++ b/src/app/utils/route-utils.ts @@ -25,6 +25,7 @@ export abstract class RouteUtils { [Layer.emerald]: true, [Layer.sapphire]: true, [Layer.cipher]: false, + [Layer.pontusx]: false, // Disable WIP Consensus on production an staging [Layer.consensus]: !isStableDeploy, }, @@ -32,6 +33,7 @@ export abstract class RouteUtils { [Layer.emerald]: true, [Layer.sapphire]: true, [Layer.cipher]: false, + [Layer.pontusx]: true, [Layer.consensus]: false, }, } satisfies Record> diff --git a/src/app/utils/rpc-utils.ts b/src/app/utils/rpc-utils.ts index fe690f2890..267de26762 100644 --- a/src/app/utils/rpc-utils.ts +++ b/src/app/utils/rpc-utils.ts @@ -20,6 +20,7 @@ const LAYER_DECIMALS: Record = { [Layer.emerald]: paraTimesConfig[Layer.emerald].decimals, [Layer.sapphire]: paraTimesConfig[Layer.sapphire].decimals, [Layer.cipher]: paraTimesConfig[Layer.cipher].decimals, + [Layer.pontusx]: paraTimesConfig[Layer.pontusx].decimals, [Layer.consensus]: consensusDecimals, } diff --git a/src/config.ts b/src/config.ts index 37073c85a3..1e6fe2b4b2 100644 --- a/src/config.ts +++ b/src/config.ts @@ -108,6 +108,32 @@ const sapphireConfig: LayerConfig = { outOfDateThreshold: 2 * 60 * 1000, } +const pontusxConfig: LayerConfig = { + mainnet: { + activeNodes: undefined, + address: undefined, + blockGasLimit: undefined, + runtimeId: undefined, + }, + testnet: { + activeNodes: 8, // TODO use correct number + address: 'oasis1qqczuf3x6glkgjuf0xgtcpjjw95r3crf7y2323xd', // TODO use correct address + // See max_batch_gas https://github.com/oasisprotocol/sapphire-paratime/blob/main/runtime/src/lib.rs#L166 + blockGasLimit: 15_000_000, + runtimeId: '000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c', + }, + local: { + activeNodes: undefined, + address: undefined, + blockGasLimit: undefined, + runtimeId: undefined, + }, + + decimals: 18, + type: RuntimeTypes.Evm, + outOfDateThreshold: 2 * 60 * 1000, +} + type LayersConfig = { [key in Layer]: LayerConfig | null } @@ -116,6 +142,7 @@ export const paraTimesConfig = { [Layer.cipher]: cipherConfig, [Layer.emerald]: emeraldConfig, [Layer.sapphire]: sapphireConfig, + [Layer.pontusx]: pontusxConfig, [Layer.consensus]: null, } satisfies LayersConfig diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 405ad70757..050556ee50 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -87,6 +87,7 @@ "paratime": "Paratime", "parentheses": "({{subject}})", "percentage": "Percentage", + "pontusx": "Pontus-X", "proposal": "Proposal", "proposer": "Proposer", "rank": "Rank", @@ -472,6 +473,7 @@ "sapphireParaTimeDesc": "Confidential EVM Compatible ParaTime providing a smart contract development environment with EVM compatibility", "emeraldParaTimeDesc": "EVM Compatible ParaTime providing smart contract environment with EVM compatibility.", "cipherParaTimeDesc": "The Cipher ParaTime is a Confidential ParaTime for executing Wasm smart contracts.", + "pontusxParaTimeDesc": "Pontus-X ParaTime", "consensusDesc": "Our scalable, high-throughput, secure, proof-of-stake consensus layer run by a decentralized set of validator nodes.", "close": "Close" }, diff --git a/src/oasis-nexus/api.ts b/src/oasis-nexus/api.ts index bd1e14cac2..68595930f8 100644 --- a/src/oasis-nexus/api.ts +++ b/src/oasis-nexus/api.ts @@ -124,6 +124,15 @@ function arrayify(arrayOrItem: null | undefined | T | T[]): T[] { return arrayOrItem } +// TODO: remove when pontusx API is ready +axios.interceptors.request.use(config => { + // Mock pontusx + if (config.url?.includes('/v1/pontusx')) { + config.url = config.url.replace('/v1/pontusx', '/v1/sapphire') + } + return config +}) + export const useGetConsensusTransactions: typeof generated.useGetConsensusTransactions = ( network, params?, diff --git a/src/oasis-nexus/generated/api.ts b/src/oasis-nexus/generated/api.ts index a2d927f428..a46c803f46 100644 --- a/src/oasis-nexus/generated/api.ts +++ b/src/oasis-nexus/generated/api.ts @@ -1759,6 +1759,7 @@ export const Runtime = { emerald: 'emerald', sapphire: 'sapphire', cipher: 'cipher', + pontusx: 'pontusx', } as const; export type Layer = typeof Layer[keyof typeof Layer]; @@ -1769,6 +1770,7 @@ export const Layer = { emerald: 'emerald', sapphire: 'sapphire', cipher: 'cipher', + pontusx: 'pontusx', consensus: 'consensus', } as const; diff --git a/src/types/layers.ts b/src/types/layers.ts index 1f4586dd6b..34c8356a42 100644 --- a/src/types/layers.ts +++ b/src/types/layers.ts @@ -10,6 +10,7 @@ export const getLayerNames = (t: TFunction): Record => ({ [Layer.emerald]: t('common.emerald'), [Layer.sapphire]: t('common.sapphire'), [Layer.cipher]: t('common.cipher'), + [Layer.pontusx]: t('common.pontusx'), [Layer.consensus]: t('common.consensus'), }) @@ -24,9 +25,10 @@ const layerOrder: Record = { [Layer.sapphire]: 2, [Layer.emerald]: 3, [Layer.cipher]: 4, + [Layer.pontusx]: 5, } -const hiddenLayers: Layer[] = [] +const hiddenLayers: Layer[] = [Layer.pontusx] export const orderByLayer = (itemA: HasLayer, itemB: HasLayer): number => layerOrder[itemA.layer] - layerOrder[itemB.layer] @@ -40,3 +42,5 @@ export const doesAnyOfTheseLayersSupportEncryptedTransactions = (layers: Layer[] uniq(layers).some(doesLayerSupportEncryptedTransactions) export const isLayerHidden = (layer: Layer): boolean => hiddenLayers.includes(layer) + +export const isNotOnHiddenLayer = (item: HasLayer) => !isLayerHidden(item.layer)