@@ -12,6 +12,7 @@ import (
1212 "github.com/oxygenpay/oxygen/internal/service/blockchain"
1313 "github.com/oxygenpay/oxygen/internal/service/merchant"
1414 "github.com/oxygenpay/oxygen/internal/service/payment"
15+ "github.com/oxygenpay/oxygen/internal/service/processing"
1516 "github.com/oxygenpay/oxygen/internal/service/transaction"
1617 "github.com/oxygenpay/oxygen/internal/service/wallet"
1718 "github.com/oxygenpay/oxygen/internal/test"
@@ -504,7 +505,7 @@ func TestService_BatchCreateWithdrawals(t *testing.T) {
504505 })
505506 })
506507
507- t .Run ("Creates 2 ETH transactions, one failed " , func (t * testing.T ) {
508+ t .Run ("Creates 2 ETH transactions, one fails due to insufficient balance " , func (t * testing.T ) {
508509 tc .Clear .Wallets (t )
509510 isTest := false
510511
@@ -607,112 +608,129 @@ func TestService_BatchCreateWithdrawals(t *testing.T) {
607608 assert .Equal (t , expectedWalletBalance , outboundBalance .Amount .StringRaw ())
608609 })
609610
610- t .Run ("Fails " , func (t * testing.T ) {
611+ t .Run ("Validation error " , func (t * testing.T ) {
611612 tc .Clear .Wallets (t )
612- t .Run ("Validation error" , func (t * testing.T ) {
613- mt , _ := tc .Must .CreateMerchant (t , 1 )
613+ mt , _ := tc .Must .CreateMerchant (t , 1 )
614614
615- merchantBalance := tc .Must .CreateBalance (t , wallet .EntityTypeMerchant , mt .ID , withBalance (eth , "123_000_000_000_000_000" , false ))
616- merchantAddress , err := tc .Services .Merchants .CreateMerchantAddress (ctx , mt .ID , merchant.CreateMerchantAddressParams {
617- Name : "A1" ,
618- Blockchain : kmswallet .Blockchain (eth .Blockchain ),
619- Address : "0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5" ,
615+ merchantBalance := tc .Must .CreateBalance (t , wallet .EntityTypeMerchant , mt .ID , withBalance (eth , "123_000_000_000_000_000" , false ))
616+ merchantAddress , err := tc .Services .Merchants .CreateMerchantAddress (ctx , mt .ID , merchant.CreateMerchantAddressParams {
617+ Name : "A1" ,
618+ Blockchain : kmswallet .Blockchain (eth .Blockchain ),
619+ Address : "0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5" ,
620+ })
621+ require .NoError (t , err )
622+
623+ makeWithdrawal := func (amount money.Money , meta payment.Metadata ) * payment.Payment {
624+ entry , err := tc .Repository .CreatePayment (ctx , repository.CreatePaymentParams {
625+ PublicID : uuid .New (),
626+ CreatedAt : time .Now (),
627+ UpdatedAt : time .Now (),
628+ Type : string (payment .TypeWithdrawal ),
629+ Status : string (payment .StatusPending ),
630+ MerchantID : mt .ID ,
631+ MerchantOrderUuid : uuid .New (),
632+ Price : repository .MoneyToNumeric (amount ),
633+ Decimals : int32 (amount .Decimals ()),
634+ Currency : amount .Ticker (),
635+ Metadata : meta .ToJSONB (),
636+ IsTest : false ,
620637 })
621638 require .NoError (t , err )
622639
623- makeWithdrawal := func (amount money.Money , meta payment.Metadata ) * payment.Payment {
624- entry , err := tc .Repository .CreatePayment (ctx , repository.CreatePaymentParams {
625- PublicID : uuid .New (),
626- CreatedAt : time .Now (),
627- UpdatedAt : time .Now (),
628- Type : string (payment .TypeWithdrawal ),
629- Status : string (payment .StatusPending ),
630- MerchantID : mt .ID ,
631- MerchantOrderUuid : uuid .New (),
632- Price : repository .MoneyToNumeric (amount ),
633- Decimals : int32 (amount .Decimals ()),
634- Currency : amount .Ticker (),
635- Metadata : meta .ToJSONB (),
636- IsTest : false ,
637- })
638- require .NoError (t , err )
639-
640- pt , err := tc .Services .Payment .GetByID (ctx , mt .ID , entry .ID )
641- require .NoError (t , err )
642-
643- return pt
644- }
645-
646- for testCaseIndex , testCase := range []struct {
647- errContains string
648- withdrawals func () []* payment.Payment
649- }{
650- {
651- // actually "payment is not withdrawal"
652- errContains : "results len mismatch" ,
653- withdrawals : func () []* payment.Payment {
654- return []* payment.Payment {tc .CreateSamplePayment (t , mt .ID )}
655- },
640+ pt , err := tc .Services .Payment .GetByID (ctx , mt .ID , entry .ID )
641+ require .NoError (t , err )
642+
643+ return pt
644+ }
645+
646+ for _ , tt := range []struct {
647+ name string
648+ assert func (t * testing.T , in []* payment.Payment , result * processing.TransferResult , err error )
649+ withdrawals func () []* payment.Payment
650+ }{
651+ {
652+ name : "payment is not withdrawal" ,
653+ withdrawals : func () []* payment.Payment {
654+ return []* payment.Payment {tc .CreateSamplePayment (t , mt .ID )}
656655 },
657- {
658- // actually "status is not pending"
659- errContains : "results len mismatch" ,
660- withdrawals : func () []* payment.Payment {
661- withdrawal , err := tc .Services .Payment .CreateWithdrawal (ctx , mt .ID , payment.CreateWithdrawalProps {
662- BalanceID : merchantBalance .UUID ,
663- AddressID : merchantAddress .UUID ,
664- AmountRaw : "0.1" ,
665- })
666- require .NoError (t , err )
667-
668- _ , err = tc .Services .Payment .Update (ctx , mt .ID , withdrawal .ID , payment.UpdateProps {Status : payment .StatusInProgress })
669- require .NoError (t , err )
670-
671- return []* payment.Payment {withdrawal }
672- },
656+ assert : func (t * testing.T , _ []* payment.Payment , _ * processing.TransferResult , err error ) {
657+ assert .ErrorContains (t , err , `withdrawals filter mismatch for status "pending"` )
673658 },
674- {
675- errContains : "invalid address id" ,
676- withdrawals : func () []* payment.Payment {
677- return []* payment.Payment {
678- makeWithdrawal (
679- lo .Must (eth .MakeAmount ("123_456" )),
680- payment.Metadata {payment .MetaBalanceID : strconv .Itoa (int (merchantBalance .ID ))},
681- ),
682- }
683- },
659+ },
660+ {
661+ name : "status is not pending" ,
662+ withdrawals : func () []* payment.Payment {
663+ withdrawal , err := tc .Services .Payment .CreateWithdrawal (ctx , mt .ID , payment.CreateWithdrawalProps {
664+ BalanceID : merchantBalance .UUID ,
665+ AddressID : merchantAddress .UUID ,
666+ AmountRaw : "0.1" ,
667+ })
668+ require .NoError (t , err )
669+
670+ _ , err = tc .Services .Payment .Update (ctx , mt .ID , withdrawal .ID , payment.UpdateProps {Status : payment .StatusInProgress })
671+ require .NoError (t , err )
672+
673+ return []* payment.Payment {withdrawal }
684674 },
685- {
686- errContains : "invalid balance id" ,
687- withdrawals : func () []* payment.Payment {
688- return []* payment.Payment {
689- makeWithdrawal (
690- lo .Must (eth .MakeAmount ("123_456" )),
691- payment.Metadata {payment .MetaAddressID : strconv .Itoa (int (merchantAddress .ID ))},
692- ),
693- }
694- },
675+ assert : func (t * testing.T , _ []* payment.Payment , _ * processing.TransferResult , err error ) {
676+ assert .ErrorContains (t , err , `withdrawals filter mismatch for status "pending"` )
695677 },
696- } {
697- t .Run (strconv .Itoa (testCaseIndex + 1 ), func (t * testing.T ) {
698- // ARRANGE
699- // Given balances
700- input := testCase .withdrawals ()
701-
702- // ACT
703- // Transfer money
704- ids := util .MapSlice (input , func (p * payment.Payment ) int64 { return p .ID })
705- result , err := tc .Services .Processing .BatchCreateWithdrawals (ctx , ids )
706- assert .Nil (t , result )
707-
708- // ASSERT
709- // Check that error contain string
710- if testCase .errContains != "" {
711- assert .ErrorContains (t , err , testCase .errContains )
678+ },
679+ {
680+ name : "invalid address id" ,
681+ withdrawals : func () []* payment.Payment {
682+ return []* payment.Payment {
683+ makeWithdrawal (
684+ lo .Must (eth .MakeAmount ("123_456" )),
685+ payment.Metadata {payment .MetaBalanceID : strconv .Itoa (int (merchantBalance .ID ))},
686+ ),
712687 }
713- })
714- }
715- })
688+ },
689+ assert : func (t * testing.T , in []* payment.Payment , result * processing.TransferResult , err error ) {
690+ assert .NoError (t , err )
691+ assert .Equal (t , int64 (1 ), result .TotalErrors )
692+ assert .ErrorContains (t , result .UnhandledErrors [0 ], "withdrawal is invalid, marked as failed" )
693+
694+ pt , _ := tc .Services .Payment .GetByID (ctx , in [0 ].MerchantID , in [0 ].ID )
695+ require .NoError (t , err )
696+ assert .Equal (t , payment .StatusFailed , pt .Status )
697+ },
698+ },
699+ {
700+ name : "invalid balance id" ,
701+ withdrawals : func () []* payment.Payment {
702+ return []* payment.Payment {
703+ makeWithdrawal (
704+ lo .Must (eth .MakeAmount ("123_456" )),
705+ payment.Metadata {payment .MetaAddressID : strconv .Itoa (int (merchantAddress .ID ))},
706+ ),
707+ }
708+ },
709+ assert : func (t * testing.T , in []* payment.Payment , result * processing.TransferResult , err error ) {
710+ assert .NoError (t , err )
711+ assert .Equal (t , int64 (1 ), result .TotalErrors )
712+ assert .ErrorContains (t , result .UnhandledErrors [0 ], "withdrawal is invalid, marked as failed" )
713+
714+ pt , _ := tc .Services .Payment .GetByID (ctx , in [0 ].MerchantID , in [0 ].ID )
715+ require .NoError (t , err )
716+ assert .Equal (t , payment .StatusFailed , pt .Status )
717+ },
718+ },
719+ } {
720+ t .Run (tt .name , func (t * testing.T ) {
721+ // ARRANGE
722+ // Given balances
723+ input := tt .withdrawals ()
724+
725+ // ACT
726+ // Create withdrawals
727+ ids := util .MapSlice (input , func (p * payment.Payment ) int64 { return p .ID })
728+ result , err := tc .Services .Processing .BatchCreateWithdrawals (ctx , ids )
729+
730+ // ASSERT
731+ tt .assert (t , input , result , err )
732+ })
733+ }
716734 })
717735
718736 t .Run ("Logic error" , func (t * testing.T ) {
0 commit comments