@@ -3,6 +3,7 @@ package swap
3
3
import (
4
4
"errors"
5
5
"fmt"
6
+ "math"
6
7
"math/big"
7
8
"net/http"
8
9
"strconv"
@@ -13,6 +14,7 @@ import (
13
14
"gorm.io/gorm"
14
15
15
16
"github.com/dwarvesf/icy-backend/internal/baserpc"
17
+ "github.com/dwarvesf/icy-backend/internal/btcrpc"
16
18
"github.com/dwarvesf/icy-backend/internal/consts"
17
19
"github.com/dwarvesf/icy-backend/internal/model"
18
20
"github.com/dwarvesf/icy-backend/internal/oracle"
@@ -40,6 +42,7 @@ type handler struct {
40
42
appConfig * config.AppConfig
41
43
oracle oracle.IOracle
42
44
baseRPC baserpc.IBaseRPC
45
+ btcRPC btcrpc.IBtcRpc
43
46
db * gorm.DB
44
47
btcProcessedTxStore onchainbtcprocessedtransaction.IStore
45
48
swapRequestStore swaprequest.IStore
@@ -50,13 +53,15 @@ func New(
50
53
appConfig * config.AppConfig ,
51
54
oracle oracle.IOracle ,
52
55
baseRPC baserpc.IBaseRPC ,
56
+ btcRPC btcrpc.IBtcRpc ,
53
57
db * gorm.DB ,
54
58
) IHandler {
55
59
return & handler {
56
60
logger : logger ,
57
61
appConfig : appConfig ,
58
62
oracle : oracle ,
59
63
baseRPC : baseRPC ,
64
+ btcRPC : btcRPC ,
60
65
db : db ,
61
66
btcProcessedTxStore : onchainbtcprocessedtransaction .New (),
62
67
swapRequestStore : swaprequest .New (),
@@ -149,15 +154,15 @@ func (h *handler) CreateSwapRequest(c *gin.Context) {
149
154
return
150
155
}
151
156
152
- icyAmountFloat , err := strconv .ParseFloat (req .ICYAmount , 64 )
157
+ icyAmountInt , err := strconv .ParseInt (req .ICYAmount , 10 , 64 )
153
158
if err != nil {
154
159
h .logger .Error ("[CreateSwapRequest][ParseFloat]" , map [string ]string {
155
160
"error" : err .Error (),
156
161
})
157
162
c .JSON (http .StatusBadRequest , view .CreateResponse [any ](nil , err , req , "invalid ICY amount" ))
158
163
return
159
164
}
160
- if icyAmountFloat < h .appConfig .MinIcySwapAmount {
165
+ if icyAmountInt < h .appConfig .MinIcySwapAmount {
161
166
c .JSON (http .StatusBadRequest , view .CreateResponse [any ](nil , fmt .Errorf ("minimum ICY amount is %v" , h .appConfig .MinIcySwapAmount ), nil , "invalid ICY amount" ))
162
167
return
163
168
}
@@ -217,3 +222,65 @@ func (h *handler) CreateSwapRequest(c *gin.Context) {
217
222
218
223
c .JSON (http .StatusOK , view .CreateResponse [any ]("success" , nil , nil , "swap request created successfully" ))
219
224
}
225
+
226
+ func (h * handler ) Info (c * gin.Context ) {
227
+ // Get minimum ICY to swap from config
228
+ minIcySwap := model.Web3BigInt {
229
+ Value : fmt .Sprintf ("%d" , h .appConfig .MinIcySwapAmount ),
230
+ Decimal : 18 ,
231
+ }
232
+
233
+ // Get ICY/BTC rate from oracle (using cached realtime rate), n ICY per 100M satoshi
234
+ rate , err := h .oracle .GetRealtimeICYBTC ()
235
+ if err != nil {
236
+ h .logger .Error ("[Info][GetCachedRealtimeICYBTC]" , map [string ]string {
237
+ "error" : err .Error (),
238
+ })
239
+ c .JSON (http .StatusInternalServerError , view .CreateResponse [any ](nil , err , nil , "failed to get ICY/BTC rate" ))
240
+ return
241
+ }
242
+
243
+ satPerUSD , err := h .btcRPC .GetSatoshiUSDPrice ()
244
+ if err != nil {
245
+ h .logger .Error ("[Info][GetSatoshiUSDPrice]" , map [string ]string {
246
+ "error" : err .Error (),
247
+ })
248
+ c .JSON (http .StatusInternalServerError , view .CreateResponse [any ](nil , err , nil , "failed to get satoshi price" ))
249
+ return
250
+ }
251
+
252
+ // Get circulated ICY balance
253
+ circulatedIcyBalance , err := h .oracle .GetCirculatedICY ()
254
+ if err != nil {
255
+ h .logger .Error ("[Info][GetCirculatedICY]" , map [string ]string {
256
+ "error" : err .Error (),
257
+ })
258
+ c .JSON (http .StatusInternalServerError , view .CreateResponse [any ](nil , err , nil , "failed to get circulated ICY balance" ))
259
+ return
260
+ }
261
+
262
+ // Get BTC supply
263
+ satBalance , err := h .oracle .GetBTCSupply ()
264
+ if err != nil {
265
+ h .logger .Error ("[Info][GetBTCSupply]" , map [string ]string {
266
+ "error" : err .Error (),
267
+ })
268
+ c .JSON (http .StatusInternalServerError , view .CreateResponse [any ](nil , err , nil , "failed to get BTC balance" ))
269
+ return
270
+ }
271
+
272
+ // <rate> (x) icy = 100M satoshi
273
+ // 1 icy = 100M / <rate> satoshi
274
+ satPerIcy := new (big.Float ).Quo (new (big.Float ).SetFloat64 (1e8 ), new (big.Float ).SetFloat64 (rate .ToFloat ()))
275
+ icyPerSat := new (big.Float ).Quo (new (big.Float ).SetFloat64 (1 ), satPerIcy )
276
+ icyPerUSD := new (big.Float ).Quo (icyPerSat , new (big.Float ).SetFloat64 (satPerUSD ))
277
+
278
+ c .JSON (http .StatusOK , view .CreateResponse [any ](map [string ]interface {}{
279
+ "circulated_icy_balance" : circulatedIcyBalance .Value ,
280
+ "satoshi_balance" : satBalance .Value ,
281
+ "satoshi_per_usd" : math .Ceil (satPerUSD * 10 ) / 10 ,
282
+ "icy_satoshi_rate" : rate .Value ,
283
+ "icy_per_usd" : icyPerUSD .String (),
284
+ "min_icy_to_swap" : minIcySwap .Value ,
285
+ }, nil , nil , "swap info retrieved successfully" ))
286
+ }
0 commit comments