1
+ import type { BankExtension , Coin } from "@cosmjs/stargate" ;
2
+
3
+ import { REWARD_GAUGE_KEY_BTC_DELEGATION } from "../../constants" ;
4
+ import * as btclightclientquery from "../../generated/babylon/btclightclient/v1/query" ;
5
+ import * as incentivequery from "../../generated/babylon/incentive/query" ;
6
+
7
+ interface Dependencies {
8
+ incentive : incentivequery . QueryClientImpl ;
9
+ btcLight : btclightclientquery . QueryClientImpl ;
10
+ bank : BankExtension [ "bank" ] ;
11
+ }
12
+
13
+ const createBTCClient = ( { incentive, bank, btcLight } : Dependencies ) => ( {
14
+ /**
15
+ * Gets the rewards of the user's account.
16
+ * @param {string } address - The address to get the rewards of.
17
+ * @returns {Promise<number> } - The rewards of the address.
18
+ */
19
+ async getRewards ( address : string ) : Promise < number > {
20
+ try {
21
+ const req = incentivequery . QueryRewardGaugesRequest . fromPartial ( {
22
+ address,
23
+ } ) ;
24
+
25
+ const rewards = await incentive . RewardGauges ( req ) ;
26
+ if ( ! rewards || ! rewards . rewardGauges ) {
27
+ return 0 ;
28
+ }
29
+
30
+ const coins =
31
+ rewards . rewardGauges [ REWARD_GAUGE_KEY_BTC_DELEGATION ] ?. coins ;
32
+ if ( ! coins ) {
33
+ return 0 ;
34
+ }
35
+
36
+ const withdrawnCoins =
37
+ rewards . rewardGauges [
38
+ REWARD_GAUGE_KEY_BTC_DELEGATION
39
+ ] ?. withdrawnCoins . reduce (
40
+ ( acc : number , coin : Coin ) => acc + Number ( coin . amount ) ,
41
+ 0 ,
42
+ ) || 0 ;
43
+
44
+ return (
45
+ coins . reduce (
46
+ ( acc : number , coin : Coin ) => acc + Number ( coin . amount ) ,
47
+ 0 ,
48
+ ) - withdrawnCoins
49
+ ) ;
50
+ } catch ( error ) {
51
+ // If error message contains "reward gauge not found", silently return 0
52
+ // This is to handle the case where the user has no rewards, meaning
53
+ // they have not staked
54
+ if (
55
+ error instanceof Error &&
56
+ error . message . includes ( "reward gauge not found" )
57
+ ) {
58
+ return 0 ;
59
+ }
60
+ throw new Error ( `Failed to fetch rewards for ${ address } ` , {
61
+ cause : error ,
62
+ } ) ;
63
+ }
64
+ } ,
65
+
66
+ /**
67
+ * Gets the balance of an address in the Babylon chain.
68
+ * @param {string } address - The address to get the balance of.
69
+ * @param {string } denom - The denom of the balance to get.
70
+ * @returns {Promise<number> } - The balance of the address.
71
+ */
72
+ async getBalance ( address : string , denom : string = "ubbn" ) : Promise < number > {
73
+ try {
74
+ const balance = await bank . balance ( address , denom ) ;
75
+ return Number ( balance ?. amount ?? 0 ) ;
76
+ } catch ( error ) {
77
+ throw new Error ( `Failed to fetch balance for ${ address } ` , {
78
+ cause : error ,
79
+ } ) ;
80
+ }
81
+ } ,
82
+
83
+ /**
84
+ * Gets the tip of the Bitcoin blockchain.
85
+ * @returns {Promise<BTCHeaderInfoResponse> } - The tip of the Bitcoin blockchain.
86
+ */
87
+ async getBTCTipHeight ( ) : Promise < number > {
88
+ try {
89
+ const req = btclightclientquery . QueryTipRequest . fromPartial ( { } ) ;
90
+ const { header } = await btcLight . Tip ( req ) ;
91
+ return Number ( header ?. height ?? 0 ) ;
92
+ } catch ( error ) {
93
+ throw new Error ( `Failed to fetch BTC tip height` , {
94
+ cause : error ,
95
+ } ) ;
96
+ }
97
+ }
98
+ } )
99
+
100
+ export default createBTCClient ;
0 commit comments