Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
4257417
feat: enable savings pots
helloscoopa Jul 21, 2025
8d6dd3b
fix: balance display and fiat calculation
helloscoopa Jul 21, 2025
e17152c
fix: race condition in duplicate and limit checks
helloscoopa Jul 21, 2025
4822155
fix: wallet balance updated without external transfer
helloscoopa Jul 21, 2025
1c1447a
fix: inconsistent pot name parsing
helloscoopa Jul 21, 2025
66facb8
fix: add MinPotNameLength
helloscoopa Jul 22, 2025
a192609
fix: main balance deduction and addition
helloscoopa Jul 22, 2025
79d9347
fix: use i18n
helloscoopa Jul 22, 2025
eea7916
fix: set default balance vlaues
helloscoopa Jul 22, 2025
e015d48
refactor: use GORM auto-timestamps
helloscoopa Jul 22, 2025
0058e9a
Merge pull request #43 from CeyLabs/dev
xbuddhi Jul 22, 2025
d8c51ae
Merge pull request #45 from CeyLabs/dev
xbuddhi Jul 23, 2025
3e323b7
fix: make pot transfer atomic
helloscoopa Jul 23, 2025
5d4f4cd
Merge pull request #46 from CeyLabs/dev
xbuddhi Jul 23, 2025
7e5cd0a
Merge pull request #47 from CeyLabs/dev
xbuddhi Jul 26, 2025
e5d1116
Merge pull request #48 from CeyLabs/dev
xbuddhi Jul 27, 2025
c70af5a
Merge pull request #49 from CeyLabs/dev
xbuddhi Jul 27, 2025
448231e
Merge pull request #50 from CeyLabs/dev
xbuddhi Jul 27, 2025
1e63eb5
fix: use gorm to manipulate wallet_balance
helloscoopa Aug 22, 2025
f82647d
Merge pull request #42 from CeyLabs/scoopa/savings-pots
xbuddhi Aug 22, 2025
d5a1610
fix: main balance display
helloscoopa Aug 22, 2025
97e21f9
fix: update /help response to include pots commands
helloscoopa Aug 22, 2025
f4968fd
fix: add usd/lkr values to main pot balance
helloscoopa Aug 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions internal/lnbits/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,13 @@ func (u User) SignKeyAuth(domain string, k1hex string) (key string, sig string,

return key, sig, nil
}

type SavingsPot struct {
ID string `json:"id" gorm:"primaryKey"`
UserID string `json:"user_id" gorm:"index"`
Name string `json:"name"`
Balance int64 `json:"balance" gorm:"default:0;check:balance >= 0" validate:"min=0"`
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"`
UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"`
User *User `gorm:"foreignKey:UserID;references:ID"`
}
42 changes: 33 additions & 9 deletions internal/telegram/balance.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,8 @@ func (bot *TipBot) balanceHandler(ctx intercept.Context) (intercept.Context, err
}

usrStr := GetUserStr(ctx.Sender())
balance, err := bot.GetUserBalance(user)
if err != nil {
log.Errorf("[/balance] Error fetching %s's balance: %s", usrStr, err)
bot.trySendMessage(ctx.Sender(), Translate(ctx, "balanceErrorMessage"))
return ctx, err
}
// Use database balance (in msat) to reflect pot transfers
balance := user.Wallet.Balance / 1000

log.Infof("[/balance] %s's balance: %s\n", usrStr, utils.FormatSats(balance))

Expand All @@ -50,9 +46,37 @@ func (bot *TipBot) balanceHandler(ctx intercept.Context) (intercept.Context, err
log.Infof("[/balance] error fetching price from coingecko\n")
}

USDValue := USDPerSat * float64(balance)
LKRValue := LKRPerSat * float64(balance)
potBalance, err := bot.GetUserTotalPotBalance(user)
if err != nil {
log.Errorf("[/balance] Error fetching %s's pot balance: %s", usrStr, err)
potBalance = 0
}

totalBalance := balance + potBalance
mainUSDValue := USDPerSat * float64(balance)
mainLKRValue := LKRPerSat * float64(balance)
totalUSDValue := USDPerSat * float64(totalBalance)
totalLKRValue := LKRPerSat * float64(totalBalance)
potUSDValue := USDPerSat * float64(potBalance)
potLKRValue := LKRPerSat * float64(potBalance)

