Merge pull request #5083 from filecoin-project/feat/miner-info-improvements
miner info cli improvements
This commit is contained in:
commit
b6046924b3
@ -23,6 +23,29 @@ func (f FIL) Unitless() string {
|
|||||||
return strings.TrimRight(strings.TrimRight(r.FloatString(18), "0"), ".")
|
return strings.TrimRight(strings.TrimRight(r.FloatString(18), "0"), ".")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var unitPrefixes = []string{"a", "f", "p", "n", "μ", "m"}
|
||||||
|
|
||||||
|
func (f FIL) Short() string {
|
||||||
|
n := BigInt(f)
|
||||||
|
|
||||||
|
dn := uint64(1)
|
||||||
|
var prefix string
|
||||||
|
for _, p := range unitPrefixes {
|
||||||
|
if n.LessThan(NewInt(dn * 1000)) {
|
||||||
|
prefix = p
|
||||||
|
break
|
||||||
|
}
|
||||||
|
dn *= 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
r := new(big.Rat).SetFrac(f.Int, big.NewInt(int64(dn)))
|
||||||
|
if r.Sign() == 0 {
|
||||||
|
return "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimRight(strings.TrimRight(r.FloatString(3), "0"), ".") + " " + prefix + "FIL"
|
||||||
|
}
|
||||||
|
|
||||||
func (f FIL) Format(s fmt.State, ch rune) {
|
func (f FIL) Format(s fmt.State, ch rune) {
|
||||||
switch ch {
|
switch ch {
|
||||||
case 's', 'v':
|
case 's', 'v':
|
||||||
|
68
chain/types/fil_test.go
Normal file
68
chain/types/fil_test.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFilShort(t *testing.T) {
|
||||||
|
for _, s := range []struct {
|
||||||
|
fil string
|
||||||
|
expect string
|
||||||
|
}{
|
||||||
|
|
||||||
|
{fil: "1", expect: "1 FIL"},
|
||||||
|
{fil: "1.1", expect: "1.1 FIL"},
|
||||||
|
{fil: "12", expect: "12 FIL"},
|
||||||
|
{fil: "123", expect: "123 FIL"},
|
||||||
|
{fil: "123456", expect: "123456 FIL"},
|
||||||
|
{fil: "123.23", expect: "123.23 FIL"},
|
||||||
|
{fil: "123456.234", expect: "123456.234 FIL"},
|
||||||
|
{fil: "123456.2341234", expect: "123456.234 FIL"},
|
||||||
|
{fil: "123456.234123445", expect: "123456.234 FIL"},
|
||||||
|
|
||||||
|
{fil: "0.1", expect: "100 mFIL"},
|
||||||
|
{fil: "0.01", expect: "10 mFIL"},
|
||||||
|
{fil: "0.001", expect: "1 mFIL"},
|
||||||
|
|
||||||
|
{fil: "0.0001", expect: "100 μFIL"},
|
||||||
|
{fil: "0.00001", expect: "10 μFIL"},
|
||||||
|
{fil: "0.000001", expect: "1 μFIL"},
|
||||||
|
|
||||||
|
{fil: "0.0000001", expect: "100 nFIL"},
|
||||||
|
{fil: "0.00000001", expect: "10 nFIL"},
|
||||||
|
{fil: "0.000000001", expect: "1 nFIL"},
|
||||||
|
|
||||||
|
{fil: "0.0000000001", expect: "100 pFIL"},
|
||||||
|
{fil: "0.00000000001", expect: "10 pFIL"},
|
||||||
|
{fil: "0.000000000001", expect: "1 pFIL"},
|
||||||
|
|
||||||
|
{fil: "0.0000000000001", expect: "100 fFIL"},
|
||||||
|
{fil: "0.00000000000001", expect: "10 fFIL"},
|
||||||
|
{fil: "0.000000000000001", expect: "1 fFIL"},
|
||||||
|
|
||||||
|
{fil: "0.0000000000000001", expect: "100 aFIL"},
|
||||||
|
{fil: "0.00000000000000001", expect: "10 aFIL"},
|
||||||
|
{fil: "0.000000000000000001", expect: "1 aFIL"},
|
||||||
|
|
||||||
|
{fil: "0.0000012", expect: "1.2 μFIL"},
|
||||||
|
{fil: "0.00000123", expect: "1.23 μFIL"},
|
||||||
|
{fil: "0.000001234", expect: "1.234 μFIL"},
|
||||||
|
{fil: "0.0000012344", expect: "1.234 μFIL"},
|
||||||
|
{fil: "0.00000123444", expect: "1.234 μFIL"},
|
||||||
|
|
||||||
|
{fil: "0.0002212", expect: "221.2 μFIL"},
|
||||||
|
{fil: "0.00022123", expect: "221.23 μFIL"},
|
||||||
|
{fil: "0.000221234", expect: "221.234 μFIL"},
|
||||||
|
{fil: "0.0002212344", expect: "221.234 μFIL"},
|
||||||
|
{fil: "0.00022123444", expect: "221.234 μFIL"},
|
||||||
|
} {
|
||||||
|
s := s
|
||||||
|
t.Run(s.fil, func(t *testing.T) {
|
||||||
|
f, err := ParseFIL(s.fil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, s.expect, f.Short())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
"github.com/filecoin-project/go-state-types/big"
|
||||||
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
|
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
@ -59,7 +60,7 @@ func infoCmdAct(cctx *cli.Context) error {
|
|||||||
|
|
||||||
ctx := lcli.ReqContext(cctx)
|
ctx := lcli.ReqContext(cctx)
|
||||||
|
|
||||||
fmt.Print("Full node: ")
|
fmt.Print("Chain: ")
|
||||||
|
|
||||||
head, err := api.ChainHead(ctx)
|
head, err := api.ChainHead(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -75,6 +76,20 @@ func infoCmdAct(cctx *cli.Context) error {
|
|||||||
fmt.Printf("[%s]", color.RedString("sync behind! (%s behind)", time.Now().Sub(time.Unix(int64(head.MinTimestamp()), 0)).Truncate(time.Second)))
|
fmt.Printf("[%s]", color.RedString("sync behind! (%s behind)", time.Now().Sub(time.Unix(int64(head.MinTimestamp()), 0)).Truncate(time.Second)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
basefee := head.MinTicketBlock().ParentBaseFee
|
||||||
|
gasCol := []color.Attribute{color.FgBlue}
|
||||||
|
switch {
|
||||||
|
case basefee.GreaterThan(big.NewInt(7000_000_000)): // 7 nFIL
|
||||||
|
gasCol = []color.Attribute{color.BgRed, color.FgBlack}
|
||||||
|
case basefee.GreaterThan(big.NewInt(3000_000_000)): // 3 nFIL
|
||||||
|
gasCol = []color.Attribute{color.FgRed}
|
||||||
|
case basefee.GreaterThan(big.NewInt(750_000_000)): // 750 uFIL
|
||||||
|
gasCol = []color.Attribute{color.FgYellow}
|
||||||
|
case basefee.GreaterThan(big.NewInt(100_000_000)): // 100 uFIL
|
||||||
|
gasCol = []color.Attribute{color.FgGreen}
|
||||||
|
}
|
||||||
|
fmt.Printf(" [basefee %s]", color.New(gasCol...).Sprint(types.FIL(basefee).Short()))
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
maddr, err := getActorAddress(ctx, nodeApi, cctx.String("actor"))
|
maddr, err := getActorAddress(ctx, nodeApi, cctx.String("actor"))
|
||||||
@ -93,15 +108,14 @@ func infoCmdAct(cctx *cli.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Miner: %s\n", color.BlueString("%s", maddr))
|
|
||||||
|
|
||||||
// Sector size
|
// Sector size
|
||||||
mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Sector Size: %s\n", types.SizeStr(types.NewInt(uint64(mi.SectorSize))))
|
ssize := types.SizeStr(types.NewInt(uint64(mi.SectorSize)))
|
||||||
|
fmt.Printf("Miner: %s (%s sectors)\n", color.BlueString("%s", maddr), ssize)
|
||||||
|
|
||||||
pow, err := api.StateMinerPower(ctx, maddr, types.EmptyTSK)
|
pow, err := api.StateMinerPower(ctx, maddr, types.EmptyTSK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -111,16 +125,16 @@ func infoCmdAct(cctx *cli.Context) error {
|
|||||||
rpercI := types.BigDiv(types.BigMul(pow.MinerPower.RawBytePower, types.NewInt(1000000)), pow.TotalPower.RawBytePower)
|
rpercI := types.BigDiv(types.BigMul(pow.MinerPower.RawBytePower, types.NewInt(1000000)), pow.TotalPower.RawBytePower)
|
||||||
qpercI := types.BigDiv(types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(1000000)), pow.TotalPower.QualityAdjPower)
|
qpercI := types.BigDiv(types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(1000000)), pow.TotalPower.QualityAdjPower)
|
||||||
|
|
||||||
fmt.Printf("Byte Power: %s / %s (%0.4f%%)\n",
|
fmt.Printf("Power: %s / %s (%0.4f%%)\n",
|
||||||
color.BlueString(types.SizeStr(pow.MinerPower.RawBytePower)),
|
|
||||||
types.SizeStr(pow.TotalPower.RawBytePower),
|
|
||||||
float64(rpercI.Int64())/10000)
|
|
||||||
|
|
||||||
fmt.Printf("Actual Power: %s / %s (%0.4f%%)\n",
|
|
||||||
color.GreenString(types.DeciStr(pow.MinerPower.QualityAdjPower)),
|
color.GreenString(types.DeciStr(pow.MinerPower.QualityAdjPower)),
|
||||||
types.DeciStr(pow.TotalPower.QualityAdjPower),
|
types.DeciStr(pow.TotalPower.QualityAdjPower),
|
||||||
float64(qpercI.Int64())/10000)
|
float64(qpercI.Int64())/10000)
|
||||||
|
|
||||||
|
fmt.Printf("\tRaw: %s / %s (%0.4f%%)\n",
|
||||||
|
color.BlueString(types.SizeStr(pow.MinerPower.RawBytePower)),
|
||||||
|
types.SizeStr(pow.TotalPower.RawBytePower),
|
||||||
|
float64(rpercI.Int64())/10000)
|
||||||
|
|
||||||
secCounts, err := api.StateMinerSectorCount(ctx, maddr, types.EmptyTSK)
|
secCounts, err := api.StateMinerSectorCount(ctx, maddr, types.EmptyTSK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -168,6 +182,10 @@ func infoCmdAct(cctx *cli.Context) error {
|
|||||||
var nactiveDeals, nVerifDeals, ndeals uint64
|
var nactiveDeals, nVerifDeals, ndeals uint64
|
||||||
var activeDealBytes, activeVerifDealBytes, dealBytes abi.PaddedPieceSize
|
var activeDealBytes, activeVerifDealBytes, dealBytes abi.PaddedPieceSize
|
||||||
for _, deal := range deals {
|
for _, deal := range deals {
|
||||||
|
if deal.State == storagemarket.StorageDealError {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
ndeals++
|
ndeals++
|
||||||
dealBytes += deal.Proposal.PieceSize
|
dealBytes += deal.Proposal.PieceSize
|
||||||
|
|
||||||
@ -186,6 +204,8 @@ func infoCmdAct(cctx *cli.Context) error {
|
|||||||
fmt.Printf("\tActive: %d, %s (Verified: %d, %s)\n", nactiveDeals, types.SizeStr(types.NewInt(uint64(activeDealBytes))), nVerifDeals, types.SizeStr(types.NewInt(uint64(activeVerifDealBytes))))
|
fmt.Printf("\tActive: %d, %s (Verified: %d, %s)\n", nactiveDeals, types.SizeStr(types.NewInt(uint64(activeDealBytes))), nVerifDeals, types.SizeStr(types.NewInt(uint64(activeVerifDealBytes))))
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
|
spendable := big.Zero()
|
||||||
|
|
||||||
// NOTE: there's no need to unlock anything here. Funds only
|
// NOTE: there's no need to unlock anything here. Funds only
|
||||||
// vest on deadline boundaries, and they're unlocked by cron.
|
// vest on deadline boundaries, and they're unlocked by cron.
|
||||||
lockedFunds, err := mas.LockedFunds()
|
lockedFunds, err := mas.LockedFunds()
|
||||||
@ -196,33 +216,47 @@ func infoCmdAct(cctx *cli.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("getting available balance: %w", err)
|
return xerrors.Errorf("getting available balance: %w", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("Miner Balance: %s\n", color.YellowString("%s", types.FIL(mact.Balance)))
|
spendable = big.Add(spendable, availBalance)
|
||||||
fmt.Printf("\tPreCommit: %s\n", types.FIL(lockedFunds.PreCommitDeposits))
|
|
||||||
fmt.Printf("\tPledge: %s\n", types.FIL(lockedFunds.InitialPledgeRequirement))
|
fmt.Printf("Miner Balance: %s\n", color.YellowString("%s", types.FIL(mact.Balance).Short()))
|
||||||
fmt.Printf("\tVesting: %s\n", types.FIL(lockedFunds.VestingFunds))
|
fmt.Printf(" PreCommit: %s\n", types.FIL(lockedFunds.PreCommitDeposits).Short())
|
||||||
color.Green("\tAvailable: %s", types.FIL(availBalance))
|
fmt.Printf(" Pledge: %s\n", types.FIL(lockedFunds.InitialPledgeRequirement).Short())
|
||||||
wb, err := api.WalletBalance(ctx, mi.Worker)
|
fmt.Printf(" Vesting: %s\n", types.FIL(lockedFunds.VestingFunds).Short())
|
||||||
if err != nil {
|
color.Green(" Available: %s", types.FIL(availBalance).Short())
|
||||||
return xerrors.Errorf("getting worker balance: %w", err)
|
|
||||||
}
|
|
||||||
color.Cyan("Worker Balance: %s", types.FIL(wb))
|
|
||||||
|
|
||||||
mb, err := api.StateMarketBalance(ctx, maddr, types.EmptyTSK)
|
mb, err := api.StateMarketBalance(ctx, maddr, types.EmptyTSK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("getting market balance: %w", err)
|
return xerrors.Errorf("getting market balance: %w", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("Market (Escrow): %s\n", types.FIL(mb.Escrow))
|
spendable = big.Add(spendable, big.Sub(mb.Escrow, mb.Locked))
|
||||||
fmt.Printf("Market (Locked): %s\n", types.FIL(mb.Locked))
|
|
||||||
|
fmt.Printf("Market Balance: %s\n", types.FIL(mb.Escrow).Short())
|
||||||
|
fmt.Printf(" Locked: %s\n", types.FIL(mb.Locked).Short())
|
||||||
|
color.Green(" Available: %s\n", types.FIL(big.Sub(mb.Escrow, mb.Locked)).Short())
|
||||||
|
|
||||||
|
wb, err := api.WalletBalance(ctx, mi.Worker)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("getting worker balance: %w", err)
|
||||||
|
}
|
||||||
|
spendable = big.Add(spendable, wb)
|
||||||
|
color.Cyan("Worker Balance: %s", types.FIL(wb).Short())
|
||||||
|
if len(mi.ControlAddresses) > 0 {
|
||||||
|
cbsum := big.Zero()
|
||||||
|
for _, ca := range mi.ControlAddresses {
|
||||||
|
b, err := api.WalletBalance(ctx, ca)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("getting control address balance: %w", err)
|
||||||
|
}
|
||||||
|
cbsum = big.Add(cbsum, b)
|
||||||
|
}
|
||||||
|
spendable = big.Add(spendable, cbsum)
|
||||||
|
|
||||||
|
fmt.Printf(" Control: %s\n", types.FIL(cbsum).Short())
|
||||||
|
}
|
||||||
|
fmt.Printf("Total Spendable: %s\n", color.YellowString(types.FIL(spendable).Short()))
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
sealdur, err := nodeApi.SectorGetExpectedSealDuration(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Expected Seal Duration: %s\n\n", sealdur)
|
|
||||||
|
|
||||||
if !cctx.Bool("hide-sectors-info") {
|
if !cctx.Bool("hide-sectors-info") {
|
||||||
fmt.Println("Sectors:")
|
fmt.Println("Sectors:")
|
||||||
err = sectorsInfo(ctx, nodeApi)
|
err = sectorsInfo(ctx, nodeApi)
|
||||||
|
Loading…
Reference in New Issue
Block a user