1
1
use crate :: network:: NetworkKind ;
2
+ use crate :: transactions:: authorization:: * ;
2
3
use crate :: transactions:: clarity:: ClarityType ;
3
4
use crate :: transactions:: constants:: * ;
4
5
use stacks_common:: address:: c32:: c32_address;
@@ -9,6 +10,7 @@ use stacks_common::types::chainstate::StacksAddress;
9
10
use stacks_common:: util:: hash:: Hash160 ;
10
11
use stacks_common:: util:: secp256k1:: Secp256k1PrivateKey ;
11
12
use stacks_common:: util:: secp256k1:: Secp256k1PublicKey ;
13
+ use stacks_common:: util:: uint:: Uint256 ;
12
14
use std:: fmt;
13
15
14
16
#[ derive( Debug ) ]
@@ -39,9 +41,9 @@ pub trait Serialize {
39
41
}
40
42
41
43
pub struct TokenTransferPayload {
42
- recipient : String ,
43
- amount : u64 ,
44
- memo : String ,
44
+ pub recipient : String ,
45
+ pub amount : u64 ,
46
+ pub memo : String ,
45
47
}
46
48
47
49
impl Serialize for TokenTransferPayload {
@@ -91,48 +93,66 @@ impl Serialize for TokenTransferPayload {
91
93
92
94
TokenTransferPayload {
93
95
recipient : addr,
94
- amount : amount ,
96
+ amount,
95
97
memo : String :: from ( memo. trim_matches ( char:: from ( 0 ) ) ) ,
96
98
}
97
99
}
98
100
}
99
101
100
- enum Payload {
102
+ pub enum Payload {
101
103
TokenTransfer ( TokenTransferPayload ) ,
102
104
}
103
105
104
106
pub struct StacksTransaction {
105
- version : TransactionVersion ,
106
- network : NetworkKind ,
107
- payload : Payload ,
108
- post_condition_mode : PostConditionMode ,
107
+ pub version : TransactionVersion ,
108
+ pub network : NetworkKind ,
109
+ pub payload : Payload ,
110
+ pub post_condition_mode : PostConditionMode ,
109
111
// post_conditions:
110
- anchor_mode : AnchorMode ,
112
+ pub anchor_mode : AnchorMode ,
113
+ pub authorization : Authorization ,
111
114
}
112
115
113
- pub fn build_token_transfer_transaction (
116
+ pub fn build_single_sig_stx_token_transfer_transaction (
114
117
recipient : String ,
115
118
amount : u64 ,
116
119
sender_key : Secp256k1PrivateKey , // private key
117
120
network : NetworkKind ,
118
121
memo : String ,
119
- nonce : Option < u64 > ,
120
- fee : Option < u64 > ,
122
+ nonce : Option < Uint256 > ,
123
+ fee : Option < Uint256 > ,
121
124
) -> StacksTransaction {
122
125
let public_key = Secp256k1PublicKey :: from_private ( & sender_key) ;
123
126
let addr =
124
127
StacksAddress :: from_public_keys ( 1 , & AddressHashMode :: SerializeP2WPKH , 1 , & vec ! [ public_key] )
125
128
. expect ( "Invalid params for generating address" ) ;
126
129
130
+ let single_sig_spending_condition = SingleSigSpendingCondition :: new (
131
+ SingleSigHashMode :: P2WPKH ,
132
+ match nonce {
133
+ Some ( n) => n,
134
+ None => Uint256 :: from_u64 ( 0 ) ,
135
+ } ,
136
+ match fee {
137
+ Some ( n) => n,
138
+ None => Uint256 :: from_u64 ( 0 ) ,
139
+ } ,
140
+ public_key,
141
+ None ,
142
+ ) ;
143
+ let authorization =
144
+ StandardAuthorization :: new ( SpendingCondition :: SingleSig ( single_sig_spending_condition) ) ;
145
+
127
146
StacksTransaction {
128
147
payload : Payload :: TokenTransfer ( TokenTransferPayload {
129
- amount : amount ,
130
- memo : memo ,
131
- recipient : recipient ,
148
+ amount,
149
+ memo,
150
+ recipient,
132
151
} ) ,
133
152
network : network. clone ( ) ,
134
- post_condition_mode : PostConditionMode :: Deny ,
153
+ post_condition_mode : PostConditionMode :: Deny , // Token transfer cannot have post conditions
135
154
version : TransactionVersion :: from_network ( & network) ,
155
+ authorization : Authorization :: Standard ( authorization) ,
136
156
anchor_mode : AnchorMode :: Any ,
137
157
}
138
158
}
@@ -232,4 +252,50 @@ mod tests {
232
252
) ;
233
253
assert_eq ! ( payload. memo, String :: from( "" ) ) ;
234
254
}
255
+
256
+ #[ test]
257
+ fn build_usingned_single_sig_tx ( ) {
258
+ let sender_key = Secp256k1PrivateKey :: from_seed ( & [ 2 ; 32 ] ) ;
259
+ let unsigned_token_transfer_tx = build_single_sig_stx_token_transfer_transaction (
260
+ String :: from ( "SP3FGQ8Z7JY9BWYZ5WM53E0M9NK7WHJF0691NZ159" ) ,
261
+ 10000 ,
262
+ sender_key,
263
+ NetworkKind :: Mainnet ,
264
+ String :: from ( "test memo" ) ,
265
+ None ,
266
+ None ,
267
+ ) ;
268
+
269
+ match unsigned_token_transfer_tx. authorization {
270
+ Authorization :: Standard ( a) => match a. spending_condition {
271
+ SpendingCondition :: SingleSig ( s) => {
272
+ assert_eq ! ( s. nonce, Uint256 :: from_u64( 0 ) ) ;
273
+ assert_eq ! ( s. fee, Uint256 :: from_u64( 0 ) ) ;
274
+ assert_eq ! ( s. hash_mode, SingleSigHashMode :: P2WPKH ) ;
275
+ assert_eq ! ( s. signature, None ) ;
276
+ assert_eq ! (
277
+ s. sender_pubkey,
278
+ Secp256k1PublicKey :: from_private( & sender_key)
279
+ ) ;
280
+ }
281
+ SpendingCondition :: MultiSig ( _) => {
282
+ assert_eq ! ( true , false ) ;
283
+ }
284
+ } ,
285
+ Authorization :: Sponsored ( _) => {
286
+ assert_eq ! ( true , false ) ;
287
+ }
288
+ }
289
+
290
+ match unsigned_token_transfer_tx. payload {
291
+ Payload :: TokenTransfer ( p) => {
292
+ assert_eq ! ( p. amount, 10000 ) ;
293
+ assert_eq ! ( p. memo, String :: from( "test memo" ) ) ;
294
+ assert_eq ! (
295
+ p. recipient,
296
+ String :: from( "SP3FGQ8Z7JY9BWYZ5WM53E0M9NK7WHJF0691NZ159" )
297
+ ) ;
298
+ }
299
+ }
300
+ }
235
301
}
0 commit comments