8
8
"regexp"
9
9
"strconv"
10
10
"strings"
11
+ "time"
12
+
13
+ "github.com/pkg/errors"
11
14
12
15
"github.com/dwarvesf/icy-backend/internal/model"
13
16
"github.com/dwarvesf/icy-backend/internal/utils/config"
@@ -118,6 +121,7 @@ func (c *blockstream) GetUTXOs(address string) ([]UTXO, error) {
118
121
}
119
122
120
123
return utxos , nil
124
+
121
125
}
122
126
123
127
func (c * blockstream ) GetBTCBalance (address string ) (* model.Web3BigInt , error ) {
@@ -128,49 +132,54 @@ func (c *blockstream) GetBTCBalance(address string) (*model.Web3BigInt, error) {
128
132
for attempt := 1 ; attempt <= maxRetries ; attempt ++ {
129
133
resp , err := c .client .Get (url )
130
134
if err != nil {
131
- lastErr = err
132
- c .logger .Error ("[getBTCBalance ][client.Get]" , map [string ]string {
133
- "error" : err .Error (),
135
+ lastErr = errors . Wrap ( err , "failed to fetch BTC balance" )
136
+ c .logger .Error ("[GetBTCBalance ][client.Get]" , map [string ]string {
137
+ "error" : lastErr .Error (),
134
138
"attempt" : strconv .Itoa (attempt ),
135
139
})
140
+ time .Sleep (time .Duration (attempt ) * time .Second ) // Exponential backoff
136
141
continue
137
142
}
138
143
144
+ // Ensure response body is closed properly
145
+ defer resp .Body .Close ()
146
+
139
147
if resp .StatusCode != http .StatusOK {
140
- lastErr = err
141
- c .logger .Error ("[getBTCBalance ][client.Get]" , map [string ]string {
142
- "error" : "unexpected status code" ,
148
+ lastErr = fmt . Errorf ( "unexpected status code: %d" , resp . StatusCode )
149
+ c .logger .Error ("[GetBTCBalance ][client.Get]" , map [string ]string {
150
+ "error" : lastErr . Error () ,
143
151
"attempt" : strconv .Itoa (attempt ),
144
152
})
145
- resp . Body . Close ( )
153
+ time . Sleep ( time . Duration ( attempt ) * time . Second )
146
154
continue
147
155
}
148
156
149
157
body , err := io .ReadAll (resp .Body )
150
- resp .Body .Close ()
151
158
if err != nil {
152
- lastErr = err
153
- c .logger .Error ("[getBTCBalance ][io.ReadAll]" , map [string ]string {
154
- "error" : err .Error (),
159
+ lastErr = errors . Wrap ( err , "failed to read response body" )
160
+ c .logger .Error ("[GetBTCBalance ][io.ReadAll]" , map [string ]string {
161
+ "error" : lastErr .Error (),
155
162
"attempt" : strconv .Itoa (attempt ),
156
163
})
157
164
continue
158
165
}
159
166
160
- var response * GetBalanceResponse
167
+ var response GetBalanceResponse
161
168
err = json .Unmarshal (body , & response )
162
169
if err != nil {
163
- lastErr = err
164
- c .logger .Error ("[getBTCBalance ][json.Unmarshal]" , map [string ]string {
165
- "error" : err .Error (),
170
+ lastErr = errors . Wrap ( err , "failed to parse JSON response" )
171
+ c .logger .Error ("[GetBTCBalance ][json.Unmarshal]" , map [string ]string {
172
+ "error" : lastErr .Error (),
166
173
"attempt" : strconv .Itoa (attempt ),
167
174
})
168
175
continue
169
176
}
170
177
178
+ // Correct balance calculation
179
+ balanceSats := response .ChainStats .FundedTxoSum - response .ChainStats .SpentTxoSum
171
180
return & model.Web3BigInt {
172
- Value : strconv .Itoa ( response . ChainStats . FundedTxoSum ),
173
- Decimal : 10 ,
181
+ Value : strconv .FormatInt ( int64 ( balanceSats ), 10 ),
182
+ Decimal : 8 , // BTC has 8 decimal places
174
183
}, nil
175
184
}
176
185
0 commit comments