@@ -23,20 +23,16 @@ func (s *Service) BatchCreateWithdrawals(ctx context.Context, withdrawalIDs []in
2323 return nil , err
2424 }
2525
26- // 1.Validate payments
27- if errValidate := s .validateWithdrawals (withdrawals ); errValidate != nil {
28- return nil , errValidate
29- }
30-
31- // 2. Get OUTBOUND wallets and balances
26+ // 1. Get OUTBOUND wallets and balances
3227 outboundWallets , outboundBalances , err := s .getOutboundWalletsWithBalancesAsMap (ctx )
3328 if err != nil {
3429 return nil , errors .Wrap (err , "unable to get outbound wallets with balances" )
3530 }
3631
3732 result := & TransferResult {}
3833
39- // 3. For each withdrawal:
34+ // 2. For each withdrawal:
35+ // - Validate
4036 // - Resolve currency
4137 // - Resolve outbound system wallet & balance
4238 // - Resolve merchant balance & withdrawal address
@@ -47,6 +43,18 @@ func (s *Service) BatchCreateWithdrawals(ctx context.Context, withdrawalIDs []in
4743 for i := range withdrawals {
4844 withdrawal := withdrawals [i ]
4945 group .Go (func () error {
46+ // Let's validate each withdrawal individually.
47+ // By doing so, we can reject it without blocking other withdrawals.
48+ if errValidate := validateWithdrawal (withdrawal ); errValidate != nil {
49+ if errUpdate := s .payments .Fail (ctx , withdrawal ); errUpdate != nil {
50+ result .registerErr (errors .Wrap (errUpdate , "unable to mark invalid withdrawal as failed" ))
51+ } else {
52+ result .registerErr (errors .Wrap (errValidate , "withdrawal is invalid, marked as failed" ))
53+ }
54+
55+ return nil
56+ }
57+
5058 currency , err := s .blockchain .GetCurrencyByTicker (withdrawal .Price .Ticker ())
5159 if err != nil {
5260 result .registerErr (errors .Wrap (err , "unable to get withdrawal currency" ))
@@ -540,27 +548,26 @@ func (s *Service) cancelWithdrawal(
540548 return nil
541549}
542550
543- func (s * Service ) validateWithdrawals (withdrawals []* payment.Payment ) error {
544- for _ , pt := range withdrawals {
545- if pt .Type != payment .TypeWithdrawal {
546- return errors .Wrap (ErrInvalidInput , "payment is not withdrawal" )
547- }
551+ func validateWithdrawal (pt * payment.Payment ) error {
552+ if pt .Type != payment .TypeWithdrawal {
553+ return errors .Wrap (ErrInvalidInput , "payment is not withdrawal" )
554+ }
548555
549- if pt .Status != payment .StatusPending {
550- return errors .Wrap (ErrInvalidInput , "withdrawal is not pending" )
551- }
556+ if pt .Status != payment .StatusPending {
557+ return errors .Wrap (ErrInvalidInput , "withdrawal is not pending" )
558+ }
552559
553- if pt .MerchantID == 0 {
554- return errors .Wrap (ErrInvalidInput , "invalid merchant id" )
555- }
560+ if pt .MerchantID == 0 {
561+ return errors .Wrap (ErrInvalidInput , "invalid merchant id" )
562+ }
556563
557- if pt .WithdrawalBalanceID () < 1 {
558- return errors .Wrap (ErrInvalidInput , "invalid balance id" )
559- }
564+ if pt .WithdrawalBalanceID () < 1 {
565+ return errors .Wrap (ErrInvalidInput , "invalid balance id" )
566+ }
560567
561- if pt . WithdrawalAddressID () < 1 {
562- return errors . Wrap ( ErrInvalidInput , "invalid address id" )
563- }
568+ // edge-case: a customer can delete the address while withdrawal is pending
569+ if pt . WithdrawalAddressID () < 1 {
570+ return errors . Wrap ( ErrInvalidInput , "invalid address id" )
564571 }
565572
566573 return nil
0 commit comments