@@ -4,8 +4,8 @@ use algod_client::{
4
4
models:: { PendingTransactionResponse , TransactionParams } ,
5
5
} ;
6
6
use algokit_transact:: {
7
- Address , AlgorandMsgpack , FeeParams , PaymentTransactionFields , SignedTransaction , Transaction ,
8
- TransactionHeader , Transactions ,
7
+ Address , AlgorandMsgpack , FeeParams , KeyRegistrationTransactionFields ,
8
+ PaymentTransactionFields , SignedTransaction , Transaction , TransactionHeader , Transactions ,
9
9
} ;
10
10
use async_trait:: async_trait;
11
11
use derive_more:: Debug ;
@@ -98,6 +98,31 @@ pub struct AssetClawbackParams {
98
98
pub clawback_target : Address ,
99
99
}
100
100
101
+ #[ derive( Debug , Clone ) ]
102
+ pub struct OnlineKeyRegistrationParams {
103
+ pub common_params : CommonParams ,
104
+ pub vote_key : [ u8 ; 32 ] ,
105
+ pub selection_key : [ u8 ; 32 ] ,
106
+ pub vote_first : u64 ,
107
+ pub vote_last : u64 ,
108
+ pub vote_key_dilution : u64 ,
109
+ pub state_proof_key : Option < [ u8 ; 64 ] > ,
110
+ }
111
+
112
+ #[ derive( Debug , Clone ) ]
113
+ pub struct OfflineKeyRegistrationParams {
114
+ pub common_params : CommonParams ,
115
+ /// Whether to prevent the account from ever participating in consensus again.
116
+ /// - `false`: Temporary offline (can be brought back online later)
117
+ /// - `true`: Permanent offline (account can never participate again)
118
+ pub prevent_account_from_ever_participating_again : bool ,
119
+ }
120
+
121
+ #[ derive( Debug , Clone ) ]
122
+ pub struct NonParticipationKeyRegistrationParams {
123
+ pub common_params : CommonParams ,
124
+ }
125
+
101
126
#[ derive( Debug , Clone ) ]
102
127
pub enum ComposerTxn {
103
128
Transaction ( Transaction ) ,
@@ -106,6 +131,9 @@ pub enum ComposerTxn {
106
131
AssetOptIn ( AssetOptInParams ) ,
107
132
AssetOptOut ( AssetOptOutParams ) ,
108
133
AssetClawback ( AssetClawbackParams ) ,
134
+ OnlineKeyRegistration ( OnlineKeyRegistrationParams ) ,
135
+ OfflineKeyRegistration ( OfflineKeyRegistrationParams ) ,
136
+ NonParticipationKeyRegistration ( NonParticipationKeyRegistrationParams ) ,
109
137
}
110
138
111
139
impl ComposerTxn {
@@ -124,6 +152,15 @@ impl ComposerTxn {
124
152
ComposerTxn :: AssetClawback ( asset_clawback_params) => {
125
153
asset_clawback_params. common_params . clone ( )
126
154
}
155
+ ComposerTxn :: OnlineKeyRegistration ( online_key_reg_params) => {
156
+ online_key_reg_params. common_params . clone ( )
157
+ }
158
+ ComposerTxn :: OfflineKeyRegistration ( offline_key_reg_params) => {
159
+ offline_key_reg_params. common_params . clone ( )
160
+ }
161
+ ComposerTxn :: NonParticipationKeyRegistration ( non_participation_params) => {
162
+ non_participation_params. common_params . clone ( )
163
+ }
127
164
_ => CommonParams :: default ( ) ,
128
165
}
129
166
}
@@ -205,6 +242,10 @@ impl Composer {
205
242
self . built_group . as_ref ( )
206
243
}
207
244
245
+ pub fn signed_group ( & self ) -> Option < & Vec < SignedTransaction > > {
246
+ self . signed_group . as_ref ( )
247
+ }
248
+
208
249
#[ cfg( feature = "default_http_client" ) ]
209
250
pub fn testnet ( ) -> Self {
210
251
Composer {
@@ -256,6 +297,29 @@ impl Composer {
256
297
self . push ( ComposerTxn :: AssetClawback ( asset_clawback_params) )
257
298
}
258
299
300
+ pub fn add_online_key_registration (
301
+ & mut self ,
302
+ online_key_reg_params : OnlineKeyRegistrationParams ,
303
+ ) -> Result < ( ) , String > {
304
+ self . push ( ComposerTxn :: OnlineKeyRegistration ( online_key_reg_params) )
305
+ }
306
+
307
+ pub fn add_offline_key_registration (
308
+ & mut self ,
309
+ offline_key_reg_params : OfflineKeyRegistrationParams ,
310
+ ) -> Result < ( ) , String > {
311
+ self . push ( ComposerTxn :: OfflineKeyRegistration ( offline_key_reg_params) )
312
+ }
313
+
314
+ pub fn add_non_participation_key_registration (
315
+ & mut self ,
316
+ non_participation_params : NonParticipationKeyRegistrationParams ,
317
+ ) -> Result < ( ) , String > {
318
+ self . push ( ComposerTxn :: NonParticipationKeyRegistration (
319
+ non_participation_params,
320
+ ) )
321
+ }
322
+
259
323
pub fn add_transaction ( & mut self , transaction : Transaction ) -> Result < ( ) , String > {
260
324
self . push ( ComposerTxn :: Transaction ( transaction) )
261
325
}
@@ -378,6 +442,48 @@ impl Composer {
378
442
} ,
379
443
)
380
444
}
445
+ ComposerTxn :: OnlineKeyRegistration ( online_key_reg_params) => {
446
+ Transaction :: KeyRegistration ( KeyRegistrationTransactionFields {
447
+ header,
448
+ vote_key : Some ( online_key_reg_params. vote_key ) ,
449
+ selection_key : Some ( online_key_reg_params. selection_key ) ,
450
+ vote_first : Some ( online_key_reg_params. vote_first ) ,
451
+ vote_last : Some ( online_key_reg_params. vote_last ) ,
452
+ vote_key_dilution : Some ( online_key_reg_params. vote_key_dilution ) ,
453
+ state_proof_key : online_key_reg_params. state_proof_key ,
454
+ non_participation : None ,
455
+ } )
456
+ }
457
+ ComposerTxn :: OfflineKeyRegistration ( offline_key_reg_params) => {
458
+ Transaction :: KeyRegistration ( KeyRegistrationTransactionFields {
459
+ header,
460
+ vote_key : None ,
461
+ selection_key : None ,
462
+ vote_first : None ,
463
+ vote_last : None ,
464
+ vote_key_dilution : None ,
465
+ state_proof_key : None ,
466
+ non_participation : if offline_key_reg_params
467
+ . prevent_account_from_ever_participating_again
468
+ {
469
+ Some ( true )
470
+ } else {
471
+ None
472
+ } ,
473
+ } )
474
+ }
475
+ ComposerTxn :: NonParticipationKeyRegistration ( _) => {
476
+ Transaction :: KeyRegistration ( KeyRegistrationTransactionFields {
477
+ header,
478
+ vote_key : None ,
479
+ selection_key : None ,
480
+ vote_first : None ,
481
+ vote_last : None ,
482
+ vote_key_dilution : None ,
483
+ state_proof_key : None ,
484
+ non_participation : Some ( true ) ,
485
+ } )
486
+ }
381
487
} ;
382
488
383
489
if calculate_fee {
@@ -731,6 +837,94 @@ mod tests {
731
837
assert ! ( composer. built_group( ) . is_some( ) ) ;
732
838
}
733
839
840
+ #[ tokio:: test]
841
+ async fn test_build_online_key_registration ( ) {
842
+ let mut composer = Composer :: testnet ( ) ;
843
+ let online_key_reg_params = OnlineKeyRegistrationParams {
844
+ common_params : CommonParams {
845
+ sender : AddressMother :: address ( ) ,
846
+ signer : None ,
847
+ rekey_to : None ,
848
+ note : None ,
849
+ lease : None ,
850
+ static_fee : None ,
851
+ extra_fee : None ,
852
+ max_fee : None ,
853
+ validity_window : None ,
854
+ first_valid_round : None ,
855
+ last_valid_round : None ,
856
+ } ,
857
+ vote_key : [ 1u8 ; 32 ] ,
858
+ selection_key : [ 2u8 ; 32 ] ,
859
+ vote_first : 100000 ,
860
+ vote_last : 200000 ,
861
+ vote_key_dilution : 10000 ,
862
+ state_proof_key : Some ( [ 3u8 ; 64 ] ) ,
863
+ } ;
864
+ assert ! (
865
+ composer
866
+ . add_online_key_registration( online_key_reg_params)
867
+ . is_ok( )
868
+ ) ;
869
+ assert ! ( composer. build( ) . await . is_ok( ) ) ;
870
+ assert ! ( composer. built_group( ) . is_some( ) ) ;
871
+ }
872
+
873
+ #[ tokio:: test]
874
+ async fn test_build_offline_key_registration ( ) {
875
+ let mut composer = Composer :: testnet ( ) ;
876
+ let offline_key_reg_params = OfflineKeyRegistrationParams {
877
+ common_params : CommonParams {
878
+ sender : AddressMother :: address ( ) ,
879
+ signer : None ,
880
+ rekey_to : None ,
881
+ note : None ,
882
+ lease : None ,
883
+ static_fee : None ,
884
+ extra_fee : None ,
885
+ max_fee : None ,
886
+ validity_window : None ,
887
+ first_valid_round : None ,
888
+ last_valid_round : None ,
889
+ } ,
890
+ prevent_account_from_ever_participating_again : false ,
891
+ } ;
892
+ assert ! (
893
+ composer
894
+ . add_offline_key_registration( offline_key_reg_params)
895
+ . is_ok( )
896
+ ) ;
897
+ assert ! ( composer. build( ) . await . is_ok( ) ) ;
898
+ assert ! ( composer. built_group( ) . is_some( ) ) ;
899
+ }
900
+
901
+ #[ tokio:: test]
902
+ async fn test_build_non_participation_key_registration ( ) {
903
+ let mut composer = Composer :: testnet ( ) ;
904
+ let non_participation_params = NonParticipationKeyRegistrationParams {
905
+ common_params : CommonParams {
906
+ sender : AddressMother :: address ( ) ,
907
+ signer : None ,
908
+ rekey_to : None ,
909
+ note : None ,
910
+ lease : None ,
911
+ static_fee : None ,
912
+ extra_fee : None ,
913
+ max_fee : None ,
914
+ validity_window : None ,
915
+ first_valid_round : None ,
916
+ last_valid_round : None ,
917
+ } ,
918
+ } ;
919
+ assert ! (
920
+ composer
921
+ . add_non_participation_key_registration( non_participation_params)
922
+ . is_ok( )
923
+ ) ;
924
+ assert ! ( composer. build( ) . await . is_ok( ) ) ;
925
+ assert ! ( composer. built_group( ) . is_some( ) ) ;
926
+ }
927
+
734
928
#[ tokio:: test]
735
929
async fn test_gather_signatures ( ) {
736
930
let mut composer = Composer :: new ( AlgodClient :: testnet ( ) , Some ( Arc :: new ( EmptySigner { } ) ) ) ;
0 commit comments