@@ -774,3 +774,182 @@ func TestFilterByPoolId(t *testing.T) {
774774 t .Fatal ("Test timed out waiting for filtered event" )
775775 }
776776}
777+
778+ func TestFilterByAddressGovernanceEvent (t * testing.T ) {
779+ // Use a stake/reward address format for proposal reward accounts
780+ stakeAddr := "stake1uyehkck0lajq8gr28t9uxnuvgcqrc6070x3k9r8048z8y5gh6ffgw"
781+ // 28 bytes = 56 hex chars for stake credential hash
782+ stakeCredHex := "abcd1234567890abcdef1234567890abcdef1234567890abcdef1234"
783+
784+ t .Run ("matches proposal reward account" , func (t * testing.T ) {
785+ cs := New (WithAddresses ([]string {stakeAddr }))
786+
787+ evt := event.Event {
788+ Payload : event.GovernanceEvent {
789+ ProposalProcedures : []event.ProposalProcedureData {
790+ {
791+ Index : 0 ,
792+ Deposit : 100000000 ,
793+ RewardAccount : stakeAddr ,
794+ ActionType : "Info" ,
795+ },
796+ },
797+ },
798+ }
799+
800+ err := cs .Start ()
801+ assert .NoError (t , err )
802+ defer cs .Stop ()
803+
804+ cs .InputChan () <- evt
805+
806+ select {
807+ case filteredEvt := <- cs .OutputChan ():
808+ assert .Equal (t , evt , filteredEvt )
809+ case <- time .After (1 * time .Second ):
810+ t .Error ("Expected event to pass filter but it didn't" )
811+ }
812+ })
813+
814+ t .Run ("matches treasury withdrawal address" , func (t * testing.T ) {
815+ // Use a payment address for treasury withdrawal
816+ paymentAddr := "addr1qx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3jcu5d8ps7zex2k2xt3uqxgjqnnj83ws8lhrn648jjxtwq2ytjqp"
817+ cs := New (WithAddresses ([]string {paymentAddr }))
818+
819+ evt := event.Event {
820+ Payload : event.GovernanceEvent {
821+ ProposalProcedures : []event.ProposalProcedureData {
822+ {
823+ Index : 0 ,
824+ Deposit : 100000000000 ,
825+ RewardAccount : "stake1..." , // Different from filter
826+ ActionType : "TreasuryWithdrawal" ,
827+ ActionData : event.GovActionData {
828+ TreasuryWithdrawal : & event.TreasuryWithdrawalActionData {
829+ Withdrawals : []event.TreasuryWithdrawalItem {
830+ {
831+ Address : paymentAddr ,
832+ Amount : 50000000000 ,
833+ },
834+ },
835+ },
836+ },
837+ },
838+ },
839+ },
840+ }
841+
842+ err := cs .Start ()
843+ assert .NoError (t , err )
844+ defer cs .Stop ()
845+
846+ cs .InputChan () <- evt
847+
848+ select {
849+ case filteredEvt := <- cs .OutputChan ():
850+ assert .Equal (t , evt , filteredEvt )
851+ case <- time .After (1 * time .Second ):
852+ t .Error ("Expected event to pass filter but it didn't" )
853+ }
854+ })
855+
856+ t .Run ("matches vote delegation stake credential" , func (t * testing.T ) {
857+ // Create a stake address that decodes to a credential hash
858+ realStakeAddr := "stake1uyehkck0lajq8gr28t9uxnuvgcqrc6070x3k9r8048z8y5gh6ffgw"
859+ cs := New (WithAddresses ([]string {realStakeAddr }))
860+
861+ // Decode the stake address to get the actual credential hash
862+ _ , data , err := bech32 .DecodeNoLimit (realStakeAddr )
863+ assert .NoError (t , err )
864+ converted , err := bech32 .ConvertBits (data , 5 , 8 , false )
865+ assert .NoError (t , err )
866+ // Skip the first byte (header) to get the credential hash
867+ credHash := hex .EncodeToString (converted [1 :])
868+
869+ evt := event.Event {
870+ Payload : event.GovernanceEvent {
871+ VoteDelegationCertificates : []event.VoteDelegationCertificateData {
872+ {
873+ CertificateType : "VoteDelegation" ,
874+ StakeCredential : credHash ,
875+ DRepType : "KeyHash" ,
876+ DRepHash : "someDRepHash" ,
877+ },
878+ },
879+ },
880+ }
881+
882+ err = cs .Start ()
883+ assert .NoError (t , err )
884+ defer cs .Stop ()
885+
886+ cs .InputChan () <- evt
887+
888+ select {
889+ case filteredEvt := <- cs .OutputChan ():
890+ assert .Equal (t , evt , filteredEvt )
891+ case <- time .After (1 * time .Second ):
892+ t .Error ("Expected event to pass filter but it didn't" )
893+ }
894+ })
895+
896+ t .Run ("does not match when address not in filter" , func (t * testing.T ) {
897+ cs := New (WithAddresses ([]string {stakeAddr }))
898+
899+ otherStakeAddr := "stake1uxxx..."
900+ evt := event.Event {
901+ Payload : event.GovernanceEvent {
902+ ProposalProcedures : []event.ProposalProcedureData {
903+ {
904+ Index : 0 ,
905+ RewardAccount : otherStakeAddr ,
906+ ActionType : "Info" ,
907+ },
908+ },
909+ },
910+ }
911+
912+ err := cs .Start ()
913+ assert .NoError (t , err )
914+ defer cs .Stop ()
915+
916+ cs .InputChan () <- evt
917+
918+ select {
919+ case <- cs .OutputChan ():
920+ t .Error ("Expected event to be filtered out but it passed through" )
921+ case <- time .After (100 * time .Millisecond ):
922+ // Expected no event
923+ }
924+ })
925+
926+ t .Run ("does not match governance event with no address data" , func (t * testing.T ) {
927+ cs := New (WithAddresses ([]string {stakeAddr }))
928+
929+ evt := event.Event {
930+ Payload : event.GovernanceEvent {
931+ // Only voting procedures, no addresses
932+ VotingProcedures : []event.VotingProcedureData {
933+ {
934+ VoterType : "DRep" ,
935+ VoterHash : stakeCredHex ,
936+ Vote : "Yes" ,
937+ },
938+ },
939+ },
940+ }
941+
942+ err := cs .Start ()
943+ assert .NoError (t , err )
944+ defer cs .Stop ()
945+
946+ cs .InputChan () <- evt
947+
948+ select {
949+ case <- cs .OutputChan ():
950+ t .Error ("Expected event to be filtered out but it passed through" )
951+ case <- time .After (100 * time .Millisecond ):
952+ // Expected no event
953+ }
954+ })
955+ }
0 commit comments