diff --git a/README.md b/README.md index e0aec23..2666935 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,7 @@ columns = [ "UNSETTLED", # the amount unsettled in the channel "CFEE", # the commit fee "LAST UPDATE", # last update of the channel + # "AGE", # approximate channel age "PRIVATE", # true if channel is private "ID", # the id of the channel # "SCID", # short channel id (BxTxO formatted) diff --git a/config/default.go b/config/default.go index 02e81a9..0fafa7f 100644 --- a/config/default.go +++ b/config/default.go @@ -43,6 +43,7 @@ columns = [ "UNSETTLED", # the amount unsettled in the channel "CFEE", # the commit fee "LAST UPDATE", # last update of the channel + # "AGE", # approximate channel age "PRIVATE", # true if channel is private "ID", # the id of the channel # "SCID", # short channel id (BxTxO formatted) diff --git a/network/models/channel.go b/network/models/channel.go index 4a3e1f2..ffdffdb 100644 --- a/network/models/channel.go +++ b/network/models/channel.go @@ -45,6 +45,7 @@ type Channel struct { TotalAmountReceived int64 UpdatesCount uint64 CSVDelay uint32 + Age uint32 Private bool PendingHTLC []*HTLC LastUpdate *time.Time diff --git a/ui/models/models.go b/ui/models/models.go index 6801622..9ada4fc 100644 --- a/ui/models/models.go +++ b/ui/models/models.go @@ -62,6 +62,7 @@ func (m *Models) RefreshChannels(ctx context.Context) error { if channel != nil && (channel.UpdatesCount < channels[i].UpdatesCount || channel.LastUpdate == nil || channel.LocalPolicy == nil || channel.RemotePolicy == nil) { + channels[i].Age = m.Info.BlockHeight - uint32(channels[i].ID>>40) err := m.network.GetChannelInfo(ctx, channels[i]) if err != nil { return err diff --git a/ui/models/sort.go b/ui/models/sort.go index a989ada..9313fab 100644 --- a/ui/models/sort.go +++ b/ui/models/sort.go @@ -40,6 +40,13 @@ func Float64Sort(a, b float64, o Order) bool { return a > b } +func UInt32Sort(a, b uint32, o Order) bool { + if o == Asc { + return a < b + } + return a > b +} + func UInt64Sort(a, b uint64, o Order) bool { if o == Asc { return a < b diff --git a/ui/views/channels.go b/ui/views/channels.go index b5a0220..701610c 100644 --- a/ui/views/channels.go +++ b/ui/views/channels.go @@ -638,6 +638,23 @@ func NewChannels(cfg *config.View, chans *models.Channels) *Channels { return color.White(opts...)(printer.Sprintf("%7d", val)) }, } + case "AGE": + channels.columns[i] = channelsColumn{ + width: 8, + name: fmt.Sprintf("%10s", columns[i]), + sort: func(order models.Order) models.ChannelsSort { + return func(c1, c2 *netmodels.Channel) bool { + return models.UInt32Sort(c1.Age, c2.Age, order) + } + }, + display: func(c *netmodels.Channel, opts ...color.Option) string { + if c.ID == 0 { + return fmt.Sprintf("%10s", "") + } + return color.White(opts...)(fmt.Sprintf("%10s", FormatAge(c.Age))) + }, + } + default: channels.columns[i] = channelsColumn{ width: 21, diff --git a/ui/views/views.go b/ui/views/views.go index 611d21e..bf4c4ca 100644 --- a/ui/views/views.go +++ b/ui/views/views.go @@ -116,3 +116,19 @@ func ToScid(id uint64) string { return fmt.Sprintf("%dx%dx%d", blocknum, txnum, outnum) } + +func FormatAge(age uint32) string { + if age < 6 { + return fmt.Sprintf("%02dm", age*10) + } + if age < 144 { + return fmt.Sprintf("%02dh", age/6) + } + if age < 4383 { + return fmt.Sprintf("%02dd%02dh", age/144, (age%144)/6) + } + if age < 52596 { + return fmt.Sprintf("%02dm%02dd%02dh", age/4383, (age%4383)/144, (age%144)/6) + } + return fmt.Sprintf("%02dy%02dm%02dd", age/52596, (age%52596)/4383, (age%4383)/144) +}