Added .payout command, cleanup link generation
This commit is contained in:
parent
25e5c06246
commit
ab823b04ad
31
bot.go
31
bot.go
|
@ -14,7 +14,6 @@ import (
|
|||
"gopkg.in/sorcix/irc.v2"
|
||||
"io"
|
||||
"log"
|
||||
"math"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"nhooyr.io/websocket"
|
||||
|
@ -277,26 +276,20 @@ func main() {
|
|||
// see about irc.ERR_NICKNAMEINUSE or irc.ERR_NICKCOLLISION to recover nick
|
||||
|
||||
payoutFound := func(e *channelEntry, b *index.FoundBlock, o *index.MainCoinbaseOutput, sub *Subscription) {
|
||||
uHeight := (b.SideHeight << 16) | (uint64(b.MainBlock.Id[0]) << 8) | uint64(b.MainBlock.Id[1])
|
||||
|
||||
payoutIndex := (b.SideHeight << uint64(math.Ceil(math.Log2(float64(e.Consensus.ChainWindowSize*4))))) | uint64(o.Index)
|
||||
|
||||
bot.Msg(sub.Nick, fmt.Sprintf(
|
||||
"%sPAYOUT%s on %s: %s%s%s XMR%s to %s%s%s :: Main height %s%d%s, Side height %d :: %s/s/%s :: Verify payout %s/p/%s",
|
||||
"%sPAYOUT%s on %s: %s%s%s XMR%s to %s%s%s :: Main height %s%d%s, Side height %d :: %s :: Verify payout %s",
|
||||
FormatColorLightGreen+FormatBold, FormatReset, e.Name,
|
||||
FormatColorOrange, FormatBold, utils.XMRUnits(o.Value), FormatReset,
|
||||
FormatItalic, utils.Shorten(o.MinerAddress.ToBase58(), 10), FormatReset,
|
||||
FormatColorRed, b.MainBlock.Height, FormatReset,
|
||||
b.SideHeight,
|
||||
e.ApiEndpoint, utils.EncodeBinaryNumber(uHeight),
|
||||
e.ApiEndpoint, utils.EncodeBinaryNumber(payoutIndex),
|
||||
GetShareLink(e.ApiEndpoint, b.SideHeight, b.MainBlock.Id),
|
||||
GetPayoutLink(e.ApiEndpoint, b.SideHeight, o.Index, e.Consensus),
|
||||
))
|
||||
|
||||
}
|
||||
|
||||
shareFound := func(e *channelEntry, tip *index.SideBlock, sub *Subscription) {
|
||||
uHeight := (tip.SideHeight << 16) | (uint64(tip.MainId[0]) << 8) | uint64(tip.MainId[1])
|
||||
|
||||
shareCount := 0
|
||||
uncleCount := 0
|
||||
|
||||
|
@ -322,11 +315,11 @@ func main() {
|
|||
|
||||
if tip.UncleOf != types.ZeroHash {
|
||||
bot.Msg(sub.Nick, fmt.Sprintf(
|
||||
"%sUNCLE SHARE FOUND%s on %s: Side height %s%d%s, Parent Side height %s%d%s :: %s/s/%s :: Accounted for %d%% of value :: Template Id %s%s%s :: Window shares %d (+%d uncles) ~%.03f%% :: Miner Address %s%s",
|
||||
"%sUNCLE SHARE FOUND%s on %s: Side height %s%d%s, Parent Side height %s%d%s :: %s :: Accounted for %d%% of value :: Template Id %s%s%s :: Window shares %d (+%d uncles) ~%.03f%% :: Miner Address %s%s",
|
||||
FormatColorLightGreen+FormatBold, FormatReset, e.Name,
|
||||
FormatColorRed, tip.SideHeight, FormatReset,
|
||||
FormatColorRed, tip.EffectiveHeight, FormatReset,
|
||||
e.ApiEndpoint, utils.EncodeBinaryNumber(uHeight),
|
||||
GetShareLink(e.ApiEndpoint, tip.SideHeight, tip.MainId),
|
||||
100-e.Consensus.UnclePenalty,
|
||||
FormatItalic, utils.Shorten(tip.TemplateId.String(), 8), FormatReset,
|
||||
shareCount, uncleCount, shareRatio*100,
|
||||
|
@ -338,10 +331,10 @@ func main() {
|
|||
uncleText = fmt.Sprintf(":: Includes %d uncle(s) for extra %d%% of their value ", len(tip.Uncles), e.Consensus.UnclePenalty)
|
||||
}
|
||||
bot.Msg(sub.Nick, fmt.Sprintf(
|
||||
"%sSHARE FOUND%s on %s: Side height %s%d%s :: %s/s/%s %s:: Template Id %s%s%s :: Window shares %d (+%d uncles) ~%.03f%% :: Miner Address %s%s",
|
||||
"%sSHARE FOUND%s on %s: Side height %s%d%s :: %s %s:: Template Id %s%s%s :: Window shares %d (+%d uncles) ~%.03f%% :: Miner Address %s%s",
|
||||
FormatColorLightGreen+FormatBold, FormatReset, e.Name,
|
||||
FormatColorRed, tip.SideHeight, FormatReset,
|
||||
e.ApiEndpoint, utils.EncodeBinaryNumber(uHeight),
|
||||
GetShareLink(e.ApiEndpoint, tip.SideHeight, tip.MainId),
|
||||
uncleText,
|
||||
FormatItalic, utils.Shorten(tip.TemplateId.String(), 8), FormatReset,
|
||||
shareCount, uncleCount, shareRatio*100,
|
||||
|
@ -351,18 +344,17 @@ func main() {
|
|||
}
|
||||
|
||||
blockFound := func(e *channelEntry, b *index.FoundBlock, previous *index.FoundBlock) {
|
||||
uHeight := (b.SideHeight << 16) | (uint64(b.MainBlock.Id[0]) << 8) | uint64(b.MainBlock.Id[1])
|
||||
effort := float64(0)
|
||||
if previous != nil {
|
||||
effort = float64(b.CumulativeDifficulty.SubWrap(previous.CumulativeDifficulty).Mul64(100).Lo) / float64(b.MainBlock.Difficulty)
|
||||
}
|
||||
|
||||
bot.Msg(e.Channel, fmt.Sprintf(
|
||||
"%sBLOCK FOUND%s on %s: Main height %s%d%s, Side height %d :: %s/s/%s :: Effort %s%.02f%%%s :: %s%d miners paid%s, total %s%s%s XMR%s :: Id %s%s",
|
||||
"%sBLOCK FOUND%s on %s: Main height %s%d%s, Side height %d :: %s :: Effort %s%.02f%%%s :: %s%d miners paid%s, total %s%s%s XMR%s :: Id %s%s",
|
||||
FormatColorLightGreen+FormatBold, FormatReset, e.Name,
|
||||
FormatColorRed, b.MainBlock.Height, FormatReset,
|
||||
b.SideHeight,
|
||||
e.ApiEndpoint, utils.EncodeBinaryNumber(uHeight),
|
||||
GetShareLink(e.ApiEndpoint, b.SideHeight, b.MainBlock.Id),
|
||||
EffortColor(effort), effort, FormatReset,
|
||||
FormatColorOrange, b.WindowOutputs, FormatReset,
|
||||
FormatColorOrange, FormatBold, utils.XMRUnits(b.MainBlock.Reward), FormatReset,
|
||||
|
@ -370,12 +362,11 @@ func main() {
|
|||
))
|
||||
|
||||
doPleromaPost(e, fmt.Sprintf(
|
||||
"BLOCK FOUND on %s, Main height %d, Side height %d :: %s/s/%s :: Effort %.02f%% :: %d miners paid, total %s XMR :: Id %s",
|
||||
"BLOCK FOUND on %s, Main height %d, Side height %d :: %s :: Effort %.02f%% :: %d miners paid, total %s XMR :: Id %s",
|
||||
e.Name,
|
||||
b.MainBlock.Height,
|
||||
b.SideHeight,
|
||||
e.ApiEndpoint,
|
||||
utils.EncodeBinaryNumber(uHeight),
|
||||
GetShareLink(e.ApiEndpoint, b.SideHeight, b.MainBlock.Id),
|
||||
effort,
|
||||
b.WindowOutputs,
|
||||
utils.XMRUnits(b.MainBlock.Reward),
|
||||
|
|
72
commands.go
72
commands.go
|
@ -69,8 +69,6 @@ var commands = []command{
|
|||
}
|
||||
poolInfo := getPoolInfo(e.ApiEndpoint)
|
||||
|
||||
uHeight := (lastFound.SideHeight << 16) | (uint64(lastFound.MainBlock.Id[0]) << 8) | uint64(lastFound.MainBlock.Id[1])
|
||||
|
||||
effort := float64(0)
|
||||
if previous != nil {
|
||||
effort = float64(lastFound.CumulativeDifficulty.SubWrap(previous.CumulativeDifficulty).Mul64(100).Lo) / float64(lastFound.MainBlock.Difficulty)
|
||||
|
@ -81,12 +79,12 @@ var commands = []command{
|
|||
currentDifficulty, _ := types.DifficultyFromString(poolInfo["mainchain"].(map[string]any)["difficulty"].(string))
|
||||
|
||||
bot.Msg(replyTo, fmt.Sprintf(
|
||||
"Pool %s, last block found at height %s%d%s %s, %s UTC :: %s/s/%s :: Effort %s%.02f%%%s :: %s%d miner outputs%s paid for %s%s%s XMR%s :: Current Effort %s%.02f%%%s :: Pool height %d :: Pool Hashrate %sH/s :: Global hashrate %sH/s",
|
||||
"Pool %s, last block found at height %s%d%s %s, %s UTC :: %s :: Effort %s%.02f%%%s :: %s%d miner outputs%s paid for %s%s%s XMR%s :: Current Effort %s%.02f%%%s :: Pool height %d :: Pool Hashrate %sH/s :: Global hashrate %sH/s",
|
||||
e.Name,
|
||||
FormatColorRed, lastFound.MainBlock.Height, FormatReset,
|
||||
TimeElapsed(lastFound.MainBlock.Timestamp),
|
||||
time.Unix(int64(lastFound.MainBlock.Timestamp), 0).UTC().Format(time.DateTime),
|
||||
e.ApiEndpoint, utils.EncodeBinaryNumber(uHeight),
|
||||
GetShareLink(e.ApiEndpoint, lastFound.SideHeight, lastFound.MainBlock.Id),
|
||||
EffortColor(effort), effort, FormatReset,
|
||||
FormatColorOrange, lastFound.WindowOutputs, FormatReset,
|
||||
FormatColorOrange, FormatBold, utils.XMRUnits(lastFound.MainBlock.Reward), FormatReset,
|
||||
|
@ -111,6 +109,7 @@ var commands = []command{
|
|||
return true
|
||||
}
|
||||
type result struct {
|
||||
Name string
|
||||
Endpoint string
|
||||
ShareCount int
|
||||
UncleCount int
|
||||
|
@ -135,6 +134,7 @@ var commands = []command{
|
|||
var tr []*result
|
||||
for _, sub := range subs {
|
||||
var r result
|
||||
r.Name = e.Name
|
||||
r.Tip = e.Tip
|
||||
r.Endpoint = e.ApiEndpoint
|
||||
r.Address = sub.Address
|
||||
|
@ -178,11 +178,13 @@ var commands = []command{
|
|||
for _, r := range results {
|
||||
ratio := float64(r.YourWeight.Lo) / float64(r.TotalWeight.Lo)
|
||||
bot.Msg(replyTo, fmt.Sprintf(
|
||||
"Your shares %d (+%d uncles) ~%.03f%% %sH/s :: Miner Statistics %s/m/%s :: Shares/Uncles position %s %s",
|
||||
"Pool %s, your shares %d (+%d uncles) ~%.03f%% %sH/s :: Miner Address %s%s%s :: Miner Statistics %s/m/%s :: Shares/Uncles position %s %s",
|
||||
r.Name,
|
||||
r.ShareCount,
|
||||
r.UncleCount,
|
||||
ratio*100,
|
||||
utils.SiUnits(ratio*float64(types.DifficultyFrom64(r.Tip.Difficulty).Div64(r.Consensus.TargetBlockTime).Lo), 2),
|
||||
FormatItalic, utils.Shorten(r.Address.ToBase58(), 10), FormatReset,
|
||||
r.Endpoint,
|
||||
utils.EncodeBinaryNumber(r.MinerId),
|
||||
r.SharesPosition.String(),
|
||||
|
@ -194,6 +196,66 @@ var commands = []command{
|
|||
|
||||
},
|
||||
},
|
||||
{
|
||||
Help: ".payout",
|
||||
Description: "Displays your last payout details across all pools",
|
||||
Match: regexp.MustCompile("(?i)^\\.(payouts?|payments?|last-payments?)[ \t]*"),
|
||||
Handle: func(db *DB, entries []*channelEntry, bot *hbot.Bot, message *hbot.Message, replyTo string, matches ...string) bool {
|
||||
subs := db.GetByNick(message.Name)
|
||||
if len(subs) == 0 {
|
||||
bot.Msg(replyTo, "No known subscriptions to your nick.")
|
||||
return true
|
||||
}
|
||||
|
||||
type result struct {
|
||||
Name string
|
||||
Endpoint string
|
||||
Payouts []*index.Payout
|
||||
Address *address.Address
|
||||
Consensus *sidechain.Consensus
|
||||
}
|
||||
|
||||
var results []*result
|
||||
|
||||
for _, e := range filterEntriesForChannel(bot, message, entries) {
|
||||
func(e *channelEntry) {
|
||||
for _, sub := range subs {
|
||||
payouts := getSliceFromAPI[*index.Payout](e.ApiEndpoint, fmt.Sprintf("/api/payouts/%s", sub.Address.ToBase58()))
|
||||
if len(payouts) > 0 {
|
||||
results = append(results, &result{
|
||||
Name: e.Name,
|
||||
Endpoint: e.ApiEndpoint,
|
||||
Payouts: payouts,
|
||||
Address: sub.Address,
|
||||
Consensus: e.Consensus,
|
||||
})
|
||||
}
|
||||
}
|
||||
}(e)
|
||||
}
|
||||
|
||||
if len(results) == 0 {
|
||||
bot.Msg(replyTo, "You do not currently have any previous payouts across the tracked pools.")
|
||||
} else {
|
||||
for _, r := range results {
|
||||
bot.Msg(replyTo, fmt.Sprintf(
|
||||
"Pool %s, last payout for address %s%s%s was %s%s%s XMR%s on block %s%d%s %s, %s UTC :: %s :: Verify payout %s",
|
||||
r.Name,
|
||||
FormatItalic, utils.Shorten(r.Address.ToBase58(), 10), FormatReset,
|
||||
FormatColorOrange, FormatBold, utils.XMRUnits(r.Payouts[0].Reward), FormatReset,
|
||||
FormatColorRed, r.Payouts[0].MainHeight, FormatReset,
|
||||
TimeElapsed(r.Payouts[0].Timestamp),
|
||||
time.Unix(int64(r.Payouts[0].Timestamp), 0).UTC().Format(time.DateTime),
|
||||
GetShareLink(r.Endpoint, r.Payouts[0].SideHeight, r.Payouts[0].MainId),
|
||||
GetPayoutLink(r.Endpoint, r.Payouts[0].SideHeight, r.Payouts[0].Index, r.Consensus),
|
||||
))
|
||||
}
|
||||
|
||||
}
|
||||
return true
|
||||
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
Help: ".subscribe MONERO_ADDRESS",
|
||||
|
|
16
utils.go
16
utils.go
|
@ -1,6 +1,12 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/p2pool/sidechain"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/utils"
|
||||
"golang.org/x/exp/constraints"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -47,3 +53,13 @@ func TimeElapsed(timestamp uint64) string {
|
|||
return strings.Join(result, " ") + " ago"
|
||||
}
|
||||
}
|
||||
|
||||
func GetShareLink(host string, sideHeight uint64, mainId types.Hash) string {
|
||||
uHeight := (sideHeight << 16) | (uint64(mainId[0]) << 8) | uint64(mainId[1])
|
||||
return fmt.Sprintf("%s/s/%s", host, utils.EncodeBinaryNumber(uHeight))
|
||||
}
|
||||
|
||||
func GetPayoutLink[T constraints.Integer](host string, sideHeight uint64, index T, consensus *sidechain.Consensus) string {
|
||||
payoutIndex := (sideHeight << uint64(math.Ceil(math.Log2(float64(consensus.ChainWindowSize*4))))) | uint64(index)
|
||||
return fmt.Sprintf("%s/p/%s", host, utils.EncodeBinaryNumber(payoutIndex))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue