diff --git a/.env.example b/.env.example index d971f81e..132aeb0c 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,15 @@ -WS_ROCOCO_CORETIME_CHAIN="WSS endpoint of the coretime chain" -WS_KUSAMA_CORETIME_CHAIN="WSS endpoint of the coretime chain" -WS_ROCOCO_RELAY_CHAIN="WSS endpoint of the coretime relay chain" -WS_KUSAMA_RELAY_CHAIN="WSS endpoint of the coretime relay chain" +WS_ROCOCO_CORETIME_CHAIN="WSS endpoint of the coretime chain on Rococo" +WS_KUSAMA_CORETIME_CHAIN="WSS endpoint of the coretime chain on Kusama" +WS_WESTEND_CORETIME_CHAIN="WSS endpiontof the coretime chain on Westend" + +WS_ROCOCO_RELAY_CHAIN="WSS endpoint of the coretime relay chain - Rococo" +WS_KUSAMA_RELAY_CHAIN="WSS endpoint of the coretime relay chain - Kusama" +WS_WESTEND_RELAY_CHAIN="WSS endpoint of the coretime relay chain - Westend" + WS_REGIONX_COCOS_CHAIN="WSS endpoint of the regionx chain" + SUBSCAN_CORETIME_ROCOCO_API="API endpoint for Rococo Coretime" SUBSCAN_CORETIME_KUSAMA_API="API endpoint for Kusama Coretime" +SUBSCAN_CORETIME_WESTEND_API="API endpoint for Westend Coretime" + EXPERIMENTAL=false diff --git a/next.config.js b/next.config.js index b468f69d..b6b645f0 100644 --- a/next.config.js +++ b/next.config.js @@ -7,11 +7,19 @@ const nextConfig = { env: { WS_ROCOCO_CORETIME_CHAIN: process.env.WS_ROCOCO_CORETIME_CHAIN || '', WS_KUSAMA_CORETIME_CHAIN: process.env.WS_KUSAMA_CORETIME_CHAIN || '', + WS_WESTEND_CORETIME_CHAIN: process.env.WS_WESTEND_CORETIME_CHAIN || '', + SUBSCAN_CORETIME_ROCOCO_API: process.env.SUBSCAN_CORETIME_ROCOCO_API || '', SUBSCAN_CORETIME_KUSAMA_API: process.env.SUBSCAN_CORETIME_KUSAMA_API || '', + SUBSCAN_CORETIME_WESTEND_API: + process.env.SUBSCAN_CORETIME_WESTEND_API || '', + WS_REGIONX_COCOS_CHAIN: process.env.WS_REGIONX_COCOS_CHAIN || '', + WS_ROCOCO_RELAY_CHAIN: process.env.WS_ROCOCO_RELAY_CHAIN, WS_KUSAMA_RELAY_CHAIN: process.env.WS_KUSAMA_RELAY_CHAIN, + WS_WESTEND_RELAY_CHAIN: process.env.WS_WESTEND_RELAY_CHAIN, + EXPERIMENTAL: process.env.EXPERIMENTAL, }, }; diff --git a/src/assets/networks/coretime/index.ts b/src/assets/networks/coretime/index.ts index 6b832342..ee2fcefe 100644 --- a/src/assets/networks/coretime/index.ts +++ b/src/assets/networks/coretime/index.ts @@ -1,4 +1,5 @@ import KusamaCoretime from './kusama.png'; import RococoCoretime from './rococo.png'; +import WestendCoretime from './westend.png'; -export { KusamaCoretime, RococoCoretime }; +export { KusamaCoretime, RococoCoretime, WestendCoretime }; diff --git a/src/assets/networks/coretime/westend.png b/src/assets/networks/coretime/westend.png new file mode 100644 index 00000000..f948c295 Binary files /dev/null and b/src/assets/networks/coretime/westend.png differ diff --git a/src/assets/networks/relay/index.ts b/src/assets/networks/relay/index.ts index c5d0bf51..d9718e63 100644 --- a/src/assets/networks/relay/index.ts +++ b/src/assets/networks/relay/index.ts @@ -1,4 +1,5 @@ import Kusama from './kusama.png'; import Rococo from './rococo.png'; +import Westend from './westend.png'; -export { Kusama, Rococo }; +export { Kusama, Rococo, Westend }; diff --git a/src/assets/networks/relay/westend.png b/src/assets/networks/relay/westend.png new file mode 100644 index 00000000..d3691587 Binary files /dev/null and b/src/assets/networks/relay/westend.png differ diff --git a/src/chaindata/index.ts b/src/chaindata/index.ts index eedbb090..df9aa1b8 100644 --- a/src/chaindata/index.ts +++ b/src/chaindata/index.ts @@ -4,6 +4,7 @@ import KusamaChains from './kusama'; import leases from './leases.json'; import RococoChains from './rococo'; import { BaseChainInfo, ChainDetails } from './types'; +import WestendChains from './westend'; const transformData = (data: ChainDetails[]): Record => { const mapping: Record = {}; @@ -16,6 +17,7 @@ const transformData = (data: ChainDetails[]): Record => { const chainData: Record> = { [NetworkType.KUSAMA]: transformData(KusamaChains), [NetworkType.ROCOCO]: transformData(RococoChains), + [NetworkType.WESTEND]: transformData(WestendChains), [NetworkType.NONE]: transformData([]), }; diff --git a/src/chaindata/westend.ts b/src/chaindata/westend.ts new file mode 100644 index 00000000..d667a6d4 --- /dev/null +++ b/src/chaindata/westend.ts @@ -0,0 +1,200 @@ +import { + chainsKaruraSVG, + chainsStandardPNG, + nodesAssetHubSVG, + nodesBridgeHubSVG, + nodesCentrifugePNG, + nodesIntegriteeSVG, + nodesInterlaySVG, + nodesKhalaSVG, + nodesKylinPNG, + nodesMoonshadowPNG, +} from '@/assets/logos'; + +import { ChainDetails } from './types'; + +const testParasWestend: ChainDetails[] = [ + { + info: 'charcoal', + paraId: 2086, + providers: { + // Centrifuge: 'wss://fullnode-collator.charcoal.centrifuge.io' // https://github.com/polkadot-js/apps/issues/8219 + }, + text: 'Charcoal', + ui: { + logo: nodesCentrifugePNG, + }, + }, + { + info: 'integritee', + paraId: 2081, + providers: { + // Integritee: 'wss://teerw1.integritee.network' // https://github.com/polkadot-js/apps/issues/8937 + }, + text: 'Integritee Network', + ui: { + color: '#658ea9', + logo: nodesIntegriteeSVG, + }, + }, + { + info: 'interlay', + paraId: 2094, + providers: { + // Interlay: 'wss://api-westend.interlay.io/parachain' // https://github.com/polkadot-js/apps/issues/6261 + }, + text: 'Interlay', + ui: { + logo: nodesInterlaySVG, + }, + }, + { + info: 'moonshadow', + paraId: 2002, + providers: { + // PureStake: 'wss://wss.moonshadow.testnet.moonbeam.network' // https://github.com/polkadot-js/apps/issues/6181 + }, + text: 'Moonshadow', + ui: { + color: '#53cbc9', + logo: nodesMoonshadowPNG, + }, + }, + { + homepage: 'https://kylin.network/', + info: 'westendPichiu', + paraId: 2112, + providers: { + // 'Kylin Network': 'wss://westend.kylin-node.co.uk' // https://github.com/polkadot-js/apps/issues/8710 + }, + text: 'Pichiu', + ui: { + logo: nodesKylinPNG, + }, + }, + { + info: 'westendStandard', + paraId: 2094, + providers: { + // 'Standard Protocol': 'wss://rpc.westend.standard.tech' // https://github.com/polkadot-js/apps/issues/8525 + }, + text: 'Standard', + ui: { + logo: chainsStandardPNG, + }, + }, + { + info: 'karura', + paraId: 2005, + providers: { + // 'Acala Foundation': 'wss://karura-westend-rpc.aca-staging.network' // https://github.com/polkadot-js/apps/issues/5830 + }, + text: 'Wendala', + ui: { + logo: chainsKaruraSVG, + }, + }, + { + info: 'whala', + paraId: 2013, + providers: { + // Phala: 'wss://whala.phala.network/ws' // https://github.com/polkadot-js/apps/issues/6181 + }, + text: 'Whala', + ui: { + color: '#03f3f3', + logo: nodesKhalaSVG, + }, + }, + { + info: 'WestendAssetHub', + isPeopleForIdentity: true, + paraId: 1000, + providers: { + Dwellir: 'wss://asset-hub-westend-rpc.dwellir.com', + 'Dwellir Tunisia': 'wss://westmint-rpc-tn.dwellir.com', + IBP1: 'wss://sys.ibp.network/westmint', + IBP2: 'wss://sys.dotters.network/westmint', + // OnFinality: 'wss://westmint.api.onfinality.io/public-ws', // https://github.com/polkadot-js/apps/issues/9955 + Parity: 'wss://westend-asset-hub-rpc.polkadot.io', + // Stakeworld: 'wss://wnd-rpc.stakeworld.io/assethub' + }, + relayName: 'westend', + teleport: [-1], + text: 'AssetHub', + ui: { + color: '#77bb77', + logo: nodesAssetHubSVG, + }, + }, + { + info: 'westendBridgeHub', + isPeopleForIdentity: true, + paraId: 1002, + providers: { + Dwellir: 'wss://bridge-hub-westend-rpc.dwellir.com', + 'Dwellir Tunisia': 'wss://westend-bridge-hub-rpc-tn.dwellir.com', + IBP1: 'wss://sys.ibp.network/bridgehub-westend', + IBP2: 'wss://sys.dotters.network/bridgehub-westend', + // OnFinality: 'wss://bridgehub-westend.api.onfinality.io/public-ws', // https://github.com/polkadot-js/apps/issues/9960 + Parity: 'wss://westend-bridge-hub-rpc.polkadot.io', + }, + relayName: 'westend', + text: 'BridgeHub', + ui: { + logo: nodesBridgeHubSVG, + }, + }, + { + info: 'westendCollectives', + isPeopleForIdentity: true, + paraId: 1001, + providers: { + Dwellir: 'wss://collectives-westend-rpc.dwellir.com', + 'Dwellir Tunisia': 'wss://westend-collectives-rpc-tn.dwellir.com', + IBP1: 'wss://sys.ibp.network/collectives-westend', + IBP2: 'wss://sys.dotters.network/collectives-westend', + Parity: 'wss://westend-collectives-rpc.polkadot.io', + }, + relayName: 'westend', + teleport: [-1], + text: 'Collectives', + ui: { + color: '#e6777a', + // logo: 'fa;people-group', + }, + }, + { + info: 'westendCoretime', + isPeopleForIdentity: true, + paraId: 1005, + providers: { + Dwellir: 'wss://coretime-westend-rpc.dwellir.com', + IBP1: 'wss://sys.ibp.network/coretime-westend', + IBP2: 'wss://sys.dotters.network/coretime-westend', + Parity: 'wss://westend-coretime-rpc.polkadot.io', + }, + relayName: 'westend', + teleport: [-1], + text: 'Coretime', + ui: {}, + }, + { + info: 'westendPeople', + isPeople: true, + isPeopleForIdentity: false, + paraId: 1004, + providers: { + Dwellir: 'wss://people-westend-rpc.dwellir.com', + IBP1: 'wss://sys.ibp.network/people-westend', + IBP2: 'wss://sys.dotters.network/people-westend', + Parity: 'wss://westend-people-rpc.polkadot.io', + }, + relayName: 'westend', + teleport: [-1], + text: 'People', + ui: {}, + }, +]; + +export default testParasWestend; diff --git a/src/components/Elements/Selectors/ChainSelector/index.tsx b/src/components/Elements/Selectors/ChainSelector/index.tsx index be15e570..b8341249 100644 --- a/src/components/Elements/Selectors/ChainSelector/index.tsx +++ b/src/components/Elements/Selectors/ChainSelector/index.tsx @@ -25,6 +25,8 @@ import { RegionX, Rococo, RococoCoretime, + Westend, + WestendCoretime, } from '@/assets/networks'; import { EXPERIMENTAL } from '@/consts'; import { ApiState } from '@/contexts/apis/types'; @@ -33,12 +35,14 @@ import { useNetwork } from '@/contexts/network'; const coretimeIcons = { [NetworkType.KUSAMA]: KusamaCoretime, [NetworkType.ROCOCO]: RococoCoretime, + [NetworkType.WESTEND]: WestendCoretime, [NetworkType.NONE]: '', }; const relayIcons = { [NetworkType.KUSAMA]: Kusama, [NetworkType.ROCOCO]: Rococo, + [NetworkType.WESTEND]: Westend, [NetworkType.NONE]: '', }; diff --git a/src/components/Elements/Selectors/NetworkSelector/index.tsx b/src/components/Elements/Selectors/NetworkSelector/index.tsx index e5cd1f19..a496aa5f 100644 --- a/src/components/Elements/Selectors/NetworkSelector/index.tsx +++ b/src/components/Elements/Selectors/NetworkSelector/index.tsx @@ -2,8 +2,11 @@ import { Box, FormControl, MenuItem, Select, Typography } from '@mui/material'; import Image from 'next/image'; import { useRouter } from 'next/router'; -import KusamaIcon from '@/assets/networks/relay/kusama.png'; -import RococoIcon from '@/assets/networks/relay/rococo.png'; +import { + Kusama as KusamaIcon, + Rococo as RococoIcon, + Westend as WestendIcon, +} from '@/assets/networks/relay'; import { useNetwork } from '@/contexts/network'; import { NetworkType } from '@/models'; @@ -33,6 +36,11 @@ const RelaySelect = () => { label: 'Kusama', icon: KusamaIcon, }, + { + value: NetworkType.WESTEND, + label: 'Westend', + icon: WestendIcon, + }, ]; return ( diff --git a/src/components/Panels/SaleInfoPanel/index.tsx b/src/components/Panels/SaleInfoPanel/index.tsx index 12ca9e6d..67162a46 100644 --- a/src/components/Panels/SaleInfoPanel/index.tsx +++ b/src/components/Panels/SaleInfoPanel/index.tsx @@ -100,7 +100,7 @@ export const SaleInfoPanel = () => { }, right: { label: 'Floor price', - value: formatBalance(saleInfo.price), + value: saleInfo.price ? formatBalance(saleInfo.price) : '---', }, }} button={ diff --git a/src/consts/index.ts b/src/consts/index.ts index 4da00f6a..e768ba5d 100644 --- a/src/consts/index.ts +++ b/src/consts/index.ts @@ -5,26 +5,34 @@ export const APP_NAME = 'Corehub'; export const SUBSCAN_CORETIME_API = { [NetworkType.ROCOCO]: process.env.SUBSCAN_CORETIME_ROCOCO_API ?? '', [NetworkType.KUSAMA]: process.env.SUBSCAN_CORETIME_KUSAMA_API ?? '', + [NetworkType.WESTEND]: process.env.SUBSCAN_CORETIME_WESTEND_API ?? '', [NetworkType.NONE]: '', }; export const SUSBCAN_CORETIME_URL = { [NetworkType.ROCOCO]: 'https://coretime-rococo.subscan.io', [NetworkType.KUSAMA]: 'https://coretime-kusama.subscan.io', + [NetworkType.WESTEND]: 'https://coretime-westend.subscan.io', [NetworkType.NONE]: '', }; export const SUSBCAN_RELAY_URL = { [NetworkType.ROCOCO]: 'https://rococo.subscan.io', [NetworkType.KUSAMA]: 'https://kusama.subscan.io', + [NetworkType.WESTEND]: 'https://westend.subscan.io/', [NetworkType.NONE]: '', }; export const WS_ROCOCO_RELAY_CHAIN = process.env.WS_ROCOCO_RELAY_CHAIN ?? ''; export const WS_KUSAMA_RELAY_CHAIN = process.env.WS_KUSAMA_RELAY_CHAIN ?? ''; +export const WS_WESTEND_RELAY_CHAIN = process.env.WS_WESTEND_RELAY_CHAIN ?? ''; + export const WS_ROCOCO_CORETIME_CHAIN = process.env.WS_ROCOCO_CORETIME_CHAIN ?? ''; export const WS_KUSAMA_CORETIME_CHAIN = process.env.WS_KUSAMA_CORETIME_CHAIN ?? ''; +export const WS_WESTEND_CORETIME_CHAIN = + process.env.WS_WESTEND_CORETIME_CHAIN ?? ''; + export const WS_REGIONX_COCOS_CHAIN = process.env.WS_REGIONX_COCOS_CHAIN ?? ''; export const EXPERIMENTAL = process.env.EXPERIMENTAL == 'true' ? true : false; diff --git a/src/contexts/apis/CoretimeApi/index.tsx b/src/contexts/apis/CoretimeApi/index.tsx index 4fa81de0..02413a9d 100644 --- a/src/contexts/apis/CoretimeApi/index.tsx +++ b/src/contexts/apis/CoretimeApi/index.tsx @@ -1,6 +1,10 @@ import React, { useContext, useEffect, useReducer } from 'react'; -import { WS_KUSAMA_CORETIME_CHAIN, WS_ROCOCO_CORETIME_CHAIN } from '@/consts'; +import { + WS_KUSAMA_CORETIME_CHAIN, + WS_ROCOCO_CORETIME_CHAIN, + WS_WESTEND_CORETIME_CHAIN, +} from '@/consts'; import { useNetwork } from '@/contexts/network'; import { useToast } from '@/contexts/toast'; import { NetworkType } from '@/models'; @@ -47,6 +51,8 @@ const CoretimeApiContextProvider = (props: any) => { return WS_ROCOCO_CORETIME_CHAIN; } else if (network === NetworkType.KUSAMA) { return WS_KUSAMA_CORETIME_CHAIN; + } else if (network === NetworkType.WESTEND) { + return WS_WESTEND_CORETIME_CHAIN; } else { return null; } diff --git a/src/contexts/apis/RelayApi/index.tsx b/src/contexts/apis/RelayApi/index.tsx index e53bb7ba..139f013a 100644 --- a/src/contexts/apis/RelayApi/index.tsx +++ b/src/contexts/apis/RelayApi/index.tsx @@ -2,7 +2,11 @@ import React, { useContext, useEffect, useReducer, useState } from 'react'; import { parseHNString } from '@/utils/functions'; -import { WS_KUSAMA_RELAY_CHAIN, WS_ROCOCO_RELAY_CHAIN } from '@/consts'; +import { + WS_KUSAMA_RELAY_CHAIN, + WS_ROCOCO_RELAY_CHAIN, + WS_WESTEND_RELAY_CHAIN, +} from '@/consts'; import { ApiState } from '@/contexts/apis/types'; import { useNetwork } from '@/contexts/network'; import { useToast } from '@/contexts/toast'; @@ -39,6 +43,8 @@ const RelayApiContextProvider = (props: any) => { return WS_ROCOCO_RELAY_CHAIN; } else if (network === NetworkType.KUSAMA) { return WS_KUSAMA_RELAY_CHAIN; + } else if (network === NetworkType.WESTEND) { + return WS_WESTEND_RELAY_CHAIN; } else { return null; } diff --git a/src/contexts/network/index.tsx b/src/contexts/network/index.tsx index 5786ac3d..58b3f608 100644 --- a/src/contexts/network/index.tsx +++ b/src/contexts/network/index.tsx @@ -33,6 +33,7 @@ const NetworkProvider = ({ children }: Props) => { if (!router.isReady) return; if (network === 'rococo') setActiveNetwork(NetworkType.ROCOCO); else if (network === 'kusama') setActiveNetwork(NetworkType.KUSAMA); + else if (network === 'westend') setActiveNetwork(NetworkType.WESTEND); else { // invalid network param. redirect to the default chain: kusama router.push( diff --git a/src/contexts/sales/index.tsx b/src/contexts/sales/index.tsx index fbba1bc3..ce9ae5ef 100644 --- a/src/contexts/sales/index.tsx +++ b/src/contexts/sales/index.tsx @@ -136,8 +136,7 @@ const SaleInfoProvider = ({ children }: Props) => { const saleInfoRaw = await coretimeApi.query.broker.saleInfo(); const saleInfo = saleInfoRaw.toJSON() as SaleInfo; - if ((saleInfoRaw.toJSON() as any).endPrice) - saleInfo.price = (saleInfoRaw.toJSON() as any).endPrice as number; + saleInfo.price = (saleInfoRaw.toJSON() as any).endPrice as number; if (!saleInfo) { setStatus(ContextStatus.UNINITIALIZED); diff --git a/src/hooks/renewableParas.ts b/src/hooks/renewableParas.ts index 5f54885c..9bee53ce 100644 --- a/src/hooks/renewableParas.ts +++ b/src/hooks/renewableParas.ts @@ -37,10 +37,11 @@ export const useRenewableParachains = () => { setStatus(ContextStatus.LOADING); - const renewals = - network === NetworkType.ROCOCO - ? await api.query.broker.potentialRenewals.entries() - : await api.query.broker.allowedRenewals.entries(); + const renewals = [NetworkType.ROCOCO, NetworkType.WESTEND].includes( + network + ) + ? await api.query.broker.potentialRenewals.entries() + : await api.query.broker.allowedRenewals.entries(); const chains: RenewableParachain[] = []; for (const [key, value] of renewals) { const data: any = key.toHuman(); diff --git a/src/hooks/sale/purchaseHistory.ts b/src/hooks/sale/purchaseHistory.ts index 9e024d9b..20bf3cf1 100644 --- a/src/hooks/sale/purchaseHistory.ts +++ b/src/hooks/sale/purchaseHistory.ts @@ -42,26 +42,29 @@ export const usePurchaseHistory = ( } else { const { list } = data as PurchaseHistoryResponse; - setData( - list.map( - ({ - account: { address }, - core, - extrinsic_index, - block_timestamp, - price, - purchased_type, - }) => + if (!list) setData([]); + else { + setData( + list.map( ({ - address, + account: { address }, core, extrinsic_index, - timestamp: block_timestamp, - price: parseInt(price), - type: purchased_type, - }) as PurchaseHistoryItem - ) - ); + block_timestamp, + price, + purchased_type, + }) => + ({ + address, + core, + extrinsic_index, + timestamp: block_timestamp, + price: parseInt(price), + type: purchased_type, + } as PurchaseHistoryItem) + ) + ); + } } } } catch { diff --git a/src/models/common/enums.ts b/src/models/common/enums.ts index 6c3164a8..2a366fd6 100644 --- a/src/models/common/enums.ts +++ b/src/models/common/enums.ts @@ -24,6 +24,8 @@ export enum NetworkType { // eslint-disable-next-line no-unused-vars KUSAMA = 'kusama', // eslint-disable-next-line no-unused-vars + WESTEND = 'westend', + // eslint-disable-next-line no-unused-vars NONE = 'none', } diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 1f77a5ea..1684d4d7 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -56,8 +56,8 @@ const Home = () => { numRenewals === 0 ? 0 : Math.floor( - renewals.reduce((sum, item) => sum + item.price, 0) / numRenewals - ); + renewals.reduce((sum, item) => sum + item.price, 0) / numRenewals + ); const { currentBurn, @@ -136,7 +136,7 @@ const Home = () => { ], bottom: { label: 'Current Price', - value: currentPrice === undefined ? '---': formatBalance(currentPrice), + value: currentPrice === undefined ? '---' : formatBalance(currentPrice), dataCy: 'current-price', }, },