mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-09-13 13:00:10 +00:00

* Lazy wallet utxo sync after broadcasting a tx * Make a more granular lock for refreshUTXOs * Don't push to forceSyncChan if it has an element * Better policy for used outpoints and wait for first sync when creating an unsigned tx * fix expire condition * lock address reading * fix small memory leak * add an rpc client dedicated for background ops * rename to follow conventions * one more rename * Compare wallet addresses by value * small fixes * Add comment --------- Co-authored-by: Michael Sutton <msutton@cs.huji.ac.il>
76 lines
2.1 KiB
Go
76 lines
2.1 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
|
|
)
|
|
|
|
type balancesType struct{ available, pending uint64 }
|
|
type balancesMapType map[*walletAddress]*balancesType
|
|
|
|
func (s *server) GetBalance(_ context.Context, _ *pb.GetBalanceRequest) (*pb.GetBalanceResponse, error) {
|
|
s.lock.RLock()
|
|
defer s.lock.RUnlock()
|
|
|
|
if !s.isSynced() {
|
|
return nil, errors.Errorf("wallet daemon is not synced yet, %s", s.formatSyncStateReport())
|
|
}
|
|
|
|
dagInfo, err := s.rpcClient.GetBlockDAGInfo()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
daaScore := dagInfo.VirtualDAAScore
|
|
balancesMap := make(balancesMapType, 0)
|
|
for _, entry := range s.utxosSortedByAmount {
|
|
amount := entry.UTXOEntry.Amount()
|
|
address := entry.address
|
|
balances, ok := balancesMap[address]
|
|
if !ok {
|
|
balances = new(balancesType)
|
|
balancesMap[address] = balances
|
|
}
|
|
if s.isUTXOSpendable(entry, daaScore) {
|
|
balances.available += amount
|
|
} else {
|
|
balances.pending += amount
|
|
}
|
|
}
|
|
|
|
addressBalances := make([]*pb.AddressBalances, len(balancesMap))
|
|
i := 0
|
|
var available, pending uint64
|
|
for walletAddress, balances := range balancesMap {
|
|
address, err := libkaspawallet.Address(s.params, s.keysFile.ExtendedPublicKeys, s.keysFile.MinimumSignatures, s.walletAddressPath(walletAddress), s.keysFile.ECDSA)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
addressBalances[i] = &pb.AddressBalances{
|
|
Address: address.String(),
|
|
Available: balances.available,
|
|
Pending: balances.pending,
|
|
}
|
|
i++
|
|
available += balances.available
|
|
pending += balances.pending
|
|
}
|
|
|
|
log.Infof("GetBalance request scanned %d UTXOs overall over %d addresses", len(s.utxosSortedByAmount), len(balancesMap))
|
|
|
|
return &pb.GetBalanceResponse{
|
|
Available: available,
|
|
Pending: pending,
|
|
AddressBalances: addressBalances,
|
|
}, nil
|
|
}
|
|
|
|
func (s *server) isUTXOSpendable(entry *walletUTXO, virtualDAAScore uint64) bool {
|
|
if !entry.UTXOEntry.IsCoinbase() {
|
|
return true
|
|
}
|
|
return entry.UTXOEntry.BlockDAAScore()+s.coinbaseMaturity < virtualDAAScore
|
|
}
|