Skip to content
This repository was archived by the owner on Dec 16, 2025. It is now read-only.

Commit e7d32f1

Browse files
committed
Merge branch 'master' into bugfix/range-update-corrupt-cache
2 parents ba75de3 + b03546c commit e7d32f1

6 files changed

Lines changed: 76 additions & 27 deletions

File tree

cointop/chart.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,11 @@ func (ct *Cointop) PortfolioChart() error {
257257
for i := range graphData {
258258
price := graphData[i]
259259
sum := p.Holdings * price
260-
if len(data)-1 >= i {
260+
if i < len(data) {
261261
data[i] += sum
262+
} else {
263+
data = append(data, sum)
262264
}
263-
data = append(data, sum)
264265
}
265266
}
266267

cointop/cointop.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ type State struct {
4444
coinsTableColumns []string
4545
convertMenuVisible bool
4646
defaultView string
47+
defaultChartRange string
4748

4849
// DEPRECATED: favorites by 'symbol' is deprecated because of collisions.
4950
favoritesBySymbol map[string]bool
@@ -243,6 +244,7 @@ func NewCointop(config *Config) (*Cointop, error) {
243244
cacheDir: DefaultCacheDir,
244245
coinsTableColumns: DefaultCoinTableHeaders,
245246
currencyConversion: DefaultCurrency,
247+
defaultChartRange: DefaultChartRange,
246248
// DEPRECATED: favorites by 'symbol' is deprecated because of collisions. Kept for backward compatibility.
247249
favoritesBySymbol: make(map[string]bool),
248250
favorites: make(map[string]bool),

cointop/config.go

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,19 @@ var possibleConfigPaths = []string{
3131
}
3232

3333
type config struct {
34-
Shortcuts map[string]interface{} `toml:"shortcuts"`
35-
Favorites map[string]interface{} `toml:"favorites"`
36-
Portfolio map[string]interface{} `toml:"portfolio"`
37-
PriceAlerts map[string]interface{} `toml:"price_alerts"`
38-
Currency interface{} `toml:"currency"`
39-
DefaultView interface{} `toml:"default_view"`
40-
CoinMarketCap map[string]interface{} `toml:"coinmarketcap"`
41-
API interface{} `toml:"api"`
42-
Colorscheme interface{} `toml:"colorscheme"`
43-
RefreshRate interface{} `toml:"refresh_rate"`
44-
CacheDir interface{} `toml:"cache_dir"`
45-
Table map[string]interface{} `toml:"table"`
34+
Shortcuts map[string]interface{} `toml:"shortcuts"`
35+
Favorites map[string]interface{} `toml:"favorites"`
36+
Portfolio map[string]interface{} `toml:"portfolio"`
37+
PriceAlerts map[string]interface{} `toml:"price_alerts"`
38+
Currency interface{} `toml:"currency"`
39+
DefaultView interface{} `toml:"default_view"`
40+
DefaultChartRange interface{} `toml:"default_chart_range"`
41+
CoinMarketCap map[string]interface{} `toml:"coinmarketcap"`
42+
API interface{} `toml:"api"`
43+
Colorscheme interface{} `toml:"colorscheme"`
44+
RefreshRate interface{} `toml:"refresh_rate"`
45+
CacheDir interface{} `toml:"cache_dir"`
46+
Table map[string]interface{} `toml:"table"`
4647
}
4748

4849
// SetupConfig loads config file
@@ -69,6 +70,9 @@ func (ct *Cointop) SetupConfig() error {
6970
if err := ct.loadDefaultViewFromConfig(); err != nil {
7071
return err
7172
}
73+
if err := ct.loadDefaultChartRangeFromConfig(); err != nil {
74+
return err
75+
}
7276
if err := ct.loadAPIKeysFromConfig(); err != nil {
7377
return err
7478
}
@@ -255,6 +259,7 @@ func (ct *Cointop) configToToml() ([]byte, error) {
255259

256260
var currencyIfc interface{} = ct.State.currencyConversion
257261
var defaultViewIfc interface{} = ct.State.defaultView
262+
var defaultChartRangeIfc interface{} = ct.State.defaultChartRange
258263
var colorschemeIfc interface{} = ct.colorschemeName
259264
var refreshRateIfc interface{} = uint(ct.State.refreshRate.Seconds())
260265
var cacheDirIfc interface{} = ct.State.cacheDir
@@ -289,18 +294,19 @@ func (ct *Cointop) configToToml() ([]byte, error) {
289294
tableMapIfc["keep_row_focus_on_sort"] = keepRowFocusOnSortIfc
290295

291296
var inputs = &config{
292-
API: apiChoiceIfc,
293-
Colorscheme: colorschemeIfc,
294-
CoinMarketCap: cmcIfc,
295-
Currency: currencyIfc,
296-
DefaultView: defaultViewIfc,
297-
Favorites: favoritesMapIfc,
298-
RefreshRate: refreshRateIfc,
299-
Shortcuts: shortcutsIfcs,
300-
Portfolio: portfolioIfc,
301-
PriceAlerts: priceAlertsMapIfc,
302-
CacheDir: cacheDirIfc,
303-
Table: tableMapIfc,
297+
API: apiChoiceIfc,
298+
Colorscheme: colorschemeIfc,
299+
CoinMarketCap: cmcIfc,
300+
Currency: currencyIfc,
301+
DefaultView: defaultViewIfc,
302+
DefaultChartRange: defaultChartRangeIfc,
303+
Favorites: favoritesMapIfc,
304+
RefreshRate: refreshRateIfc,
305+
Shortcuts: shortcutsIfcs,
306+
Portfolio: portfolioIfc,
307+
PriceAlerts: priceAlertsMapIfc,
308+
CacheDir: cacheDirIfc,
309+
Table: tableMapIfc,
304310
}
305311

306312
var b bytes.Buffer
@@ -399,6 +405,21 @@ func (ct *Cointop) loadDefaultViewFromConfig() error {
399405
return nil
400406
}
401407

408+
// LoadDefaultChartRangeFromConfig loads default chart range from config file to struct
409+
func (ct *Cointop) loadDefaultChartRangeFromConfig() error {
410+
ct.debuglog("loadDefaultChartRangeFromConfig()")
411+
if defaultChartRange, ok := ct.config.DefaultChartRange.(string); ok {
412+
// validate configured value
413+
_, ok := ct.chartRangesMap[defaultChartRange]
414+
if !ok {
415+
return fmt.Errorf("invalid default chart range %q. Valid ranges are: %s", defaultChartRange, strings.Join(ChartRanges(), ","))
416+
}
417+
ct.State.defaultChartRange = defaultChartRange
418+
ct.State.selectedChartRange = defaultChartRange
419+
}
420+
return nil
421+
}
422+
402423
// LoadAPIKeysFromConfig loads API keys from config file to struct
403424
func (ct *Cointop) loadAPIKeysFromConfig() error {
404425
ct.debuglog("loadAPIKeysFromConfig()")

cointop/portfolio.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,12 +529,25 @@ func (ct *Cointop) GetPortfolioSlice() []*Coin {
529529
return sliced
530530
}
531531

532+
OUTER:
532533
for i := range ct.State.allCoins {
533534
coin := ct.State.allCoins[i]
534535
p, isNew := ct.PortfolioEntry(coin)
535536
if isNew {
536537
continue
537538
}
539+
// check not already found
540+
updateSlice := -1
541+
for j := range sliced {
542+
if coin.Symbol == sliced[j].Symbol {
543+
if coin.Rank >= sliced[j].Rank {
544+
continue OUTER // skip updates from lower-ranked coins
545+
}
546+
updateSlice = j // update this later
547+
break
548+
}
549+
}
550+
538551
coin.Holdings = p.Holdings
539552
balance := coin.Price * p.Holdings
540553
balancestr := fmt.Sprintf("%.2f", balance)
@@ -543,7 +556,12 @@ func (ct *Cointop) GetPortfolioSlice() []*Coin {
543556
}
544557
balance, _ = strconv.ParseFloat(balancestr, 64)
545558
coin.Balance = balance
546-
sliced = append(sliced, coin)
559+
if updateSlice == -1 {
560+
sliced = append(sliced, coin)
561+
} else {
562+
sliced[updateSlice] = coin
563+
}
564+
547565
}
548566

549567
sort.Slice(sliced, func(i, j int) bool {

docs/content/config.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ You can configure the actions you want for each key in `config.toml`:
3939
```toml
4040
currency = "USD"
4141
default_view = ""
42+
default_chart_range = "1Y"
4243
api = "coingecko"
4344
colorscheme = "cointop"
4445
refresh_rate = 60

docs/content/faq.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,12 @@ draft: false
328328

329329
In the config file, set `default_view = "default"`
330330

331+
## How do I set the default chart range?
332+
333+
In the config file, set `default_chart_range = "3M"`
334+
335+
Supported date ranges are `All Time`, `YTD`, `1Y`, `6M`, `3M`, `1M`, `7D`, `3D`, `24H`.
336+
331337
## How can use a different config file other than the default?
332338

333339
Run cointop with the `--config` flag, eg `cointop --config="/path/to/config.toml"`, to use the specified file as the config.

0 commit comments

Comments
 (0)