diff --git a/config.yaml.example b/config.yaml.example index 9258d6a2..ab8c4080 100644 --- a/config.yaml.example +++ b/config.yaml.example @@ -43,6 +43,11 @@ nostr: third_party: coinmarketcap_api_key: "your-cmc-api-key-here" # optional — get free key at coinmarketcap.com/api +# DCA bot integration +dca: + wallet_username: "" # when sats are received by this Telegram username, reset DCA retry counts + api_url: "https://bitcoindeepa-dca-be-production.up.railway.app" + # API Configuration api: # Analytics API - HMAC authenticated endpoints for data export diff --git a/internal/config.go b/internal/config.go index 3ead8fd2..36be4668 100644 --- a/internal/config.go +++ b/internal/config.go @@ -19,8 +19,14 @@ var Configuration = struct { Nostr NostrConfiguration `yaml:"nostr"` API APIConfiguration `yaml:"api"` ThirdParty ThirdPartyConfiguration `yaml:"third_party"` + DCA DCAConfiguration `yaml:"dca"` }{} +type DCAConfiguration struct { + WalletUsername string `yaml:"wallet_username"` + ApiUrl string `yaml:"api_url"` +} + type NostrConfiguration struct { PrivateKey string `yaml:"private_key"` } diff --git a/internal/dca/dca.go b/internal/dca/dca.go new file mode 100644 index 00000000..88e8e840 --- /dev/null +++ b/internal/dca/dca.go @@ -0,0 +1,42 @@ +package dca + +import ( + "net/http" + "strings" + "time" + + "github.com/LightningTipBot/LightningTipBot/internal" + log "github.com/sirupsen/logrus" +) + +// NotifyDeposit checks whether the given recipient username matches the configured +// DCA wallet username and, if so, asks the DCA backend to reset its retry counts. +func NotifyDeposit(toUsername string) { + wallet := strings.TrimPrefix(internal.Configuration.DCA.WalletUsername, "@") + if wallet == "" || strings.TrimPrefix(toUsername, "@") != wallet { + return + } + + apiUrl := strings.TrimSuffix(internal.Configuration.DCA.ApiUrl, "/") + if apiUrl == "" { + log.Errorln("[DCA] dca.api_url is not configured, skipping reset-retry-counts call") + return + } + + url := apiUrl + "/transaction/reset-retry-counts" + req, err := http.NewRequest(http.MethodPost, url, nil) + if err != nil { + log.Errorf("[DCA] Error creating reset-retry-counts request: %s", err.Error()) + return + } + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{Timeout: 10 * time.Second} + resp, err := client.Do(req) + if err != nil { + log.Errorf("[DCA] Error calling reset-retry-counts: %s", err.Error()) + return + } + defer resp.Body.Close() + log.Infof("[DCA] reset-retry-counts called for %s, status: %s", toUsername, resp.Status) +} diff --git a/internal/lnbits/webhook/webhook.go b/internal/lnbits/webhook/webhook.go index 53e81240..4b457ad3 100644 --- a/internal/lnbits/webhook/webhook.go +++ b/internal/lnbits/webhook/webhook.go @@ -6,6 +6,7 @@ import ( "time" "github.com/LightningTipBot/LightningTipBot/internal" + "github.com/LightningTipBot/LightningTipBot/internal/dca" "github.com/LightningTipBot/LightningTipBot/internal/lnbits" "github.com/LightningTipBot/LightningTipBot/internal/telegram" "github.com/LightningTipBot/LightningTipBot/internal/utils" @@ -100,6 +101,8 @@ func (w *Server) receive(writer http.ResponseWriter, request *http.Request) { } log.Infoln(fmt.Sprintf("[⚡️ WebHook] User %s (%d) received invoice of %d sat.", telegram.GetUserStr(user.Telegram), user.Telegram.ID, webhookEvent.Amount/1000)) + go dca.NotifyDeposit(telegram.GetUserStr(user.Telegram)) + writer.WriteHeader(200) // trigger invoice events diff --git a/internal/telegram/transaction.go b/internal/telegram/transaction.go index a5a1af1e..022a0548 100644 --- a/internal/telegram/transaction.go +++ b/internal/telegram/transaction.go @@ -6,6 +6,7 @@ import ( log "github.com/sirupsen/logrus" + "github.com/LightningTipBot/LightningTipBot/internal/dca" "github.com/LightningTipBot/LightningTipBot/internal/lnbits" tb "gopkg.in/lightningtipbot/telebot.v3" ) @@ -73,6 +74,7 @@ func (t *Transaction) Send() (success bool, err error) { success, err = t.SendTransaction(t.Bot, t.From, t.To, t.Amount, t.Memo) if success { t.Success = success + go dca.NotifyDeposit(t.ToUser) } // save transaction to db