The Morpheus Dashboard provides a comprehensive view of the Morpheus token ecosystem, focusing on supply metrics and staking behavior. The dashboard is divided into two main components: Supply and Staking.
The Supply component visualizes key metrics related to the Morpheus token supply, including total and circulating supply, price and trading volume, market cap, protocol liquidity, locked and burned tokens, and holder distribution.
This chart displays the total supply and circulating supply of Morpheus tokens over time.
/total_and_circ_supply
const processData = (data) => {
return data.map(item => ({
date: format(parse(item.date, 'dd/MM/yyyy', new Date()), 'MMM d, yyyy'),
dateObj: parse(item.date, 'dd/MM/yyyy', new Date()),
totalSupply: item.total_supply,
circulatingSupply: item.circulating_supply
})).sort((a, b) => a.dateObj - b.dateObj);
};
<ResponsiveContainer width="100%" height={400}>
<LineChart
data={chartData}
margin={{
top: 20,
right: 30,
left: 20,
bottom: 30,
}}
>
<CartesianGrid strokeDasharray="3 3" stroke="#444" />
<XAxis
dataKey="date"
tick={{ fill: '#FFFFFF', fontSize: '10px' }}
angle={-45}
textAnchor="end"
height={70}
>
<Label value="Date" offset={-20} position="insideBottom" style={{ fill: '#FFFFFF', fontWeight: 'bold' }} />
</XAxis>
<YAxis tick={{ fill: '#FFFFFF', fontSize: '10px' }} tickFormatter={(value) => formatNumberWithOutDecimal(value)}>
<Label value="Supply" angle={-90} offset={-13} position="insideLeft" style={{ fill: '#FFFFFF', fontWeight: 'bold', textAnchor: 'middle' }} />
</YAxis>
<Tooltip content={<CustomTooltip />} />
<Legend verticalAlign="top" height={36} />
<Line type="monotone" dataKey="totalSupply" stroke="#8884d8" activeDot={{ r: 8, fill: '#01FF85' }} dot={{ r: 2, fill: "#8884d8" }} name="Total Supply" />
<Line type="monotone" dataKey="circulatingSupply" stroke="#82ca9d" activeDot={{ r: 8, fill: '#01FF85' }} dot={{ r: 2, fill: "#82ca9d" }} name="Circulating Supply" />
</LineChart>
</ResponsiveContainer>
This chart shows the price trends of the Morpheus token and its trading volume over time.
/prices_and_trading_volume
const processData = (data) => {
const prices = data.prices.map(([date, price]) => ({
date: format(parse(date, 'dd/MM/yyyy', new Date()), 'MMM d, yyyy'),
dateObj: parse(date, 'dd/MM/yyyy', new Date()),
price: price
}));
const volumes = data.total_volumes.map(([date, volume]) => ({
date: format(parse(date, 'dd/MM/yyyy', new Date()), 'MMM d, yyyy'),
dateObj: parse(date, 'dd/MM/yyyy', new Date()),
volume: volume
}));
return prices.map(priceItem => ({
...priceItem,
volume: volumes.find(v => v.date === priceItem.date)?.volume || 0
})).sort((a, b) => a.dateObj - b.dateObj);
};
<ResponsiveContainer width="100%" height={400}>
{dataKey === 'price' ? (
<LineChart data={chartData}>
<CartesianGrid strokeDasharray="3 3" stroke="#444" />
<XAxis
dataKey="date"
tick={{ fill: '#FFFFFF', fontSize: '10px' }}
angle={-45}
textAnchor="end"
height={70}
>
<Label value="Date" offset={-20} position="insideBottom" style={{ fill: '#FFFFFF', fontWeight: 'bold' }} />
</XAxis>
<YAxis
tick={{ fill: '#FFFFFF', fontSize: '10px' }}
domain={['auto', 'auto']}
>
<Label value={yAxisLabel} angle={-90} position="insideLeft" style={{ fill: '#FFFFFF', fontWeight: 'bold', textAnchor: 'middle' }} />
</YAxis>
<Tooltip content={<CustomTooltip dataKey={dataKey} />} />
<Legend verticalAlign="top" height={36} />
<Line type="monotone" dataKey="price" stroke="#8884d8" activeDot={{ r: 8 }} dot={{ r: 2 }} name="Price" />
</LineChart>
) : (
<BarChart data={chartData}>
<CartesianGrid strokeDasharray="3 3" stroke="#444" />
<XAxis
dataKey="date"
tick={{ fill: '#FFFFFF', fontSize: '10px' }}
angle={-45}
textAnchor="end"
height={70}
>
<Label value="Date" offset={-20} position="insideBottom" style={{ fill: '#FFFFFF', fontWeight: 'bold' }} />
</XAxis>
<YAxis
tick={{ fill: '#FFFFFF', fontSize: '10px' }}
domain={['auto', 'auto']}
tickFormatter={(value) => formatNumberWithOutDecimal(value)}
>
<Label value={yAxisLabel} angle={-90} position="insideLeft" style={{ fill: '#FFFFFF', fontWeight: 'bold', textAnchor: 'middle' }} />
</YAxis>
<Tooltip content={<CustomTooltip dataKey={dataKey} />} />
<Legend verticalAlign="top" height={36} />
<Bar dataKey="volume" fill="#8884d8" name="Volume" />
</BarChart>
)}
</ResponsiveContainer>
These cards display the current and circulating supply market cap, as well as the pool-owned liquidity in USD, MOR, and stETH.
- Market Cap:
/get_market_cap
- Protocol Liquidity:
/protocol_liquidity
Info cards with toggle buttons for different metrics.
This chart shows the cumulative amount of MOR tokens that have been locked and burned over time.
/locked_and_burnt_mor
const processData = (data) => {
const burnedData = Object.entries(data.burnt_mor.cumulative_mor_burnt).map(([date, value]) => ({
date: format(parse(date, 'dd/MM/yyyy', new Date()), 'MMM d, yyyy'),
dateObj: parse(date, 'dd/MM/yyyy', new Date()),
burned: value,
locked: data.locked_mor.cumulative_mor_locked[date]
}));
return burnedData.sort((a, b) => a.dateObj - b.dateObj);
};
<ResponsiveContainer width="100%" height={400}>
<LineChart
data={chartData}
margin={{
top: 20,
right: 30,
left: 20,
bottom: 30,
}}
>
<CartesianGrid strokeDasharray="3 3" stroke="#444" />
<XAxis
dataKey="date"
tick={{ fill: '#FFFFFF', fontSize: '10px' }}
angle={-45}
textAnchor="end"
height={70}
>
<Label value="Date" offset={-20} position="insideBottom" style={{ fill: '#FFFFFF', fontWeight: 'bold' }} />
</XAxis>
<YAxis
tick={{ fill: '#FFFFFF', fontSize: '10px' }}
domain={['auto', 'auto']}
tickFormatter={(value) => formatNumberWithOutDecimal(value)}
>
<Label value={yAxisLabel} angle={-90} position="insideLeft" style={{ fill: '#FFFFFF', fontWeight: 'bold', textAnchor: 'middle' }} />
</YAxis>
<Tooltip content={<CustomTooltip />} />
<Legend verticalAlign="top" height={36} />
<Line type="monotone" dataKey={dataKey} stroke="#8884d8" activeDot={{ r: 8, fill: '#01FF85' }} dot={{ r: 2, fill: "#8884d8" }} name={selectedOption.value} />
</LineChart>
</ResponsiveContainer>
This chart displays the distribution of MOR token holders by range.
/mor_holders_by_range
Bar chart showing the number of holders for different MOR holding ranges.
The Staking component provides insights into the staking behavior of Morpheus token holders, including distribution of stake times, power multipliers, and emission statistics.
This chart displays the daily number of unique stakers for each pool (Capital and Code) and the combined total.
/analyze-mor-stakers
Line chart showing daily unique stakers for Capital (Pool 0), Code (Pool 1), and Combined.
These cards display various staking metrics including average stake time, average multiplier, and MOR rewards.
/analyze-mor-stakers
Info cards showing metrics for Capital (Pool 0), Code (Pool 1), and Combined.
This chart displays the APY and daily MOR rewards per stETH for different staking periods.
/give_mor_reward
Line chart with toggle button for APY/Rewards, X-axis showing staking period in days.
This chart shows the distribution of stake times among users.
/get_stake_info
<ResponsiveContainer width="100%" height={400}>
<BarChart
data={chartData}
margin={{ top: 20, right: 30, left: 20, bottom: 30 }}
>
<CartesianGrid strokeDasharray="3 3" stroke="#444" />
<XAxis
dataKey="range"
tick={{ fill: '#FFFFFF', fontSize: '12px' }}
interval={0}
>
<Label value="Years Staked" offset={-20} position="insideBottom" style={{ fill: '#FFFFFF', fontWeight: 'bold' }} />
</XAxis>
<YAxis tick={{ fill: '#FFFFFF', fontSize: '12px' }}>
<Label value="Number of Stakers" angle={-90} position="insideLeft" style={{ fill: '#FFFFFF', fontWeight: 'bold', textAnchor: 'middle' }} />
</YAxis>
<Tooltip content={<CustomTooltip />} />
<Legend verticalAlign="top" height={36} />
<Bar dataKey="frequency" fill="#8884d8" name="Number of Stakers" />
</BarChart>
</ResponsiveContainer>
This chart shows the distribution of power multipliers among stakers.
/get_stake_info
Similar to Stake Time Distribution Chart, but with "Power Multiplier Range" on X-axis.
This card shows the daily and total percentage of emissions allocated to stakers.
/analyze-mor-stakers
const getDailyMorStakeEmittedPercentage = () => {
let daily_relative_emission_percentage = 0
if (selectedUniqueStaker.key === 'pool_0') {
daily_relative_emission_percentage = (data.stakereward_analysis['0'].daily_reward_sum / data.emissionreward_analysis.new_emissions['Capital Emission']) * 100
}
else if (selectedUniqueStaker.key === 'pool_1') {
daily_relative_emission_percentage = (data.stakereward_analysis['1'].daily_reward_sum / data.emissionreward_analysis.new_emissions['Code Emission']) * 100
}
else {
daily_relative_emission_percentage = (
(data.stakereward_analysis['0'].daily_reward_sum + data.stakereward_analysis['1'].daily_reward_sum) /
(data.emissionreward_analysis.new_emissions['Capital Emission'] + data.emissionreward_analysis.new_emissions['Code Emission'])
)
* 100
}
return daily_relative_emission_percentage;
}
const getTotalMorStakeEmittedPercentage = () => {
let total_relative_emission_percentage = 0
if (selectedUniqueStaker.key === 'pool_0') {
total_relative_emission_percentage = (data.stakereward_analysis['0'].total_current_user_reward_sum / data.emissionreward_analysis.total_emissions['Capital Emission']) * 100
}
else if (selectedUniqueStaker.key === 'pool_1') {
total_relative_emission_percentage = (data.stakereward_analysis['1'].total_current_user_reward_sum / data.emissionreward_analysis.total_emissions['Code Emission']) * 100
}
else {
total_relative_emission_percentage = (
(data.stakereward_analysis['0'].total_current_user_reward_sum + data