63 lines
1.5 KiB
Go
63 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// ================== Stato locale (anti-doppio ordine) ==================
|
|
|
|
type Lock struct {
|
|
TS time.Time `json:"ts"`
|
|
From string `json:"from"`
|
|
To string `json:"to"`
|
|
AmountFrom float64 `json:"amount_from"`
|
|
Status string `json:"status"` // pending/confirmed/cancelled
|
|
}
|
|
type PortfolioState struct {
|
|
Version int `json:"version"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Balances map[string]float64 `json:"balances"`
|
|
Locks []Lock `json:"locks"`
|
|
}
|
|
|
|
func loadState(path string) (PortfolioState, error) {
|
|
b, err := os.ReadFile(path)
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
return PortfolioState{Version: 1, UpdatedAt: time.Now().UTC(), Balances: map[string]float64{}, Locks: []Lock{}}, nil
|
|
}
|
|
if err != nil {
|
|
return PortfolioState{}, err
|
|
}
|
|
var s PortfolioState
|
|
if err := json.Unmarshal(b, &s); err != nil {
|
|
return PortfolioState{}, err
|
|
}
|
|
return s, nil
|
|
}
|
|
|
|
func saveState(path string, s PortfolioState) error {
|
|
s.UpdatedAt = time.Now().UTC()
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
return err
|
|
}
|
|
b, _ := json.Marshal(s)
|
|
return os.WriteFile(path, b, 0o644)
|
|
}
|
|
|
|
func assetShort(label string) string {
|
|
parts := strings.Split(label, ".")
|
|
if len(parts) != 2 {
|
|
return label
|
|
}
|
|
right := parts[1]
|
|
if i := strings.Index(right, "-"); i > 0 {
|
|
right = right[:i]
|
|
}
|
|
return parts[0] + "." + right
|
|
}
|