package state import ( "encoding/gob" "fmt" "os" "sync" "dejo_node/internal/staking" "dejo_node/internal/transactions" ) type State struct { mu sync.RWMutex Balances map[string]uint64 } func NewState() *State { return &State{ Balances: make(map[string]uint64), } } func (s *State) Apply(tx *transactions.Transaction) error { s.mu.Lock() defer s.mu.Unlock() if tx.From == tx.To { return fmt.Errorf("transação inválida: origem = destino") } if tx.Value <= 0 { return fmt.Errorf("valor zero não permitido") } fromBal := s.Balances[tx.From] if fromBal < uint64(tx.Value) { return fmt.Errorf("saldo insuficiente: %s tem %d, precisa de %f", tx.From, fromBal, tx.Value) } s.Balances[tx.From] -= uint64(tx.Value) s.Balances[tx.To] += uint64(tx.Value) return nil } func (s *State) Transfer(from, to string, amount uint64) error { s.mu.Lock() defer s.mu.Unlock() if s.Balances[from] < amount { return fmt.Errorf("saldo insuficiente") } s.Balances[from] -= amount s.Balances[to] += amount return nil } func (s *State) Mint(to string, amount uint64) { s.mu.Lock() defer s.mu.Unlock() s.Balances[to] += amount } func (s *State) Stake(address string, amount uint64, dur int64) error { if err := s.Transfer(address, "staking_pool", amount); err != nil { return err } return staking.NewStakingStore().Stake(address, amount, uint64(dur)) } func (s *State) Unstake(address string) error { s.mu.Lock() defer s.mu.Unlock() if err := staking.NewStakingStore().Unstake(address); err != nil { return err } s.Balances[address] += 1000 // Exemplo: devolve saldo fixo return nil } func (s *State) SaveToDisk(path string) error { f, err := os.Create(path) if err != nil { return err } defer f.Close() enc := gob.NewEncoder(f) return enc.Encode(s.Balances) } func (s *State) LoadFromDisk(path string) error { f, err := os.Open(path) if err != nil { if os.IsNotExist(err) { s.Balances = make(map[string]uint64) return nil } return err } defer f.Close() dec := gob.NewDecoder(f) return dec.Decode(&s.Balances) }