@@ -8,7 +8,7 @@ use signal_hook::{
88} ;
99use solana_cli_config:: { Config , CONFIG_FILE } ;
1010use solana_client:: rpc_client:: RpcClient ;
11- use solana_program:: get_all_pdas_available;
11+ use solana_program:: { get_all_pdas_available, get_program_pda , resolve_rpc_url , OtterBuildParams } ;
1212use solana_sdk:: {
1313 bpf_loader_upgradeable:: { self , UpgradeableLoaderState } ,
1414 pubkey:: Pubkey ,
@@ -196,14 +196,29 @@ async fn main() -> anyhow::Result<()> {
196196 . takes_value ( true )
197197 . help ( "The address of the program to close the PDA" ) ) )
198198 . subcommand ( SubCommand :: with_name ( "list-program-pdas" )
199- . about ( "List all the PDA information associated with a program ID" )
199+ . about ( "List all the PDA information associated with a program ID. Requires custom RPC endpoint" )
200+ . arg ( Arg :: with_name ( "program-id" )
201+ . long ( "program-id" )
202+ . required ( true )
203+ . takes_value ( true ) ) )
204+ . subcommand ( SubCommand :: with_name ( "get-program-pda" )
205+ . about ( "Get uploaded PDA information for a given program ID and signer" )
200206 . arg ( Arg :: with_name ( "program-id" )
201207 . long ( "program-id" )
202208 . required ( true )
203209 . takes_value ( true )
204- . help ( "Program ID of the program to list PDAs for" ) ) )
210+ )
211+ . arg ( Arg :: with_name ( "signer" )
212+ . short ( "s" )
213+ . long ( "signer" )
214+ . required ( false )
215+ . takes_value ( true )
216+ . help ( "Signer to get the PDA for" )
217+ )
218+ )
205219 . get_matches ( ) ;
206220
221+ let connection = resolve_rpc_url ( matches. value_of ( "url" ) . map ( |s| s. to_string ( ) ) ) ?;
207222 let res = match matches. subcommand ( ) {
208223 ( "build" , Some ( sub_m) ) => {
209224 let mount_directory = sub_m. value_of ( "mount-directory" ) . map ( |s| s. to_string ( ) ) ;
@@ -256,10 +271,7 @@ async fn main() -> anyhow::Result<()> {
256271 }
257272 ( "get-program-hash" , Some ( sub_m) ) => {
258273 let program_id = sub_m. value_of ( "program-id" ) . unwrap ( ) ;
259- let program_hash = get_program_hash (
260- matches. value_of ( "url" ) . map ( |s| s. to_string ( ) ) ,
261- Pubkey :: try_from ( program_id) ?,
262- ) ?;
274+ let program_hash = get_program_hash ( & connection, Pubkey :: try_from ( program_id) ?) ?;
263275 println ! ( "{}" , program_hash) ;
264276 Ok ( ( ) )
265277 }
@@ -285,7 +297,7 @@ async fn main() -> anyhow::Result<()> {
285297 verify_from_repo (
286298 remote,
287299 mount_path,
288- matches . value_of ( "url" ) . map ( |s| s . to_string ( ) ) ,
300+ & connection ,
289301 repo_url,
290302 commit_hash,
291303 Pubkey :: try_from ( program_id) ?,
@@ -303,12 +315,16 @@ async fn main() -> anyhow::Result<()> {
303315 }
304316 ( "close" , Some ( sub_m) ) => {
305317 let program_id = sub_m. value_of ( "program-id" ) . unwrap ( ) ;
306- process_close ( Pubkey :: try_from ( program_id) ?) . await
318+ process_close ( Pubkey :: try_from ( program_id) ?, & connection ) . await
307319 }
308320 ( "list-program-pdas" , Some ( sub_m) ) => {
309321 let program_id = sub_m. value_of ( "program-id" ) . unwrap ( ) ;
310- let url = matches. value_of ( "url" ) . map ( |s| s. to_string ( ) ) ;
311- list_program_pdas ( Pubkey :: try_from ( program_id) ?, url) . await
322+ list_program_pdas ( Pubkey :: try_from ( program_id) ?, & connection) . await
323+ }
324+ ( "get-program-pda" , Some ( sub_m) ) => {
325+ let program_id = sub_m. value_of ( "program-id" ) . unwrap ( ) ;
326+ let signer = sub_m. value_of ( "signer" ) . map ( |s| s. to_string ( ) ) ;
327+ print_program_pda ( Pubkey :: try_from ( program_id) ?, signer, & connection) . await
312328 }
313329 // Handle other subcommands in a similar manner, for now let's panic
314330 _ => panic ! (
@@ -387,8 +403,7 @@ pub fn get_buffer_hash(url: Option<String>, buffer_address: Pubkey) -> anyhow::R
387403 Ok ( program_hash)
388404}
389405
390- pub fn get_program_hash ( url : Option < String > , program_id : Pubkey ) -> anyhow:: Result < String > {
391- let client = get_client ( url) ;
406+ pub fn get_program_hash ( client : & RpcClient , program_id : Pubkey ) -> anyhow:: Result < String > {
392407 let program_buffer =
393408 Pubkey :: find_program_address ( & [ program_id. as_ref ( ) ] , & bpf_loader_upgradeable:: id ( ) ) . 0 ;
394409 let offset = UpgradeableLoaderState :: size_of_programdata_metadata ( ) ;
@@ -397,8 +412,7 @@ pub fn get_program_hash(url: Option<String>, program_id: Pubkey) -> anyhow::Resu
397412 Ok ( program_hash)
398413}
399414
400- pub fn get_genesis_hash ( url : Option < String > ) -> anyhow:: Result < String > {
401- let client = get_client ( url) ;
415+ pub fn get_genesis_hash ( client : & RpcClient ) -> anyhow:: Result < String > {
402416 let genesis_hash = client. get_genesis_hash ( ) ?;
403417 Ok ( genesis_hash. to_string ( ) )
404418}
@@ -741,7 +755,7 @@ pub fn verify_from_image(
741755pub async fn verify_from_repo (
742756 remote : bool ,
743757 relative_mount_path : String ,
744- connection_url : Option < String > ,
758+ connection : & RpcClient ,
745759 repo_url : String ,
746760 commit_hash : Option < String > ,
747761 program_id : Pubkey ,
@@ -756,7 +770,7 @@ pub async fn verify_from_repo(
756770 temp_dir_opt : & mut Option < String > ,
757771) -> anyhow:: Result < ( ) > {
758772 if remote {
759- let genesis_hash = get_genesis_hash ( connection_url . clone ( ) ) ?;
773+ let genesis_hash = get_genesis_hash ( connection ) ?;
760774 if genesis_hash != MAINNET_GENESIS_HASH {
761775 return Err ( anyhow ! ( "Remote verification only works with mainnet. Please omit the --remote flag to verify locally." ) ) ;
762776 }
@@ -849,7 +863,7 @@ pub async fn verify_from_repo(
849863 & commit_hash. clone ( ) ,
850864 args. iter ( ) . map ( |& s| s. into ( ) ) . collect ( ) ,
851865 program_id,
852- connection_url ,
866+ connection ,
853867 skip_prompt,
854868 path_to_keypair,
855869 )
@@ -987,7 +1001,7 @@ pub async fn verify_from_repo(
9871001 base_image. clone ( ) ,
9881002 bpf_flag,
9891003 library_name. clone ( ) ,
990- connection_url . clone ( ) ,
1004+ connection ,
9911005 program_id,
9921006 cargo_args. clone ( ) ,
9931007 container_id_opt,
@@ -1010,7 +1024,7 @@ pub async fn verify_from_repo(
10101024 & commit_hash. clone ( ) ,
10111025 args. iter ( ) . map ( |& s| s. into ( ) ) . collect ( ) ,
10121026 program_id,
1013- connection_url ,
1027+ connection ,
10141028 skip_prompt,
10151029 path_to_keypair,
10161030 )
@@ -1035,7 +1049,7 @@ pub fn build_and_verify_repo(
10351049 base_image : Option < String > ,
10361050 bpf_flag : bool ,
10371051 library_name : String ,
1038- connection_url : Option < String > ,
1052+ connection : & RpcClient ,
10391053 program_id : Pubkey ,
10401054 cargo_args : Vec < String > ,
10411055 container_id_opt : & mut Option < String > ,
@@ -1069,7 +1083,7 @@ pub fn build_and_verify_repo(
10691083 "Fetching on-chain program data for program ID: {}" ,
10701084 program_id,
10711085 ) ;
1072- let program_hash = get_program_hash ( connection_url , program_id) ?;
1086+ let program_hash = get_program_hash ( connection , program_id) ?;
10731087
10741088 Ok ( ( build_hash, program_hash) )
10751089}
@@ -1122,14 +1136,27 @@ pub fn get_pkg_name_from_cargo_toml(cargo_toml_file: &str) -> Option<String> {
11221136 Some ( pkg. name )
11231137}
11241138
1125- pub async fn list_program_pdas ( program_id : Pubkey , url : Option < String > ) -> anyhow:: Result < ( ) > {
1126- let client = get_client ( url) ;
1139+ pub fn print_build_params ( pubkey : & Pubkey , build_params : & OtterBuildParams ) {
1140+ println ! ( "----------------------------------------------------------------" ) ;
1141+ println ! ( "Address: {:?}" , pubkey) ;
1142+ println ! ( "----------------------------------------------------------------" ) ;
1143+ println ! ( "{}" , build_params) ;
1144+ }
1145+
1146+ pub async fn list_program_pdas ( program_id : Pubkey , client : & RpcClient ) -> anyhow:: Result < ( ) > {
11271147 let pdas = get_all_pdas_available ( & client, & program_id) . await ?;
11281148 for ( pda, build_params) in pdas {
1129- println ! ( "----------------------------------------------------------------" ) ;
1130- println ! ( "PDA: {:?}" , pda) ;
1131- println ! ( "----------------------------------------------------------------" ) ;
1132- println ! ( "{}" , build_params) ;
1149+ print_build_params ( & pda, & build_params) ;
11331150 }
11341151 Ok ( ( ) )
11351152}
1153+
1154+ pub async fn print_program_pda (
1155+ program_id : Pubkey ,
1156+ signer : Option < String > ,
1157+ client : & RpcClient ,
1158+ ) -> anyhow:: Result < ( ) > {
1159+ let ( pda, build_params) = get_program_pda ( & client, & program_id, signer) . await ?;
1160+ print_build_params ( & pda, & build_params) ;
1161+ Ok ( ( ) )
1162+ }
0 commit comments