@@ -8,6 +8,7 @@ mod mcp_setup;
88mod process;
99mod profile;
1010mod proxy;
11+ mod psapi;
1112mod runtime;
1213mod settings;
1314mod store;
@@ -850,6 +851,230 @@ fn api_regenerate_token() -> Result<Value, String> {
850851 } ) )
851852}
852853
854+ // ---- ProxyShard billing API ----
855+
856+ /// Saved billing-API key (empty string when unset).
857+ #[ tauri:: command]
858+ fn ps_get_key ( ) -> Result < String , String > {
859+ psapi:: get_key ( ) . map_err ( |e| e. to_string ( ) )
860+ }
861+
862+ #[ tauri:: command]
863+ fn ps_set_key ( key : String ) -> Result < ( ) , String > {
864+ psapi:: set_key ( key) . map_err ( |e| e. to_string ( ) )
865+ }
866+
867+ /// Account profile (email, active_orders, wallet_balance cents) — also acts
868+ /// as the "is the key valid?" probe.
869+ #[ tauri:: command]
870+ async fn ps_me ( ) -> Result < Value , String > {
871+ psapi:: call ( "GET" , "/user/api/me" , & [ ] , None )
872+ . await
873+ . map_err ( |e| e. to_string ( ) )
874+ }
875+
876+ #[ tauri:: command]
877+ async fn ps_orders ( status : String , offset : Option < i64 > , limit : Option < i64 > ) -> Result < Value , String > {
878+ let mut q = vec ! [ ( "status" . to_string( ) , status) ] ;
879+ if let Some ( o) = offset {
880+ q. push ( ( "offset" . into ( ) , o. to_string ( ) ) ) ;
881+ }
882+ if let Some ( l) = limit {
883+ q. push ( ( "limit" . into ( ) , l. to_string ( ) ) ) ;
884+ }
885+ psapi:: call ( "GET" , "/user/api/orders" , & q, None )
886+ . await
887+ . map_err ( |e| e. to_string ( ) )
888+ }
889+
890+ #[ tauri:: command]
891+ async fn ps_order ( id : i64 ) -> Result < Value , String > {
892+ psapi:: call ( "GET" , & format ! ( "/user/api/orders/{id}" ) , & [ ] , None )
893+ . await
894+ . map_err ( |e| e. to_string ( ) )
895+ }
896+
897+ #[ tauri:: command]
898+ async fn ps_active ( order_id : i64 ) -> Result < Value , String > {
899+ psapi:: call (
900+ "GET" ,
901+ "/user/api/proxies/active" ,
902+ & [ ( "order_id" . into ( ) , order_id. to_string ( ) ) ] ,
903+ None ,
904+ )
905+ . await
906+ . map_err ( |e| e. to_string ( ) )
907+ }
908+
909+ /// Pull an order's active proxies into the local proxy list. Returns count added.
910+ #[ tauri:: command]
911+ async fn ps_import_order ( order_id : i64 , kind : String ) -> Result < usize , String > {
912+ psapi:: import_order_proxies ( order_id, kind)
913+ . await
914+ . map_err ( |e| e. to_string ( ) )
915+ }
916+
917+ #[ tauri:: command]
918+ async fn ps_products ( ) -> Result < Value , String > {
919+ psapi:: call ( "GET" , "/user/api/proxies/products" , & [ ] , None )
920+ . await
921+ . map_err ( |e| e. to_string ( ) )
922+ }
923+
924+ #[ tauri:: command]
925+ async fn ps_available_count ( ) -> Result < Value , String > {
926+ psapi:: call ( "GET" , "/user/api/proxies/available-count" , & [ ] , None )
927+ . await
928+ . map_err ( |e| e. to_string ( ) )
929+ }
930+
931+ #[ tauri:: command]
932+ async fn ps_calculate (
933+ product : String ,
934+ location : Option < String > ,
935+ cycle : Option < String > ,
936+ quantity : Option < i64 > ,
937+ promo_code : Option < String > ,
938+ addons_json : Option < String > ,
939+ ) -> Result < Value , String > {
940+ let mut q = vec ! [ ( "product" . to_string( ) , product) ] ;
941+ if let Some ( v) = location. filter ( |s| !s. is_empty ( ) ) {
942+ q. push ( ( "location" . into ( ) , v) ) ;
943+ }
944+ if let Some ( v) = cycle. filter ( |s| !s. is_empty ( ) ) {
945+ q. push ( ( "cycle" . into ( ) , v) ) ;
946+ }
947+ if let Some ( v) = quantity {
948+ q. push ( ( "quantity" . into ( ) , v. to_string ( ) ) ) ;
949+ }
950+ if let Some ( v) = promo_code. filter ( |s| !s. is_empty ( ) ) {
951+ q. push ( ( "promo_code" . into ( ) , v) ) ;
952+ }
953+ // JSON array of add-ons, e.g. [{"addon_key":"p0f_slots","qty":5}].
954+ // reqwest URL-encodes the value.
955+ if let Some ( v) = addons_json. filter ( |s| !s. is_empty ( ) ) {
956+ q. push ( ( "addons_json" . into ( ) , v) ) ;
957+ }
958+ psapi:: call ( "GET" , "/user/api/orders/calculate" , & q, None )
959+ . await
960+ . map_err ( |e| e. to_string ( ) )
961+ }
962+
963+ #[ tauri:: command]
964+ async fn ps_purchase ( body : Value ) -> Result < Value , String > {
965+ psapi:: call ( "POST" , "/user/api/orders/purchase" , & [ ] , Some ( body) )
966+ . await
967+ . map_err ( |e| e. to_string ( ) )
968+ }
969+
970+ /// Buy extra GB of residential traffic for an order.
971+ #[ tauri:: command]
972+ async fn ps_add_bandwidth ( id : i64 , amount : i64 , promo_code : Option < String > ) -> Result < Value , String > {
973+ let mut body = serde_json:: json!( { "amount" : amount } ) ;
974+ if let Some ( p) = promo_code. filter ( |s| !s. is_empty ( ) ) {
975+ body[ "promo_code" ] = Value :: String ( p) ;
976+ }
977+ psapi:: call (
978+ "POST" ,
979+ & format ! ( "/user/api/orders/{id}/add-bandwidth" ) ,
980+ & [ ] ,
981+ Some ( body) ,
982+ )
983+ . await
984+ . map_err ( |e| e. to_string ( ) )
985+ }
986+
987+ /// Account-owner traffic for a residential proxy type ("standart" | "premium").
988+ #[ tauri:: command]
989+ async fn ps_profile_traffic ( proxy_type : String ) -> Result < Value , String > {
990+ psapi:: call (
991+ "GET" ,
992+ "/user/api/proxies/profile" ,
993+ & [ ( "proxy_type" . into ( ) , proxy_type) ] ,
994+ None ,
995+ )
996+ . await
997+ . map_err ( |e| e. to_string ( ) )
998+ }
999+
1000+ #[ tauri:: command]
1001+ async fn ps_renew ( id : i64 ) -> Result < Value , String > {
1002+ psapi:: call ( "POST" , & format ! ( "/user/api/orders/{id}/renew" ) , & [ ] , None )
1003+ . await
1004+ . map_err ( |e| e. to_string ( ) )
1005+ }
1006+
1007+ /// Residential location reference data (for the proxy generator).
1008+ #[ tauri:: command]
1009+ async fn ps_countries ( proxy_type : String ) -> Result < Value , String > {
1010+ psapi:: call (
1011+ "GET" ,
1012+ "/user/api/proxies/countries" ,
1013+ & [ ( "proxy_type" . into ( ) , proxy_type) ] ,
1014+ None ,
1015+ )
1016+ . await
1017+ . map_err ( |e| e. to_string ( ) )
1018+ }
1019+
1020+ #[ tauri:: command]
1021+ async fn ps_regions ( proxy_type : String , country_code : String ) -> Result < Value , String > {
1022+ psapi:: call (
1023+ "GET" ,
1024+ "/user/api/proxies/regions" ,
1025+ & [
1026+ ( "proxy_type" . into ( ) , proxy_type) ,
1027+ ( "country_code" . into ( ) , country_code) ,
1028+ ] ,
1029+ None ,
1030+ )
1031+ . await
1032+ . map_err ( |e| e. to_string ( ) )
1033+ }
1034+
1035+ #[ tauri:: command]
1036+ async fn ps_cities ( proxy_type : String , country_code : String , region_code : String ) -> Result < Value , String > {
1037+ psapi:: call (
1038+ "GET" ,
1039+ "/user/api/proxies/cities" ,
1040+ & [
1041+ ( "proxy_type" . into ( ) , proxy_type) ,
1042+ ( "country_code" . into ( ) , country_code) ,
1043+ ( "region_code" . into ( ) , region_code) ,
1044+ ] ,
1045+ None ,
1046+ )
1047+ . await
1048+ . map_err ( |e| e. to_string ( ) )
1049+ }
1050+
1051+ /// Assign OS-fingerprint signatures to proxy IPs (consumes p0f slots).
1052+ /// `items` is an array of `{ ip, signature }`.
1053+ #[ tauri:: command]
1054+ async fn ps_signature_set ( order_id : i64 , items : Value ) -> Result < Value , String > {
1055+ psapi:: call (
1056+ "POST" ,
1057+ & format ! ( "/user/api/orders/{order_id}/signature/set" ) ,
1058+ & [ ] ,
1059+ Some ( serde_json:: json!( { "items" : items } ) ) ,
1060+ )
1061+ . await
1062+ . map_err ( |e| e. to_string ( ) )
1063+ }
1064+
1065+ /// Set/clear an order's tag.
1066+ #[ tauri:: command]
1067+ async fn ps_set_tag ( id : i64 , tag : String ) -> Result < Value , String > {
1068+ psapi:: call (
1069+ "POST" ,
1070+ & format ! ( "/user/api/orders/{id}/tag" ) ,
1071+ & [ ] ,
1072+ Some ( serde_json:: json!( { "tag" : tag } ) ) ,
1073+ )
1074+ . await
1075+ . map_err ( |e| e. to_string ( ) )
1076+ }
1077+
8531078#[ cfg_attr( mobile, tauri:: mobile_entry_point) ]
8541079pub fn run ( ) {
8551080 tauri:: Builder :: default ( )
@@ -898,6 +1123,25 @@ pub fn run() {
8981123 settings_save,
8991124 api_info,
9001125 api_regenerate_token,
1126+ ps_get_key,
1127+ ps_set_key,
1128+ ps_me,
1129+ ps_orders,
1130+ ps_order,
1131+ ps_active,
1132+ ps_import_order,
1133+ ps_products,
1134+ ps_available_count,
1135+ ps_calculate,
1136+ ps_purchase,
1137+ ps_add_bandwidth,
1138+ ps_profile_traffic,
1139+ ps_renew,
1140+ ps_set_tag,
1141+ ps_countries,
1142+ ps_regions,
1143+ ps_cities,
1144+ ps_signature_set,
9011145 cookies_export,
9021146 cookies_export_to_file,
9031147 cookies_import,
0 commit comments