1+ use std:: { collections:: BTreeMap , time:: Duration } ;
2+
3+ use :: protobuf:: MessageField ;
4+ use anyhow:: { bail, ensure, Context } ;
5+ use humantime:: format_duration;
6+ use protobuf:: dynamic_value:: { dynamic_value, DynamicValue } ;
7+ use pyth_lazer_protocol:: router:: TimestampUs ;
8+
19pub mod transaction {
210 pub use crate :: protobuf:: pyth_lazer_transaction:: * ;
311}
@@ -13,3 +21,137 @@ pub mod governance_instruction {
1321mod protobuf {
1422 include ! ( concat!( env!( "OUT_DIR" ) , "/protobuf/mod.rs" ) ) ;
1523}
24+
25+ impl DynamicValue {
26+ pub fn try_option_from_serde ( value : serde_value:: Value ) -> anyhow:: Result < Option < Self > > {
27+ match value {
28+ serde_value:: Value :: Option ( value) => {
29+ if let Some ( value) = value {
30+ Ok ( Some ( ( * value) . try_into ( ) ?) )
31+ } else {
32+ Ok ( None )
33+ }
34+ }
35+ value => Ok ( Some ( value. try_into ( ) ?) ) ,
36+ }
37+ }
38+
39+ pub fn to_timestamp ( & self ) -> anyhow:: Result < TimestampUs > {
40+ let value = self . value . as_ref ( ) . context ( "missing DynamicValue.value" ) ?;
41+ match value {
42+ dynamic_value:: Value :: TimestampValue ( ts) => Ok ( ts. try_into ( ) ?) ,
43+ _ => bail ! ( "expected timestamp, got {:?}" , self ) ,
44+ }
45+ }
46+
47+ pub fn to_duration ( & self ) -> anyhow:: Result < Duration > {
48+ let value = self . value . as_ref ( ) . context ( "missing DynamicValue.value" ) ?;
49+ match value {
50+ dynamic_value:: Value :: DurationValue ( duration) => Ok ( duration. clone ( ) . into ( ) ) ,
51+ _ => bail ! ( "expected duration, got {:?}" , self ) ,
52+ }
53+ }
54+ }
55+
56+ impl TryFrom < serde_value:: Value > for DynamicValue {
57+ type Error = anyhow:: Error ;
58+
59+ fn try_from ( value : serde_value:: Value ) -> Result < Self , Self :: Error > {
60+ let converted = match value {
61+ serde_value:: Value :: Bool ( value) => dynamic_value:: Value :: BoolValue ( value) ,
62+ serde_value:: Value :: U8 ( value) => dynamic_value:: Value :: UintValue ( value. into ( ) ) ,
63+ serde_value:: Value :: U16 ( value) => dynamic_value:: Value :: UintValue ( value. into ( ) ) ,
64+ serde_value:: Value :: U32 ( value) => dynamic_value:: Value :: UintValue ( value. into ( ) ) ,
65+ serde_value:: Value :: U64 ( value) => dynamic_value:: Value :: UintValue ( value) ,
66+ serde_value:: Value :: I8 ( value) => dynamic_value:: Value :: IntValue ( value. into ( ) ) ,
67+ serde_value:: Value :: I16 ( value) => dynamic_value:: Value :: IntValue ( value. into ( ) ) ,
68+ serde_value:: Value :: I32 ( value) => dynamic_value:: Value :: IntValue ( value. into ( ) ) ,
69+ serde_value:: Value :: I64 ( value) => dynamic_value:: Value :: IntValue ( value) ,
70+ serde_value:: Value :: F32 ( value) => dynamic_value:: Value :: DoubleValue ( value. into ( ) ) ,
71+ serde_value:: Value :: F64 ( value) => dynamic_value:: Value :: DoubleValue ( value) ,
72+ serde_value:: Value :: Char ( value) => dynamic_value:: Value :: StringValue ( value. to_string ( ) ) ,
73+ serde_value:: Value :: String ( value) => dynamic_value:: Value :: StringValue ( value) ,
74+ serde_value:: Value :: Bytes ( value) => dynamic_value:: Value :: BytesValue ( value) ,
75+ serde_value:: Value :: Seq ( values) => {
76+ let mut items = Vec :: new ( ) ;
77+ for value in values {
78+ items. push ( value. try_into ( ) ?) ;
79+ }
80+ dynamic_value:: Value :: List ( dynamic_value:: List {
81+ items,
82+ special_fields : Default :: default ( ) ,
83+ } )
84+ }
85+ serde_value:: Value :: Map ( values) => {
86+ let mut items = Vec :: new ( ) ;
87+ for ( key, value) in values {
88+ let key = match key {
89+ serde_value:: Value :: String ( key) => key,
90+ _ => bail ! ( "unsupported key type: expected string, got {:?}" , key) ,
91+ } ;
92+ items. push ( dynamic_value:: MapItem {
93+ key : Some ( key) ,
94+ value : MessageField :: some ( value. try_into ( ) ?) ,
95+ special_fields : Default :: default ( ) ,
96+ } )
97+ }
98+ dynamic_value:: Value :: Map ( dynamic_value:: Map {
99+ items,
100+ special_fields : Default :: default ( ) ,
101+ } )
102+ }
103+ serde_value:: Value :: Unit
104+ | serde_value:: Value :: Option ( _)
105+ | serde_value:: Value :: Newtype ( _) => bail ! ( "unsupported type: {:?}" , value) ,
106+ } ;
107+ Ok ( DynamicValue {
108+ value : Some ( converted) ,
109+ special_fields : Default :: default ( ) ,
110+ } )
111+ }
112+ }
113+
114+ impl TryFrom < DynamicValue > for serde_value:: Value {
115+ type Error = anyhow:: Error ;
116+
117+ fn try_from ( value : DynamicValue ) -> Result < Self , Self :: Error > {
118+ let value = value. value . context ( "missing DynamicValue.value" ) ?;
119+ match value {
120+ dynamic_value:: Value :: StringValue ( value) => Ok ( serde_value:: Value :: String ( value) ) ,
121+ dynamic_value:: Value :: DoubleValue ( value) => Ok ( serde_value:: Value :: F64 ( value) ) ,
122+ dynamic_value:: Value :: UintValue ( value) => Ok ( serde_value:: Value :: U64 ( value) ) ,
123+ dynamic_value:: Value :: IntValue ( value) => Ok ( serde_value:: Value :: I64 ( value) ) ,
124+ dynamic_value:: Value :: BoolValue ( value) => Ok ( serde_value:: Value :: Bool ( value) ) ,
125+ dynamic_value:: Value :: BytesValue ( value) => Ok ( serde_value:: Value :: Bytes ( value) ) ,
126+ dynamic_value:: Value :: DurationValue ( duration) => {
127+ let s: Duration = duration. into ( ) ;
128+ Ok ( serde_value:: Value :: String ( format_duration ( s) . to_string ( ) ) )
129+ }
130+ dynamic_value:: Value :: TimestampValue ( ts) => {
131+ let ts = TimestampUs :: try_from ( & ts) ?;
132+ Ok ( serde_value:: Value :: U64 ( ts. 0 ) )
133+ }
134+ dynamic_value:: Value :: List ( list) => {
135+ let mut output = Vec :: new ( ) ;
136+ for item in list. items {
137+ output. push ( item. try_into ( ) ?) ;
138+ }
139+ Ok ( serde_value:: Value :: Seq ( output) . into ( ) )
140+ }
141+ dynamic_value:: Value :: Map ( map) => {
142+ let mut output = BTreeMap :: new ( ) ;
143+ for item in map. items {
144+ let key = item. key . context ( "missing DynamicValue.MapItem.key" ) ?;
145+ let value = item
146+ . value
147+ . into_option ( )
148+ . context ( "missing DynamicValue.MapItem.value" ) ?
149+ . try_into ( ) ?;
150+ let old = output. insert ( serde_value:: Value :: String ( key) , value) ;
151+ ensure ! ( old. is_none( ) , "duplicate DynamicValue.MapItem.key" ) ;
152+ }
153+ Ok ( serde_value:: Value :: Map ( output) . into ( ) )
154+ }
155+ }
156+ }
157+ }
0 commit comments