suix_getLatestSuiSystemState
Returns the latest system state of the Sui network, including validator information, staking pools, and system parameters.
Overviewā
The suix_getLatestSuiSystemState
method provides comprehensive information about the current state of the Sui network. This includes detailed validator information, staking pools, system parameters, governance settings, and network configuration. This method is essential for applications that need to understand the complete network state, build staking interfaces, or analyze network governance and validator performance.
Parametersā
This method takes no parameters.
Returnsā
Returns a comprehensive system state object containing all network information.
Field | Type | Description |
---|---|---|
epoch | string | Current epoch number |
protocolVersion | string | Current protocol version |
systemStateVersion | string | System state schema version |
storageFundTotalObjectStorageRebates | string | Total storage fund rebates |
storageFundNonRefundableBalance | string | Non-refundable storage fund balance |
referenceGasPrice | string | Current reference gas price |
safeMode | boolean | Whether the network is in safe mode |
safeModeStorageRewards | string | Storage rewards in safe mode |
safeModeComputationRewards | string | Computation rewards in safe mode |
safeModeStorageRebates | string | Storage rebates in safe mode |
safeModeNonRefundableStorageFee | string | Non-refundable storage fee in safe mode |
epochStartTimestampMs | string | Epoch start timestamp in milliseconds |
epochDurationMs | string | Epoch duration in milliseconds |
stakeSubsidyBalance | string | Current stake subsidy balance |
stakeSubsidyDistributionCounter | string | Stake subsidy distribution counter |
stakeSubsidyCurrentDistributionAmount | string | Current distribution amount |
stakeSubsidyPeriodLength | string | Stake subsidy period length |
stakeSubsidyDecreaseRate | number | Rate of subsidy decrease |
totalStake | string | Total stake in the network |
activeValidators | array | Array of active validator objects |
pendingActiveValidatorsId | string | ID of pending active validators object |
pendingActiveValidatorsSize | string | Size of pending active validators |
pendingRemovals | array | Array of validators pending removal |
stakingPoolMappingsId | string | ID of staking pool mappings object |
stakingPoolMappingsSize | string | Size of staking pool mappings |
inactivePoolsId | string | ID of inactive pools object |
inactivePoolsSize | string | Size of inactive pools |
validatorCandidatesId | string | ID of validator candidates object |
validatorCandidatesSize | string | Size of validator candidates |
Active Validator Object Structureā
Each validator in the activeValidators
array contains:
Field | Type | Description |
---|---|---|
suiAddress | string | Validator's Sui address |
protocolPubkeyBytes | string | Protocol public key bytes |
networkPubkeyBytes | string | Network public key bytes |
workerPubkeyBytes | string | Worker public key bytes |
proofOfPossessionBytes | string | Proof of possession bytes |
name | string | Validator name |
description | string | Validator description |
imageUrl | string | Validator image URL |
projectUrl | string | Validator project URL |
networkAddress | string | Network address |
p2pAddress | string | P2P address |
primaryAddress | string | Primary address |
workerAddress | string | Worker address |
nextEpochProtocolPubkeyBytes | string | Next epoch protocol pubkey |
nextEpochProofOfPossession | string | Next epoch proof of possession |
nextEpochNetworkPubkeyBytes | string | Next epoch network pubkey |
nextEpochWorkerPubkeyBytes | string | Next epoch worker pubkey |
nextEpochNetworkAddress | string | Next epoch network address |
nextEpochP2pAddress | string | Next epoch P2P address |
nextEpochPrimaryAddress | string | Next epoch primary address |
nextEpochWorkerAddress | string | Next epoch worker address |
votingPower | string | Validator's voting power |
operationCapId | string | Operation capability ID |
gasPrice | string | Validator's gas price |
commissionRate | string | Commission rate (in basis points) |
nextEpochStake | string | Stake for next epoch |
nextEpochGasPrice | string | Gas price for next epoch |
nextEpochCommissionRate | string | Commission rate for next epoch |
stakingPoolId | string | Associated staking pool ID |
stakingPoolActivationEpoch | string | When staking pool was activated |
stakingPoolDeactivationEpoch | string | When staking pool will deactivate (if applicable) |
stakingPoolSuiBalance | string | SUI balance in staking pool |
rewardsPool | string | Rewards pool balance |
poolTokenBalance | string | Pool token balance |
pendingStake | string | Pending stake amount |
pendingPoolTokenWithdraw | string | Pending pool token withdrawals |
pendingTotalSuiWithdraw | string | Pending SUI withdrawals |
exchangeRatesId | string | Exchange rates object ID |
exchangeRatesSize | string | Exchange rates object size |
Code Examplesā
- cURL
- JavaScript
- Python
# Get latest system state
curl -X POST https://sui-mainnet.dwellir.com/YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "suix_getLatestSuiSystemState",
"params": [],
"id": 1
}'
import { SuiClient } from '@mysten/sui.js/client';
const client = new SuiClient({
url: 'https://sui-mainnet.dwellir.com/YOUR_API_KEY'
});
// Get latest system state
async function getLatestSystemState() {
try {
const systemState = await client.getLatestSuiSystemState();
console.log(`Current Epoch: ${systemState.epoch}`);
console.log(`Protocol Version: ${systemState.protocolVersion}`);
console.log(`Active Validators: ${systemState.activeValidators.length}`);
console.log(`Total Stake: ${Number(systemState.totalStake) / 1_000_000_000} SUI`);
console.log(`Reference Gas Price: ${systemState.referenceGasPrice} MIST`);
console.log(`Safe Mode: ${systemState.safeMode}`);
return systemState;
} catch (error) {
console.error('Failed to get system state:', error);
return null;
}
}
// System state analyzer with comprehensive insights
class SystemStateAnalyzer {
constructor(client) {
this.client = client;
}
async analyzeSystemState() {
const systemState = await this.client.getLatestSuiSystemState();
if (!systemState) {
return { error: 'Failed to retrieve system state' };
}
const analysis = {
networkInfo: this.analyzeNetworkInfo(systemState),
validatorAnalysis: this.analyzeValidators(systemState.activeValidators),
stakingAnalysis: this.analyzeStaking(systemState),
economicMetrics: this.analyzeEconomics(systemState),
governanceMetrics: this.analyzeGovernance(systemState),
protocolInfo: this.analyzeProtocol(systemState),
systemHealth: this.assessSystemHealth(systemState)
};
return analysis;
}
analyzeNetworkInfo(systemState) {
const epochStartTime = new Date(Number(systemState.epochStartTimestampMs));
const epochDuration = Number(systemState.epochDurationMs);
const timeInEpoch = Date.now() - Number(systemState.epochStartTimestampMs);
const progressPercent = (timeInEpoch / epochDuration) * 100;
return {
currentEpoch: systemState.epoch,
protocolVersion: systemState.protocolVersion,
epochStartTime: epochStartTime.toISOString(),
epochDurationHours: epochDuration / (1000 * 60 * 60),
epochProgressPercent: Math.min(100, Math.max(0, progressPercent)),
timeRemainingHours: Math.max(0, (epochDuration - timeInEpoch) / (1000 * 60 * 60)),
safeMode: systemState.safeMode,
referenceGasPrice: Number(systemState.referenceGasPrice)
};
}
analyzeValidators(validators) {
const validatorMetrics = validators.map(validator => ({
address: validator.suiAddress,
name: validator.name,
votingPower: BigInt(validator.votingPower),
stakingPoolBalance: BigInt(validator.stakingPoolSuiBalance),
commissionRate: Number(validator.commissionRate) / 100, // Convert basis points to percentage
gasPrice: Number(validator.gasPrice),
pendingStake: BigInt(validator.pendingStake),
rewardsPool: BigInt(validator.rewardsPool)
}));
const totalVotingPower = validatorMetrics.reduce((sum, v) => sum + v.votingPower, BigInt(0));
const totalStakingBalance = validatorMetrics.reduce((sum, v) => sum + v.stakingPoolBalance, BigInt(0));
// Sort by voting power
validatorMetrics.sort((a, b) => b.votingPower > a.votingPower ? 1 : -1);
return {
totalValidators: validators.length,
totalVotingPower: Number(totalVotingPower),
totalStakingBalanceSUI: Number(totalStakingBalance) / 1_000_000_000,
averageCommissionRate: validatorMetrics.reduce((sum, v) => sum + v.commissionRate, 0) / validators.length,
commissionRateRange: {
min: Math.min(...validatorMetrics.map(v => v.commissionRate)),
max: Math.max(...validatorMetrics.map(v => v.commissionRate))
},
gasPriceRange: {
min: Math.min(...validatorMetrics.map(v => v.gasPrice)),
max: Math.max(...validatorMetrics.map(v => v.gasPrice)),
average: validatorMetrics.reduce((sum, v) => sum + v.gasPrice, 0) / validators.length
},
topValidators: validatorMetrics.slice(0, 10).map(v => ({
address: v.address,
name: v.name,
votingPowerSUI: Number(v.votingPower) / 1_000_000_000,
stakingBalanceSUI: Number(v.stakingPoolBalance) / 1_000_000_000,
commissionRate: v.commissionRate,
gasPrice: v.gasPrice
})),
concentrationMetrics: this.calculateValidatorConcentration(validatorMetrics, totalVotingPower)
};
}
calculateValidatorConcentration(validators, totalVotingPower) {
// Calculate concentration metrics
const top5Power = validators.slice(0, 5).reduce((sum, v) => sum + v.votingPower, BigInt(0));
const top10Power = validators.slice(0, 10).reduce((sum, v) => sum + v.votingPower, BigInt(0));
const top20Power = validators.slice(0, 20).reduce((sum, v) => sum + v.votingPower, BigInt(0));
// Nakamoto coefficient (validators needed for >33% voting power)
let cumulativePower = BigInt(0);
const thresholdPower = totalVotingPower * BigInt(33) / BigInt(100);
let nakamotoCoefficient = 0;
for (const validator of validators) {
cumulativePower += validator.votingPower;
nakamotoCoefficient++;
if (cumulativePower > thresholdPower) break;
}
return {
top5Percentage: Number(top5Power * BigInt(10000) / totalVotingPower) / 100,
top10Percentage: Number(top10Power * BigInt(10000) / totalVotingPower) / 100,
top20Percentage: Number(top20Power * BigInt(10000) / totalVotingPower) / 100,
nakamotoCoefficient: nakamotoCoefficient,
giniCoefficient: this.calculateGiniCoefficient(validators.map(v => Number(v.votingPower)))
};
}
calculateGiniCoefficient(values) {
if (values.length === 0) return 0;
const sorted = [...values].sort((a, b) => a - b);
const n = sorted.length;
let numerator = 0;
let denominator = 0;
for (let i = 0; i < n; i++) {
numerator += (i + 1) * sorted[i];
denominator += sorted[i];
}
return denominator > 0 ? (2 * numerator) / (n * denominator) - (n + 1) / n : 0;
}
analyzeStaking(systemState) {
const totalStake = BigInt(systemState.totalStake);
const stakeSubsidyBalance = BigInt(systemState.stakeSubsidyBalance);
const currentDistribution = BigInt(systemState.stakeSubsidyCurrentDistributionAmount);
// Calculate total staking pool balances
const totalStakingPools = systemState.activeValidators.reduce(
(sum, validator) => sum + BigInt(validator.stakingPoolSuiBalance),
BigInt(0)
);
const totalPendingStake = systemState.activeValidators.reduce(
(sum, validator) => sum + BigInt(validator.pendingStake),
BigInt(0)
);
const totalRewardsPool = systemState.activeValidators.reduce(
(sum, validator) => sum + BigInt(validator.rewardsPool),
BigInt(0)
);
return {
totalNetworkStakeSUI: Number(totalStake) / 1_000_000_000,
totalStakingPoolsSUI: Number(totalStakingPools) / 1_000_000_000,
totalPendingStakeSUI: Number(totalPendingStake) / 1_000_000_000,
totalRewardsPoolSUI: Number(totalRewardsPool) / 1_000_000_000,
stakeSubsidy: {
balanceSUI: Number(stakeSubsidyBalance) / 1_000_000_000,
currentDistributionSUI: Number(currentDistribution) / 1_000_000_000,
distributionCounter: Number(systemState.stakeSubsidyDistributionCounter),
periodLength: Number(systemState.stakeSubsidyPeriodLength),
decreaseRate: systemState.stakeSubsidyDecreaseRate
},
stakingMetrics: {
pendingActiveValidators: systemState.pendingActiveValidatorsSize,
pendingRemovals: systemState.pendingRemovals.length,
inactivePoolsSize: systemState.inactivePoolsSize,
validatorCandidatesSize: systemState.validatorCandidatesSize
}
};
}
analyzeEconomics(systemState) {
const storageFundTotal = BigInt(systemState.storageFundTotalObjectStorageRebates);
const storageFundNonRefundable = BigInt(systemState.storageFundNonRefundableBalance);
const refundableBalance = storageFundTotal - storageFundNonRefundable;
return {
referenceGasPriceMIST: Number(systemState.referenceGasPrice),
referenceGasPriceSUI: Number(systemState.referenceGasPrice) / 1_000_000_000,
storageFund: {
totalRebatesSUI: Number(storageFundTotal) / 1_000_000_000,
nonRefundableBalanceSUI: Number(storageFundNonRefundable) / 1_000_000_000,
refundableBalanceSUI: Number(refundableBalance) / 1_000_000_000,
refundablePercentage: storageFundTotal > 0 ?
Number(refundableBalance * BigInt(10000) / storageFundTotal) / 100 : 0
},
safeModeRewards: systemState.safeMode ? {
storageRewardsSUI: Number(systemState.safeModeStorageRewards) / 1_000_000_000,
computationRewardsSUI: Number(systemState.safeModeComputationRewards) / 1_000_000_000,
storageRebatesSUI: Number(systemState.safeModeStorageRebates) / 1_000_000_000,
nonRefundableStorageFeeSUI: Number(systemState.safeModeNonRefundableStorageFee) / 1_000_000_000
} : null
};
}
analyzeGovernance(systemState) {
const totalValidators = systemState.activeValidators.length;
const totalStake = BigInt(systemState.totalStake);
// Calculate quorum requirements
const byzantineThreshold = totalStake * BigInt(33) / BigInt(100);
const superMajorityThreshold = totalStake * BigInt(67) / BigInt(100);
return {
protocolVersion: systemState.protocolVersion,
systemStateVersion: systemState.systemStateVersion,
governanceThresholds: {
byzantineToleranceStakeSUI: Number(byzantineThreshold) / 1_000_000_000,
superMajorityStakeSUI: Number(superMajorityThreshold) / 1_000_000_000,
byzantineTolerancePercentage: 33.33,
superMajorityPercentage: 66.67
},
validatorGovernance: {
totalValidators: totalValidators,
pendingRemovals: systemState.pendingRemovals.length,
candidateValidators: Number(systemState.validatorCandidatesSize),
activationsPending: Number(systemState.pendingActiveValidatorsSize)
}
};
}
analyzeProtocol(systemState) {
return {
currentVersion: systemState.protocolVersion,
systemStateVersion: systemState.systemStateVersion,
safeModeActive: systemState.safeMode,
epochInfo: {
current: systemState.epoch,
startTime: new Date(Number(systemState.epochStartTimestampMs)).toISOString(),
durationMs: Number(systemState.epochDurationMs),
durationHours: Number(systemState.epochDurationMs) / (1000 * 60 * 60)
},
networkIds: {
stakingPoolMappingsId: systemState.stakingPoolMappingsId,
inactivePoolsId: systemState.inactivePoolsId,
validatorCandidatesId: systemState.validatorCandidatesId,
pendingActiveValidatorsId: systemState.pendingActiveValidatorsId
}
};
}
assessSystemHealth(systemState) {
const healthScore = {
overall: 100,
factors: []
};
// Check safe mode
if (systemState.safeMode) {
healthScore.overall -= 30;
healthScore.factors.push({
factor: 'Safe Mode Active',
impact: -30,
description: 'Network is operating in safe mode with limited functionality'
});
}
// Check validator count
const validatorCount = systemState.activeValidators.length;
if (validatorCount < 50) {
healthScore.overall -= 15;
healthScore.factors.push({
factor: 'Low Validator Count',
impact: -15,
description: `Only ${validatorCount} active validators`
});
} else if (validatorCount < 100) {
healthScore.overall -= 5;
healthScore.factors.push({
factor: 'Moderate Validator Count',
impact: -5,
description: `${validatorCount} active validators could be higher for better decentralization`
});
}
// Check stake concentration
const validators = systemState.activeValidators.map(v => BigInt(v.stakingPoolSuiBalance));
const totalStake = validators.reduce((sum, stake) => sum + stake, BigInt(0));
const sortedValidators = validators.sort((a, b) => b > a ? 1 : -1);
const top5Stake = sortedValidators.slice(0, 5).reduce((sum, stake) => sum + stake, BigInt(0));
const concentrationPercent = totalStake > 0 ? Number(top5Stake * BigInt(10000) / totalStake) / 100 : 0;
if (concentrationPercent > 60) {
healthScore.overall -= 20;
healthScore.factors.push({
factor: 'High Stake Concentration',
impact: -20,
description: `Top 5 validators control ${concentrationPercent.toFixed(1)}% of stake`
});
} else if (concentrationPercent > 40) {
healthScore.overall -= 10;
healthScore.factors.push({
factor: 'Moderate Stake Concentration',
impact: -10,
description: `Top 5 validators control ${concentrationPercent.toFixed(1)}% of stake`
});
}
// Check pending changes
const pendingRemovals = systemState.pendingRemovals.length;
if (pendingRemovals > validatorCount * 0.1) { // More than 10% pending removal
healthScore.overall -= 15;
healthScore.factors.push({
factor: 'High Validator Churn',
impact: -15,
description: `${pendingRemovals} validators pending removal`
});
}
return {
score: Math.max(0, healthScore.overall),
status: healthScore.overall >= 80 ? 'Healthy' :
healthScore.overall >= 60 ? 'Warning' : 'Critical',
factors: healthScore.factors,
recommendations: this.generateHealthRecommendations(healthScore.factors)
};
}
generateHealthRecommendations(factors) {
const recommendations = [];
factors.forEach(factor => {
switch (factor.factor) {
case 'Safe Mode Active':
recommendations.push('Monitor network status for safe mode resolution');
break;
case 'Low Validator Count':
recommendations.push('Encourage more validator participation for better decentralization');
break;
case 'High Stake Concentration':
recommendations.push('Consider redistributing stake across more validators');
break;
case 'High Validator Churn':
recommendations.push('Monitor validator stability and network conditions');
break;
}
});
return recommendations;
}
}
// System state monitoring and alerting
class SystemStateMonitor {
constructor(client) {
this.client = client;
this.previousState = null;
this.alerts = [];
this.thresholds = {
validatorCountChange: 5,
stakeChangePercent: 10,
gasPriceChangePercent: 25,
newEpochAlert: true
};
}
async monitor() {
try {
const currentState = await this.client.getLatestSuiSystemState();
if (this.previousState) {
this.checkForChanges(this.previousState, currentState);
}
this.previousState = currentState;
// Log current status
console.log(`š System Status - Epoch ${currentState.epoch}`);
console.log(` Validators: ${currentState.activeValidators.length}`);
console.log(` Total Stake: ${Number(currentState.totalStake) / 1_000_000_000:.0f} SUI`);
console.log(` Gas Price: ${currentState.referenceGasPrice} MIST`);
console.log(` Safe Mode: ${currentState.safeMode ? 'ACTIVE' : 'INACTIVE'}`);
return currentState;
} catch (error) {
console.error('Error monitoring system state:', error);
return null;
}
}
checkForChanges(previous, current) {
const alerts = [];
// Check for new epoch
if (previous.epoch !== current.epoch) {
alerts.push({
type: 'NEW_EPOCH',
message: `New epoch started: ${previous.epoch} ā ${current.epoch}`,
severity: 'INFO',
data: {
previousEpoch: previous.epoch,
currentEpoch: current.epoch,
epochStartTime: new Date(Number(current.epochStartTimestampMs)).toISOString()
}
});
}
// Check validator count changes
const validatorCountChange = current.activeValidators.length - previous.activeValidators.length;
if (Math.abs(validatorCountChange) >= this.thresholds.validatorCountChange) {
alerts.push({
type: 'VALIDATOR_COUNT_CHANGE',
message: `Validator count changed by ${validatorCountChange} (${previous.activeValidators.length} ā ${current.activeValidators.length})`,
severity: validatorCountChange > 0 ? 'INFO' : 'WARNING',
data: {
change: validatorCountChange,
previous: previous.activeValidators.length,
current: current.activeValidators.length
}
});
}
// Check stake changes
const previousStake = BigInt(previous.totalStake);
const currentStake = BigInt(current.totalStake);
const stakeChange = currentStake - previousStake;
const stakeChangePercent = previousStake > 0 ?
Number(stakeChange * BigInt(10000) / previousStake) / 100 : 0;
if (Math.abs(stakeChangePercent) >= this.thresholds.stakeChangePercent) {
alerts.push({
type: 'TOTAL_STAKE_CHANGE',
message: `Total stake changed by ${stakeChangePercent.toFixed(1)}% (${Number(stakeChange) / 1_000_000_000:+.0f} SUI)`,
severity: 'INFO',
data: {
changePercent: stakeChangePercent,
changeSUI: Number(stakeChange) / 1_000_000_000,
previousSUI: Number(previousStake) / 1_000_000_000,
currentSUI: Number(currentStake) / 1_000_000_000
}
});
}
// Check gas price changes
const previousGasPrice = Number(previous.referenceGasPrice);
const currentGasPrice = Number(current.referenceGasPrice);
const gasPriceChangePercent = previousGasPrice > 0 ?
((currentGasPrice - previousGasPrice) / previousGasPrice) * 100 : 0;
if (Math.abs(gasPriceChangePercent) >= this.thresholds.gasPriceChangePercent) {
alerts.push({
type: 'GAS_PRICE_CHANGE',
message: `Reference gas price changed by ${gasPriceChangePercent.toFixed(1)}% (${previousGasPrice} ā ${currentGasPrice} MIST)`,
severity: 'WARNING',
data: {
changePercent: gasPriceChangePercent,
previous: previousGasPrice,
current: currentGasPrice
}
});
}
// Check safe mode changes
if (previous.safeMode !== current.safeMode) {
alerts.push({
type: 'SAFE_MODE_CHANGE',
message: `Safe mode ${current.safeMode ? 'ACTIVATED' : 'DEACTIVATED'}`,
severity: current.safeMode ? 'CRITICAL' : 'INFO',
data: {
safeMode: current.safeMode,
previousSafeMode: previous.safeMode
}
});
}
// Store alerts
alerts.forEach(alert => {
alert.timestamp = Date.now();
this.alerts.push(alert);
this.logAlert(alert);
});
return alerts;
}
logAlert(alert) {
const emoji = {
'INFO': 'šµ',
'WARNING': 'š”',
'CRITICAL': 'š“'
}[alert.severity] || 'š¢';
console.log(`${emoji} [${alert.severity}] ${alert.message}`);
}
async startMonitoring(intervalMinutes = 10) {
console.log(`š Starting system state monitoring (every ${intervalMinutes} minutes)`);
// Initial monitoring
await this.monitor();
const intervalId = setInterval(async () => {
await this.monitor();
}, intervalMinutes * 60 * 1000);
return () => {
clearInterval(intervalId);
console.log('System state monitoring stopped');
};
}
}
// Usage examples
// Get basic system state
const systemState = await getLatestSystemState();
// Comprehensive system analysis
const analyzer = new SystemStateAnalyzer(client);
const analysis = await analyzer.analyzeSystemState();
if (analysis && !analysis.error) {
console.log('\n=== SYSTEM STATE ANALYSIS ===');
// Network Information
console.log('\nš Network Information:');
console.log(` Epoch: ${analysis.networkInfo.currentEpoch}`);
console.log(` Protocol Version: ${analysis.networkInfo.protocolVersion}`);
console.log(` Epoch Progress: ${analysis.networkInfo.epochProgressPercent.toFixed(1)}%`);
console.log(` Time Remaining: ${analysis.networkInfo.timeRemainingHours.toFixed(1)} hours`);
console.log(` Safe Mode: ${analysis.networkInfo.safeMode ? 'ACTIVE' : 'INACTIVE'}`);
console.log(` Gas Price: ${analysis.networkInfo.referenceGasPrice} MIST`);
// Validator Analysis
console.log('\nš„ Validator Analysis:');
console.log(` Active Validators: ${analysis.validatorAnalysis.totalValidators}`);
console.log(` Total Staked: ${analysis.validatorAnalysis.totalStakingBalanceSUI.toFixed(0)} SUI`);
console.log(` Average Commission: ${analysis.validatorAnalysis.averageCommissionRate.toFixed(2)}%`);
console.log(` Commission Range: ${analysis.validatorAnalysis.commissionRateRange.min.toFixed(2)}% - ${analysis.validatorAnalysis.commissionRateRange.max.toFixed(2)}%`);
console.log(` Top 5 Control: ${analysis.validatorAnalysis.concentrationMetrics.top5Percentage.toFixed(1)}%`);
console.log(` Nakamoto Coefficient: ${analysis.validatorAnalysis.concentrationMetrics.nakamotoCoefficient}`);
// Staking Analysis
console.log('\nš° Staking Analysis:');
console.log(` Network Stake: ${analysis.stakingAnalysis.totalNetworkStakeSUI.toFixed(0)} SUI`);
console.log(` Pending Stake: ${analysis.stakingAnalysis.totalPendingStakeSUI.toFixed(0)} SUI`);
console.log(` Rewards Pool: ${analysis.stakingAnalysis.totalRewardsPoolSUI.toFixed(0)} SUI`);
console.log(` Subsidy Balance: ${analysis.stakingAnalysis.stakeSubsidy.balanceSUI.toFixed(0)} SUI`);
console.log(` Current Distribution: ${analysis.stakingAnalysis.stakeSubsidy.currentDistributionSUI.toFixed(0)} SUI`);
// Economic Metrics
console.log('\nšø Economic Metrics:');
console.log(` Reference Gas Price: ${analysis.economicMetrics.referenceGasPriceSUI.toFixed(9)} SUI`);
console.log(` Storage Fund Total: ${analysis.economicMetrics.storageFund.totalRebatesSUI.toFixed(0)} SUI`);
console.log(` Refundable: ${analysis.economicMetrics.storageFund.refundableBalanceSUI.toFixed(0)} SUI (${analysis.economicMetrics.storageFund.refundablePercentage.toFixed(1)}%)`);
// System Health
console.log('\nš„ System Health:');
console.log(` Overall Score: ${analysis.systemHealth.score}/100 (${analysis.systemHealth.status})`);
if (analysis.systemHealth.factors.length > 0) {
console.log(' Health Factors:');
analysis.systemHealth.factors.forEach(factor => {
console.log(` ${factor.factor}: ${factor.impact} points - ${factor.description}`);
});
}
if (analysis.systemHealth.recommendations.length > 0) {
console.log(' Recommendations:');
analysis.systemHealth.recommendations.forEach(rec => {
console.log(` ⢠${rec}`);
});
}
// Top Validators
console.log('\nš Top 5 Validators:');
analysis.validatorAnalysis.topValidators.slice(0, 5).forEach((validator, index) => {
console.log(` ${index + 1}. ${validator.name || validator.address.substring(0, 16) + '...'}`);
console.log(` Stake: ${validator.stakingBalanceSUI.toFixed(0)} SUI`);
console.log(` Commission: ${validator.commissionRate.toFixed(2)}%`);
console.log(` Gas Price: ${validator.gasPrice} MIST`);
});
}
// Start system monitoring (uncomment to run continuously)
// const monitor = new SystemStateMonitor(client);
// const stopMonitoring = await monitor.startMonitoring(10); // Check every 10 minutes
// Example monitoring output
console.log('\nš Example Monitoring Output:');
console.log('š Starting system state monitoring (every 10 minutes)');
console.log('š System Status - Epoch 251');
console.log(' Validators: 120');
console.log(' Total Stake: 2,500,000 SUI');
console.log(' Gas Price: 1000 MIST');
console.log(' Safe Mode: INACTIVE');
console.log('šµ [INFO] New epoch started: 250 ā 251');
console.log('š” [WARNING] Reference gas price changed by +5.0% (1000 ā 1050 MIST)');
import requests
import json
import time
import statistics
import threading
from typing import Dict, List, Any, Optional
from dataclasses import dataclass, field
from datetime import datetime, timedelta
@dataclass
class SystemStateAlert:
alert_type: str
message: str
severity: str
timestamp: float
data: Dict[str, Any] = field(default_factory=dict)
class SuiSystemStateClient:
def __init__(self, rpc_url: str):
self.rpc_url = rpc_url
def get_latest_system_state(self) -> Optional[Dict[str, Any]]:
"""Get the latest Sui system state"""
payload = {
"jsonrpc": "2.0",
"method": "suix_getLatestSuiSystemState",
"params": [],
"id": 1
}
try:
response = requests.post(
self.rpc_url,
headers={'Content-Type': 'application/json'},
data=json.dumps(payload),
timeout=30
)
result = response.json()
if 'error' in result:
print(f"RPC Error: {result['error']}")
return None
return result['result']
except Exception as e:
print(f"Error fetching system state: {e}")
return None
class SystemStateAnalyzer:
def __init__(self, client: SuiSystemStateClient):
self.client = client
def analyze_system_state(self) -> Dict[str, Any]:
"""Perform comprehensive analysis of the system state"""
system_state = self.client.get_latest_system_state()
if not system_state:
return {'error': 'Failed to retrieve system state'}
analysis = {
'network_info': self._analyze_network_info(system_state),
'validator_analysis': self._analyze_validators(system_state['activeValidators']),
'staking_analysis': self._analyze_staking(system_state),
'economic_metrics': self._analyze_economics(system_state),
'governance_metrics': self._analyze_governance(system_state),
'protocol_info': self._analyze_protocol(system_state),
'system_health': self._assess_system_health(system_state)
}
return analysis
def _analyze_network_info(self, system_state: Dict[str, Any]) -> Dict[str, Any]:
"""Analyze network information"""
epoch_start_time = datetime.fromtimestamp(int(system_state['epochStartTimestampMs']) / 1000)
epoch_duration_ms = int(system_state['epochDurationMs'])
time_in_epoch = (datetime.now() - epoch_start_time).total_seconds() * 1000
progress_percent = min(100, max(0, (time_in_epoch / epoch_duration_ms) * 100))
return {
'current_epoch': system_state['epoch'],
'protocol_version': system_state['protocolVersion'],
'epoch_start_time': epoch_start_time.isoformat(),
'epoch_duration_hours': epoch_duration_ms / (1000 * 60 * 60),
'epoch_progress_percent': progress_percent,
'time_remaining_hours': max(0, (epoch_duration_ms - time_in_epoch) / (1000 * 60 * 60)),
'safe_mode': system_state['safeMode'],
'reference_gas_price': int(system_state['referenceGasPrice'])
}
def _analyze_validators(self, validators: List[Dict[str, Any]]) -> Dict[str, Any]:
"""Analyze validator information"""
validator_metrics = []
for validator in validators:
metrics = {
'address': validator['suiAddress'],
'name': validator.get('name', ''),
'voting_power': int(validator['votingPower']),
'staking_pool_balance': int(validator['stakingPoolSuiBalance']),
'commission_rate': int(validator['commissionRate']) / 100, # Convert basis points
'gas_price': int(validator['gasPrice']),
'pending_stake': int(validator['pendingStake']),
'rewards_pool': int(validator['rewardsPool'])
}
validator_metrics.append(metrics)
# Calculate totals
total_voting_power = sum(v['voting_power'] for v in validator_metrics)
total_staking_balance = sum(v['staking_pool_balance'] for v in validator_metrics)
# Sort by voting power
validator_metrics.sort(key=lambda v: v['voting_power'], reverse=True)
return {
'total_validators': len(validators),
'total_voting_power': total_voting_power,
'total_staking_balance_sui': total_staking_balance / 1_000_000_000,
'average_commission_rate': statistics.mean([v['commission_rate'] for v in validator_metrics]),
'commission_rate_range': {
'min': min(v['commission_rate'] for v in validator_metrics),
'max': max(v['commission_rate'] for v in validator_metrics)
},
'gas_price_range': {
'min': min(v['gas_price'] for v in validator_metrics),
'max': max(v['gas_price'] for v in validator_metrics),
'average': statistics.mean([v['gas_price'] for v in validator_metrics])
},
'top_validators': self._format_top_validators(validator_metrics[:10]),
'concentration_metrics': self._calculate_validator_concentration(validator_metrics, total_voting_power)
}
def _format_top_validators(self, validators: List[Dict]) -> List[Dict]:
"""Format top validators for display"""
return [
{
'address': v['address'],
'name': v['name'],
'voting_power_sui': v['voting_power'] / 1_000_000_000,
'staking_balance_sui': v['staking_pool_balance'] / 1_000_000_000,
'commission_rate': v['commission_rate'],
'gas_price': v['gas_price']
}
for v in validators
]
def _calculate_validator_concentration(self, validators: List[Dict], total_voting_power: int) -> Dict[str, Any]:
"""Calculate validator concentration metrics"""
# Calculate concentration percentages
top_5_power = sum(v['voting_power'] for v in validators[:5])
top_10_power = sum(v['voting_power'] for v in validators[:10])
top_20_power = sum(v['voting_power'] for v in validators[:min(20, len(validators))])
# Calculate Nakamoto coefficient
cumulative_power = 0
threshold_power = total_voting_power * 33 // 100
nakamoto_coefficient = 0
for validator in validators:
cumulative_power += validator['voting_power']
nakamoto_coefficient += 1
if cumulative_power > threshold_power:
break
return {
'top_5_percentage': (top_5_power / total_voting_power * 100) if total_voting_power > 0 else 0,
'top_10_percentage': (top_10_power / total_voting_power * 100) if total_voting_power > 0 else 0,
'top_20_percentage': (top_20_power / total_voting_power * 100) if total_voting_power > 0 else 0,
'nakamoto_coefficient': nakamoto_coefficient,
'gini_coefficient': self._calculate_gini_coefficient([v['voting_power'] for v in validators])
}
def _calculate_gini_coefficient(self, values: List[int]) -> float:
"""Calculate Gini coefficient for distribution analysis"""
if not values:
return 0.0
sorted_values = sorted(values)
n = len(sorted_values)
if n == 0 or sum(sorted_values) == 0:
return 0.0
numerator = sum((i + 1) * value for i, value in enumerate(sorted_values))
denominator = n * sum(sorted_values)
return (2 * numerator / denominator) - (n + 1) / n
def _analyze_staking(self, system_state: Dict[str, Any]) -> Dict[str, Any]:
"""Analyze staking information"""
total_stake = int(system_state['totalStake'])
stake_subsidy_balance = int(system_state['stakeSubsidyBalance'])
current_distribution = int(system_state['stakeSubsidyCurrentDistributionAmount'])
# Calculate aggregated staking pool data
validators = system_state['activeValidators']
total_staking_pools = sum(int(v['stakingPoolSuiBalance']) for v in validators)
total_pending_stake = sum(int(v['pendingStake']) for v in validators)
total_rewards_pool = sum(int(v['rewardsPool']) for v in validators)
return {
'total_network_stake_sui': total_stake / 1_000_000_000,
'total_staking_pools_sui': total_staking_pools / 1_000_000_000,
'total_pending_stake_sui': total_pending_stake / 1_000_000_000,
'total_rewards_pool_sui': total_rewards_pool / 1_000_000_000,
'stake_subsidy': {
'balance_sui': stake_subsidy_balance / 1_000_000_000,
'current_distribution_sui': current_distribution / 1_000_000_000,
'distribution_counter': int(system_state['stakeSubsidyDistributionCounter']),
'period_length': int(system_state['stakeSubsidyPeriodLength']),
'decrease_rate': system_state['stakeSubsidyDecreaseRate']
},
'staking_metrics': {
'pending_active_validators': system_state['pendingActiveValidatorsSize'],
'pending_removals': len(system_state['pendingRemovals']),
'inactive_pools_size': system_state['inactivePoolsSize'],
'validator_candidates_size': system_state['validatorCandidatesSize']
}
}
def _analyze_economics(self, system_state: Dict[str, Any]) -> Dict[str, Any]:
"""Analyze economic metrics"""
storage_fund_total = int(system_state['storageFundTotalObjectStorageRebates'])
storage_fund_non_refundable = int(system_state['storageFundNonRefundableBalance'])
refundable_balance = storage_fund_total - storage_fund_non_refundable
economics = {
'reference_gas_price_mist': int(system_state['referenceGasPrice']),
'reference_gas_price_sui': int(system_state['referenceGasPrice']) / 1_000_000_000,
'storage_fund': {
'total_rebates_sui': storage_fund_total / 1_000_000_000,
'non_refundable_balance_sui': storage_fund_non_refundable / 1_000_000_000,
'refundable_balance_sui': refundable_balance / 1_000_000_000,
'refundable_percentage': (refundable_balance / storage_fund_total * 100) if storage_fund_total > 0 else 0
}
}
# Add safe mode rewards if active
if system_state['safeMode']:
economics['safe_mode_rewards'] = {
'storage_rewards_sui': int(system_state['safeModeStorageRewards']) / 1_000_000_000,
'computation_rewards_sui': int(system_state['safeModeComputationRewards']) / 1_000_000_000,
'storage_rebates_sui': int(system_state['safeModeStorageRebates']) / 1_000_000_000,
'non_refundable_storage_fee_sui': int(system_state['safeModeNonRefundableStorageFee']) / 1_000_000_000
}
return economics
def _analyze_governance(self, system_state: Dict[str, Any]) -> Dict[str, Any]:
"""Analyze governance metrics"""
total_validators = len(system_state['activeValidators'])
total_stake = int(system_state['totalStake'])
return {
'protocol_version': system_state['protocolVersion'],
'system_state_version': system_state['systemStateVersion'],
'governance_thresholds': {
'byzantine_tolerance_stake_sui': (total_stake * 33 // 100) / 1_000_000_000,
'super_majority_stake_sui': (total_stake * 67 // 100) / 1_000_000_000,
'byzantine_tolerance_percentage': 33.33,
'super_majority_percentage': 66.67
},
'validator_governance': {
'total_validators': total_validators,
'pending_removals': len(system_state['pendingRemovals']),
'candidate_validators': int(system_state['validatorCandidatesSize']),
'activations_pending': int(system_state['pendingActiveValidatorsSize'])
}
}
def _analyze_protocol(self, system_state: Dict[str, Any]) -> Dict[str, Any]:
"""Analyze protocol information"""
epoch_start_time = datetime.fromtimestamp(int(system_state['epochStartTimestampMs']) / 1000)
epoch_duration_ms = int(system_state['epochDurationMs'])
return {
'current_version': system_state['protocolVersion'],
'system_state_version': system_state['systemStateVersion'],
'safe_mode_active': system_state['safeMode'],
'epoch_info': {
'current': system_state['epoch'],
'start_time': epoch_start_time.isoformat(),
'duration_ms': epoch_duration_ms,
'duration_hours': epoch_duration_ms / (1000 * 60 * 60)
},
'network_ids': {
'staking_pool_mappings_id': system_state['stakingPoolMappingsId'],
'inactive_pools_id': system_state['inactivePoolsId'],
'validator_candidates_id': system_state['validatorCandidatesId'],
'pending_active_validators_id': system_state['pendingActiveValidatorsId']
}
}
def _assess_system_health(self, system_state: Dict[str, Any]) -> Dict[str, Any]:
"""Assess overall system health"""
health_score = {'overall': 100, 'factors': []}
# Check safe mode
if system_state['safeMode']:
health_score['overall'] -= 30
health_score['factors'].append({
'factor': 'Safe Mode Active',
'impact': -30,
'description': 'Network is operating in safe mode with limited functionality'
})
# Check validator count
validator_count = len(system_state['activeValidators'])
if validator_count < 50:
health_score['overall'] -= 15
health_score['factors'].append({
'factor': 'Low Validator Count',
'impact': -15,
'description': f'Only {validator_count} active validators'
})
elif validator_count < 100:
health_score['overall'] -= 5
health_score['factors'].append({
'factor': 'Moderate Validator Count',
'impact': -5,
'description': f'{validator_count} active validators could be higher'
})
# Check stake concentration
validators = system_state['activeValidators']
stakes = [int(v['stakingPoolSuiBalance']) for v in validators]
total_stake = sum(stakes)
if stakes:
sorted_stakes = sorted(stakes, reverse=True)
top_5_stake = sum(sorted_stakes[:5])
concentration_percent = (top_5_stake / total_stake * 100) if total_stake > 0 else 0
if concentration_percent > 60:
health_score['overall'] -= 20
health_score['factors'].append({
'factor': 'High Stake Concentration',
'impact': -20,
'description': f'Top 5 validators control {concentration_percent:.1f}% of stake'
})
elif concentration_percent > 40:
health_score['overall'] -= 10
health_score['factors'].append({
'factor': 'Moderate Stake Concentration',
'impact': -10,
'description': f'Top 5 validators control {concentration_percent:.1f}% of stake'
})
# Check pending changes
pending_removals = len(system_state['pendingRemovals'])
if pending_removals > validator_count * 0.1: # More than 10%
health_score['overall'] -= 15
health_score['factors'].append({
'factor': 'High Validator Churn',
'impact': -15,
'description': f'{pending_removals} validators pending removal'
})
return {
'score': max(0, health_score['overall']),
'status': 'Healthy' if health_score['overall'] >= 80 else
'Warning' if health_score['overall'] >= 60 else 'Critical',
'factors': health_score['factors'],
'recommendations': self._generate_health_recommendations(health_score['factors'])
}
def _generate_health_recommendations(self, factors: List[Dict]) -> List[str]:
"""Generate health recommendations based on factors"""
recommendations = []
for factor in factors:
if factor['factor'] == 'Safe Mode Active':
recommendations.append('Monitor network status for safe mode resolution')
elif factor['factor'] == 'Low Validator Count':
recommendations.append('Encourage more validator participation')
elif factor['factor'] == 'High Stake Concentration':
recommendations.append('Consider redistributing stake across more validators')
elif factor['factor'] == 'High Validator Churn':
recommendations.append('Monitor validator stability and network conditions')
return recommendations
class SystemStateMonitor:
def __init__(self, client: SuiSystemStateClient):
self.client = client
self.previous_state = None
self.alerts = []
self.is_monitoring = False
self.monitor_thread = None
self.thresholds = {
'validator_count_change': 5,
'stake_change_percent': 10,
'gas_price_change_percent': 25,
'new_epoch_alert': True
}
def monitor(self) -> Optional[Dict[str, Any]]:
"""Monitor system state and check for changes"""
try:
current_state = self.client.get_latest_system_state()
if not current_state:
return None
if self.previous_state:
self._check_for_changes(self.previous_state, current_state)
self.previous_state = current_state
# Log current status
validator_count = len(current_state['activeValidators'])
total_stake_sui = int(current_state['totalStake']) / 1_000_000_000
gas_price = current_state['referenceGasPrice']
safe_mode = 'ACTIVE' if current_state['safeMode'] else 'INACTIVE'
print(f"š System Status - Epoch {current_state['epoch']}")
print(f" Validators: {validator_count}")
print(f" Total Stake: {total_stake_sui:.0f} SUI")
print(f" Gas Price: {gas_price} MIST")
print(f" Safe Mode: {safe_mode}")
return current_state
except Exception as e:
print(f"Error monitoring system state: {e}")
return None
def _check_for_changes(self, previous: Dict[str, Any], current: Dict[str, Any]):
"""Check for significant changes between states"""
alerts = []
# Check for new epoch
if previous['epoch'] != current['epoch']:
epoch_start_time = datetime.fromtimestamp(int(current['epochStartTimestampMs']) / 1000)
alerts.append(SystemStateAlert(
alert_type='NEW_EPOCH',
message=f"New epoch started: {previous['epoch']} ā {current['epoch']}",
severity='INFO',
timestamp=time.time(),
data={
'previous_epoch': previous['epoch'],
'current_epoch': current['epoch'],
'epoch_start_time': epoch_start_time.isoformat()
}
))
# Check validator count changes
prev_validator_count = len(previous['activeValidators'])
curr_validator_count = len(current['activeValidators'])
validator_change = curr_validator_count - prev_validator_count
if abs(validator_change) >= self.thresholds['validator_count_change']:
alerts.append(SystemStateAlert(
alert_type='VALIDATOR_COUNT_CHANGE',
message=f"Validator count changed by {validator_change:+d} ({prev_validator_count} ā {curr_validator_count})",
severity='INFO' if validator_change > 0 else 'WARNING',
timestamp=time.time(),
data={
'change': validator_change,
'previous': prev_validator_count,
'current': curr_validator_count
}
))
# Check stake changes
prev_stake = int(previous['totalStake'])
curr_stake = int(current['totalStake'])
stake_change = curr_stake - prev_stake
stake_change_percent = (stake_change / prev_stake * 100) if prev_stake > 0 else 0
if abs(stake_change_percent) >= self.thresholds['stake_change_percent']:
alerts.append(SystemStateAlert(
alert_type='TOTAL_STAKE_CHANGE',
message=f"Total stake changed by {stake_change_percent:+.1f}% ({stake_change / 1_000_000_000:+.0f} SUI)",
severity='INFO',
timestamp=time.time(),
data={
'change_percent': stake_change_percent,
'change_sui': stake_change / 1_000_000_000,
'previous_sui': prev_stake / 1_000_000_000,
'current_sui': curr_stake / 1_000_000_000
}
))
# Check gas price changes
prev_gas_price = int(previous['referenceGasPrice'])
curr_gas_price = int(current['referenceGasPrice'])
gas_price_change_percent = ((curr_gas_price - prev_gas_price) / prev_gas_price * 100) if prev_gas_price > 0 else 0
if abs(gas_price_change_percent) >= self.thresholds['gas_price_change_percent']:
alerts.append(SystemStateAlert(
alert_type='GAS_PRICE_CHANGE',
message=f"Reference gas price changed by {gas_price_change_percent:+.1f}% ({prev_gas_price} ā {curr_gas_price} MIST)",
severity='WARNING',
timestamp=time.time(),
data={
'change_percent': gas_price_change_percent,
'previous': prev_gas_price,
'current': curr_gas_price
}
))
# Check safe mode changes
if previous['safeMode'] != current['safeMode']:
alerts.append(SystemStateAlert(
alert_type='SAFE_MODE_CHANGE',
message=f"Safe mode {'ACTIVATED' if current['safeMode'] else 'DEACTIVATED'}",
severity='CRITICAL' if current['safeMode'] else 'INFO',
timestamp=time.time(),
data={
'safe_mode': current['safeMode'],
'previous_safe_mode': previous['safeMode']
}
))
# Store and log alerts
for alert in alerts:
self.alerts.append(alert)
self._log_alert(alert)
def _log_alert(self, alert: SystemStateAlert):
"""Log an alert with appropriate emoji"""
emoji_map = {
'INFO': 'šµ',
'WARNING': 'š”',
'CRITICAL': 'š“'
}
emoji = emoji_map.get(alert.severity, 'š¢')
print(f"{emoji} [{alert.severity}] {alert.message}")
def start_monitoring(self, interval_minutes: int = 10, duration_hours: int = 24):
"""Start monitoring system state"""
if self.is_monitoring:
print("System state monitoring already in progress")
return
print(f"š Starting system state monitoring (every {interval_minutes} minutes)")
self.is_monitoring = True
def monitor_loop():
start_time = time.time()
end_time = start_time + (duration_hours * 3600)
# Initial monitoring
self.monitor()
while self.is_monitoring and time.time() < end_time:
time.sleep(interval_minutes * 60)
if self.is_monitoring:
self.monitor()
self.is_monitoring = False
print("System state monitoring completed")
self.monitor_thread = threading.Thread(target=monitor_loop, daemon=True)
self.monitor_thread.start()
def stop_monitoring(self):
"""Stop system state monitoring"""
self.is_monitoring = False
if self.monitor_thread:
self.monitor_thread.join(timeout=5)
print("System state monitoring stopped")
# Usage examples
client = SuiSystemStateClient('https://sui-mainnet.dwellir.com/YOUR_API_KEY')
# Example 1: Get basic system state
print("Getting latest system state...")
system_state = client.get_latest_system_state()
if system_state:
validator_count = len(system_state['activeValidators'])
total_stake_sui = int(system_state['totalStake']) / 1_000_000_000
print(f"System State Summary:")
print(f" Current Epoch: {system_state['epoch']}")
print(f" Protocol Version: {system_state['protocolVersion']}")
print(f" Active Validators: {validator_count}")
print(f" Total Stake: {total_stake_sui:.0f} SUI")
print(f" Reference Gas Price: {system_state['referenceGasPrice']} MIST")
print(f" Safe Mode: {'ACTIVE' if system_state['safeMode'] else 'INACTIVE'}")
# Show some validator details
print(f"\nTop 3 Validators by Staking Pool Balance:")
validators = system_state['activeValidators']
sorted_validators = sorted(validators, key=lambda v: int(v['stakingPoolSuiBalance']), reverse=True)
for i, validator in enumerate(sorted_validators[:3], 1):
balance_sui = int(validator['stakingPoolSuiBalance']) / 1_000_000_000
commission = int(validator['commissionRate']) / 100
name = validator.get('name', validator['suiAddress'][:16] + '...')
print(f" {i}. {name}")
print(f" Balance: {balance_sui:.0f} SUI")
print(f" Commission: {commission:.2f}%")
print(f" Gas Price: {validator['gasPrice']} MIST")
# Example 2: Comprehensive system analysis
print(f"\n" + "="*50)
print("COMPREHENSIVE SYSTEM STATE ANALYSIS")
print("="*50)
analyzer = SystemStateAnalyzer(client)
analysis = analyzer.analyze_system_state()
if 'error' not in analysis:
# Network Information
network = analysis['network_info']
print(f"\nš Network Information:")
print(f" Epoch: {network['current_epoch']}")
print(f" Protocol Version: {network['protocol_version']}")
print(f" Epoch Progress: {network['epoch_progress_percent']:.1f}%")
print(f" Time Remaining: {network['time_remaining_hours']:.1f} hours")
print(f" Safe Mode: {'ACTIVE' if network['safe_mode'] else 'INACTIVE'}")
print(f" Gas Price: {network['reference_gas_price']} MIST")
# Validator Analysis
validators = analysis['validator_analysis']
print(f"\nš„ Validator Analysis:")
print(f" Active Validators: {validators['total_validators']}")
print(f" Total Staked: {validators['total_staking_balance_sui']:.0f} SUI")
print(f" Average Commission: {validators['average_commission_rate']:.2f}%")
print(f" Commission Range: {validators['commission_rate_range']['min']:.2f}% - {validators['commission_rate_range']['max']:.2f}%")
print(f" Top 5 Control: {validators['concentration_metrics']['top_5_percentage']:.1f}%")
print(f" Nakamoto Coefficient: {validators['concentration_metrics']['nakamoto_coefficient']}")
print(f" Gini Coefficient: {validators['concentration_metrics']['gini_coefficient']:.3f}")
# Staking Analysis
staking = analysis['staking_analysis']
print(f"\nš° Staking Analysis:")
print(f" Network Stake: {staking['total_network_stake_sui']:.0f} SUI")
print(f" Pending Stake: {staking['total_pending_stake_sui']:.0f} SUI")
print(f" Rewards Pool: {staking['total_rewards_pool_sui']:.0f} SUI")
print(f" Subsidy Balance: {staking['stake_subsidy']['balance_sui']:.0f} SUI")
print(f" Current Distribution: {staking['stake_subsidy']['current_distribution_sui']:.0f} SUI")
# Economic Metrics
economics = analysis['economic_metrics']
print(f"\nšø Economic Metrics:")
print(f" Reference Gas Price: {economics['reference_gas_price_sui']:.9f} SUI")
print(f" Storage Fund Total: {economics['storage_fund']['total_rebates_sui']:.0f} SUI")
print(f" Refundable Balance: {economics['storage_fund']['refundable_balance_sui']:.0f} SUI")
print(f" Refundable Percentage: {economics['storage_fund']['refundable_percentage']:.1f}%")
# System Health
health = analysis['system_health']
print(f"\nš„ System Health:")
print(f" Overall Score: {health['score']}/100 ({health['status']})")
if health['factors']:
print(f" Health Factors:")
for factor in health['factors']:
print(f" {factor['factor']}: {factor['impact']:+d} points - {factor['description']}")
if health['recommendations']:
print(f" Recommendations:")
for rec in health['recommendations']:
print(f" ⢠{rec}")
# Top Validators
print(f"\nš Top 5 Validators:")
for i, validator in enumerate(validators['top_validators'][:5], 1):
name = validator['name'] or validator['address'][:16] + '...'
print(f" {i}. {name}")
print(f" Stake: {validator['staking_balance_sui']:.0f} SUI")
print(f" Commission: {validator['commission_rate']:.2f}%")
print(f" Gas Price: {validator['gas_price']} MIST")
# Example 3: Set up monitoring
print(f"\nš Setting up system state monitoring...")
monitor = SystemStateMonitor(client)
# Demonstrate monitoring setup (don't run for extended period in example)
print("Monitor configured to check every 10 minutes for system changes")
print("Use monitor.start_monitoring(10, 24) to monitor for 24 hours")
# Example of monitoring output
print(f"\nExample monitoring output:")
print("š Starting system state monitoring (every 10 minutes)")
print("š System Status - Epoch 251")
print(" Validators: 120")
print(" Total Stake: 2500000 SUI")
print(" Gas Price: 1000 MIST")
print(" Safe Mode: INACTIVE")
print("šµ [INFO] New epoch started: 250 ā 251")
print("š” [WARNING] Reference gas price changed by +5.0% (1000 ā 1050 MIST)")
print("š“ [CRITICAL] Safe mode ACTIVATED")