1
1
package cmd
2
2
3
3
import (
4
+ "context"
5
+ "encoding/json"
4
6
"fmt"
7
+ "net/http"
8
+ "strings"
9
+ "time"
5
10
6
11
tea "github.com/charmbracelet/bubbletea"
7
12
"github.com/spf13/cobra"
@@ -15,6 +20,140 @@ import (
15
20
"github.com/initia-labs/weave/registry"
16
21
)
17
22
23
+ // Constants for denomination handling
24
+ const (
25
+ utiaDenom = "utia"
26
+ tiaDenom = "TIA"
27
+ tiaExponent = 6
28
+ uinitDenom = "uinit"
29
+ initDenom = "INIT"
30
+ initExponent = 6
31
+
32
+ testnetRegistryURL = "https://registry.testnet.initia.xyz/initia/assetlist.json"
33
+ mainnetRegistryURL = "https://registry.initia.xyz/initia/assetlist.json"
34
+ )
35
+
36
+ type DenomUnit struct {
37
+ Denom string `json:"denom"`
38
+ Exponent int `json:"exponent"`
39
+ }
40
+
41
+ const (
42
+ DefaultTimeout = 3 * time .Second
43
+ )
44
+
45
+ type Asset struct {
46
+ DenomUnits []DenomUnit `json:"denom_units"`
47
+ Base string `json:"base"`
48
+ Display string `json:"display"`
49
+ }
50
+
51
+ type AssetList struct {
52
+ Assets []Asset `json:"assets"`
53
+ }
54
+
55
+ // formatAmount formats an amount string with the given exponent
56
+ func formatAmount (amount string , exponent int ) string {
57
+ if len (amount ) > exponent {
58
+ decimalPos := len (amount ) - exponent
59
+ amount = amount [:decimalPos ] + "." + amount [decimalPos :]
60
+ } else {
61
+ zeros := strings .Repeat ("0" , exponent - len (amount ))
62
+ amount = "0." + zeros + amount
63
+ }
64
+
65
+ // Trim trailing zeros and decimal point if necessary
66
+ amount = strings .TrimRight (strings .TrimRight (amount , "0" ), "." )
67
+ if amount == "" {
68
+ amount = "0"
69
+ }
70
+ return amount
71
+ }
72
+
73
+ func fetchInitiaRegistryAssetList (chainType registry.ChainType ) (* AssetList , error ) {
74
+ ctx , cancel := context .WithTimeout (context .Background (), DefaultTimeout )
75
+ defer cancel ()
76
+
77
+ registryURL := testnetRegistryURL
78
+ if chainType == registry .InitiaL1Mainnet {
79
+ registryURL = mainnetRegistryURL
80
+ }
81
+
82
+ req , err := http .NewRequestWithContext (ctx , "GET" , registryURL , nil )
83
+ if err != nil {
84
+ return nil , fmt .Errorf ("failed to create request: %w" , err )
85
+ }
86
+
87
+ resp , err := http .DefaultClient .Do (req )
88
+ if err != nil {
89
+ return nil , fmt .Errorf ("failed to fetch asset list: %w" , err )
90
+ }
91
+ defer resp .Body .Close ()
92
+
93
+ if resp .StatusCode != http .StatusOK {
94
+ return nil , fmt .Errorf ("unexpected status code: %d" , resp .StatusCode )
95
+ }
96
+
97
+ var assetList AssetList
98
+ if err := json .NewDecoder (resp .Body ).Decode (& assetList ); err != nil {
99
+ return nil , fmt .Errorf ("failed to decode asset list: %w" , err )
100
+ }
101
+ return & assetList , nil
102
+ }
103
+
104
+ func convertToDisplayDenom (coins * cosmosutils.Coins , assetList * AssetList ) * cosmosutils.Coins {
105
+ if coins == nil {
106
+ return nil
107
+ }
108
+
109
+ result := make (cosmosutils.Coins , 0 , len (* coins ))
110
+ for _ , coin := range * coins {
111
+ displayCoin := coin
112
+
113
+ // Handle special cases first
114
+ switch coin .Denom {
115
+ case utiaDenom :
116
+ displayCoin .Amount = formatAmount (coin .Amount , tiaExponent )
117
+ displayCoin .Denom = tiaDenom
118
+ result = append (result , displayCoin )
119
+ continue
120
+ case uinitDenom :
121
+ displayCoin .Amount = formatAmount (coin .Amount , initExponent )
122
+ displayCoin .Denom = initDenom
123
+ result = append (result , displayCoin )
124
+ continue
125
+ }
126
+
127
+ // Handle other denoms via asset list
128
+ if assetList != nil {
129
+ if displayDenom , exponent := findHighestExponentDenom (assetList , coin .Denom ); exponent > 0 {
130
+ displayCoin .Amount = formatAmount (coin .Amount , exponent )
131
+ displayCoin .Denom = displayDenom
132
+ }
133
+ }
134
+ result = append (result , displayCoin )
135
+ }
136
+ return & result
137
+ }
138
+
139
+ // findHighestExponentDenom finds the denomination with the highest exponent for a given base denom
140
+ func findHighestExponentDenom (assetList * AssetList , baseDenom string ) (string , int ) {
141
+ for _ , asset := range assetList .Assets {
142
+ if asset .Base == baseDenom {
143
+ maxExponent := 0
144
+ displayDenom := baseDenom
145
+ for _ , unit := range asset .DenomUnits {
146
+ if unit .Exponent > maxExponent {
147
+ maxExponent = unit .Exponent
148
+ displayDenom = unit .Denom
149
+ }
150
+ }
151
+ return displayDenom , maxExponent
152
+ }
153
+ }
154
+ return baseDenom , 0
155
+ }
156
+
18
157
func GasStationCommand () * cobra.Command {
19
158
cmd := & cobra.Command {
20
159
Use : "gas-station" ,
@@ -115,6 +254,19 @@ func showGasStationBalance() error {
115
254
return err
116
255
}
117
256
257
+ // Fetch asset list and convert denoms before printing
258
+ testnetAssetList , err := fetchInitiaRegistryAssetList (registry .InitiaL1Testnet )
259
+ if err != nil {
260
+ // Log the error but continue with nil assetList
261
+ fmt .Printf ("Warning: Failed to fetch asset list: %v. Displaying original denominations.\n " , err )
262
+ testnetAssetList = nil
263
+ }
264
+
265
+ // Convert balances to display denoms
266
+ initiaL1TestnetBalances = convertToDisplayDenom (initiaL1TestnetBalances , testnetAssetList )
267
+ celestiaTestnetBalance = convertToDisplayDenom (celestiaTestnetBalance , nil ) // nil assetList for Celestia
268
+ celestiaMainnetBalance = convertToDisplayDenom (celestiaMainnetBalance , nil ) // nil assetList for Celestia
269
+
118
270
maxWidth := getMaxWidth (initiaL1TestnetBalances , celestiaTestnetBalance , celestiaMainnetBalance )
119
271
if maxWidth < len (cosmosutils .NoBalancesText ) {
120
272
maxWidth = len (cosmosutils .NoBalancesText )
@@ -132,7 +284,7 @@ func gasStationShowCommand() *cobra.Command {
132
284
Short : "Show Initia and Celestia Gas Station addresses and balances" ,
133
285
RunE : func (cmd * cobra.Command , args []string ) error {
134
286
if config .IsFirstTimeSetup () {
135
- fmt .Println ("Please setup Gas Station first, by running `gas-station setup`" )
287
+ fmt .Println ("Please setup Gas Station first, by running `weave gas-station setup`" )
136
288
return nil
137
289
}
138
290
0 commit comments