diff --git a/internal/core/application/transaction_service.go b/internal/core/application/transaction_service.go index d4fca7c..b4671e4 100644 --- a/internal/core/application/transaction_service.go +++ b/internal/core/application/transaction_service.go @@ -357,6 +357,13 @@ func (ts *TransactionService) Transfer( if len(balance) <= 0 { return "", fmt.Errorf("account %s has 0 balance", accountName) } + for asset, amount := range outputs.totalAmountByAsset() { + if (balance[asset].Confirmed + balance[asset].Unconfirmed) < amount { + return "", fmt.Errorf( + "not enough funds to cover amount %d of asset %s", amount, asset, + ) + } + } utxos, err := utxoRepo.GetSpendableUtxosForAccount( ctx, account.Namespace, diff --git a/internal/infrastructure/coin-selector/smallest-subset/selector.go b/internal/infrastructure/coin-selector/smallest-subset/selector.go index 3f6b096..326f356 100644 --- a/internal/infrastructure/coin-selector/smallest-subset/selector.go +++ b/internal/infrastructure/coin-selector/smallest-subset/selector.go @@ -27,7 +27,7 @@ func (s *selector) SelectUtxos( }) targetUtxos := make([]*domain.Utxo, 0) - totalAmount := uint64(0) + balance := uint64(0) for i := range utxos { utxo := utxos[i] if utxo.IsConfidential() && !utxo.IsRevealed() { @@ -35,15 +35,21 @@ func (s *selector) SelectUtxos( } if utxo.Asset == targetAsset { targetUtxos = append(targetUtxos, utxo) + balance += utxo.Value } } + if targetAmount == balance { + return targetUtxos, 0, nil + } + indexes := selectUtxos(targetAmount, targetUtxos) if len(indexes) <= 0 { return nil, 0, ErrTargetAmountNotReached } selectedUtxos := make([]*domain.Utxo, 0) + totalAmount := uint64(0) for _, v := range indexes { totalAmount += targetUtxos[v].Value selectedUtxos = append(selectedUtxos, targetUtxos[v])