Merge pull request #286 from blockworks-foundation/platform-status
consolidate platform status items
This commit is contained in:
commit
f8048e5e6f
|
@ -1,45 +1,8 @@
|
||||||
import { Connection } from '@solana/web3.js'
|
|
||||||
import mangoStore from '@store/mangoStore'
|
|
||||||
import { useEffect, useState } from 'react'
|
|
||||||
import useInterval from './shared/useInterval'
|
|
||||||
import { formatNumericValue } from 'utils/numbers'
|
import { formatNumericValue } from 'utils/numbers'
|
||||||
import Tooltip from './shared/Tooltip'
|
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
import { StatusDot } from './Tps'
|
import { StatusDot } from './Tps'
|
||||||
|
import { rpcAlertThreshold, rpcWarningThreshold } from './StatusBar'
|
||||||
|
|
||||||
const rpcAlertThreshold = 250
|
const RpcPing = ({ rpcPing }: { rpcPing: number }) => {
|
||||||
const rpcWarningThreshold = 500
|
|
||||||
|
|
||||||
const getPingTime = async (
|
|
||||||
connection: Connection,
|
|
||||||
setRpcPing: (x: number) => void,
|
|
||||||
) => {
|
|
||||||
const startTime = Date.now()
|
|
||||||
try {
|
|
||||||
await connection.getSlot()
|
|
||||||
|
|
||||||
const endTime = Date.now()
|
|
||||||
const pingTime = endTime - startTime
|
|
||||||
setRpcPing(pingTime)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error pinging the RPC:', error)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const RpcPing = () => {
|
|
||||||
const { t } = useTranslation('common')
|
|
||||||
const connection = mangoStore((s) => s.connection)
|
|
||||||
const [rpcPing, setRpcPing] = useState(0)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
getPingTime(connection, setRpcPing)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
useInterval(() => {
|
|
||||||
getPingTime(connection, setRpcPing)
|
|
||||||
}, 30 * 1000)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
|
@ -48,12 +11,10 @@ const RpcPing = () => {
|
||||||
alert={rpcAlertThreshold}
|
alert={rpcAlertThreshold}
|
||||||
warning={rpcWarningThreshold}
|
warning={rpcWarningThreshold}
|
||||||
/>
|
/>
|
||||||
<Tooltip content={t('rpc-ping')}>
|
<span className="font-mono text-xs text-th-fgd-2">
|
||||||
<span className="font-mono text-xs text-th-fgd-2">
|
<span className="mr-1">{formatNumericValue(rpcPing, 0)}</span>
|
||||||
<span className="mr-1">{formatNumericValue(rpcPing, 0)}</span>
|
<span className="font-normal text-th-fgd-4">MS</span>
|
||||||
<span className="font-normal text-th-fgd-4">MS</span>
|
</span>
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,15 +1,24 @@
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import Tps from './Tps'
|
import Tps, { StatusDot } from './Tps'
|
||||||
import DiscordIcon from './icons/DiscordIcon'
|
import DiscordIcon from './icons/DiscordIcon'
|
||||||
import { TwitterIcon } from './icons/TwitterIcon'
|
import { TwitterIcon } from './icons/TwitterIcon'
|
||||||
import { DocumentTextIcon } from '@heroicons/react/20/solid'
|
import { DocumentTextIcon } from '@heroicons/react/20/solid'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useMemo, useState } from 'react'
|
||||||
import { IDL } from '@blockworks-foundation/mango-v4'
|
import { IDL } from '@blockworks-foundation/mango-v4'
|
||||||
import RpcPing from './RpcPing'
|
import RpcPing from './RpcPing'
|
||||||
import Tooltip from './shared/Tooltip'
|
import Tooltip from './shared/Tooltip'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
import useOffchainServicesHealth from 'hooks/useOffchainServicesHealth'
|
||||||
|
import mangoStore from '@store/mangoStore'
|
||||||
|
import { Connection } from '@solana/web3.js'
|
||||||
|
import { sumBy } from 'lodash'
|
||||||
|
import useInterval from './shared/useInterval'
|
||||||
|
|
||||||
const DEFAULT_LATEST_COMMIT = { sha: '', url: '' }
|
const DEFAULT_LATEST_COMMIT = { sha: '', url: '' }
|
||||||
|
export const tpsAlertThreshold = 1300
|
||||||
|
export const tpsWarningThreshold = 1000
|
||||||
|
export const rpcAlertThreshold = 250
|
||||||
|
export const rpcWarningThreshold = 500
|
||||||
|
|
||||||
const getLatestCommit = async () => {
|
const getLatestCommit = async () => {
|
||||||
try {
|
try {
|
||||||
|
@ -32,10 +41,81 @@ const getLatestCommit = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getRecentPerformance = async (
|
||||||
|
connection: Connection,
|
||||||
|
setTps: (x: number) => void,
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const samples = 2
|
||||||
|
const response = await connection.getRecentPerformanceSamples(samples)
|
||||||
|
const totalSecs = sumBy(response, 'samplePeriodSecs')
|
||||||
|
const totalTransactions = sumBy(response, 'numTransactions')
|
||||||
|
const tps = totalTransactions / totalSecs
|
||||||
|
|
||||||
|
setTps(tps)
|
||||||
|
} catch {
|
||||||
|
console.warn('Unable to fetch TPS')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPingTime = async (
|
||||||
|
connection: Connection,
|
||||||
|
setRpcPing: (x: number) => void,
|
||||||
|
) => {
|
||||||
|
const startTime = Date.now()
|
||||||
|
try {
|
||||||
|
await connection.getSlot()
|
||||||
|
|
||||||
|
const endTime = Date.now()
|
||||||
|
const pingTime = endTime - startTime
|
||||||
|
setRpcPing(pingTime)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error pinging the RPC:', error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getOverallStatus = (
|
||||||
|
tps: number,
|
||||||
|
rpcPing: number,
|
||||||
|
offchainHealth: number,
|
||||||
|
) => {
|
||||||
|
if (tps < tpsWarningThreshold) {
|
||||||
|
return 'severly-degraded'
|
||||||
|
} else if (
|
||||||
|
tps < tpsAlertThreshold ||
|
||||||
|
rpcPing > rpcWarningThreshold ||
|
||||||
|
offchainHealth !== 200
|
||||||
|
) {
|
||||||
|
return 'degraded'
|
||||||
|
} else return 'operational'
|
||||||
|
}
|
||||||
|
|
||||||
const StatusBar = ({ collapsed }: { collapsed: boolean }) => {
|
const StatusBar = ({ collapsed }: { collapsed: boolean }) => {
|
||||||
const { t } = useTranslation('common')
|
const { t } = useTranslation('common')
|
||||||
const [latestCommit, setLatestCommit] = useState(DEFAULT_LATEST_COMMIT)
|
const [latestCommit, setLatestCommit] = useState(DEFAULT_LATEST_COMMIT)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const { offchainHealth, isLoading: loadingOffchainHealth } =
|
||||||
|
useOffchainServicesHealth()
|
||||||
|
const connection = mangoStore((s) => s.connection)
|
||||||
|
const [tps, setTps] = useState(0)
|
||||||
|
const [rpcPing, setRpcPing] = useState(0)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getPingTime(connection, setRpcPing)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useInterval(() => {
|
||||||
|
getPingTime(connection, setRpcPing)
|
||||||
|
}, 30 * 1000)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getRecentPerformance(connection, setTps)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useInterval(() => {
|
||||||
|
getRecentPerformance(connection, setTps)
|
||||||
|
}, 60 * 1000)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { sha } = latestCommit
|
const { sha } = latestCommit
|
||||||
|
@ -44,16 +124,65 @@ const StatusBar = ({ collapsed }: { collapsed: boolean }) => {
|
||||||
}
|
}
|
||||||
}, [latestCommit])
|
}, [latestCommit])
|
||||||
|
|
||||||
|
const platformHealth = useMemo(() => {
|
||||||
|
return getOverallStatus(tps, rpcPing, offchainHealth)
|
||||||
|
}, [tps, rpcPing, offchainHealth])
|
||||||
|
|
||||||
|
const dotColor =
|
||||||
|
platformHealth === 'severly-degraded'
|
||||||
|
? 'bg-th-error'
|
||||||
|
: platformHealth === 'degraded'
|
||||||
|
? 'bg-th-warning'
|
||||||
|
: 'bg-th-success'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`fixed hidden ${
|
className={`fixed hidden ${
|
||||||
collapsed ? 'w-[calc(100vw-64px)]' : 'w-[calc(100vw-200px)]'
|
collapsed ? 'w-[calc(100vw-64px)]' : 'w-[calc(100vw-200px)]'
|
||||||
} bottom-0 z-10 bg-th-input-bkg px-4 py-1 md:grid md:grid-cols-3 md:px-6`}
|
} bottom-0 z-10 bg-th-input-bkg px-4 py-1 md:grid md:grid-cols-3 md:px-6`}
|
||||||
>
|
>
|
||||||
<div className="col-span-1 flex items-center space-x-2">
|
<div className="col-span-1 flex items-center">
|
||||||
<Tps />
|
<Tooltip
|
||||||
<span className="text-th-fgd-4">|</span>
|
content={
|
||||||
<RpcPing />
|
<div className="space-y-2">
|
||||||
|
<div>
|
||||||
|
<p className="mb-0.5">{t('solana-tps')}</p>
|
||||||
|
<Tps tps={tps} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="mb-0.5">{t('rpc-ping')}</p>
|
||||||
|
<RpcPing rpcPing={rpcPing} />
|
||||||
|
</div>
|
||||||
|
{!loadingOffchainHealth ? (
|
||||||
|
<div className="flex items-center">
|
||||||
|
<StatusDot
|
||||||
|
status={offchainHealth}
|
||||||
|
alert={201}
|
||||||
|
warning={301}
|
||||||
|
/>
|
||||||
|
<span className="text-xs text-th-fgd-2">
|
||||||
|
{t('offchain-services')}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
placement="top-start"
|
||||||
|
>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<div className="relative mr-1 h-3 w-3">
|
||||||
|
<div
|
||||||
|
className={`absolute left-0.5 top-0.5 h-2 w-2 rounded-full ${dotColor}`}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className={`absolute h-3 w-3 rounded-full opacity-40 ${dotColor}`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p className="tooltip-underline text-xs leading-none">
|
||||||
|
{t(platformHealth)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-1 flex items-center justify-center">
|
<div className="col-span-1 flex items-center justify-center">
|
||||||
<Tooltip content={t('program-version')}>
|
<Tooltip content={t('program-version')}>
|
||||||
|
|
|
@ -1,45 +1,8 @@
|
||||||
import { useEffect, useState } from 'react'
|
import { CLUSTER } from '@store/mangoStore'
|
||||||
import sumBy from 'lodash/sumBy'
|
|
||||||
import { Connection } from '@solana/web3.js'
|
|
||||||
import mangoStore, { CLUSTER } from '@store/mangoStore'
|
|
||||||
import useInterval from './shared/useInterval'
|
|
||||||
import { formatNumericValue } from 'utils/numbers'
|
import { formatNumericValue } from 'utils/numbers'
|
||||||
import Tooltip from './shared/Tooltip'
|
import { tpsAlertThreshold, tpsWarningThreshold } from './StatusBar'
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
|
|
||||||
const tpsAlertThreshold = 1000
|
|
||||||
const tpsWarningThreshold = 1300
|
|
||||||
|
|
||||||
const getRecentPerformance = async (
|
|
||||||
connection: Connection,
|
|
||||||
setTps: (x: number) => void,
|
|
||||||
) => {
|
|
||||||
try {
|
|
||||||
const samples = 2
|
|
||||||
const response = await connection.getRecentPerformanceSamples(samples)
|
|
||||||
const totalSecs = sumBy(response, 'samplePeriodSecs')
|
|
||||||
const totalTransactions = sumBy(response, 'numTransactions')
|
|
||||||
const tps = totalTransactions / totalSecs
|
|
||||||
|
|
||||||
setTps(tps)
|
|
||||||
} catch {
|
|
||||||
console.warn('Unable to fetch TPS')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Tps = () => {
|
|
||||||
const { t } = useTranslation('common')
|
|
||||||
const connection = mangoStore((s) => s.connection)
|
|
||||||
const [tps, setTps] = useState(0)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
getRecentPerformance(connection, setTps)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
useInterval(() => {
|
|
||||||
getRecentPerformance(connection, setTps)
|
|
||||||
}, 60 * 1000)
|
|
||||||
|
|
||||||
|
const Tps = ({ tps }: { tps: number }) => {
|
||||||
if (CLUSTER == 'mainnet-beta') {
|
if (CLUSTER == 'mainnet-beta') {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -50,12 +13,9 @@ const Tps = () => {
|
||||||
warning={tpsWarningThreshold}
|
warning={tpsWarningThreshold}
|
||||||
isLessThan
|
isLessThan
|
||||||
/>
|
/>
|
||||||
<Tooltip content={t('solana-tps-desc')}>
|
<span className="font-mono text-xs text-th-fgd-2">
|
||||||
<span className="font-mono text-xs text-th-fgd-2">
|
{formatNumericValue(tps, 0)}
|
||||||
<span className="mr-1">{formatNumericValue(tps, 0)}</span>
|
</span>
|
||||||
<span className="font-normal text-th-fgd-4">TPS</span>
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
import useInterval from '@components/shared/useInterval'
|
||||||
|
import { useQuery } from '@tanstack/react-query'
|
||||||
|
import { useMemo } from 'react'
|
||||||
|
|
||||||
|
const fetchOffchainHealth = async () => {
|
||||||
|
try {
|
||||||
|
const [dbHealthResponse, redisHealthResponse, serverHealthResponse] =
|
||||||
|
await Promise.all([
|
||||||
|
fetch('https://api.mngo.cloud/data/health/db'),
|
||||||
|
fetch('https://api.mngo.cloud/data/health/redis'),
|
||||||
|
fetch('https://api.mngo.cloud/data/health/server'),
|
||||||
|
])
|
||||||
|
const [dbHealth, redisHealth, serverHealth] = await Promise.all([
|
||||||
|
dbHealthResponse.json(),
|
||||||
|
redisHealthResponse.json(),
|
||||||
|
serverHealthResponse.json(),
|
||||||
|
])
|
||||||
|
return { dbHealth, redisHealth, serverHealth }
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Failed to check offchain services health', e)
|
||||||
|
return { dbHealth: 500, redisHealth: 500, serverHealth: 500 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useOffchainServicesHealth() {
|
||||||
|
const {
|
||||||
|
data: offchainHealthData,
|
||||||
|
isLoading,
|
||||||
|
refetch,
|
||||||
|
} = useQuery(['offchain-health'], () => fetchOffchainHealth(), {
|
||||||
|
cacheTime: 1000 * 60 * 10,
|
||||||
|
staleTime: 1000 * 60,
|
||||||
|
retry: 3,
|
||||||
|
})
|
||||||
|
|
||||||
|
useInterval(() => {
|
||||||
|
refetch()
|
||||||
|
}, 60 * 1000)
|
||||||
|
|
||||||
|
const offchainHealth = useMemo(() => {
|
||||||
|
if (!offchainHealthData) return 500
|
||||||
|
const somethingWrong = Object.values(offchainHealthData).filter(
|
||||||
|
(v) => v !== 200,
|
||||||
|
)
|
||||||
|
if (!somethingWrong.length) {
|
||||||
|
return 200
|
||||||
|
} else if (somethingWrong.length < 3) {
|
||||||
|
return 300
|
||||||
|
} else return 500
|
||||||
|
}, [offchainHealthData])
|
||||||
|
return { offchainHealth, isLoading }
|
||||||
|
}
|
|
@ -58,6 +58,7 @@
|
||||||
"date": "Date",
|
"date": "Date",
|
||||||
"date-from": "Date From",
|
"date-from": "Date From",
|
||||||
"date-to": "Date To",
|
"date-to": "Date To",
|
||||||
|
"degraded": "Degraded",
|
||||||
"delegate": "Delegate",
|
"delegate": "Delegate",
|
||||||
"delegate-account": "Delegate Account",
|
"delegate-account": "Delegate Account",
|
||||||
"delegate-account-info": "Account delegated to: {{delegate}}",
|
"delegate-account-info": "Account delegated to: {{delegate}}",
|
||||||
|
@ -121,6 +122,8 @@
|
||||||
"new-account-success": "Your new account is ready 😎",
|
"new-account-success": "Your new account is ready 😎",
|
||||||
"new-version": "New version available",
|
"new-version": "New version available",
|
||||||
"no": "No",
|
"no": "No",
|
||||||
|
"offchain-services": "Offchain Services",
|
||||||
|
"operational": "Operational",
|
||||||
"optional": "Optional",
|
"optional": "Optional",
|
||||||
"outstanding-balance": "Outstanding Balance",
|
"outstanding-balance": "Outstanding Balance",
|
||||||
"overview": "Overview",
|
"overview": "Overview",
|
||||||
|
@ -142,7 +145,7 @@
|
||||||
"risks": "Risks",
|
"risks": "Risks",
|
||||||
"rolling-change": "24h Change",
|
"rolling-change": "24h Change",
|
||||||
"route": "Route",
|
"route": "Route",
|
||||||
"rpc-ping": "Ping time with the RPC node",
|
"rpc-ping": "RPC Ping",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
"select": "Select",
|
"select": "Select",
|
||||||
"select-borrow-token": "Select Borrow Token",
|
"select-borrow-token": "Select Borrow Token",
|
||||||
|
@ -152,9 +155,9 @@
|
||||||
"select-withdraw-token": "Select Withdraw Token",
|
"select-withdraw-token": "Select Withdraw Token",
|
||||||
"sell": "Sell",
|
"sell": "Sell",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
|
"severly-degraded": "Severly Degraded",
|
||||||
"show-more": "Show More",
|
"show-more": "Show More",
|
||||||
"solana-tps": "Solana TPS",
|
"solana-tps": "Solana TPS",
|
||||||
"solana-tps-desc": "Solana Network – transactions per second",
|
|
||||||
"soon": "Soon",
|
"soon": "Soon",
|
||||||
"spot": "Spot",
|
"spot": "Spot",
|
||||||
"spot-markets": "Spot Markets",
|
"spot-markets": "Spot Markets",
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
"date": "Date",
|
"date": "Date",
|
||||||
"date-from": "Date From",
|
"date-from": "Date From",
|
||||||
"date-to": "Date To",
|
"date-to": "Date To",
|
||||||
|
"degraded": "Degraded",
|
||||||
"delegate": "Delegate",
|
"delegate": "Delegate",
|
||||||
"delegate-account": "Delegate Account",
|
"delegate-account": "Delegate Account",
|
||||||
"delegate-account-info": "Account delegated to: {{delegate}}",
|
"delegate-account-info": "Account delegated to: {{delegate}}",
|
||||||
|
@ -121,6 +122,8 @@
|
||||||
"new-account-success": "Your new account is ready 😎",
|
"new-account-success": "Your new account is ready 😎",
|
||||||
"new-version": "New version available",
|
"new-version": "New version available",
|
||||||
"no": "No",
|
"no": "No",
|
||||||
|
"offchain-services": "Offchain Services",
|
||||||
|
"operational": "Operational",
|
||||||
"optional": "Optional",
|
"optional": "Optional",
|
||||||
"outstanding-balance": "Outstanding Balance",
|
"outstanding-balance": "Outstanding Balance",
|
||||||
"overview": "Overview",
|
"overview": "Overview",
|
||||||
|
@ -142,7 +145,7 @@
|
||||||
"risks": "Risks",
|
"risks": "Risks",
|
||||||
"rolling-change": "24h Change",
|
"rolling-change": "24h Change",
|
||||||
"route": "Route",
|
"route": "Route",
|
||||||
"rpc-ping": "Ping time with the RPC node",
|
"rpc-ping": "RPC Ping",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
"select": "Select",
|
"select": "Select",
|
||||||
"select-borrow-token": "Select Borrow Token",
|
"select-borrow-token": "Select Borrow Token",
|
||||||
|
@ -152,9 +155,9 @@
|
||||||
"select-withdraw-token": "Select Withdraw Token",
|
"select-withdraw-token": "Select Withdraw Token",
|
||||||
"sell": "Sell",
|
"sell": "Sell",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
|
"severly-degraded": "Severly Degraded",
|
||||||
"show-more": "Show More",
|
"show-more": "Show More",
|
||||||
"solana-tps": "Solana TPS",
|
"solana-tps": "Solana TPS",
|
||||||
"solana-tps-desc": "Solana Network – transactions per second",
|
|
||||||
"soon": "Soon",
|
"soon": "Soon",
|
||||||
"spot": "Spot",
|
"spot": "Spot",
|
||||||
"spot-markets": "Spot Markets",
|
"spot-markets": "Spot Markets",
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
"date": "Date",
|
"date": "Date",
|
||||||
"date-from": "Date From",
|
"date-from": "Date From",
|
||||||
"date-to": "Date To",
|
"date-to": "Date To",
|
||||||
|
"degraded": "Degraded",
|
||||||
"delegate": "Delegate",
|
"delegate": "Delegate",
|
||||||
"delegate-account": "Delegate Account",
|
"delegate-account": "Delegate Account",
|
||||||
"delegate-account-info": "Account delegated to: {{delegate}}",
|
"delegate-account-info": "Account delegated to: {{delegate}}",
|
||||||
|
@ -121,6 +122,8 @@
|
||||||
"new-account-success": "Your new account is ready 😎",
|
"new-account-success": "Your new account is ready 😎",
|
||||||
"new-version": "New version available",
|
"new-version": "New version available",
|
||||||
"no": "No",
|
"no": "No",
|
||||||
|
"offchain-services": "Offchain Services",
|
||||||
|
"operational": "Operational",
|
||||||
"optional": "Optional",
|
"optional": "Optional",
|
||||||
"outstanding-balance": "Outstanding Balance",
|
"outstanding-balance": "Outstanding Balance",
|
||||||
"overview": "Overview",
|
"overview": "Overview",
|
||||||
|
@ -142,7 +145,7 @@
|
||||||
"risks": "Risks",
|
"risks": "Risks",
|
||||||
"rolling-change": "24h Change",
|
"rolling-change": "24h Change",
|
||||||
"route": "Route",
|
"route": "Route",
|
||||||
"rpc-ping": "Ping time with the RPC node",
|
"rpc-ping": "RPC Ping",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
"select": "Select",
|
"select": "Select",
|
||||||
"select-borrow-token": "Select Borrow Token",
|
"select-borrow-token": "Select Borrow Token",
|
||||||
|
@ -152,9 +155,9 @@
|
||||||
"select-withdraw-token": "Select Withdraw Token",
|
"select-withdraw-token": "Select Withdraw Token",
|
||||||
"sell": "Sell",
|
"sell": "Sell",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
|
"severly-degraded": "Severly Degraded",
|
||||||
"show-more": "Show More",
|
"show-more": "Show More",
|
||||||
"solana-tps": "Solana TPS",
|
"solana-tps": "Solana TPS",
|
||||||
"solana-tps-desc": "Solana Network – transactions per second",
|
|
||||||
"soon": "Soon",
|
"soon": "Soon",
|
||||||
"spot": "Spot",
|
"spot": "Spot",
|
||||||
"spot-markets": "Spot Markets",
|
"spot-markets": "Spot Markets",
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
"date": "日期",
|
"date": "日期",
|
||||||
"date-from": "从",
|
"date-from": "从",
|
||||||
"date-to": "至",
|
"date-to": "至",
|
||||||
|
"degraded": "Degraded",
|
||||||
"delegate": "委托",
|
"delegate": "委托",
|
||||||
"delegate-account": "委托帐户",
|
"delegate-account": "委托帐户",
|
||||||
"delegate-account-info": "帐户委托给: {{delegate}}",
|
"delegate-account-info": "帐户委托给: {{delegate}}",
|
||||||
|
@ -120,7 +121,9 @@
|
||||||
"new-account-success": "您的新帐户准备好了😎",
|
"new-account-success": "您的新帐户准备好了😎",
|
||||||
"new-version": "新版本出来了",
|
"new-version": "新版本出来了",
|
||||||
"no": "不",
|
"no": "不",
|
||||||
|
"offchain-services": "Offchain Services",
|
||||||
"optional": "可选",
|
"optional": "可选",
|
||||||
|
"operational": "Operational",
|
||||||
"outstanding-balance": "未结余额",
|
"outstanding-balance": "未结余额",
|
||||||
"overview": "摘要",
|
"overview": "摘要",
|
||||||
"perp": "合约",
|
"perp": "合约",
|
||||||
|
@ -151,9 +154,9 @@
|
||||||
"select-withdraw-token": "选提出币种",
|
"select-withdraw-token": "选提出币种",
|
||||||
"sell": "卖",
|
"sell": "卖",
|
||||||
"settings": "设置",
|
"settings": "设置",
|
||||||
|
"severly-degraded": "Severly Degraded",
|
||||||
"show-more": "显示更多",
|
"show-more": "显示更多",
|
||||||
"solana-tps": "Solana TPS",
|
"solana-tps": "Solana TPS",
|
||||||
"solana-tps-desc": "Solana网络–每秒的交易量",
|
|
||||||
"soon": "等一下",
|
"soon": "等一下",
|
||||||
"spot": "现货",
|
"spot": "现货",
|
||||||
"spot-markets": "现货市场",
|
"spot-markets": "现货市场",
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
"date": "日期",
|
"date": "日期",
|
||||||
"date-from": "從",
|
"date-from": "從",
|
||||||
"date-to": "至",
|
"date-to": "至",
|
||||||
|
"degraded": "Degraded",
|
||||||
"delegate": "委託",
|
"delegate": "委託",
|
||||||
"delegate-account": "委託帳戶",
|
"delegate-account": "委託帳戶",
|
||||||
"delegate-account-info": "帳戶委託給: {{delegate}}",
|
"delegate-account-info": "帳戶委託給: {{delegate}}",
|
||||||
|
@ -120,6 +121,8 @@
|
||||||
"new-account-success": "您的新帳戶準備好了😎",
|
"new-account-success": "您的新帳戶準備好了😎",
|
||||||
"new-version": "新版本出來了",
|
"new-version": "新版本出來了",
|
||||||
"no": "不",
|
"no": "不",
|
||||||
|
"offchain-services": "Offchain Services",
|
||||||
|
"operational": "Operational",
|
||||||
"optional": "可選",
|
"optional": "可選",
|
||||||
"outstanding-balance": "未結餘額",
|
"outstanding-balance": "未結餘額",
|
||||||
"overview": "摘要",
|
"overview": "摘要",
|
||||||
|
@ -151,9 +154,9 @@
|
||||||
"select-withdraw-token": "選提出幣種",
|
"select-withdraw-token": "選提出幣種",
|
||||||
"sell": "賣",
|
"sell": "賣",
|
||||||
"settings": "設置",
|
"settings": "設置",
|
||||||
|
"severly-degraded": "Severly Degraded",
|
||||||
"show-more": "顯示更多",
|
"show-more": "顯示更多",
|
||||||
"solana-tps": "Solana TPS",
|
"solana-tps": "Solana TPS",
|
||||||
"solana-tps-desc": "Solana網絡–每秒的交易量",
|
|
||||||
"soon": "等一下",
|
"soon": "等一下",
|
||||||
"spot": "現貨",
|
"spot": "現貨",
|
||||||
"spot-markets": "現貨市場",
|
"spot-markets": "現貨市場",
|
||||||
|
|
Loading…
Reference in New Issue