1
1
use std:: mem:: size_of;
2
2
use anchor_lang:: prelude:: * ;
3
3
use solana_program:: account_info:: AccountInfo ;
4
- use pyth_sdk_solana:: load_price_feed_from_account_info;
5
4
6
- declare_id ! ( "9azQ2ePzPvMPQgHric53kdSNmwjVM5KijDE4ANFCE9D4" ) ;
5
+ pub mod state;
6
+ use state:: PriceFeed ;
7
+ use state:: AdminConfig ;
7
8
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" ) ;
13
13
14
14
#[ derive( Accounts ) ]
15
15
pub struct InitRequest < ' info > {
@@ -25,12 +25,10 @@ pub struct InitRequest<'info> {
25
25
#[ derive( Accounts ) ]
26
26
pub struct QueryRequest < ' info > {
27
27
pub config : Account < ' info , AdminConfig > ,
28
- /// CHECK: Pyth structs don't seem to support Anchor deserialization
29
28
#[ 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 > ,
32
30
#[ account( address = config. collateral_price_feed_id @ ErrorCode :: InvalidArgument ) ]
33
- pub pyth_collateral_account : AccountInfo < ' info > ,
31
+ pub pyth_collateral_account : Account < ' info , PriceFeed > ,
34
32
}
35
33
36
34
#[ program]
@@ -46,66 +44,63 @@ pub mod example_sol_anchor_contract {
46
44
msg ! ( "Loan quantity is {}." , loan_qty) ;
47
45
msg ! ( "Collateral quantity is {}." , collateral_qty) ;
48
46
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 ;
51
50
// With high confidence, the maximum value of the loan is
52
51
// (price + conf) * loan_qty * 10 ^ (expo).
53
52
// Here is more explanation on confidence interval in Pyth:
54
53
// 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 ) ) ?;
57
54
let current_timestamp1 = Clock :: get ( ) ?. unix_timestamp ;
58
- let result1 = feed1
55
+ let loan_price = loan_feed
59
56
. get_price_no_older_than ( current_timestamp1, 60 )
60
57
. ok_or ( ErrorCode :: PythOffline ) ?;
61
- let loan_max_price = result1
58
+ let loan_max_price = loan_price
62
59
. price
63
- . checked_add ( result1 . conf as i64 )
60
+ . checked_add ( loan_price . conf as i64 )
64
61
. ok_or ( ErrorCode :: Overflow ) ?;
65
62
let mut loan_max_value = loan_max_price
66
63
. checked_mul ( loan_qty)
67
64
. ok_or ( ErrorCode :: Overflow ) ?;
68
65
msg ! (
69
66
"The maximum loan value is {} * 10^({})." ,
70
67
loan_max_value,
71
- result1 . expo
68
+ loan_price . expo
72
69
) ;
73
70
74
71
// With high confidence, the minimum value of the collateral is
75
72
// (price - conf) * collateral_qty * 10 ^ (expo).
76
73
// Here is more explanation on confidence interval in Pyth:
77
74
// 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 ) ) ?;
80
75
let current_timestamp2 = Clock :: get ( ) ?. unix_timestamp ;
81
- let result2 = feed2
76
+ let collateral_price = collateral_feed
82
77
. get_price_no_older_than ( current_timestamp2, 60 )
83
78
. ok_or ( ErrorCode :: PythOffline ) ?;
84
- let collateral_min_price = result2
79
+ let collateral_min_price = collateral_price
85
80
. price
86
- . checked_sub ( result2 . conf as i64 )
81
+ . checked_sub ( collateral_price . conf as i64 )
87
82
. ok_or ( ErrorCode :: Overflow ) ?;
88
83
let mut collateral_min_value = collateral_min_price
89
84
. checked_mul ( collateral_qty)
90
85
. ok_or ( ErrorCode :: Overflow ) ?;
91
86
msg ! (
92
87
"The minimum collateral value is {} * 10^({})." ,
93
88
collateral_min_value,
94
- result2 . expo
89
+ collateral_price . expo
95
90
) ;
96
91
97
92
// If the loan and collateral prices use different exponent,
98
93
// normalize the value.
99
- if result1 . expo > result2 . expo {
94
+ if loan_price . expo > collateral_price . expo {
100
95
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 )
102
97
. ok_or ( ErrorCode :: Overflow ) ?;
103
98
collateral_min_value = collateral_min_value
104
99
. checked_mul ( normalize)
105
100
. ok_or ( ErrorCode :: Overflow ) ?;
106
- } else if result1 . expo < result2 . expo {
101
+ } else if loan_price . expo < collateral_price . expo {
107
102
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 )
109
104
. ok_or ( ErrorCode :: Overflow ) ?;
110
105
loan_max_value = loan_max_value
111
106
. checked_mul ( normalize)
@@ -121,23 +116,3 @@ pub mod example_sol_anchor_contract {
121
116
}
122
117
}
123
118
}
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