Skip to content

Commit

Permalink
refactor(blockstream): improve error handling and calculations
Browse files Browse the repository at this point in the history
  • Loading branch information
lmquang committed Feb 24, 2025
1 parent 54da296 commit 83ceca6
Showing 1 changed file with 26 additions and 17 deletions.
43 changes: 26 additions & 17 deletions internal/btcrpc/blockstream/blockstream.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import (
"regexp"
"strconv"
"strings"
"time"

"github.com/pkg/errors"

"github.com/dwarvesf/icy-backend/internal/model"
"github.com/dwarvesf/icy-backend/internal/utils/config"
Expand Down Expand Up @@ -118,6 +121,7 @@ func (c *blockstream) GetUTXOs(address string) ([]UTXO, error) {
}

return utxos, nil

}

func (c *blockstream) GetBTCBalance(address string) (*model.Web3BigInt, error) {
Expand All @@ -128,49 +132,54 @@ func (c *blockstream) GetBTCBalance(address string) (*model.Web3BigInt, error) {
for attempt := 1; attempt <= maxRetries; attempt++ {
resp, err := c.client.Get(url)
if err != nil {
lastErr = err
c.logger.Error("[getBTCBalance][client.Get]", map[string]string{
"error": err.Error(),
lastErr = errors.Wrap(err, "failed to fetch BTC balance")
c.logger.Error("[GetBTCBalance][client.Get]", map[string]string{
"error": lastErr.Error(),
"attempt": strconv.Itoa(attempt),
})
time.Sleep(time.Duration(attempt) * time.Second) // Exponential backoff
continue
}

// Ensure response body is closed properly
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
lastErr = err
c.logger.Error("[getBTCBalance][client.Get]", map[string]string{
"error": "unexpected status code",
lastErr = fmt.Errorf("unexpected status code: %d", resp.StatusCode)
c.logger.Error("[GetBTCBalance][client.Get]", map[string]string{
"error": lastErr.Error(),
"attempt": strconv.Itoa(attempt),
})
resp.Body.Close()
time.Sleep(time.Duration(attempt) * time.Second)
continue
}

body, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
lastErr = err
c.logger.Error("[getBTCBalance][io.ReadAll]", map[string]string{
"error": err.Error(),
lastErr = errors.Wrap(err, "failed to read response body")
c.logger.Error("[GetBTCBalance][io.ReadAll]", map[string]string{
"error": lastErr.Error(),
"attempt": strconv.Itoa(attempt),
})
continue
}

var response *GetBalanceResponse
var response GetBalanceResponse
err = json.Unmarshal(body, &response)
if err != nil {
lastErr = err
c.logger.Error("[getBTCBalance][json.Unmarshal]", map[string]string{
"error": err.Error(),
lastErr = errors.Wrap(err, "failed to parse JSON response")
c.logger.Error("[GetBTCBalance][json.Unmarshal]", map[string]string{
"error": lastErr.Error(),
"attempt": strconv.Itoa(attempt),
})
continue
}

// Correct balance calculation
balanceSats := response.ChainStats.FundedTxoSum - response.ChainStats.SpentTxoSum
return &model.Web3BigInt{
Value: strconv.Itoa(response.ChainStats.FundedTxoSum),
Decimal: 10,
Value: strconv.FormatInt(int64(balanceSats), 10),
Decimal: 8, // BTC has 8 decimal places
}, nil
}

Expand Down

0 comments on commit 83ceca6

Please sign in to comment.