Files
crypto-price-bot/internal/services/tele/view/price.go
T
thuanle 2f875032f6 feat: add rich token message renderer with conditional rows
Introduce unified rich token message rendering with fixed row order
and conditional visibility based on available sources.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-26 17:18:34 +07:00

143 lines
3.5 KiB
Go

package view
import (
"fmt"
"strings"
"time"
"github.com/jedib0t/go-pretty/v6/table"
"golang.org/x/text/language"
"golang.org/x/text/message"
"me.thuanle/bbot/internal/helper/binancex"
"me.thuanle/bbot/internal/services/tele/view/helper"
"me.thuanle/bbot/internal/utils/timex"
)
func RenderPrice(price float64) string {
mFmt := message.NewPrinter(language.AmericanEnglish)
switch {
case price > 1000:
return mFmt.Sprintf("%0.0f", price)
case price > 100:
return mFmt.Sprintf("%0.1f", price)
case price > 10:
return mFmt.Sprintf("%0.2f", price)
case price > 1:
return mFmt.Sprintf("%0.3f", price)
case price > 0.1:
return mFmt.Sprintf("%0.4f", price)
case price > 0.01:
return mFmt.Sprintf("%0.5f", price)
case price > 0.001:
return mFmt.Sprintf("%0.6f", price)
case price > 0.0001:
return mFmt.Sprintf("%0.7f", price)
default:
return mFmt.Sprintf("%0.8f", price)
}
}
func RenderOnPriceMessage(symbol string, spotPrice float64, futurePrice float64, fundrate float64, fundtime int64, marginRate float64) string {
return fmt.Sprintf(
"%s\n"+
" Spot: %s - Future: %s \n"+
" Fund rate: %.4f%% %s in %s\n"+
" Margin rate: %.3f%%",
RenderSymbolInfo(symbol),
RenderPrice(spotPrice), RenderPrice(futurePrice),
fundrate*100, IconOfFundingFeeDirection(fundrate), timex.CdMinuteStringTime(time.UnixMilli(fundtime)),
marginRate*365*100,
)
}
func RenderOnAlphaPriceMessage(symbol string, price float64, change24h float64) string {
icon := "🟢"
if change24h < 0 {
icon = "🔴"
}
return fmt.Sprintf(
"🅰️ %s\n"+
" Price: $%s\n"+
" 24h: %s%.2f%%",
symbol,
RenderPrice(price),
icon, change24h,
)
}
type RichTokenMessageInput struct {
Token string
HasSpot bool
SpotPrice float64
HasFuture bool
FuturePrice float64
FundingRate float64
FundingTimeMs int64
HasAlpha bool
AlphaPrice float64
HasAlpha24h bool
Alpha24hChange float64
HasMarginAPR bool
MarginAPRPercent float64
}
func RenderRichTokenMessage(in RichTokenMessageInput) string {
rows := []string{fmt.Sprintf("🪙 %s", strings.ToUpper(in.Token))}
if in.HasSpot {
rows = append(rows, fmt.Sprintf("💵 Spot: $%s", RenderPrice(in.SpotPrice)))
}
if in.HasFuture {
rows = append(rows, fmt.Sprintf("📈 Future: $%s", RenderPrice(in.FuturePrice)))
}
if in.HasAlpha {
rows = append(rows, fmt.Sprintf("🅰️ Alpha: $%s", RenderPrice(in.AlphaPrice)))
}
if in.HasSpot && in.HasFuture && in.SpotPrice > 0 {
delta := in.FuturePrice - in.SpotPrice
deltaPct := delta / in.SpotPrice * 100
rows = append(rows, fmt.Sprintf("🧭 Basis: $%+s (%+.2f%%)", RenderPrice(delta), deltaPct))
}
if in.HasFuture {
rows = append(rows, fmt.Sprintf("💸 Funding: %.4f%% %s in %s",
in.FundingRate*100,
IconOfFundingFeeDirection(in.FundingRate),
timex.CdMinuteStringTime(time.UnixMilli(in.FundingTimeMs)),
))
}
if in.HasMarginAPR {
rows = append(rows, fmt.Sprintf("🏦 Margin: %.3f%% APR", in.MarginAPRPercent))
}
if in.HasAlpha24h {
icon := "🟢"
if in.Alpha24hChange < 0 {
icon = "🔴"
}
rows = append(rows, fmt.Sprintf("📊 Alpha 24h: %s%+.2f%%", icon, in.Alpha24hChange))
}
return strings.Join(rows, "\n")
}
func RenderOnGetTopPricesMessage(symbols []string, price []float64, fundRate []float64) string {
t := helper.NewNoBorderTableWriter("", "Price", "Fund")
mFmt := message.NewPrinter(language.AmericanEnglish)
for i, symbol := range symbols {
t.AppendRow(table.Row{
binancex.Symbol2Token(symbol),
mFmt.Sprintf("%.2f", price[i]),
mFmt.Sprintf("%.3f%%", fundRate[i]*100),
})
}
return t.Render()
}