11use std:: mem:: size_of;
22use anchor_lang:: prelude:: * ;
33use solana_program:: account_info:: AccountInfo ;
4- use pyth_sdk_solana:: load_price_feed_from_account_info;
54
6- declare_id ! ( "9azQ2ePzPvMPQgHric53kdSNmwjVM5KijDE4ANFCE9D4" ) ;
5+ pub mod state;
6+ use state:: PriceFeed ;
7+ use state:: AdminConfig ;
78
8- #[ account]
9- pub struct AdminConfig {
10- pub loan_price_feed_id : Pubkey ,
11- pub collateral_price_feed_id : Pubkey ,
12- }
9+ mod error;
10+ use error:: ErrorCode ;
11+
12+ declare_id ! ( "BZh3CP454Ca1C9yBp2tpGAkXoKFti9x8ShJLSxNDpoxa" ) ;
1313
1414#[ derive( Accounts ) ]
1515pub struct InitRequest < ' info > {
@@ -25,12 +25,10 @@ pub struct InitRequest<'info> {
2525#[ derive( Accounts ) ]
2626pub struct QueryRequest < ' info > {
2727 pub config : Account < ' info , AdminConfig > ,
28- /// CHECK: Pyth structs don't seem to support Anchor deserialization
2928 #[ account( address = config. loan_price_feed_id @ ErrorCode :: InvalidArgument ) ]
30- pub pyth_loan_account : AccountInfo < ' info > ,
31- /// CHECK: Pyth structs don't seem to support Anchor deserialization
29+ pub pyth_loan_account : Account < ' info , PriceFeed > ,
3230 #[ account( address = config. collateral_price_feed_id @ ErrorCode :: InvalidArgument ) ]
33- pub pyth_collateral_account : AccountInfo < ' info > ,
31+ pub pyth_collateral_account : Account < ' info , PriceFeed > ,
3432}
3533
3634#[ program]
@@ -46,66 +44,63 @@ pub mod example_sol_anchor_contract {
4644 msg ! ( "Loan quantity is {}." , loan_qty) ;
4745 msg ! ( "Collateral quantity is {}." , collateral_qty) ;
4846
49- let pyth_loan_account = & ctx. accounts . pyth_loan_account ;
50- let pyth_collateral_account = & ctx. accounts . pyth_collateral_account ;
47+
48+ let loan_feed = & ctx. accounts . pyth_loan_account ;
49+ let collateral_feed = & ctx. accounts . pyth_collateral_account ;
5150 // With high confidence, the maximum value of the loan is
5251 // (price + conf) * loan_qty * 10 ^ (expo).
5352 // Here is more explanation on confidence interval in Pyth:
5453 // https://docs.pyth.network/consume-data/best-practices
55- let feed1 = load_price_feed_from_account_info ( pyth_loan_account)
56- . map_err ( |_x| error ! ( ErrorCode :: PythError ) ) ?;
5754 let current_timestamp1 = Clock :: get ( ) ?. unix_timestamp ;
58- let result1 = feed1
55+ let loan_price = loan_feed
5956 . get_price_no_older_than ( current_timestamp1, 60 )
6057 . ok_or ( ErrorCode :: PythOffline ) ?;
61- let loan_max_price = result1
58+ let loan_max_price = loan_price
6259 . price
63- . checked_add ( result1 . conf as i64 )
60+ . checked_add ( loan_price . conf as i64 )
6461 . ok_or ( ErrorCode :: Overflow ) ?;
6562 let mut loan_max_value = loan_max_price
6663 . checked_mul ( loan_qty)
6764 . ok_or ( ErrorCode :: Overflow ) ?;
6865 msg ! (
6966 "The maximum loan value is {} * 10^({})." ,
7067 loan_max_value,
71- result1 . expo
68+ loan_price . expo
7269 ) ;
7370
7471 // With high confidence, the minimum value of the collateral is
7572 // (price - conf) * collateral_qty * 10 ^ (expo).
7673 // Here is more explanation on confidence interval in Pyth:
7774 // https://docs.pyth.network/consume-data/best-practices
78- let feed2 = load_price_feed_from_account_info ( pyth_collateral_account)
79- . map_err ( |_x| error ! ( ErrorCode :: PythError ) ) ?;
8075 let current_timestamp2 = Clock :: get ( ) ?. unix_timestamp ;
81- let result2 = feed2
76+ let collateral_price = collateral_feed
8277 . get_price_no_older_than ( current_timestamp2, 60 )
8378 . ok_or ( ErrorCode :: PythOffline ) ?;
84- let collateral_min_price = result2
79+ let collateral_min_price = collateral_price
8580 . price
86- . checked_sub ( result2 . conf as i64 )
81+ . checked_sub ( collateral_price . conf as i64 )
8782 . ok_or ( ErrorCode :: Overflow ) ?;
8883 let mut collateral_min_value = collateral_min_price
8984 . checked_mul ( collateral_qty)
9085 . ok_or ( ErrorCode :: Overflow ) ?;
9186 msg ! (
9287 "The minimum collateral value is {} * 10^({})." ,
9388 collateral_min_value,
94- result2 . expo
89+ collateral_price . expo
9590 ) ;
9691
9792 // If the loan and collateral prices use different exponent,
9893 // normalize the value.
99- if result1 . expo > result2 . expo {
94+ if loan_price . expo > collateral_price . expo {
10095 let normalize = ( 10 as i64 )
101- . checked_pow ( ( result1 . expo - result2 . expo ) as u32 )
96+ . checked_pow ( ( loan_price . expo - collateral_price . expo ) as u32 )
10297 . ok_or ( ErrorCode :: Overflow ) ?;
10398 collateral_min_value = collateral_min_value
10499 . checked_mul ( normalize)
105100 . ok_or ( ErrorCode :: Overflow ) ?;
106- } else if result1 . expo < result2 . expo {
101+ } else if loan_price . expo < collateral_price . expo {
107102 let normalize = ( 10 as i64 )
108- . checked_pow ( ( result2 . expo - result1 . expo ) as u32 )
103+ . checked_pow ( ( collateral_price . expo - loan_price . expo ) as u32 )
109104 . ok_or ( ErrorCode :: Overflow ) ?;
110105 loan_max_value = loan_max_value
111106 . checked_mul ( normalize)
@@ -121,23 +116,3 @@ pub mod example_sol_anchor_contract {
121116 }
122117 }
123118}
124-
125- #[ error_code]
126- pub enum ErrorCode {
127- #[ msg( "You are not authorized to perform this action." ) ]
128- Unauthorized ,
129- #[ msg( "The config has already been initialized." ) ]
130- ReInitialize ,
131- #[ msg( "The config has not been initialized." ) ]
132- UnInitialize ,
133- #[ msg( "Argument is invalid." ) ]
134- InvalidArgument ,
135- #[ msg( "An overflow occurs." ) ]
136- Overflow ,
137- #[ msg( "Pyth has an internal error." ) ]
138- PythError ,
139- #[ msg( "Pyth price oracle is offline." ) ]
140- PythOffline ,
141- #[ msg( "The loan value is higher than the collateral value." ) ]
142- LoanValueTooHigh ,
143- }
0 commit comments