@@ -761,3 +761,167 @@ async fn test_multicast_subscriber_allowlist_feed_authority_different_user_payer
761761 "Non-feed authority should fail when user_payer doesn't match"
762762 ) ;
763763}
764+
765+ /// Feed authority can remove from subscriber allowlist.
766+ #[ tokio:: test]
767+ async fn test_multicast_subscriber_allowlist_feed_authority_remove ( ) {
768+ let ( mut banks_client, program_id, payer, recent_blockhash) = init_test ( ) . await ;
769+
770+ let client_ip = [ 100 , 0 , 0 , 6 ] . into ( ) ;
771+ let user_payer = payer. pubkey ( ) ;
772+
773+ let ( program_config_pubkey, _) = get_program_config_pda ( & program_id) ;
774+ let ( globalstate_pubkey, _) = get_globalstate_pda ( & program_id) ;
775+
776+ // 1. Initialize global state
777+ execute_transaction (
778+ & mut banks_client,
779+ recent_blockhash,
780+ program_id,
781+ DoubleZeroInstruction :: InitGlobalState ( ) ,
782+ vec ! [
783+ AccountMeta :: new( program_config_pubkey, false ) ,
784+ AccountMeta :: new( globalstate_pubkey, false ) ,
785+ ] ,
786+ & payer,
787+ )
788+ . await ;
789+
790+ // 2. Create feed authority
791+ let feed = Keypair :: new ( ) ;
792+ transfer ( & mut banks_client, & payer, & feed. pubkey ( ) , 10_000_000_000 ) . await ;
793+
794+ execute_transaction (
795+ & mut banks_client,
796+ recent_blockhash,
797+ program_id,
798+ DoubleZeroInstruction :: SetAuthority ( SetAuthorityArgs {
799+ feed_authority_pk : Some ( feed. pubkey ( ) ) ,
800+ ..Default :: default ( )
801+ } ) ,
802+ vec ! [ AccountMeta :: new( globalstate_pubkey, false ) ] ,
803+ & payer,
804+ )
805+ . await ;
806+
807+ // 3. Create and activate multicast group
808+ let globalstate = get_account_data ( & mut banks_client, globalstate_pubkey)
809+ . await
810+ . expect ( "Unable to get Account" )
811+ . get_global_state ( )
812+ . unwrap ( ) ;
813+
814+ let ( multicastgroup_pubkey, _) =
815+ get_multicastgroup_pda ( & program_id, globalstate. account_index + 1 ) ;
816+
817+ execute_transaction (
818+ & mut banks_client,
819+ recent_blockhash,
820+ program_id,
821+ DoubleZeroInstruction :: CreateMulticastGroup ( MulticastGroupCreateArgs {
822+ code : "feed-remove" . to_string ( ) ,
823+ max_bandwidth : 1_000_000_000 ,
824+ owner : payer. pubkey ( ) ,
825+ use_onchain_allocation : false ,
826+ } ) ,
827+ vec ! [
828+ AccountMeta :: new( multicastgroup_pubkey, false ) ,
829+ AccountMeta :: new( globalstate_pubkey, false ) ,
830+ ] ,
831+ & payer,
832+ )
833+ . await ;
834+
835+ execute_transaction (
836+ & mut banks_client,
837+ recent_blockhash,
838+ program_id,
839+ DoubleZeroInstruction :: ActivateMulticastGroup ( MulticastGroupActivateArgs {
840+ multicast_ip : [ 224 , 254 , 0 , 6 ] . into ( ) ,
841+ } ) ,
842+ vec ! [
843+ AccountMeta :: new( multicastgroup_pubkey, false ) ,
844+ AccountMeta :: new( globalstate_pubkey, false ) ,
845+ ] ,
846+ & payer,
847+ )
848+ . await ;
849+
850+ // 4. Payer creates access pass and adds allowlist entry
851+ let ( accesspass_pubkey, _) = get_accesspass_pda ( & program_id, & client_ip, & user_payer) ;
852+
853+ execute_transaction (
854+ & mut banks_client,
855+ recent_blockhash,
856+ program_id,
857+ DoubleZeroInstruction :: SetAccessPass ( SetAccessPassArgs {
858+ accesspass_type : AccessPassType :: Prepaid ,
859+ client_ip,
860+ last_access_epoch : 100 ,
861+ allow_multiple_ip : false ,
862+ } ) ,
863+ vec ! [
864+ AccountMeta :: new( accesspass_pubkey, false ) ,
865+ AccountMeta :: new( globalstate_pubkey, false ) ,
866+ AccountMeta :: new( user_payer, false ) ,
867+ ] ,
868+ & payer,
869+ )
870+ . await ;
871+
872+ execute_transaction (
873+ & mut banks_client,
874+ recent_blockhash,
875+ program_id,
876+ DoubleZeroInstruction :: AddMulticastGroupSubAllowlist ( AddMulticastGroupSubAllowlistArgs {
877+ client_ip,
878+ user_payer,
879+ } ) ,
880+ vec ! [
881+ AccountMeta :: new( multicastgroup_pubkey, false ) ,
882+ AccountMeta :: new( accesspass_pubkey, false ) ,
883+ AccountMeta :: new( globalstate_pubkey, false ) ,
884+ ] ,
885+ & payer,
886+ )
887+ . await ;
888+
889+ let accesspass = get_account_data ( & mut banks_client, accesspass_pubkey)
890+ . await
891+ . expect ( "Unable to get Account" )
892+ . get_accesspass ( )
893+ . unwrap ( ) ;
894+ assert_eq ! ( accesspass. mgroup_sub_allowlist. len( ) , 1 ) ;
895+
896+ // 5. Feed authority removes subscriber allowlist entry — should succeed
897+ let recent_blockhash = banks_client. get_latest_blockhash ( ) . await . unwrap ( ) ;
898+ let res = try_execute_transaction (
899+ & mut banks_client,
900+ recent_blockhash,
901+ program_id,
902+ DoubleZeroInstruction :: RemoveMulticastGroupSubAllowlist (
903+ RemoveMulticastGroupSubAllowlistArgs {
904+ client_ip,
905+ user_payer,
906+ } ,
907+ ) ,
908+ vec ! [
909+ AccountMeta :: new( multicastgroup_pubkey, false ) ,
910+ AccountMeta :: new( accesspass_pubkey, false ) ,
911+ AccountMeta :: new( globalstate_pubkey, false ) ,
912+ ] ,
913+ & feed,
914+ )
915+ . await ;
916+ assert ! (
917+ res. is_ok( ) ,
918+ "Feed authority should be able to remove from subscriber allowlist"
919+ ) ;
920+
921+ let accesspass = get_account_data ( & mut banks_client, accesspass_pubkey)
922+ . await
923+ . expect ( "Unable to get Account" )
924+ . get_accesspass ( )
925+ . unwrap ( ) ;
926+ assert_eq ! ( accesspass. mgroup_sub_allowlist. len( ) , 0 ) ;
927+ }
0 commit comments