1717 relayer_stage:: { RelayerConfig , RelayerStage } ,
1818 } ,
1919 repair:: repair_service,
20+ tip_manager:: TipManager ,
2021 validator:: ValidatorStartProgress ,
2122 } ,
2223 solana_geyser_plugin_manager:: GeyserPluginManagerRequest ,
3637 str:: FromStr ,
3738 sync:: {
3839 atomic:: { AtomicBool , Ordering } ,
39- Arc , RwLock ,
40+ Arc , RwLock , Mutex ,
4041 } ,
4142 thread:: { self , Builder } ,
4243 time:: { Duration , SystemTime } ,
@@ -56,6 +57,7 @@ pub struct AdminRpcRequestMetadata {
5657 pub staked_nodes_overrides : Arc < RwLock < HashMap < Pubkey , u64 > > > ,
5758 pub post_init : Arc < RwLock < Option < AdminRpcRequestMetadataPostInit > > > ,
5859 pub rpc_to_plugin_manager_sender : Option < Sender < GeyserPluginManagerRequest > > ,
60+ pub tip_manager : Arc < Mutex < TipManager > > ,
5961}
6062
6163impl Metadata for AdminRpcRequestMetadata { }
@@ -292,6 +294,12 @@ pub trait AdminRpc {
292294 meta : Self :: Metadata ,
293295 addr : String ,
294296 ) -> Result < ( ) > ;
297+
298+ #[ rpc( meta, name = "getMevCommission" ) ]
299+ fn get_mev_commission ( & self , meta : Self :: Metadata ) -> Result < u16 > ;
300+
301+ #[ rpc( meta, name = "setMevCommission" ) ]
302+ fn set_mev_commission ( & self , meta : Self :: Metadata , commission_bps : u16 ) -> Result < ( ) > ;
295303}
296304
297305pub struct AdminRpcImpl ;
@@ -871,6 +879,26 @@ impl AdminRpc for AdminRpcImpl {
871879 Ok ( ( ) )
872880 } )
873881 }
882+
883+ fn get_mev_commission ( & self , meta : Self :: Metadata ) -> Result < u16 > {
884+ debug ! ( "get_mev_commission request received" ) ;
885+ let tip_manager = meta. tip_manager . lock ( ) . unwrap ( ) ;
886+ Ok ( tip_manager. get_commission_bps ( ) )
887+ }
888+
889+ fn set_mev_commission ( & self , meta : Self :: Metadata , commission_bps : u16 ) -> Result < ( ) > {
890+ debug ! ( "set_mev_commission request received" ) ;
891+
892+ if commission_bps > 10000 {
893+ return Err ( jsonrpc_core:: error:: Error :: invalid_params (
894+ "Commission bps cannot be larger than 100%" ,
895+ ) )
896+ }
897+
898+ let mut tip_manager = meta. tip_manager . lock ( ) . unwrap ( ) ;
899+ tip_manager. set_commission_bps ( commission_bps) ;
900+ Ok ( ( ) )
901+ }
874902}
875903
876904impl AdminRpcImpl {
@@ -1070,6 +1098,7 @@ mod tests {
10701098 solana_core:: {
10711099 admin_rpc_post_init:: { KeyUpdaterType , KeyUpdaters } ,
10721100 consensus:: tower_storage:: NullTowerStorage ,
1101+ tip_manager:: TipManagerConfig ,
10731102 validator:: { Validator , ValidatorConfig , ValidatorTpuConfig } ,
10741103 } ,
10751104 solana_gossip:: { cluster_info:: ClusterInfo , node:: Node } ,
@@ -1144,6 +1173,7 @@ mod tests {
11441173 let relayer_config = Arc :: new ( Mutex :: new ( RelayerConfig :: default ( ) ) ) ;
11451174 let shred_receiver_address = Arc :: new ( ArcSwap :: default ( ) ) ;
11461175 let shred_retransmit_receiver_address = Arc :: new ( ArcSwap :: default ( ) ) ;
1176+ let shared_tip_manager = Arc :: new ( Mutex :: new ( TipManager :: new ( TipManagerConfig :: default ( ) ) ) ) ;
11471177 let meta = AdminRpcRequestMetadata {
11481178 rpc_addr : None ,
11491179 start_time : SystemTime :: now ( ) ,
@@ -1170,9 +1200,11 @@ mod tests {
11701200 relayer_config,
11711201 shred_receiver_address,
11721202 shred_retransmit_receiver_address,
1203+ tip_manager : shared_tip_manager. clone ( ) ,
11731204 } ) ) ) ,
11741205 staked_nodes_overrides : Arc :: new ( RwLock :: new ( HashMap :: new ( ) ) ) ,
11751206 rpc_to_plugin_manager_sender : None ,
1207+ tip_manager : shared_tip_manager,
11761208 } ;
11771209 let mut io = MetaIoHandler :: default ( ) ;
11781210 io. extend_with ( AdminRpcImpl . to_delegate ( ) ) ;
@@ -1593,6 +1625,7 @@ mod tests {
15931625 post_init : post_init. clone ( ) ,
15941626 staked_nodes_overrides : Arc :: new ( RwLock :: new ( HashMap :: new ( ) ) ) ,
15951627 rpc_to_plugin_manager_sender : None ,
1628+ tip_manager : Arc :: new ( Mutex :: new ( TipManager :: new ( TipManagerConfig :: default ( ) ) ) ) ,
15961629 } ;
15971630
15981631 let _validator = Validator :: new (
@@ -1699,4 +1732,105 @@ mod tests {
16991732 . expect ( "actual response deserialization" ) ;
17001733 assert_eq ! ( actual_parsed_response, expected_parsed_response) ;
17011734 }
1735+
1736+ #[ test]
1737+ fn test_get_mev_commission ( ) {
1738+ let test_validator = TestValidatorWithAdminRpc :: new ( ) ;
1739+
1740+ // Test getting initial commission (should be 0 by default)
1741+ let request = r#"{"jsonrpc":"2.0","id":1,"method":"getMevCommission","params":[]}"# ;
1742+ let response = test_validator. handle_request ( & request) ;
1743+ let parsed_response: Value = serde_json:: from_str ( & response. expect ( "response" ) ) . expect ( "parse" ) ;
1744+
1745+ // Should return 0 (default commission)
1746+ assert_eq ! ( parsed_response[ "result" ] , 0 ) ;
1747+ assert_eq ! ( parsed_response[ "id" ] , 1 ) ;
1748+ }
1749+
1750+ #[ test]
1751+ fn test_set_mev_commission_valid ( ) {
1752+ let test_validator = TestValidatorWithAdminRpc :: new ( ) ;
1753+
1754+ // Test setting valid commission (50% = 5000 bps)
1755+ let request = r#"{"jsonrpc":"2.0","id":1,"method":"setMevCommission","params":[5000]}"# ;
1756+ let response = test_validator. handle_request ( & request) ;
1757+ let parsed_response: Value = serde_json:: from_str ( & response. expect ( "response" ) ) . expect ( "parse" ) ;
1758+
1759+ // Should succeed
1760+ assert_eq ! ( parsed_response[ "result" ] , Value :: Null ) ;
1761+ assert_eq ! ( parsed_response[ "id" ] , 1 ) ;
1762+
1763+ // Verify the commission was actually set by getting it
1764+ let get_request = r#"{"jsonrpc":"2.0","id":2,"method":"getMevCommission","params":[]}"# ;
1765+ let get_response = test_validator. handle_request ( & get_request) ;
1766+ let get_parsed: Value = serde_json:: from_str ( & get_response. expect ( "response" ) ) . expect ( "parse" ) ;
1767+
1768+ assert_eq ! ( get_parsed[ "result" ] , 5000 ) ;
1769+ }
1770+
1771+ #[ test]
1772+ fn test_set_mev_commission_max_valid ( ) {
1773+ let test_validator = TestValidatorWithAdminRpc :: new ( ) ;
1774+
1775+ // Test setting maximum valid commission (100% = 10000 bps)
1776+ let request = r#"{"jsonrpc":"2.0","id":1,"method":"setMevCommission","params":[10000]}"# ;
1777+ let response = test_validator. handle_request ( & request) ;
1778+ let parsed_response: Value = serde_json:: from_str ( & response. expect ( "response" ) ) . expect ( "parse" ) ;
1779+
1780+ // Should succeed
1781+ assert_eq ! ( parsed_response[ "result" ] , Value :: Null ) ;
1782+
1783+ // Verify it was set
1784+ let get_request = r#"{"jsonrpc":"2.0","id":2,"method":"getMevCommission","params":[]}"# ;
1785+ let get_response = test_validator. handle_request ( & get_request) ;
1786+ let get_parsed: Value = serde_json:: from_str ( & get_response. expect ( "response" ) ) . expect ( "parse" ) ;
1787+
1788+ assert_eq ! ( get_parsed[ "result" ] , 10000 ) ;
1789+ }
1790+
1791+ #[ test]
1792+ fn test_set_mev_commission_invalid_too_high ( ) {
1793+ let test_validator = TestValidatorWithAdminRpc :: new ( ) ;
1794+
1795+ // Test setting invalid commission (>100% = >10000 bps)
1796+ let request = r#"{"jsonrpc":"2.0","id":1,"method":"setMevCommission","params":[10001]}"# ;
1797+ let response = test_validator. handle_request ( & request) ;
1798+ let parsed_response: Value = serde_json:: from_str ( & response. expect ( "response" ) ) . expect ( "parse" ) ;
1799+
1800+ // Should return error
1801+ assert ! ( parsed_response[ "error" ] . is_object( ) ) ;
1802+ assert_eq ! ( parsed_response[ "error" ] [ "code" ] , -32602 ) ; // Invalid params error code
1803+ assert ! ( parsed_response[ "error" ] [ "message" ] . as_str( ) . unwrap( ) . contains( "Commission bps cannot be larger than 100%" ) ) ;
1804+
1805+ // Verify commission wasn't changed (should still be 0)
1806+ let get_request = r#"{"jsonrpc":"2.0","id":2,"method":"getMevCommission","params":[]}"# ;
1807+ let get_response = test_validator. handle_request ( & get_request) ;
1808+ let get_parsed: Value = serde_json:: from_str ( & get_response. expect ( "response" ) ) . expect ( "parse" ) ;
1809+
1810+ assert_eq ! ( get_parsed[ "result" ] , 0 ) ;
1811+ }
1812+
1813+ #[ test]
1814+ fn test_set_mev_commission_zero ( ) {
1815+ let test_validator = TestValidatorWithAdminRpc :: new ( ) ;
1816+
1817+ // First set to non-zero
1818+ let set_request = r#"{"jsonrpc":"2.0","id":1,"method":"setMevCommission","params":[2500]}"# ;
1819+ test_validator. handle_request ( & set_request) ;
1820+
1821+ // Then set back to zero
1822+ let zero_request = r#"{"jsonrpc":"2.0","id":2,"method":"setMevCommission","params":[0]}"# ;
1823+ let response = test_validator. handle_request ( & zero_request) ;
1824+ let parsed_response: Value = serde_json:: from_str ( & response. expect ( "response" ) ) . expect ( "parse" ) ;
1825+
1826+ // Should succeed
1827+ assert_eq ! ( parsed_response[ "result" ] , Value :: Null ) ;
1828+
1829+ // Verify it was set to zero
1830+ let get_request = r#"{"jsonrpc":"2.0","id":3,"method":"getMevCommission","params":[]}"# ;
1831+ let get_response = test_validator. handle_request ( & get_request) ;
1832+ let get_parsed: Value = serde_json:: from_str ( & get_response. expect ( "response" ) ) . expect ( "parse" ) ;
1833+
1834+ assert_eq ! ( get_parsed[ "result" ] , 0 ) ;
1835+ }
17021836}
0 commit comments