1
+ use move_core_types:: identifier:: Identifier ;
1
2
use move_core_types:: language_storage:: TypeTag ;
2
3
use serde:: { Deserialize , Serialize } ;
3
4
use 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 } ;
5
7
use tw_memory:: Data ;
6
8
use tw_misc:: serde:: as_string;
7
9
8
10
use crate :: address:: SuiAddress ;
9
11
12
+ use super :: sui_types:: TransactionExpiration ;
10
13
use super :: {
11
- command:: Argument ,
12
- sui_types:: { ObjectArg , ObjectID , SequenceNumber } ,
14
+ command:: { Argument , Command } ,
15
+ sui_types:: { CallArg , ObjectArg , ObjectDigest , ObjectID , ObjectRef , SequenceNumber } ,
13
16
} ;
14
17
15
18
#[ derive( Debug , Deserialize , Serialize ) ]
@@ -21,6 +24,18 @@ pub struct PaymentConfig {
21
24
pub digest : String ,
22
25
}
23
26
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
+
24
39
#[ derive( Debug , Deserialize , Serialize ) ]
25
40
pub struct GasConfig {
26
41
#[ serde( with = "as_string" ) ]
@@ -32,20 +47,42 @@ pub struct GasConfig {
32
47
33
48
#[ derive( Debug , Deserialize , Serialize ) ]
34
49
pub 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
+ } ,
35
57
#[ serde( rename_all = "camelCase" ) ]
36
58
Shared {
37
59
mutable : bool ,
38
60
#[ serde( with = "as_string" ) ]
39
61
initial_shared_version : u64 ,
40
62
object_id : String ,
41
63
} ,
64
+ #[ serde( rename_all = "camelCase" ) ]
65
+ Receiving {
66
+ digest : String ,
67
+ version : u64 ,
68
+ object_id : String ,
69
+ } ,
42
70
}
43
71
44
72
impl TryFrom < InputObjectArg > for ObjectArg {
45
73
type Error = SigningError ;
46
74
47
75
fn try_from ( arg : InputObjectArg ) -> Result < Self , Self :: Error > {
48
76
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
+ ) ) ) ,
49
86
InputObjectArg :: Shared {
50
87
mutable,
51
88
initial_shared_version,
@@ -55,6 +92,15 @@ impl TryFrom<InputObjectArg> for ObjectArg {
55
92
initial_shared_version : SequenceNumber ( initial_shared_version) ,
56
93
mutable,
57
94
} ) ,
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
+ ) ) ) ,
58
104
}
59
105
}
60
106
}
@@ -65,6 +111,17 @@ pub enum InputArg {
65
111
Object ( InputObjectArg ) ,
66
112
}
67
113
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
+
68
125
#[ derive( Debug , Deserialize , Serialize ) ]
69
126
#[ serde( rename_all = "camelCase" ) ]
70
127
pub struct Input {
@@ -79,8 +136,17 @@ pub struct Input {
79
136
#[ serde( tag = "kind" ) ]
80
137
pub enum TransactionArg {
81
138
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
+ } ,
84
150
}
85
151
86
152
impl From < TransactionArg > for Argument {
@@ -89,6 +155,10 @@ impl From<TransactionArg> for Argument {
89
155
TransactionArg :: GasCoin => Argument :: GasCoin ,
90
156
TransactionArg :: Input { index } => Argument :: Input ( index) ,
91
157
TransactionArg :: Result { index } => Argument :: Result ( index) ,
158
+ TransactionArg :: NestedResult {
159
+ index,
160
+ result_index,
161
+ } => Argument :: NestedResult ( index, result_index) ,
92
162
}
93
163
}
94
164
}
@@ -105,10 +175,6 @@ impl From<TypeTagWrapper> for TypeTag {
105
175
#[ derive( Debug , Deserialize , Serialize ) ]
106
176
#[ serde( tag = "kind" ) ]
107
177
pub enum Transaction {
108
- SplitCoins {
109
- coin : TransactionArg ,
110
- amounts : Vec < TransactionArg > ,
111
- } ,
112
178
#[ serde( rename_all = "camelCase" ) ]
113
179
MoveCall {
114
180
target : String ,
@@ -119,14 +185,144 @@ pub enum Transaction {
119
185
objects : Vec < TransactionArg > ,
120
186
address : TransactionArg ,
121
187
} ,
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
+ }
122
318
}
123
319
124
320
#[ derive( Debug , Deserialize , Serialize ) ]
125
321
#[ serde( rename_all = "camelCase" ) ]
126
322
pub struct RawTransaction {
127
323
pub version : u8 ,
128
324
pub sender : SuiAddress ,
129
- pub expiration : Option < u64 > ,
325
+ pub expiration : Option < Expiration > ,
130
326
pub gas_config : GasConfig ,
131
327
pub inputs : Vec < Input > ,
132
328
pub transactions : Vec < Transaction > ,
0 commit comments