message := fmt.Sprintf(Translate(ctx, "balanceMessage"),
utils.FormatSats(balance),
utils.FormatFloatWithCommas(mainUSDValue),
utils.FormatFloatWithCommas(mainLKRValue))

if potBalance > 0 {
potInfo := fmt.Sprintf(Translate(ctx, "potBalanceInfo"),
utils.FormatSats(potBalance),
utils.FormatFloatWithCommas(potUSDValue),
utils.FormatFloatWithCommas(potLKRValue))
totalInfo := fmt.Sprintf(Translate(ctx, "totalBalanceInfo"),
utils.FormatSats(totalBalance),
utils.FormatFloatWithCommas(totalUSDValue),
utils.FormatFloatWithCommas(totalLKRValue))
message += "\n" + potInfo + "\n" + totalInfo
}

bot.trySendMessage(ctx.Sender(), fmt.Sprintf(Translate(ctx, "balanceMessage"), utils.FormatSats(balance), utils.FormatFloatWithCommas(USDValue), utils.FormatFloatWithCommas(LKRValue)))
bot.trySendMessage(ctx.Sender(), message)
return ctx, nil
}
4 changes: 4 additions & 0 deletions internal/telegram/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ func AutoMigration() *Databases {
if err != nil {
panic(err)
}
err = orm.AutoMigrate(&lnbits.SavingsPot{})
if err != nil {
panic(err)
}

txLogger, err := gorm.Open(sqlite.Open(internal.Configuration.Database.TransactionsPath), &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true, FullSaveAssociations: true})
if err != nil {
Expand Down
80 changes: 80 additions & 0 deletions internal/telegram/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,86 @@ func (bot TipBot) getHandler() []InterceptionWrapper {
},
},
},
{
Endpoints: []interface{}{"/createpot"},
Handler: bot.createPotHandler,
Interceptor: &Interceptor{
Before: []intercept.Func{
bot.requirePrivateChatInterceptor,
bot.localizerInterceptor,
bot.logMessageInterceptor,
bot.requireUserInterceptor,
bot.lockInterceptor,
},
OnDefer: []intercept.Func{
bot.unlockInterceptor,
},
},
},
{
Endpoints: []interface{}{"/pots"},
Handler: bot.listPotsHandler,
Interceptor: &Interceptor{
Before: []intercept.Func{
bot.requirePrivateChatInterceptor,
bot.localizerInterceptor,
bot.logMessageInterceptor,
bot.requireUserInterceptor,
bot.lockInterceptor,
},
OnDefer: []intercept.Func{
bot.unlockInterceptor,
},
},
},
{
Endpoints: []interface{}{"/addtopot"},
Handler: bot.addToPotHandler,
Interceptor: &Interceptor{
Before: []intercept.Func{
bot.requirePrivateChatInterceptor,
bot.localizerInterceptor,
bot.logMessageInterceptor,
bot.requireUserInterceptor,
bot.lockInterceptor,
},
OnDefer: []intercept.Func{
bot.unlockInterceptor,
},
},
},
{
Endpoints: []interface{}{"/withdrawfrompot"},
Handler: bot.withdrawFromPotHandler,
Interceptor: &Interceptor{
Before: []intercept.Func{
bot.requirePrivateChatInterceptor,
bot.localizerInterceptor,
bot.logMessageInterceptor,
bot.requireUserInterceptor,
bot.lockInterceptor,
},
OnDefer: []intercept.Func{
bot.unlockInterceptor,
},
},
},
{
Endpoints: []interface{}{"/deletepot"},
Handler: bot.deletePotHandler,
Interceptor: &Interceptor{
Before: []intercept.Func{
bot.requirePrivateChatInterceptor,
bot.localizerInterceptor,
bot.logMessageInterceptor,
bot.requireUserInterceptor,
bot.lockInterceptor,
},
OnDefer: []intercept.Func{
bot.unlockInterceptor,
},
},
},
{
Endpoints: []interface{}{"/send", &btnSendMenuEnter},
Handler: bot.sendHandler,
Expand Down
Loading
Loading