7
7
PC_ACCTYPE_PRICE ,
8
8
PC_COMP_SIZE ,
9
9
PC_PRICE_T_COMP_OFFSET ,
10
+ PC_STATUS_TRADING ,
10
11
} ,
11
12
bytemuck:: {
12
13
Pod ,
@@ -39,7 +40,9 @@ pub struct PriceAccount {
39
40
pub timestamp_ : i64 ,
40
41
/// Minimum valid publisher quotes for a succesful aggregation
41
42
pub min_pub_ : u8 ,
42
- pub unused_1_ : i8 ,
43
+ /// Whether the current aggregate price has been sent as a message to the message buffer.
44
+ /// 0 = false, 1 = true. (this is a u8 to make the Pod trait happy)
45
+ pub message_sent_ : u8 ,
43
46
pub unused_2_ : i16 ,
44
47
pub unused_3_ : i32 ,
45
48
/// Corresponding product account
@@ -69,7 +72,7 @@ pub struct PriceComponent {
69
72
}
70
73
71
74
#[ repr( C ) ]
72
- #[ derive( Debug , Copy , Clone , Pod , Zeroable ) ]
75
+ #[ derive( Copy , Clone , Pod , Zeroable ) ]
73
76
pub struct PriceInfo {
74
77
pub price_ : i64 ,
75
78
pub conf_ : u64 ,
@@ -79,7 +82,7 @@ pub struct PriceInfo {
79
82
}
80
83
81
84
#[ repr( C ) ]
82
- #[ derive( Debug , Copy , Clone , Pod , Zeroable ) ]
85
+ #[ derive( Copy , Clone , Pod , Zeroable ) ]
83
86
pub struct PriceEma {
84
87
pub val_ : i64 ,
85
88
pub numer_ : i64 ,
@@ -91,3 +94,101 @@ impl PythAccount for PriceAccount {
91
94
/// Equal to the offset of `comp_` in `PriceAccount`, see the trait comment for more detail
92
95
const INITIAL_SIZE : u32 = PC_PRICE_T_COMP_OFFSET as u32 ;
93
96
}
97
+
98
+ /// Message format for sending data to other chains via the accumulator program
99
+ /// When serialized, each message starts with a unique 1-byte discriminator, followed by the
100
+ /// serialized struct data in the definition(s) below.
101
+ ///
102
+ /// Messages are forward-compatible. You may add new fields to messages after all previously
103
+ /// defined fields. All code for parsing messages must ignore any extraneous bytes at the end of
104
+ /// the message (which could be fields that the code does not yet understand).
105
+ #[ repr( C ) ]
106
+ #[ derive( Debug , Copy , Clone , PartialEq ) ]
107
+ pub struct PriceFeedMessage {
108
+ pub id : [ u8 ; 32 ] ,
109
+ pub price : i64 ,
110
+ pub conf : u64 ,
111
+ pub exponent : i32 ,
112
+ /// The timestamp of this price update in seconds
113
+ pub publish_time : i64 ,
114
+ /// The timestamp of the previous price update. This field is intended to allow users to
115
+ /// identify the single unique price update for any moment in time:
116
+ /// for any time t, the unique update is the one such that prev_publish_time < t <= publish_time.
117
+ ///
118
+ /// Note that there may not be such an update while we are migrating to the new message-sending logic,
119
+ /// as some price updates on pythnet may not be sent to other chains (because the message-sending
120
+ /// logic may not have triggered). We can solve this problem by making the message-sending mandatory
121
+ /// (which we can do once publishers have migrated over).
122
+ pub prev_publish_time : i64 ,
123
+ pub ema_price : i64 ,
124
+ pub ema_conf : u64 ,
125
+ }
126
+
127
+ impl PriceFeedMessage {
128
+ // The size of the serialized message. Note that this is not the same as the size of the struct
129
+ // (because of the discriminator & struct padding/alignment).
130
+ pub const MESSAGE_SIZE : usize = 1 + 32 + 8 + 8 + 4 + 8 + 8 + 8 + 8 ;
131
+ pub const DISCRIMINATOR : u8 = 0 ;
132
+
133
+ pub fn from_price_account ( key : & Pubkey , account : & PriceAccount ) -> Self {
134
+ let ( price, conf, publish_time) = if account. agg_ . status_ == PC_STATUS_TRADING {
135
+ ( account. agg_ . price_ , account. agg_ . conf_ , account. timestamp_ )
136
+ } else {
137
+ (
138
+ account. prev_price_ ,
139
+ account. prev_conf_ ,
140
+ account. prev_timestamp_ ,
141
+ )
142
+ } ;
143
+
144
+ Self {
145
+ id : key. to_bytes ( ) ,
146
+ price,
147
+ conf,
148
+ exponent : account. exponent ,
149
+ publish_time,
150
+ prev_publish_time : account. prev_timestamp_ ,
151
+ ema_price : account. twap_ . val_ ,
152
+ ema_conf : account. twac_ . val_ as u64 ,
153
+ }
154
+ }
155
+
156
+ /// Serialize this message as an array of bytes (including the discriminator)
157
+ /// Note that it would be more idiomatic to return a `Vec`, but that approach adds
158
+ /// to the size of the compiled binary (which is already close to the size limit).
159
+ #[ allow( unused_assignments) ]
160
+ pub fn as_bytes ( & self ) -> [ u8 ; PriceFeedMessage :: MESSAGE_SIZE ] {
161
+ let mut bytes = [ 0u8 ; PriceFeedMessage :: MESSAGE_SIZE ] ;
162
+
163
+ let mut i: usize = 0 ;
164
+
165
+ bytes[ i..i + 1 ] . clone_from_slice ( & [ PriceFeedMessage :: DISCRIMINATOR ] ) ;
166
+ i += 1 ;
167
+
168
+ bytes[ i..i + 32 ] . clone_from_slice ( & self . id [ ..] ) ;
169
+ i += 32 ;
170
+
171
+ bytes[ i..i + 8 ] . clone_from_slice ( & self . price . to_be_bytes ( ) ) ;
172
+ i += 8 ;
173
+
174
+ bytes[ i..i + 8 ] . clone_from_slice ( & self . conf . to_be_bytes ( ) ) ;
175
+ i += 8 ;
176
+
177
+ bytes[ i..i + 4 ] . clone_from_slice ( & self . exponent . to_be_bytes ( ) ) ;
178
+ i += 4 ;
179
+
180
+ bytes[ i..i + 8 ] . clone_from_slice ( & self . publish_time . to_be_bytes ( ) ) ;
181
+ i += 8 ;
182
+
183
+ bytes[ i..i + 8 ] . clone_from_slice ( & self . prev_publish_time . to_be_bytes ( ) ) ;
184
+ i += 8 ;
185
+
186
+ bytes[ i..i + 8 ] . clone_from_slice ( & self . ema_price . to_be_bytes ( ) ) ;
187
+ i += 8 ;
188
+
189
+ bytes[ i..i + 8 ] . clone_from_slice ( & self . ema_conf . to_be_bytes ( ) ) ;
190
+ i += 8 ;
191
+
192
+ bytes
193
+ }
194
+ }
0 commit comments