1+ use move_core_types:: identifier:: Identifier ;
12use move_core_types:: language_storage:: TypeTag ;
23use serde:: { Deserialize , Serialize } ;
34use std:: str:: FromStr ;
4- use tw_coin_entry:: error:: prelude:: SigningError ;
5+ use tw_coin_entry:: error:: prelude:: * ;
6+ use tw_coin_entry:: error:: prelude:: { SigningError , SigningErrorType , SigningResult } ;
57use tw_memory:: Data ;
68use tw_misc:: serde:: as_string;
79
810use crate :: address:: SuiAddress ;
911
12+ use super :: sui_types:: TransactionExpiration ;
1013use super :: {
11- command:: Argument ,
12- sui_types:: { ObjectArg , ObjectID , SequenceNumber } ,
14+ command:: { Argument , Command } ,
15+ sui_types:: { CallArg , ObjectArg , ObjectDigest , ObjectID , ObjectRef , SequenceNumber } ,
1316} ;
1417
1518#[ derive( Debug , Deserialize , Serialize ) ]
@@ -21,6 +24,18 @@ pub struct PaymentConfig {
2124 pub digest : String ,
2225}
2326
27+ impl TryFrom < PaymentConfig > for ObjectRef {
28+ type Error = SigningError ;
29+
30+ fn try_from ( config : PaymentConfig ) -> Result < Self , Self :: Error > {
31+ Ok ( (
32+ ObjectID :: from_str ( & config. object_id ) ?,
33+ SequenceNumber ( config. version ) ,
34+ ObjectDigest :: from_str ( & config. digest ) ?,
35+ ) )
36+ }
37+ }
38+
2439#[ derive( Debug , Deserialize , Serialize ) ]
2540pub struct GasConfig {
2641 #[ serde( with = "as_string" ) ]
@@ -32,20 +47,42 @@ pub struct GasConfig {
3247
3348#[ derive( Debug , Deserialize , Serialize ) ]
3449pub enum InputObjectArg {
50+ #[ serde( rename_all = "camelCase" ) ]
51+ ImmOrOwned {
52+ object_id : String ,
53+ #[ serde( with = "as_string" ) ]
54+ version : u64 ,
55+ digest : String ,
56+ } ,
3557 #[ serde( rename_all = "camelCase" ) ]
3658 Shared {
3759 mutable : bool ,
3860 #[ serde( with = "as_string" ) ]
3961 initial_shared_version : u64 ,
4062 object_id : String ,
4163 } ,
64+ #[ serde( rename_all = "camelCase" ) ]
65+ Receiving {
66+ digest : String ,
67+ version : u64 ,
68+ object_id : String ,
69+ } ,
4270}
4371
4472impl TryFrom < InputObjectArg > for ObjectArg {
4573 type Error = SigningError ;
4674
4775 fn try_from ( arg : InputObjectArg ) -> Result < Self , Self :: Error > {
4876 match arg {
77+ InputObjectArg :: ImmOrOwned {
78+ object_id,
79+ version,
80+ digest,
81+ } => Ok ( ObjectArg :: ImmOrOwnedObject ( (
82+ ObjectID :: from_str ( & object_id) ?,
83+ SequenceNumber ( version) ,
84+ ObjectDigest :: from_str ( & digest) ?,
85+ ) ) ) ,
4986 InputObjectArg :: Shared {
5087 mutable,
5188 initial_shared_version,
@@ -55,6 +92,15 @@ impl TryFrom<InputObjectArg> for ObjectArg {
5592 initial_shared_version : SequenceNumber ( initial_shared_version) ,
5693 mutable,
5794 } ) ,
95+ InputObjectArg :: Receiving {
96+ digest,
97+ version,
98+ object_id,
99+ } => Ok ( ObjectArg :: Receiving ( (
100+ ObjectID :: from_str ( & object_id) ?,
101+ SequenceNumber ( version) ,
102+ ObjectDigest :: from_str ( & digest) ?,
103+ ) ) ) ,
58104 }
59105 }
60106}
@@ -65,6 +111,17 @@ pub enum InputArg {
65111 Object ( InputObjectArg ) ,
66112}
67113
114+ impl TryFrom < InputArg > for CallArg {
115+ type Error = SigningError ;
116+
117+ fn try_from ( arg : InputArg ) -> Result < Self , Self :: Error > {
118+ match arg {
119+ InputArg :: Pure ( data) => Ok ( CallArg :: Pure ( data) ) ,
120+ InputArg :: Object ( object) => Ok ( CallArg :: Object ( object. try_into ( ) ?) ) ,
121+ }
122+ }
123+ }
124+
68125#[ derive( Debug , Deserialize , Serialize ) ]
69126#[ serde( rename_all = "camelCase" ) ]
70127pub struct Input {
@@ -79,8 +136,17 @@ pub struct Input {
79136#[ serde( tag = "kind" ) ]
80137pub enum TransactionArg {
81138 GasCoin ,
82- Input { index : u16 } ,
83- Result { index : u16 } ,
139+ Input {
140+ index : u16 ,
141+ } ,
142+ Result {
143+ index : u16 ,
144+ } ,
145+ #[ serde( rename_all = "camelCase" ) ]
146+ NestedResult {
147+ index : u16 ,
148+ result_index : u16 ,
149+ } ,
84150}
85151
86152impl From < TransactionArg > for Argument {
@@ -89,6 +155,10 @@ impl From<TransactionArg> for Argument {
89155 TransactionArg :: GasCoin => Argument :: GasCoin ,
90156 TransactionArg :: Input { index } => Argument :: Input ( index) ,
91157 TransactionArg :: Result { index } => Argument :: Result ( index) ,
158+ TransactionArg :: NestedResult {
159+ index,
160+ result_index,
161+ } => Argument :: NestedResult ( index, result_index) ,
92162 }
93163 }
94164}
@@ -105,10 +175,6 @@ impl From<TypeTagWrapper> for TypeTag {
105175#[ derive( Debug , Deserialize , Serialize ) ]
106176#[ serde( tag = "kind" ) ]
107177pub enum Transaction {
108- SplitCoins {
109- coin : TransactionArg ,
110- amounts : Vec < TransactionArg > ,
111- } ,
112178 #[ serde( rename_all = "camelCase" ) ]
113179 MoveCall {
114180 target : String ,
@@ -119,14 +185,144 @@ pub enum Transaction {
119185 objects : Vec < TransactionArg > ,
120186 address : TransactionArg ,
121187 } ,
188+ SplitCoins {
189+ coin : TransactionArg ,
190+ amounts : Vec < TransactionArg > ,
191+ } ,
192+ MergeCoins {
193+ destination : TransactionArg ,
194+ sources : Vec < TransactionArg > ,
195+ } ,
196+ Publish {
197+ modules : Vec < Data > ,
198+ dependencies : Vec < String > ,
199+ } ,
200+ #[ serde( rename_all = "camelCase" ) ]
201+ MakeMoveVec {
202+ type_tag : Option < TypeTagWrapper > ,
203+ arguments : Vec < TransactionArg > ,
204+ } ,
205+ #[ serde( rename_all = "camelCase" ) ]
206+ Upgrade {
207+ modules : Vec < Data > ,
208+ dependencies : Vec < String > ,
209+ package_id : String ,
210+ ticket : TransactionArg ,
211+ } ,
212+ }
213+
214+ impl TryFrom < Transaction > for Command {
215+ type Error = SigningError ;
216+
217+ fn try_from ( transaction : Transaction ) -> Result < Self , Self :: Error > {
218+ match transaction {
219+ Transaction :: MoveCall {
220+ target,
221+ type_arguments,
222+ arguments,
223+ } => {
224+ let parts: Vec < & str > = target. split ( "::" ) . collect ( ) ;
225+ if parts. len ( ) != 3 {
226+ return SigningError :: err ( SigningErrorType :: Error_invalid_params )
227+ . context ( "Invalid target format for MoveCall command" ) ;
228+ }
229+ let package = ObjectID :: from_str ( parts[ 0 ] ) . context ( "Failed to parse package ID" ) ?;
230+ let module = Identifier :: from_str ( parts[ 1 ] )
231+ . tw_err ( |_| SigningErrorType :: Error_invalid_params )
232+ . context ( "Failed to parse module" ) ?;
233+ let function = Identifier :: from_str ( parts[ 2 ] )
234+ . tw_err ( |_| SigningErrorType :: Error_invalid_params )
235+ . context ( "Failed to parse function" ) ?;
236+ Ok ( Command :: move_call (
237+ package,
238+ module,
239+ function,
240+ type_arguments. into_iter ( ) . map ( |tag| tag. into ( ) ) . collect ( ) ,
241+ arguments
242+ . into_iter ( )
243+ . map ( |argument| argument. into ( ) )
244+ . collect ( ) ,
245+ ) )
246+ } ,
247+ Transaction :: TransferObjects { objects, address } => Ok ( Command :: TransferObjects (
248+ objects. into_iter ( ) . map ( |object| object. into ( ) ) . collect ( ) ,
249+ address. into ( ) ,
250+ ) ) ,
251+ Transaction :: SplitCoins { coin, amounts } => Ok ( Command :: SplitCoins (
252+ coin. into ( ) ,
253+ amounts. into_iter ( ) . map ( |amount| amount. into ( ) ) . collect ( ) ,
254+ ) ) ,
255+ Transaction :: MergeCoins {
256+ destination,
257+ sources,
258+ } => Ok ( Command :: MergeCoins (
259+ destination. into ( ) ,
260+ sources. into_iter ( ) . map ( |source| source. into ( ) ) . collect ( ) ,
261+ ) ) ,
262+ Transaction :: Publish {
263+ modules,
264+ dependencies,
265+ } => Ok ( Command :: Publish (
266+ modules,
267+ dependencies
268+ . into_iter ( )
269+ . map ( |dependency| {
270+ ObjectID :: from_str ( & dependency) . context ( "Failed to parse object ID" )
271+ } )
272+ . collect :: < SigningResult < Vec < _ > > > ( ) ?,
273+ ) ) ,
274+ Transaction :: MakeMoveVec {
275+ type_tag,
276+ arguments,
277+ } => Ok ( Command :: MakeMoveVec (
278+ type_tag. map ( |tag| tag. into ( ) ) ,
279+ arguments
280+ . into_iter ( )
281+ . map ( |argument| argument. into ( ) )
282+ . collect ( ) ,
283+ ) ) ,
284+ Transaction :: Upgrade {
285+ modules,
286+ dependencies,
287+ package_id,
288+ ticket,
289+ } => Ok ( Command :: Upgrade (
290+ modules,
291+ dependencies
292+ . into_iter ( )
293+ . map ( |dependency| {
294+ ObjectID :: from_str ( & dependency) . context ( "Failed to parse object ID" )
295+ } )
296+ . collect :: < SigningResult < Vec < _ > > > ( ) ?,
297+ ObjectID :: from_str ( & package_id) . context ( "Failed to parse object ID" ) ?,
298+ ticket. into ( ) ,
299+ ) ) ,
300+ }
301+ }
302+ }
303+
304+ // Taken from here: https://github.com/MystenLabs/ts-sdks/blob/68e1b649c125f031b72ff7816d1ff653ef47cb53/packages/typescript/src/transactions/data/v1.ts#L271
305+ #[ derive( Debug , Deserialize , Serialize ) ]
306+ pub enum Expiration {
307+ None ( bool ) ,
308+ Epoch ( u64 ) ,
309+ }
310+
311+ impl From < Expiration > for TransactionExpiration {
312+ fn from ( expiration : Expiration ) -> Self {
313+ match expiration {
314+ Expiration :: None ( _) => TransactionExpiration :: None ,
315+ Expiration :: Epoch ( epoch) => TransactionExpiration :: Epoch ( epoch) ,
316+ }
317+ }
122318}
123319
124320#[ derive( Debug , Deserialize , Serialize ) ]
125321#[ serde( rename_all = "camelCase" ) ]
126322pub struct RawTransaction {
127323 pub version : u8 ,
128324 pub sender : SuiAddress ,
129- pub expiration : Option < u64 > ,
325+ pub expiration : Option < Expiration > ,
130326 pub gas_config : GasConfig ,
131327 pub inputs : Vec < Input > ,
132328 pub transactions : Vec < Transaction > ,
0 commit comments