1
+ use std:: error:: Error ;
2
+ use std:: io:: { BufRead , Write } ;
3
+ use std:: str:: FromStr ;
4
+
5
+ use poc_framework:: solana_sdk:: instruction:: { AccountMeta , Instruction } ;
6
+ use poc_framework:: solana_sdk:: signature:: Keypair ;
7
+ use poc_framework:: { Environment , LocalEnvironment , solana_sdk:: pubkey:: Pubkey , solana_transaction_status:: EncodedConfirmedTransaction } ;
8
+ use tempfile:: NamedTempFile ;
9
+ pub struct Challenge < R : BufRead , W : Write > {
10
+ input : R ,
11
+ output : W ,
12
+ pub env : LocalEnvironment
13
+ }
14
+
15
+ impl < R : BufRead , W : Write > Challenge < R , W > {
16
+ pub fn new ( input : R , output : W ) -> Challenge < R , W > {
17
+ let env = LocalEnvironment :: builder ( ) . build ( ) ;
18
+ Challenge {
19
+ input,
20
+ output,
21
+ env,
22
+ }
23
+ }
24
+
25
+ /// Reads program from input and deploys on environment
26
+ pub fn input_program ( & mut self ) -> Result < Pubkey , Box < dyn Error > > {
27
+ let mut line = String :: new ( ) ;
28
+ writeln ! ( self . output, "program len: " ) ?;
29
+ self . input . read_line ( & mut line) ?;
30
+ let len: usize = line. trim ( ) . parse ( ) ?;
31
+
32
+ let mut input_so = vec ! [ 0 ; len] ;
33
+ self . input . read_exact ( & mut input_so) ?;
34
+
35
+ let mut input_file = NamedTempFile :: new ( ) ?;
36
+ input_file. write_all ( & input_so) ?;
37
+
38
+ let program_address = self . env . deploy_program ( input_file. path ( ) ) ;
39
+ Ok ( program_address)
40
+ }
41
+
42
+ /// Reads instruction accounts/data from input and sends in transaction to specified program
43
+ ///
44
+ /// # Account Format:
45
+ /// `[meta] [pubkey]`
46
+ ///
47
+ /// `[meta]` - contains "s" if account is a signer, "w" if it is writable
48
+ /// `[pubkey]` - the address of the account
49
+ pub fn input_instruction ( & mut self , program_id : Pubkey , signers : & [ & Keypair ] ) -> Result < EncodedConfirmedTransaction , Box < dyn Error > > {
50
+ let mut line = String :: new ( ) ;
51
+ writeln ! ( self . output, "num accounts: " ) ?;
52
+ self . input . read_line ( & mut line) ?;
53
+ let num_accounts: usize = line. trim ( ) . parse ( ) ?;
54
+
55
+ let mut metas = vec ! [ ] ;
56
+ for _ in 0 ..num_accounts {
57
+ line. clear ( ) ;
58
+ self . input . read_line ( & mut line) ?;
59
+
60
+ let mut it = line. trim ( ) . split ( ' ' ) ;
61
+ let meta = it. next ( ) . ok_or ( "bad meta" ) ?;
62
+ let pubkey = it. next ( ) . ok_or ( "bad pubkey" ) ?;
63
+ let pubkey = Pubkey :: from_str ( pubkey) ?;
64
+
65
+ let is_signer = meta. contains ( 's' ) ;
66
+ let is_writable = meta. contains ( 'w' ) ;
67
+
68
+ if is_writable {
69
+ metas. push ( AccountMeta :: new ( pubkey, is_signer) ) ;
70
+ } else {
71
+ metas. push ( AccountMeta :: new_readonly ( pubkey, is_signer) ) ;
72
+ }
73
+ }
74
+
75
+ line. clear ( ) ;
76
+ writeln ! ( self . output, "ix len" ) ?;
77
+ self . input . read_line ( & mut line) ?;
78
+ let ix_data_len: usize = line. trim ( ) . parse ( ) ?;
79
+ let mut ix_data = vec ! [ 0 ; ix_data_len] ;
80
+
81
+ self . input . read_exact ( & mut ix_data) ?;
82
+
83
+ let ix = Instruction :: new_with_bytes (
84
+ program_id,
85
+ & ix_data,
86
+ metas
87
+ ) ;
88
+
89
+ Ok ( self . env . execute_as_transaction ( & [ ix] , signers) )
90
+ }
91
+ }
0 commit comments