1use std::borrow::Cow;
4use std::fmt::Display;
5use std::path::PathBuf;
6use std::str::FromStr;
7use std::time::Duration as StdDuration;
8
9use either::Either;
10use masp_primitives::transaction::components::sapling::builder::BuildParams;
11use masp_primitives::zip32::PseudoExtendedKey;
12use namada_core::address::{Address, MASP};
13use namada_core::chain::{BlockHeight, ChainId, Epoch};
14use namada_core::collections::HashMap;
15use namada_core::dec::Dec;
16use namada_core::ethereum_events::EthAddress;
17use namada_core::keccak::KeccakHash;
18use namada_core::key::{SchemeType, common};
19use namada_core::masp::{DiversifierIndex, MaspEpoch, PaymentAddress};
20use namada_core::string_encoding::StringEncoded;
21use namada_core::time::DateTimeUtc;
22use namada_core::token::Amount;
23use namada_core::{storage, token};
24use namada_governance::cli::onchain::{
25 DefaultProposal, PgfFundingProposal, PgfStewardProposal,
26};
27use namada_ibc::IbcShieldingData;
28use namada_io::{Io, display_line};
29use namada_token::masp::utils::RetryStrategy;
30use namada_tx::Memo;
31use namada_tx::data::GasLimit;
32use serde::{Deserialize, Serialize};
33use zeroize::Zeroizing;
34
35use crate::error::Error;
36use crate::eth_bridge::bridge_pool;
37use crate::ibc::core::host::types::identifiers::{ChannelId, PortId};
38use crate::ibc::{NamadaMemo, NamadaMemoData};
39use crate::rpc::{
40 get_registry_from_xcs_osmosis_contract, osmosis_denom_from_namada_denom,
41 query_ibc_denom, query_osmosis_route_and_min_out,
42};
43use crate::signing::{SigningData, gen_disposable_signing_key};
44use crate::wallet::{DatedSpendingKey, DatedViewingKey};
45use crate::{Namada, rpc, tx};
46
47#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
50#[repr(transparent)]
51pub struct Duration(pub StdDuration);
52
53impl ::std::str::FromStr for Duration {
54 type Err = String;
55
56 #[inline]
57 fn from_str(s: &str) -> Result<Self, Self::Err> {
58 ::duration_str::parse(s).map(Duration)
59 }
60}
61
62pub trait NamadaTypes: Clone + std::fmt::Debug {
64 type Address: Clone + std::fmt::Debug;
66 type AddrOrNativeToken: Clone + std::fmt::Debug + From<Self::Address>;
68 type Keypair: Clone + std::fmt::Debug;
70 type TendermintAddress: Clone + std::fmt::Debug;
73 type ConfigRpcTendermintAddress: Clone
75 + std::fmt::Debug
76 + From<Self::TendermintAddress>;
77 type EthereumAddress: Clone + std::fmt::Debug;
79 type ViewingKey: Clone + std::fmt::Debug;
81 type SpendingKey: Clone + std::fmt::Debug;
83 type DatedViewingKey: Clone + std::fmt::Debug;
85 type DatedSpendingKey: Clone + std::fmt::Debug;
87 type PaymentAddress: Clone + std::fmt::Debug;
89 type BalanceOwner: Clone + std::fmt::Debug;
91 type PublicKey: Clone + std::fmt::Debug;
93 type TransferSource: Clone + std::fmt::Debug;
95 type TransferTarget: Clone + std::fmt::Debug;
97 type Data: Clone + std::fmt::Debug;
99 type BpConversionTable: Clone + std::fmt::Debug;
101 type MaspIndexerAddress: Clone + std::fmt::Debug;
103 type BlockHeight: Clone + std::fmt::Debug;
105}
106
107#[derive(Clone, Debug)]
109pub struct SdkTypes;
110
111#[derive(Clone, Debug, Serialize, Deserialize)]
114pub struct BpConversionTableEntry {
115 pub alias: String,
118 pub conversion_rate: f64,
120}
121
122impl NamadaTypes for SdkTypes {
123 type AddrOrNativeToken = Address;
124 type Address = Address;
125 type BalanceOwner = namada_core::masp::BalanceOwner;
126 type BlockHeight = namada_core::chain::BlockHeight;
127 type BpConversionTable = HashMap<Address, BpConversionTableEntry>;
128 type ConfigRpcTendermintAddress = tendermint_rpc::Url;
129 type Data = Vec<u8>;
130 type DatedSpendingKey = DatedSpendingKey;
131 type DatedViewingKey = DatedViewingKey;
132 type EthereumAddress = ();
133 type Keypair = namada_core::key::common::SecretKey;
134 type MaspIndexerAddress = String;
135 type PaymentAddress = namada_core::masp::PaymentAddress;
136 type PublicKey = namada_core::key::common::PublicKey;
137 type SpendingKey = PseudoExtendedKey;
138 type TendermintAddress = tendermint_rpc::Url;
139 type TransferSource = namada_core::masp::TransferSource;
140 type TransferTarget = namada_core::masp::TransferTarget;
141 type ViewingKey = namada_core::masp::ExtendedViewingKey;
142}
143
144#[derive(Clone, Debug)]
146pub struct Query<C: NamadaTypes = SdkTypes> {
147 pub ledger_address: C::ConfigRpcTendermintAddress,
149}
150
151#[derive(Clone, Debug)]
153pub struct QueryWithoutCtx<C: NamadaTypes = SdkTypes> {
154 pub ledger_address: C::TendermintAddress,
156}
157
158#[derive(Clone, Debug)]
160pub struct QueryResult<C: NamadaTypes = SdkTypes> {
161 pub query: Query<C>,
163 pub tx_hash: String,
165}
166
167#[derive(Clone, Debug)]
169pub struct TxCustom<C: NamadaTypes = SdkTypes> {
170 pub tx: Tx<C>,
172 pub code_path: Option<PathBuf>,
174 pub data_path: Option<C::Data>,
176 pub serialized_tx: Option<C::Data>,
178 pub owner: Option<C::Address>,
180 pub signatures: Vec<C::Data>,
182 pub wrapper_signature: Option<C::Data>,
184}
185
186impl<C: NamadaTypes> TxBuilder<C> for TxCustom<C> {
187 fn tx<F>(self, func: F) -> Self
188 where
189 F: FnOnce(Tx<C>) -> Tx<C>,
190 {
191 TxCustom {
192 tx: func(self.tx),
193 ..self
194 }
195 }
196}
197
198impl<C: NamadaTypes> TxCustom<C> {
199 pub fn code_path(self, code_path: PathBuf) -> Self {
201 Self {
202 code_path: Some(code_path),
203 ..self
204 }
205 }
206
207 pub fn data_path(self, data_path: C::Data) -> Self {
209 Self {
210 data_path: Some(data_path),
211 ..self
212 }
213 }
214
215 pub fn serialized_tx(self, serialized_tx: C::Data) -> Self {
217 Self {
218 serialized_tx: Some(serialized_tx),
219 ..self
220 }
221 }
222
223 pub fn owner(self, owner: Option<C::Address>) -> Self {
225 Self { owner, ..self }
226 }
227}
228
229impl TxCustom {
230 pub async fn build(
232 &self,
233 context: &impl Namada,
234 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
235 tx::build_custom(context, self).await
236 }
237}
238
239#[derive(Copy, Clone, Debug)]
241pub enum InputAmount {
242 Validated(token::DenominatedAmount),
245 Unvalidated(token::DenominatedAmount),
249}
250
251impl std::str::FromStr for InputAmount {
252 type Err = <token::DenominatedAmount as std::str::FromStr>::Err;
253
254 fn from_str(s: &str) -> Result<Self, Self::Err> {
255 token::DenominatedAmount::from_str(s).map(InputAmount::Unvalidated)
256 }
257}
258
259impl From<token::DenominatedAmount> for InputAmount {
260 fn from(amt: token::DenominatedAmount) -> Self {
261 InputAmount::Unvalidated(amt)
262 }
263}
264
265#[derive(Clone, Debug)]
267pub struct TxTransparentTransfer<C: NamadaTypes = SdkTypes> {
268 pub tx: Tx<C>,
270 pub sources: Vec<TxTransparentSource<C>>,
272 pub targets: Vec<TxTransparentTarget<C>>,
274 pub tx_code_path: PathBuf,
276}
277
278impl<C: NamadaTypes> TxBuilder<C> for TxTransparentTransfer<C> {
279 fn tx<F>(self, func: F) -> Self
280 where
281 F: FnOnce(Tx<C>) -> Tx<C>,
282 {
283 TxTransparentTransfer {
284 tx: func(self.tx),
285 ..self
286 }
287 }
288}
289
290impl<C: NamadaTypes> TxTransparentTransfer<C> {
291 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
293 Self {
294 tx_code_path,
295 ..self
296 }
297 }
298}
299
300impl TxTransparentTransfer {
301 pub async fn build(
303 &mut self,
304 context: &impl Namada,
305 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
306 tx::build_transparent_transfer(context, self).await
307 }
308}
309
310#[derive(Clone, Debug)]
312pub struct TxShieldedSource<C: NamadaTypes = SdkTypes> {
313 pub source: C::SpendingKey,
315 pub token: C::Address,
317 pub amount: InputAmount,
319}
320
321#[derive(Clone, Debug)]
323pub struct TxShieldedTarget<C: NamadaTypes = SdkTypes> {
324 pub target: C::PaymentAddress,
326 pub token: C::Address,
328 pub amount: InputAmount,
330}
331
332#[derive(Clone, Debug)]
334pub struct TxShieldedTransfer<C: NamadaTypes = SdkTypes> {
335 pub tx: Tx<C>,
337 pub sources: Vec<TxShieldedSource<C>>,
339 pub targets: Vec<TxShieldedTarget<C>>,
341 pub gas_spending_key: Option<C::SpendingKey>,
343 pub tx_code_path: PathBuf,
345}
346
347impl<C: NamadaTypes> TxBuilder<C> for TxShieldedTransfer<C> {
348 fn tx<F>(self, func: F) -> Self
349 where
350 F: FnOnce(Tx<C>) -> Tx<C>,
351 {
352 TxShieldedTransfer {
353 tx: func(self.tx),
354 ..self
355 }
356 }
357}
358
359impl TxShieldedTransfer {
360 pub async fn build(
362 &mut self,
363 context: &impl Namada,
364 bparams: &mut impl BuildParams,
365 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
366 tx::build_shielded_transfer(context, self, bparams).await
367 }
368}
369
370#[derive(Clone, Debug)]
372pub struct TxTransparentSource<C: NamadaTypes = SdkTypes> {
373 pub source: C::Address,
375 pub token: C::Address,
377 pub amount: InputAmount,
379}
380
381#[derive(Clone, Debug)]
383pub struct TxShieldingTransfer<C: NamadaTypes = SdkTypes> {
384 pub tx: Tx<C>,
386 pub targets: Vec<TxShieldedTarget<C>>,
388 pub sources: Vec<TxTransparentSource<C>>,
390 pub frontend_sus_fee: Option<(C::TransferTarget, Dec)>,
392 pub tx_code_path: PathBuf,
394}
395
396impl<C: NamadaTypes> TxBuilder<C> for TxShieldingTransfer<C> {
397 fn tx<F>(self, func: F) -> Self
398 where
399 F: FnOnce(Tx<C>) -> Tx<C>,
400 {
401 TxShieldingTransfer {
402 tx: func(self.tx),
403 ..self
404 }
405 }
406}
407
408impl TxShieldingTransfer {
409 pub async fn build(
411 &mut self,
412 context: &impl Namada,
413 bparams: &mut impl BuildParams,
414 ) -> crate::error::Result<(namada_tx::Tx, SigningData, MaspEpoch)> {
415 tx::build_shielding_transfer(context, self, bparams).await
416 }
417}
418
419#[derive(Clone, Debug)]
421pub struct TxTransparentTarget<C: NamadaTypes = SdkTypes> {
422 pub target: C::Address,
424 pub token: C::Address,
426 pub amount: InputAmount,
428}
429
430#[derive(Clone, Debug)]
432pub struct TxUnshieldingTransfer<C: NamadaTypes = SdkTypes> {
433 pub tx: Tx<C>,
435 pub sources: Vec<TxShieldedSource<C>>,
437 pub targets: Vec<TxTransparentTarget<C>>,
439 pub gas_spending_key: Option<C::SpendingKey>,
441 pub frontend_sus_fee: Option<(C::TransferTarget, Dec)>,
443 pub tx_code_path: PathBuf,
445}
446
447impl<C: NamadaTypes> TxBuilder<C> for TxUnshieldingTransfer<C> {
448 fn tx<F>(self, func: F) -> Self
449 where
450 F: FnOnce(Tx<C>) -> Tx<C>,
451 {
452 TxUnshieldingTransfer {
453 tx: func(self.tx),
454 ..self
455 }
456 }
457}
458
459impl TxUnshieldingTransfer {
460 pub async fn build(
462 &mut self,
463 context: &impl Namada,
464 bparams: &mut impl BuildParams,
465 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
466 tx::build_unshielding_transfer(context, self, bparams).await
467 }
468}
469
470#[derive(Serialize, Deserialize, Debug, Clone)]
472pub struct OsmosisPoolHop {
473 pub pool_id: String,
475 pub token_out_denom: String,
478}
479
480impl FromStr for OsmosisPoolHop {
481 type Err = String;
482
483 fn from_str(s: &str) -> Result<Self, Self::Err> {
484 s.split_once(':').map_or_else(
485 || {
486 Err(format!(
487 "Expected <pool-id>:<output-denom> string, but found \
488 {s:?} instead"
489 ))
490 },
491 |(pool_id, token_out_denom)| {
492 Ok(OsmosisPoolHop {
493 pool_id: pool_id.to_owned(),
494 token_out_denom: token_out_denom.to_owned(),
495 })
496 },
497 )
498 }
499}
500
501#[derive(Debug, Clone, Serialize, Deserialize)]
502#[serde(rename_all = "snake_case")]
503pub enum Slippage {
505 MinOutputAmount(Amount),
507 Twap {
509 slippage_percentage: Dec,
513 },
514}
515
516#[derive(Debug, Clone)]
518pub struct TxOsmosisSwap<C: NamadaTypes = SdkTypes> {
519 pub transfer: TxIbcTransfer<C>,
521 pub output_denom: String,
523 pub recipient: Either<C::Address, C::PaymentAddress>,
525 pub overflow: Option<C::Address>,
531 pub slippage: Option<Slippage>,
533 pub local_recovery_addr: String,
535 pub route: Option<Vec<OsmosisPoolHop>>,
537 pub osmosis_lcd_rpc: Option<String>,
539 pub osmosis_sqs_rpc: Option<String>,
541 pub frontend_sus_fee: Option<(C::PaymentAddress, Dec)>,
545}
546
547impl TxOsmosisSwap<SdkTypes> {
548 pub async fn into_ibc_transfer<F>(
550 self,
551 ctx: &impl Namada,
552 confirm_swap: F,
553 ) -> crate::error::Result<TxIbcTransfer<SdkTypes>>
554 where
555 F: FnOnce(&[OsmosisPoolHop], &Amount, Option<&Amount>) -> bool,
556 {
557 #[derive(Serialize)]
558 struct Memo {
559 wasm: Wasm,
560 }
561
562 #[derive(Serialize)]
563 struct Wasm {
564 contract: String,
565 msg: Message,
566 }
567
568 #[derive(Serialize)]
569 struct Message {
570 osmosis_swap: OsmosisSwap,
571 }
572
573 #[derive(Serialize)]
574 struct OsmosisSwap {
575 receiver: String,
576 output_denom: String,
577 slippage: Slippage,
578 on_failed_delivery: LocalRecoveryAddr,
579 route: Vec<OsmosisPoolHop>,
580 #[serde(skip_serializing_if = "Option::is_none")]
581 final_memo: Option<serde_json::Map<String, serde_json::Value>>,
582 }
583
584 #[derive(Serialize)]
585 struct LocalRecoveryAddr {
586 local_recovery_addr: String,
587 }
588
589 #[inline]
590 fn assert_json_obj(
591 value: serde_json::Value,
592 ) -> serde_json::Map<String, serde_json::Value> {
593 match value {
594 serde_json::Value::Object(x) => x,
595 _ => unreachable!(),
596 }
597 }
598
599 const OSMOSIS_SQS_SERVER: &str = "https://sqsprod.osmosis.zone";
600 const OSMOSIS_LCD_SERVER: &str = "https://lcd.osmosis.zone";
601
602 let Self {
603 mut transfer,
604 recipient,
605 slippage,
606 local_recovery_addr,
607 route: fixed_route,
608 overflow,
609 osmosis_lcd_rpc,
610 osmosis_sqs_rpc,
611 output_denom: namada_output_denom,
612 frontend_sus_fee,
613 } = self;
614
615 let osmosis_lcd_rpc = osmosis_lcd_rpc
616 .map_or(Cow::Borrowed(OSMOSIS_LCD_SERVER), Cow::Owned);
617 let osmosis_sqs_rpc = osmosis_sqs_rpc
618 .map_or(Cow::Borrowed(OSMOSIS_SQS_SERVER), Cow::Owned);
619
620 let recipient = recipient.map_either(
621 |addr| addr,
622 |payment_addr| async move {
623 let overflow_receiver = if let Some(overflow) = overflow {
624 overflow
625 } else {
626 let addr = (&gen_disposable_signing_key(ctx).await).into();
627 display_line!(
628 ctx.io(),
629 "Sending unshielded funds to disposable address {addr}",
630 );
631 addr
632 };
633 (payment_addr, overflow_receiver)
634 },
635 );
636
637 if !bech32::decode(&local_recovery_addr)
639 .is_ok_and(|(hrp, data)| hrp.as_str() == "osmo" && data.len() == 20)
640 {
641 return Err(Error::Other(format!(
642 "Invalid Osmosis recovery address {local_recovery_addr:?}"
643 )));
644 }
645 if !bech32::decode(&transfer.receiver)
646 .is_ok_and(|(hrp, data)| hrp.as_str() == "osmo" && data.len() == 32)
647 {
648 return Err(Error::Other(format!(
649 "Invalid Osmosis contract address {local_recovery_addr:?}"
650 )));
651 }
652
653 let registry_xcs_addr = get_registry_from_xcs_osmosis_contract(
654 &osmosis_lcd_rpc,
655 &transfer.receiver,
656 )
657 .await?;
658
659 let namada_input_denom =
660 query_ibc_denom(ctx, transfer.token.to_string(), None).await;
661
662 let (osmosis_input_denom, _) = osmosis_denom_from_namada_denom(
663 &osmosis_lcd_rpc,
664 ®istry_xcs_addr,
665 &namada_input_denom,
666 )
667 .await?;
668
669 let (osmosis_output_denom, namada_output_addr) =
670 osmosis_denom_from_namada_denom(
671 &osmosis_lcd_rpc,
672 ®istry_xcs_addr,
673 &namada_output_denom,
674 )
675 .await?;
676
677 let (route, trade_min_output_amount, quote) =
678 query_osmosis_route_and_min_out(
679 ctx,
680 &transfer.token,
681 &osmosis_input_denom,
682 transfer.amount,
683 &osmosis_output_denom,
684 &osmosis_sqs_rpc,
685 fixed_route,
686 slippage,
687 )
688 .await?;
689
690 if !confirm_swap(&route, &trade_min_output_amount, quote.as_ref()) {
691 return Err(Error::Other("Swap has been cancelled".to_owned()));
692 }
693
694 let (receiver, final_memo) = match recipient {
695 Either::Left(transparent_recipient) => {
696 (transparent_recipient.encode_compat(), None)
697 }
698 Either::Right(fut) => {
699 let (payment_addr, overflow_receiver) = fut.await;
700
701 let amount_to_shield = trade_min_output_amount;
702 let shielding_tx = tx::gen_ibc_shielding_transfer(
703 ctx,
704 GenIbcShieldingTransfer {
705 query: Query {
706 ledger_address: transfer.tx.ledger_address.clone(),
707 },
708 output_folder: None,
709 target: payment_addr,
710 asset: IbcShieldingTransferAsset::Address(
711 namada_output_addr,
712 ),
713 amount: InputAmount::Validated(
714 token::DenominatedAmount::new(
715 amount_to_shield,
716 0u8.into(),
717 ),
718 ),
719 expiration: transfer.tx.expiration.clone(),
720 frontend_sus_fee,
721 },
722 )
723 .await?
724 .ok_or_else(|| {
725 Error::Other(
726 "Failed to generate IBC shielding transfer".to_owned(),
727 )
728 })?;
729
730 let memo = assert_json_obj(
731 serde_json::to_value(&NamadaMemo {
732 namada: NamadaMemoData::OsmosisSwap {
733 shielding_data: StringEncoded::new(
734 IbcShieldingData(shielding_tx),
735 ),
736 shielded_amount: amount_to_shield,
737 overflow_receiver,
738 },
739 })
740 .unwrap(),
741 );
742
743 (MASP.encode_compat(), Some(memo))
744 }
745 };
746
747 let cosmwasm_memo = Memo {
748 wasm: Wasm {
749 contract: transfer.receiver.clone(),
750 msg: Message {
751 osmosis_swap: OsmosisSwap {
752 output_denom: osmosis_output_denom,
753 slippage: Slippage::MinOutputAmount(
754 trade_min_output_amount,
755 ),
756 final_memo,
757 receiver,
758 on_failed_delivery: LocalRecoveryAddr {
759 local_recovery_addr,
760 },
761 route,
762 },
763 },
764 },
765 };
766 let namada_memo = transfer.ibc_memo.take().map(|memo| {
767 assert_json_obj(
768 serde_json::to_value(&NamadaMemo {
769 namada: NamadaMemoData::Memo(memo),
770 })
771 .unwrap(),
772 )
773 });
774
775 let memo = {
776 let mut m = serde_json::to_value(&cosmwasm_memo).unwrap();
777 let m_obj = m.as_object_mut().unwrap();
778
779 if let Some(mut namada_memo) = namada_memo {
780 m_obj.append(&mut namada_memo);
781 }
782
783 m
784 };
785
786 transfer.ibc_memo = Some(serde_json::to_string(&memo).unwrap());
787 Ok(transfer)
788 }
789}
790
791#[derive(Clone, Debug)]
793pub struct TxIbcTransfer<C: NamadaTypes = SdkTypes> {
794 pub tx: Tx<C>,
796 pub source: C::TransferSource,
798 pub receiver: String,
800 pub token: C::Address,
802 pub amount: InputAmount,
804 pub port_id: PortId,
806 pub channel_id: ChannelId,
808 pub timeout_height: Option<u64>,
810 pub timeout_sec_offset: Option<u64>,
812 pub refund_target: Option<C::TransferTarget>,
814 pub ibc_shielding_data: Option<IbcShieldingData>,
816 pub ibc_memo: Option<String>,
818 pub gas_spending_key: Option<C::SpendingKey>,
820 pub frontend_sus_fee: Option<(C::TransferTarget, Dec)>,
822 pub tx_code_path: PathBuf,
824}
825
826impl<C: NamadaTypes> TxBuilder<C> for TxIbcTransfer<C> {
827 fn tx<F>(self, func: F) -> Self
828 where
829 F: FnOnce(Tx<C>) -> Tx<C>,
830 {
831 TxIbcTransfer {
832 tx: func(self.tx),
833 ..self
834 }
835 }
836}
837
838impl<C: NamadaTypes> TxIbcTransfer<C> {
839 pub fn source(self, source: C::TransferSource) -> Self {
841 Self { source, ..self }
842 }
843
844 pub fn receiver(self, receiver: String) -> Self {
846 Self { receiver, ..self }
847 }
848
849 pub fn token(self, token: C::Address) -> Self {
851 Self { token, ..self }
852 }
853
854 pub fn amount(self, amount: InputAmount) -> Self {
856 Self { amount, ..self }
857 }
858
859 pub fn port_id(self, port_id: PortId) -> Self {
861 Self { port_id, ..self }
862 }
863
864 pub fn channel_id(self, channel_id: ChannelId) -> Self {
866 Self { channel_id, ..self }
867 }
868
869 pub fn timeout_height(self, timeout_height: u64) -> Self {
871 Self {
872 timeout_height: Some(timeout_height),
873 ..self
874 }
875 }
876
877 pub fn timeout_sec_offset(self, timeout_sec_offset: u64) -> Self {
879 Self {
880 timeout_sec_offset: Some(timeout_sec_offset),
881 ..self
882 }
883 }
884
885 pub fn refund_target(self, refund_target: C::TransferTarget) -> Self {
887 Self {
888 refund_target: Some(refund_target),
889 ..self
890 }
891 }
892
893 pub fn ibc_shielding_data(self, shielding_data: IbcShieldingData) -> Self {
895 Self {
896 ibc_shielding_data: Some(shielding_data),
897 ..self
898 }
899 }
900
901 pub fn ibc_memo(self, ibc_memo: String) -> Self {
903 Self {
904 ibc_memo: Some(ibc_memo),
905 ..self
906 }
907 }
908
909 pub fn gas_spending_keys(self, gas_spending_key: C::SpendingKey) -> Self {
911 Self {
912 gas_spending_key: Some(gas_spending_key),
913 ..self
914 }
915 }
916
917 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
919 Self {
920 tx_code_path,
921 ..self
922 }
923 }
924}
925
926impl TxIbcTransfer {
927 pub async fn build(
929 &self,
930 context: &impl Namada,
931 bparams: &mut impl BuildParams,
932 ) -> crate::error::Result<(namada_tx::Tx, SigningData, Option<MaspEpoch>)>
933 {
934 tx::build_ibc_transfer(context, self, bparams).await
935 }
936}
937
938#[derive(Clone, Debug)]
940pub struct InitProposal<C: NamadaTypes = SdkTypes> {
941 pub tx: Tx<C>,
943 pub proposal_data: C::Data,
945 pub is_pgf_stewards: bool,
947 pub is_pgf_funding: bool,
949 pub tx_code_path: PathBuf,
951}
952
953impl<C: NamadaTypes> TxBuilder<C> for InitProposal<C> {
954 fn tx<F>(self, func: F) -> Self
955 where
956 F: FnOnce(Tx<C>) -> Tx<C>,
957 {
958 InitProposal {
959 tx: func(self.tx),
960 ..self
961 }
962 }
963}
964
965impl<C: NamadaTypes> InitProposal<C> {
966 pub fn proposal_data(self, proposal_data: C::Data) -> Self {
968 Self {
969 proposal_data,
970 ..self
971 }
972 }
973
974 pub fn is_pgf_stewards(self, is_pgf_stewards: bool) -> Self {
976 Self {
977 is_pgf_stewards,
978 ..self
979 }
980 }
981
982 pub fn is_pgf_funding(self, is_pgf_funding: bool) -> Self {
984 Self {
985 is_pgf_funding,
986 ..self
987 }
988 }
989
990 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
992 Self {
993 tx_code_path,
994 ..self
995 }
996 }
997}
998
999impl InitProposal {
1000 pub async fn build(
1002 &self,
1003 context: &impl Namada,
1004 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
1005 let current_epoch = rpc::query_epoch(context.client()).await?;
1006 let governance_parameters =
1007 rpc::query_governance_parameters(context.client()).await;
1008
1009 if self.is_pgf_funding {
1010 let proposal = PgfFundingProposal::try_from(
1011 self.proposal_data.as_ref(),
1012 )
1013 .map_err(|e| {
1014 crate::error::TxSubmitError::FailedGovernaneProposalDeserialize(
1015 e.to_string(),
1016 )
1017 })?
1018 .validate(&governance_parameters, current_epoch, self.tx.force)
1019 .map_err(|e| {
1020 crate::error::TxSubmitError::InvalidProposal(e.to_string())
1021 })?;
1022
1023 tx::build_pgf_funding_proposal(context, self, proposal).await
1024 } else if self.is_pgf_stewards {
1025 let proposal = PgfStewardProposal::try_from(
1026 self.proposal_data.as_ref(),
1027 )
1028 .map_err(|e| {
1029 crate::error::TxSubmitError::FailedGovernaneProposalDeserialize(
1030 e.to_string(),
1031 )
1032 })?;
1033 let nam_address = context.native_token();
1034 let author_balance = rpc::get_token_balance(
1035 context.client(),
1036 &nam_address,
1037 &proposal.proposal.author,
1038 None,
1039 )
1040 .await?;
1041 let proposal = proposal
1042 .validate(
1043 &governance_parameters,
1044 current_epoch,
1045 author_balance,
1046 self.tx.force,
1047 )
1048 .map_err(|e| {
1049 crate::error::TxSubmitError::InvalidProposal(e.to_string())
1050 })?;
1051
1052 tx::build_pgf_stewards_proposal(context, self, proposal).await
1053 } else {
1054 let proposal = DefaultProposal::try_from(
1055 self.proposal_data.as_ref(),
1056 )
1057 .map_err(|e| {
1058 crate::error::TxSubmitError::FailedGovernaneProposalDeserialize(
1059 e.to_string(),
1060 )
1061 })?;
1062 let nam_address = context.native_token();
1063 let author_balance = rpc::get_token_balance(
1064 context.client(),
1065 &nam_address,
1066 &proposal.proposal.author,
1067 None,
1068 )
1069 .await?;
1070 let proposal = proposal
1071 .validate(
1072 &governance_parameters,
1073 current_epoch,
1074 author_balance,
1075 self.tx.force,
1076 )
1077 .map_err(|e| {
1078 crate::error::TxSubmitError::InvalidProposal(e.to_string())
1079 })?;
1080 tx::build_default_proposal(context, self, proposal).await
1081 }
1082 }
1083}
1084
1085#[derive(Clone, Debug)]
1087pub struct VoteProposal<C: NamadaTypes = SdkTypes> {
1088 pub tx: Tx<C>,
1090 pub proposal_id: u64,
1092 pub vote: String,
1094 pub voter_address: C::Address,
1096 pub tx_code_path: PathBuf,
1098}
1099
1100impl<C: NamadaTypes> TxBuilder<C> for VoteProposal<C> {
1101 fn tx<F>(self, func: F) -> Self
1102 where
1103 F: FnOnce(Tx<C>) -> Tx<C>,
1104 {
1105 VoteProposal {
1106 tx: func(self.tx),
1107 ..self
1108 }
1109 }
1110}
1111
1112impl<C: NamadaTypes> VoteProposal<C> {
1113 pub fn proposal_id(self, proposal_id: u64) -> Self {
1115 Self {
1116 proposal_id,
1117 ..self
1118 }
1119 }
1120
1121 pub fn vote(self, vote: String) -> Self {
1123 Self { vote, ..self }
1124 }
1125
1126 pub fn voter(self, voter_address: C::Address) -> Self {
1128 Self {
1129 voter_address,
1130 ..self
1131 }
1132 }
1133
1134 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
1136 Self {
1137 tx_code_path,
1138 ..self
1139 }
1140 }
1141}
1142
1143impl VoteProposal {
1144 pub async fn build(
1146 &self,
1147 context: &impl Namada,
1148 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
1149 let current_epoch = rpc::query_epoch(context.client()).await?;
1150 tx::build_vote_proposal(context, self, current_epoch).await
1151 }
1152}
1153
1154#[derive(Clone, Debug)]
1156pub struct TxInitAccount<C: NamadaTypes = SdkTypes> {
1157 pub tx: Tx<C>,
1159 pub vp_code_path: PathBuf,
1161 pub tx_code_path: PathBuf,
1163 pub public_keys: Vec<C::PublicKey>,
1165 pub threshold: Option<u8>,
1167}
1168
1169impl<C: NamadaTypes> TxBuilder<C> for TxInitAccount<C> {
1170 fn tx<F>(self, func: F) -> Self
1171 where
1172 F: FnOnce(Tx<C>) -> Tx<C>,
1173 {
1174 TxInitAccount {
1175 tx: func(self.tx),
1176 ..self
1177 }
1178 }
1179}
1180
1181impl<C: NamadaTypes> TxInitAccount<C> {
1182 pub fn public_keys(self, public_keys: Vec<C::PublicKey>) -> Self {
1184 Self {
1185 public_keys,
1186 ..self
1187 }
1188 }
1189
1190 pub fn threshold(self, threshold: u8) -> Self {
1192 Self {
1193 threshold: Some(threshold),
1194 ..self
1195 }
1196 }
1197
1198 pub fn vp_code_path(self, vp_code_path: PathBuf) -> Self {
1200 Self {
1201 vp_code_path,
1202 ..self
1203 }
1204 }
1205
1206 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
1208 Self {
1209 tx_code_path,
1210 ..self
1211 }
1212 }
1213}
1214
1215impl TxInitAccount {
1216 pub async fn build(
1218 &self,
1219 context: &impl Namada,
1220 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
1221 tx::build_init_account(context, self).await
1222 }
1223}
1224
1225#[derive(Clone, Debug)]
1227pub struct TxBecomeValidator<C: NamadaTypes = SdkTypes> {
1228 pub tx: Tx<C>,
1230 pub address: C::Address,
1232 pub scheme: SchemeType,
1234 pub consensus_key: Option<C::PublicKey>,
1236 pub eth_cold_key: Option<C::PublicKey>,
1238 pub eth_hot_key: Option<C::PublicKey>,
1240 pub protocol_key: Option<C::PublicKey>,
1242 pub commission_rate: Dec,
1244 pub max_commission_rate_change: Dec,
1246 pub email: String,
1248 pub description: Option<String>,
1250 pub website: Option<String>,
1252 pub discord_handle: Option<String>,
1254 pub avatar: Option<String>,
1256 pub name: Option<String>,
1258 pub tx_code_path: PathBuf,
1260 pub unsafe_dont_encrypt: bool,
1262}
1263
1264impl<C: NamadaTypes> TxBuilder<C> for TxBecomeValidator<C> {
1265 fn tx<F>(self, func: F) -> Self
1266 where
1267 F: FnOnce(Tx<C>) -> Tx<C>,
1268 {
1269 TxBecomeValidator {
1270 tx: func(self.tx),
1271 ..self
1272 }
1273 }
1274}
1275
1276impl<C: NamadaTypes> TxBecomeValidator<C> {
1277 pub fn address(self, address: C::Address) -> Self {
1279 Self { address, ..self }
1280 }
1281
1282 pub fn commission_rate(self, commission_rate: Dec) -> Self {
1284 Self {
1285 commission_rate,
1286 ..self
1287 }
1288 }
1289
1290 pub fn max_commission_rate_change(
1292 self,
1293 max_commission_rate_change: Dec,
1294 ) -> Self {
1295 Self {
1296 max_commission_rate_change,
1297 ..self
1298 }
1299 }
1300
1301 pub fn email(self, email: String) -> Self {
1303 Self { email, ..self }
1304 }
1305
1306 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
1308 Self {
1309 tx_code_path,
1310 ..self
1311 }
1312 }
1313}
1314
1315impl TxBecomeValidator {
1316 pub async fn build(
1318 &self,
1319 context: &impl Namada,
1320 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
1321 tx::build_become_validator(context, self).await
1322 }
1323}
1324
1325#[derive(Clone, Debug)]
1327pub struct TxInitValidator<C: NamadaTypes = SdkTypes> {
1328 pub tx: Tx<C>,
1330 pub scheme: SchemeType,
1332 pub account_keys: Vec<C::PublicKey>,
1334 pub threshold: Option<u8>,
1336 pub consensus_key: Option<C::PublicKey>,
1338 pub eth_cold_key: Option<C::PublicKey>,
1340 pub eth_hot_key: Option<C::PublicKey>,
1342 pub protocol_key: Option<C::PublicKey>,
1344 pub commission_rate: Dec,
1346 pub max_commission_rate_change: Dec,
1348 pub email: String,
1350 pub description: Option<String>,
1352 pub website: Option<String>,
1354 pub discord_handle: Option<String>,
1356 pub avatar: Option<String>,
1358 pub name: Option<String>,
1360 pub validator_vp_code_path: PathBuf,
1362 pub tx_init_account_code_path: PathBuf,
1364 pub tx_become_validator_code_path: PathBuf,
1366 pub unsafe_dont_encrypt: bool,
1368}
1369
1370#[derive(Clone, Debug)]
1372pub struct TxUpdateAccount<C: NamadaTypes = SdkTypes> {
1373 pub tx: Tx<C>,
1375 pub vp_code_path: Option<PathBuf>,
1377 pub tx_code_path: PathBuf,
1379 pub addr: C::Address,
1381 pub public_keys: Vec<C::PublicKey>,
1383 pub threshold: Option<u8>,
1385}
1386
1387impl<C: NamadaTypes> TxBuilder<C> for TxUpdateAccount<C> {
1388 fn tx<F>(self, func: F) -> Self
1389 where
1390 F: FnOnce(Tx<C>) -> Tx<C>,
1391 {
1392 TxUpdateAccount {
1393 tx: func(self.tx),
1394 ..self
1395 }
1396 }
1397}
1398
1399impl<C: NamadaTypes> TxUpdateAccount<C> {
1400 pub fn vp_code_path(self, vp_code_path: PathBuf) -> Self {
1402 Self {
1403 vp_code_path: Some(vp_code_path),
1404 ..self
1405 }
1406 }
1407
1408 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
1410 Self {
1411 tx_code_path,
1412 ..self
1413 }
1414 }
1415
1416 pub fn addr(self, addr: C::Address) -> Self {
1418 Self { addr, ..self }
1419 }
1420
1421 pub fn public_keys(self, public_keys: Vec<C::PublicKey>) -> Self {
1423 Self {
1424 public_keys,
1425 ..self
1426 }
1427 }
1428
1429 pub fn threshold(self, threshold: u8) -> Self {
1431 Self {
1432 threshold: Some(threshold),
1433 ..self
1434 }
1435 }
1436}
1437
1438impl TxUpdateAccount {
1439 pub async fn build(
1441 &self,
1442 context: &impl Namada,
1443 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
1444 tx::build_update_account(context, self).await
1445 }
1446}
1447
1448#[derive(Clone, Debug)]
1450pub struct Bond<C: NamadaTypes = SdkTypes> {
1451 pub tx: Tx<C>,
1453 pub validator: C::Address,
1455 pub amount: token::Amount,
1457 pub source: Option<C::Address>,
1460 pub tx_code_path: PathBuf,
1462}
1463
1464impl<C: NamadaTypes> TxBuilder<C> for Bond<C> {
1465 fn tx<F>(self, func: F) -> Self
1466 where
1467 F: FnOnce(Tx<C>) -> Tx<C>,
1468 {
1469 Bond {
1470 tx: func(self.tx),
1471 ..self
1472 }
1473 }
1474}
1475
1476impl<C: NamadaTypes> Bond<C> {
1477 pub fn validator(self, validator: C::Address) -> Self {
1479 Self { validator, ..self }
1480 }
1481
1482 pub fn amount(self, amount: token::Amount) -> Self {
1484 Self { amount, ..self }
1485 }
1486
1487 pub fn source(self, source: C::Address) -> Self {
1490 Self {
1491 source: Some(source),
1492 ..self
1493 }
1494 }
1495
1496 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
1498 Self {
1499 tx_code_path,
1500 ..self
1501 }
1502 }
1503}
1504
1505impl Bond {
1506 pub async fn build(
1508 &self,
1509 context: &impl Namada,
1510 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
1511 tx::build_bond(context, self).await
1512 }
1513}
1514
1515#[derive(Clone, Debug)]
1517pub struct Unbond<C: NamadaTypes = SdkTypes> {
1518 pub tx: Tx<C>,
1520 pub validator: C::Address,
1522 pub amount: token::Amount,
1524 pub source: Option<C::Address>,
1527 pub tx_code_path: PathBuf,
1529}
1530
1531impl Unbond {
1532 pub async fn build(
1534 &self,
1535 context: &impl Namada,
1536 ) -> crate::error::Result<(
1537 namada_tx::Tx,
1538 SigningData,
1539 Option<(Epoch, token::Amount)>,
1540 )> {
1541 tx::build_unbond(context, self).await
1542 }
1543}
1544
1545impl<C: NamadaTypes> TxBuilder<C> for Unbond<C> {
1546 fn tx<F>(self, func: F) -> Self
1547 where
1548 F: FnOnce(Tx<C>) -> Tx<C>,
1549 {
1550 Unbond {
1551 tx: func(self.tx),
1552 ..self
1553 }
1554 }
1555}
1556
1557impl<C: NamadaTypes> Unbond<C> {
1558 pub fn validator(self, validator: C::Address) -> Self {
1560 Self { validator, ..self }
1561 }
1562
1563 pub fn amount(self, amount: token::Amount) -> Self {
1565 Self { amount, ..self }
1566 }
1567
1568 pub fn source(self, source: C::Address) -> Self {
1571 Self {
1572 source: Some(source),
1573 ..self
1574 }
1575 }
1576
1577 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
1579 Self {
1580 tx_code_path,
1581 ..self
1582 }
1583 }
1584}
1585
1586#[derive(Clone, Debug)]
1588pub struct Redelegate<C: NamadaTypes = SdkTypes> {
1589 pub tx: Tx<C>,
1591 pub src_validator: C::Address,
1593 pub dest_validator: C::Address,
1595 pub owner: C::Address,
1597 pub amount: token::Amount,
1599 pub tx_code_path: PathBuf,
1601}
1602
1603impl Redelegate {
1604 pub async fn build(
1606 &self,
1607 context: &impl Namada,
1608 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
1609 tx::build_redelegation(context, self).await
1610 }
1611}
1612
1613impl<C: NamadaTypes> Redelegate<C> {
1614 pub fn src_validator(self, src_validator: C::Address) -> Self {
1616 Self {
1617 src_validator,
1618 ..self
1619 }
1620 }
1621
1622 pub fn dest_validator(self, dest_validator: C::Address) -> Self {
1624 Self {
1625 dest_validator,
1626 ..self
1627 }
1628 }
1629
1630 pub fn owner(self, owner: C::Address) -> Self {
1632 Self { owner, ..self }
1633 }
1634
1635 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
1637 Self {
1638 tx_code_path,
1639 ..self
1640 }
1641 }
1642}
1643
1644impl<C: NamadaTypes> TxBuilder<C> for Redelegate<C> {
1645 fn tx<F>(self, func: F) -> Self
1646 where
1647 F: FnOnce(Tx<C>) -> Tx<C>,
1648 {
1649 Redelegate {
1650 tx: func(self.tx),
1651 ..self
1652 }
1653 }
1654}
1655
1656#[derive(Clone, Debug)]
1658pub struct RevealPk<C: NamadaTypes = SdkTypes> {
1659 pub tx: Tx<C>,
1661 pub public_key: C::PublicKey,
1663}
1664
1665impl<C: NamadaTypes> TxBuilder<C> for RevealPk<C> {
1666 fn tx<F>(self, func: F) -> Self
1667 where
1668 F: FnOnce(Tx<C>) -> Tx<C>,
1669 {
1670 RevealPk {
1671 tx: func(self.tx),
1672 ..self
1673 }
1674 }
1675}
1676
1677impl<C: NamadaTypes> RevealPk<C> {
1678 pub fn public_key(self, public_key: C::PublicKey) -> Self {
1680 Self { public_key, ..self }
1681 }
1682}
1683
1684impl RevealPk {
1685 pub async fn build(
1687 &self,
1688 context: &impl Namada,
1689 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
1690 tx::build_reveal_pk(context, &self.tx, &self.public_key).await
1691 }
1692}
1693
1694#[derive(Clone, Debug)]
1696pub struct Complete {
1697 pub shell: Shell,
1699}
1700
1701#[allow(missing_docs)]
1703#[derive(Clone, Copy, Debug)]
1704pub enum Shell {
1705 Bash,
1706 Elvish,
1707 Fish,
1708 PowerShell,
1709 Zsh,
1710 Nushell,
1711}
1712
1713impl Display for Shell {
1714 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1715 self.possible_value().get_name().fmt(f)
1716 }
1717}
1718
1719impl FromStr for Shell {
1720 type Err = String;
1721
1722 fn from_str(s: &str) -> Result<Self, Self::Err> {
1723 use clap::ValueEnum;
1724
1725 for variant in Self::value_variants() {
1726 if variant.possible_value().matches(s, false) {
1727 return Ok(*variant);
1728 }
1729 }
1730 Err(format!("invalid variant: {s}"))
1731 }
1732}
1733
1734impl Shell {
1735 fn possible_value(&self) -> clap::builder::PossibleValue {
1736 use clap::builder::PossibleValue;
1737 match self {
1738 Shell::Bash => PossibleValue::new("bash"),
1739 Shell::Elvish => PossibleValue::new("elvish"),
1740 Shell::Fish => PossibleValue::new("fish"),
1741 Shell::PowerShell => PossibleValue::new("powershell"),
1742 Shell::Zsh => PossibleValue::new("zsh"),
1743 Shell::Nushell => PossibleValue::new("nushell"),
1744 }
1745 }
1746}
1747
1748impl clap::ValueEnum for Shell {
1749 fn value_variants<'a>() -> &'a [Self] {
1750 &[
1751 Shell::Bash,
1752 Shell::Elvish,
1753 Shell::Fish,
1754 Shell::PowerShell,
1755 Shell::Zsh,
1756 Shell::Nushell,
1757 ]
1758 }
1759
1760 fn to_possible_value<'a>(&self) -> Option<clap::builder::PossibleValue> {
1761 Some(self.possible_value())
1762 }
1763}
1764
1765#[derive(Clone, Debug)]
1767pub struct QueryProposalVotes<C: NamadaTypes = SdkTypes> {
1768 pub query: Query<C>,
1770 pub proposal_id: u64,
1772 pub voter: Option<C::Address>,
1774}
1775
1776#[derive(Clone, Debug)]
1778pub struct QueryProposal<C: NamadaTypes = SdkTypes> {
1779 pub query: Query<C>,
1781 pub proposal_id: Option<u64>,
1783}
1784
1785#[derive(Clone, Debug)]
1787pub struct QueryProtocolParameters<C: NamadaTypes = SdkTypes> {
1788 pub query: Query<C>,
1790}
1791
1792#[derive(Clone, Debug)]
1794pub struct QueryPgf<C: NamadaTypes = SdkTypes> {
1795 pub query: Query<C>,
1797}
1798
1799#[derive(Clone, Debug)]
1801pub struct Withdraw<C: NamadaTypes = SdkTypes> {
1802 pub tx: Tx<C>,
1804 pub validator: C::Address,
1806 pub source: Option<C::Address>,
1809 pub tx_code_path: PathBuf,
1811}
1812
1813impl<C: NamadaTypes> TxBuilder<C> for Withdraw<C> {
1814 fn tx<F>(self, func: F) -> Self
1815 where
1816 F: FnOnce(Tx<C>) -> Tx<C>,
1817 {
1818 Withdraw {
1819 tx: func(self.tx),
1820 ..self
1821 }
1822 }
1823}
1824
1825impl<C: NamadaTypes> Withdraw<C> {
1826 pub fn validator(self, validator: C::Address) -> Self {
1828 Self { validator, ..self }
1829 }
1830
1831 pub fn source(self, source: C::Address) -> Self {
1834 Self {
1835 source: Some(source),
1836 ..self
1837 }
1838 }
1839
1840 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
1842 Self {
1843 tx_code_path,
1844 ..self
1845 }
1846 }
1847}
1848
1849impl Withdraw {
1850 pub async fn build(
1852 &self,
1853 context: &impl Namada,
1854 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
1855 tx::build_withdraw(context, self).await
1856 }
1857}
1858
1859#[derive(Clone, Debug)]
1861pub struct ClaimRewards<C: NamadaTypes = SdkTypes> {
1862 pub tx: Tx<C>,
1864 pub validator: C::Address,
1866 pub source: Option<C::Address>,
1869 pub tx_code_path: PathBuf,
1871}
1872
1873impl<C: NamadaTypes> TxBuilder<C> for ClaimRewards<C> {
1874 fn tx<F>(self, func: F) -> Self
1875 where
1876 F: FnOnce(Tx<C>) -> Tx<C>,
1877 {
1878 ClaimRewards {
1879 tx: func(self.tx),
1880 ..self
1881 }
1882 }
1883}
1884
1885impl ClaimRewards {
1886 pub async fn build(
1888 &self,
1889 context: &impl Namada,
1890 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
1891 tx::build_claim_rewards(context, self).await
1892 }
1893}
1894
1895#[derive(Clone, Debug)]
1897pub struct QueryConversions<C: NamadaTypes = SdkTypes> {
1898 pub query: Query<C>,
1900 pub token: Option<C::Address>,
1902 pub epoch: Option<MaspEpoch>,
1904 pub dump_tree: bool,
1906}
1907
1908#[derive(Clone, Debug)]
1910pub struct QueryAccount<C: NamadaTypes = SdkTypes> {
1911 pub query: Query<C>,
1913 pub owner: C::Address,
1915}
1916
1917#[derive(Clone, Debug)]
1919pub struct QueryBalance<C: NamadaTypes = SdkTypes> {
1920 pub query: Query<C>,
1922 pub owner: C::BalanceOwner,
1924 pub token: C::Address,
1926 pub no_conversions: bool,
1928 pub height: Option<C::BlockHeight>,
1930}
1931
1932#[derive(Clone, Debug)]
1935pub struct QueryShieldingRewardsEstimate<C: NamadaTypes = SdkTypes> {
1936 pub query: Query<C>,
1938 pub owner: C::ViewingKey,
1940}
1941
1942#[derive(Clone, Debug)]
1944pub struct QueryTransfers<C: NamadaTypes = SdkTypes> {
1945 pub query: Query<C>,
1947 pub owner: Option<C::BalanceOwner>,
1949 pub token: Option<C::Address>,
1951}
1952
1953#[derive(Clone, Debug)]
1955pub struct QueryBonds<C: NamadaTypes = SdkTypes> {
1956 pub query: Query<C>,
1958 pub owner: Option<C::Address>,
1960 pub validator: Option<C::Address>,
1962}
1963
1964#[derive(Clone, Debug)]
1966pub struct QueryBondedStake<C: NamadaTypes = SdkTypes> {
1967 pub query: Query<C>,
1969 pub validator: Option<C::Address>,
1971 pub epoch: Option<Epoch>,
1973}
1974
1975#[derive(Clone, Debug)]
1977pub struct QueryValidatorState<C: NamadaTypes = SdkTypes> {
1978 pub query: Query<C>,
1980 pub validator: C::Address,
1982 pub epoch: Option<Epoch>,
1984}
1985
1986#[derive(Clone, Debug)]
1987pub struct CommissionRateChange<C: NamadaTypes = SdkTypes> {
1989 pub tx: Tx<C>,
1991 pub validator: C::Address,
1993 pub rate: Dec,
1995 pub tx_code_path: PathBuf,
1997}
1998
1999impl<C: NamadaTypes> TxBuilder<C> for CommissionRateChange<C> {
2000 fn tx<F>(self, func: F) -> Self
2001 where
2002 F: FnOnce(Tx<C>) -> Tx<C>,
2003 {
2004 CommissionRateChange {
2005 tx: func(self.tx),
2006 ..self
2007 }
2008 }
2009}
2010
2011impl<C: NamadaTypes> CommissionRateChange<C> {
2012 pub fn validator(self, validator: C::Address) -> Self {
2014 Self { validator, ..self }
2015 }
2016
2017 pub fn rate(self, rate: Dec) -> Self {
2019 Self { rate, ..self }
2020 }
2021
2022 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
2024 Self {
2025 tx_code_path,
2026 ..self
2027 }
2028 }
2029}
2030
2031impl CommissionRateChange {
2032 pub async fn build(
2034 &self,
2035 context: &impl Namada,
2036 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
2037 tx::build_validator_commission_change(context, self).await
2038 }
2039}
2040
2041#[derive(Clone, Debug)]
2042pub struct ConsensusKeyChange<C: NamadaTypes = SdkTypes> {
2044 pub tx: Tx<C>,
2046 pub validator: C::Address,
2048 pub consensus_key: Option<C::PublicKey>,
2050 pub unsafe_dont_encrypt: bool,
2052 pub tx_code_path: PathBuf,
2054}
2055
2056impl<C: NamadaTypes> TxBuilder<C> for ConsensusKeyChange<C> {
2057 fn tx<F>(self, func: F) -> Self
2058 where
2059 F: FnOnce(Tx<C>) -> Tx<C>,
2060 {
2061 ConsensusKeyChange {
2062 tx: func(self.tx),
2063 ..self
2064 }
2065 }
2066}
2067
2068impl<C: NamadaTypes> ConsensusKeyChange<C> {
2069 pub fn validator(self, validator: C::Address) -> Self {
2071 Self { validator, ..self }
2072 }
2073
2074 pub fn consensus_key(self, consensus_key: C::PublicKey) -> Self {
2076 Self {
2077 consensus_key: Some(consensus_key),
2078 ..self
2079 }
2080 }
2081
2082 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
2084 Self {
2085 tx_code_path,
2086 ..self
2087 }
2088 }
2089}
2090
2091impl ConsensusKeyChange {
2092 pub async fn build(
2094 &self,
2095 context: &impl Namada,
2096 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
2097 tx::build_change_consensus_key(context, self).await
2098 }
2099}
2100
2101#[derive(Clone, Debug)]
2102pub struct MetaDataChange<C: NamadaTypes = SdkTypes> {
2104 pub tx: Tx<C>,
2106 pub validator: C::Address,
2108 pub email: Option<String>,
2110 pub description: Option<String>,
2112 pub website: Option<String>,
2114 pub discord_handle: Option<String>,
2116 pub avatar: Option<String>,
2118 pub name: Option<String>,
2120 pub commission_rate: Option<Dec>,
2122 pub tx_code_path: PathBuf,
2124}
2125
2126impl<C: NamadaTypes> TxBuilder<C> for MetaDataChange<C> {
2127 fn tx<F>(self, func: F) -> Self
2128 where
2129 F: FnOnce(Tx<C>) -> Tx<C>,
2130 {
2131 MetaDataChange {
2132 tx: func(self.tx),
2133 ..self
2134 }
2135 }
2136}
2137
2138impl<C: NamadaTypes> MetaDataChange<C> {
2139 pub fn validator(self, validator: C::Address) -> Self {
2141 Self { validator, ..self }
2142 }
2143
2144 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
2146 Self {
2147 tx_code_path,
2148 ..self
2149 }
2150 }
2151
2152 pub fn email(self, email: String) -> Self {
2154 Self {
2155 email: Some(email),
2156 ..self
2157 }
2158 }
2159
2160 pub fn description(self, description: String) -> Self {
2162 Self {
2163 description: Some(description),
2164 ..self
2165 }
2166 }
2167
2168 pub fn website(self, website: String) -> Self {
2170 Self {
2171 website: Some(website),
2172 ..self
2173 }
2174 }
2175
2176 pub fn discord_handle(self, discord_handle: String) -> Self {
2178 Self {
2179 discord_handle: Some(discord_handle),
2180 ..self
2181 }
2182 }
2183
2184 pub fn avatar(self, avatar: String) -> Self {
2186 Self {
2187 avatar: Some(avatar),
2188 ..self
2189 }
2190 }
2191
2192 pub fn name(self, name: String) -> Self {
2194 Self {
2195 name: Some(name),
2196 ..self
2197 }
2198 }
2199
2200 pub fn commission_rate(self, commission_rate: Dec) -> Self {
2202 Self {
2203 commission_rate: Some(commission_rate),
2204 ..self
2205 }
2206 }
2207}
2208
2209impl MetaDataChange {
2210 pub async fn build(
2212 &self,
2213 context: &impl Namada,
2214 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
2215 tx::build_validator_metadata_change(context, self).await
2216 }
2217}
2218
2219#[derive(Clone, Debug)]
2220pub struct UpdateStewardCommission<C: NamadaTypes = SdkTypes> {
2222 pub tx: Tx<C>,
2224 pub steward: C::Address,
2226 pub commission: C::Data,
2228 pub tx_code_path: PathBuf,
2230}
2231
2232impl<C: NamadaTypes> TxBuilder<C> for UpdateStewardCommission<C> {
2233 fn tx<F>(self, func: F) -> Self
2234 where
2235 F: FnOnce(Tx<C>) -> Tx<C>,
2236 {
2237 UpdateStewardCommission {
2238 tx: func(self.tx),
2239 ..self
2240 }
2241 }
2242}
2243
2244impl<C: NamadaTypes> UpdateStewardCommission<C> {
2245 pub fn steward(self, steward: C::Address) -> Self {
2247 Self { steward, ..self }
2248 }
2249
2250 pub fn commission(self, commission: C::Data) -> Self {
2252 Self { commission, ..self }
2253 }
2254
2255 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
2257 Self {
2258 tx_code_path,
2259 ..self
2260 }
2261 }
2262}
2263
2264impl UpdateStewardCommission {
2265 pub async fn build(
2267 &self,
2268 context: &impl Namada,
2269 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
2270 tx::build_update_steward_commission(context, self).await
2271 }
2272}
2273
2274#[derive(Clone, Debug)]
2275pub struct ResignSteward<C: NamadaTypes = SdkTypes> {
2277 pub tx: Tx<C>,
2279 pub steward: C::Address,
2281 pub tx_code_path: PathBuf,
2283}
2284
2285impl<C: NamadaTypes> TxBuilder<C> for ResignSteward<C> {
2286 fn tx<F>(self, func: F) -> Self
2287 where
2288 F: FnOnce(Tx<C>) -> Tx<C>,
2289 {
2290 ResignSteward {
2291 tx: func(self.tx),
2292 ..self
2293 }
2294 }
2295}
2296
2297impl<C: NamadaTypes> ResignSteward<C> {
2298 pub fn steward(self, steward: C::Address) -> Self {
2300 Self { steward, ..self }
2301 }
2302
2303 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
2305 Self {
2306 tx_code_path,
2307 ..self
2308 }
2309 }
2310}
2311
2312impl ResignSteward {
2313 pub async fn build(
2315 &self,
2316 context: &impl Namada,
2317 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
2318 tx::build_resign_steward(context, self).await
2319 }
2320}
2321
2322#[derive(Clone, Debug)]
2323pub struct TxUnjailValidator<C: NamadaTypes = SdkTypes> {
2325 pub tx: Tx<C>,
2327 pub validator: C::Address,
2329 pub tx_code_path: PathBuf,
2331}
2332
2333impl<C: NamadaTypes> TxBuilder<C> for TxUnjailValidator<C> {
2334 fn tx<F>(self, func: F) -> Self
2335 where
2336 F: FnOnce(Tx<C>) -> Tx<C>,
2337 {
2338 TxUnjailValidator {
2339 tx: func(self.tx),
2340 ..self
2341 }
2342 }
2343}
2344
2345impl<C: NamadaTypes> TxUnjailValidator<C> {
2346 pub fn validator(self, validator: C::Address) -> Self {
2348 Self { validator, ..self }
2349 }
2350
2351 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
2353 Self {
2354 tx_code_path,
2355 ..self
2356 }
2357 }
2358}
2359
2360impl TxUnjailValidator {
2361 pub async fn build(
2363 &self,
2364 context: &impl Namada,
2365 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
2366 tx::build_unjail_validator(context, self).await
2367 }
2368}
2369
2370#[derive(Clone, Debug)]
2371pub struct TxDeactivateValidator<C: NamadaTypes = SdkTypes> {
2373 pub tx: Tx<C>,
2375 pub validator: C::Address,
2377 pub tx_code_path: PathBuf,
2379}
2380
2381impl<C: NamadaTypes> TxBuilder<C> for TxDeactivateValidator<C> {
2382 fn tx<F>(self, func: F) -> Self
2383 where
2384 F: FnOnce(Tx<C>) -> Tx<C>,
2385 {
2386 TxDeactivateValidator {
2387 tx: func(self.tx),
2388 ..self
2389 }
2390 }
2391}
2392
2393impl<C: NamadaTypes> TxDeactivateValidator<C> {
2394 pub fn validator(self, validator: C::Address) -> Self {
2396 Self { validator, ..self }
2397 }
2398
2399 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
2401 Self {
2402 tx_code_path,
2403 ..self
2404 }
2405 }
2406}
2407
2408impl TxDeactivateValidator {
2409 pub async fn build(
2411 &self,
2412 context: &impl Namada,
2413 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
2414 tx::build_deactivate_validator(context, self).await
2415 }
2416}
2417
2418#[derive(Clone, Debug)]
2419pub struct TxReactivateValidator<C: NamadaTypes = SdkTypes> {
2421 pub tx: Tx<C>,
2423 pub validator: C::Address,
2425 pub tx_code_path: PathBuf,
2427}
2428
2429impl<C: NamadaTypes> TxBuilder<C> for TxReactivateValidator<C> {
2430 fn tx<F>(self, func: F) -> Self
2431 where
2432 F: FnOnce(Tx<C>) -> Tx<C>,
2433 {
2434 TxReactivateValidator {
2435 tx: func(self.tx),
2436 ..self
2437 }
2438 }
2439}
2440
2441impl<C: NamadaTypes> TxReactivateValidator<C> {
2442 pub fn validator(self, validator: C::Address) -> Self {
2444 Self { validator, ..self }
2445 }
2446
2447 pub fn tx_code_path(self, tx_code_path: PathBuf) -> Self {
2449 Self {
2450 tx_code_path,
2451 ..self
2452 }
2453 }
2454}
2455
2456impl TxReactivateValidator {
2457 pub async fn build(
2459 &self,
2460 context: &impl Namada,
2461 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
2462 tx::build_reactivate_validator(context, self).await
2463 }
2464}
2465
2466#[derive(Clone, Debug)]
2467pub struct ShieldedSync<C: NamadaTypes = SdkTypes> {
2471 pub ledger_address: C::ConfigRpcTendermintAddress,
2473 pub last_query_height: Option<BlockHeight>,
2475 pub spending_keys: Vec<C::DatedSpendingKey>,
2477 pub viewing_keys: Vec<C::DatedViewingKey>,
2479 pub with_indexer: Option<C::MaspIndexerAddress>,
2484 pub wait_for_last_query_height: bool,
2486 pub max_concurrent_fetches: usize,
2489 pub block_batch_size: usize,
2491 pub retry_strategy: RetryStrategy,
2494}
2495
2496#[derive(Clone, Debug)]
2498pub struct QueryCommissionRate<C: NamadaTypes = SdkTypes> {
2499 pub query: Query<C>,
2501 pub validator: C::Address,
2503 pub epoch: Option<Epoch>,
2505}
2506
2507#[derive(Clone, Debug)]
2509pub struct QueryMetaData<C: NamadaTypes = SdkTypes> {
2510 pub query: Query<C>,
2512 pub validator: C::Address,
2514}
2515
2516#[derive(Clone, Debug)]
2518pub struct QuerySlashes<C: NamadaTypes = SdkTypes> {
2519 pub query: Query<C>,
2521 pub validator: Option<C::Address>,
2523}
2524
2525#[derive(Clone, Debug)]
2527pub struct QueryRewards<C: NamadaTypes = SdkTypes> {
2528 pub query: Query<C>,
2530 pub source: Option<C::Address>,
2532 pub validator: C::Address,
2534 pub epoch: Option<Epoch>,
2536}
2537
2538#[derive(Clone, Debug)]
2540pub struct QueryDelegations<C: NamadaTypes = SdkTypes> {
2541 pub query: Query<C>,
2543 pub owner: C::Address,
2545}
2546
2547#[derive(Clone, Debug)]
2549pub struct QueryTotalSupply<C: NamadaTypes = SdkTypes> {
2550 pub query: Query<C>,
2552 pub token: C::Address,
2554}
2555
2556#[derive(Clone, Debug)]
2558pub struct QueryEffNativeSupply<C: NamadaTypes = SdkTypes> {
2559 pub query: Query<C>,
2561}
2562
2563#[derive(Clone, Debug)]
2565pub struct QueryStakingRewardsRate<C: NamadaTypes = SdkTypes> {
2566 pub query: Query<C>,
2568}
2569
2570#[derive(Clone, Debug)]
2572pub struct QueryFindValidator<C: NamadaTypes = SdkTypes> {
2573 pub query: Query<C>,
2575 pub addr: Either<String, C::Address>,
2577}
2578
2579#[derive(Clone, Debug)]
2581pub struct QueryRawBytes<C: NamadaTypes = SdkTypes> {
2582 pub storage_key: storage::Key,
2584 pub query: Query<C>,
2586}
2587
2588#[derive(Clone, Debug)]
2590pub struct QueryIbcRateLimit<C: NamadaTypes = SdkTypes> {
2591 pub query: Query<C>,
2593 pub token: C::Address,
2595}
2596
2597#[derive(Clone, Debug, Default)]
2599pub enum TxExpiration {
2600 NoExpiration,
2602 #[default]
2604 Default,
2605 Custom(DateTimeUtc),
2607}
2608
2609impl TxExpiration {
2610 pub fn to_datetime(&self) -> Option<DateTimeUtc> {
2612 match self {
2613 TxExpiration::NoExpiration => None,
2614 TxExpiration::Default =>
2616 {
2617 #[allow(clippy::disallowed_methods)]
2618 Some(DateTimeUtc::now() + namada_core::time::Duration::hours(1))
2619 }
2620 TxExpiration::Custom(exp) => Some(exp.to_owned()),
2621 }
2622 }
2623}
2624
2625#[derive(Clone, Debug)]
2627pub enum DryRun {
2628 Inner,
2630 Wrapper,
2632}
2633
2634#[derive(Clone, Debug)]
2636pub enum DumpTx {
2637 Inner,
2639 Wrapper,
2641}
2642
2643#[derive(Clone, Debug)]
2645pub struct Wrapper<C: NamadaTypes = SdkTypes> {
2646 pub broadcast_only: bool,
2648 pub fee_amount: Option<InputAmount>,
2650 pub wrapper_fee_payer: Option<C::PublicKey>,
2652 pub fee_token: C::AddrOrNativeToken,
2654 pub gas_limit: GasLimit,
2656}
2657
2658#[derive(Clone, Debug)]
2660pub struct Tx<C: NamadaTypes = SdkTypes> {
2661 pub dry_run: Option<DryRun>,
2663 pub dump_tx: Option<DumpTx>,
2666 pub output_folder: Option<PathBuf>,
2668 pub force: bool,
2670 pub ledger_address: C::ConfigRpcTendermintAddress,
2672 pub initialized_account_alias: Option<String>,
2675 pub wallet_alias_force: bool,
2678 pub wrap_tx: Option<Wrapper<C>>,
2681 pub expiration: TxExpiration,
2683 pub chain_id: Option<ChainId>,
2685 pub signing_keys: Vec<C::PublicKey>,
2687 pub tx_reveal_code_path: PathBuf,
2689 pub password: Option<Zeroizing<String>>,
2691 pub memo: Option<Memo>,
2693 pub use_device: bool,
2695 pub device_transport: DeviceTransport,
2697}
2698
2699#[derive(Debug, Clone, Copy, Default)]
2701pub enum DeviceTransport {
2702 #[default]
2704 Hid,
2705 Tcp,
2707}
2708
2709impl FromStr for DeviceTransport {
2710 type Err = String;
2711
2712 fn from_str(s: &str) -> Result<Self, Self::Err> {
2713 match s.trim().to_ascii_lowercase().as_str() {
2714 "hid" => Ok(Self::Hid),
2715 "tcp" => Ok(Self::Tcp),
2716 raw => Err(format!(
2717 "Unexpected device transport \"{raw}\". Valid options are \
2718 \"hid\" or \"tcp\"."
2719 )),
2720 }
2721 }
2722}
2723
2724pub trait TxBuilder<C: NamadaTypes>: Sized {
2726 fn tx<F>(self, func: F) -> Self
2728 where
2729 F: FnOnce(Tx<C>) -> Tx<C>;
2730 fn dry_run(self, dry_run: Option<DryRun>) -> Self {
2732 self.tx(|x| Tx { dry_run, ..x })
2733 }
2734 fn dump_tx(self, dump_tx: Option<DumpTx>) -> Self {
2736 self.tx(|x| Tx { dump_tx, ..x })
2737 }
2738 fn output_folder(self, output_folder: PathBuf) -> Self {
2740 self.tx(|x| Tx {
2741 output_folder: Some(output_folder),
2742 ..x
2743 })
2744 }
2745 fn force(self, force: bool) -> Self {
2747 self.tx(|x| Tx { force, ..x })
2748 }
2749 fn wrap_it(self, wrapper: Option<Wrapper<C>>) -> Self {
2751 self.tx(|x| Tx {
2752 wrap_tx: wrapper,
2753 ..x
2754 })
2755 }
2756 fn ledger_address(self, ledger_address: C::TendermintAddress) -> Self {
2758 self.tx(|x| Tx {
2759 ledger_address: C::ConfigRpcTendermintAddress::from(ledger_address),
2760 ..x
2761 })
2762 }
2763 fn initialized_account_alias(
2766 self,
2767 initialized_account_alias: String,
2768 ) -> Self {
2769 self.tx(|x| Tx {
2770 initialized_account_alias: Some(initialized_account_alias),
2771 ..x
2772 })
2773 }
2774 fn wallet_alias_force(self, wallet_alias_force: bool) -> Self {
2777 self.tx(|x| Tx {
2778 wallet_alias_force,
2779 ..x
2780 })
2781 }
2782 fn chain_id(self, chain_id: ChainId) -> Self {
2784 self.tx(|x| Tx {
2785 chain_id: Some(chain_id),
2786 ..x
2787 })
2788 }
2789 fn signing_keys(self, signing_keys: Vec<C::PublicKey>) -> Self {
2791 self.tx(|x| Tx { signing_keys, ..x })
2792 }
2793 fn tx_reveal_code_path(self, tx_reveal_code_path: PathBuf) -> Self {
2795 self.tx(|x| Tx {
2796 tx_reveal_code_path,
2797 ..x
2798 })
2799 }
2800 fn password(self, password: Zeroizing<String>) -> Self {
2802 self.tx(|x| Tx {
2803 password: Some(password),
2804 ..x
2805 })
2806 }
2807 fn memo(self, memo: Vec<u8>) -> Self {
2809 self.tx(|x| Tx {
2810 memo: Some(memo),
2811 ..x
2812 })
2813 }
2814}
2815
2816impl<C: NamadaTypes> TxBuilder<C> for Tx<C> {
2817 fn tx<F>(self, func: F) -> Self
2818 where
2819 F: FnOnce(Tx<C>) -> Tx<C>,
2820 {
2821 func(self)
2822 }
2823}
2824
2825#[derive(Clone, Debug)]
2827pub struct KeyGen {
2828 pub scheme: SchemeType,
2830 pub shielded: bool,
2832 pub raw: bool,
2834 pub alias: String,
2836 pub alias_force: bool,
2838 pub unsafe_dont_encrypt: bool,
2840 pub derivation_path: String,
2842 pub prompt_bip39_passphrase: bool,
2844 pub allow_non_compliant: bool,
2846 pub birthday: Option<BlockHeight>,
2849}
2850
2851#[derive(Clone, Debug)]
2853pub struct KeyDerive {
2854 pub scheme: SchemeType,
2856 pub shielded: bool,
2858 pub alias: String,
2860 pub alias_force: bool,
2862 pub unsafe_dont_encrypt: bool,
2864 pub unsafe_pure_zip32: bool,
2866 pub derivation_path: String,
2868 pub allow_non_compliant: bool,
2870 pub prompt_bip39_passphrase: bool,
2872 pub use_device: bool,
2874 pub device_transport: DeviceTransport,
2876 pub birthday: Option<BlockHeight>,
2879}
2880
2881#[derive(Clone, Copy, Debug)]
2883pub struct KeyAddressList {
2884 pub transparent_only: bool,
2886 pub shielded_only: bool,
2888 pub keys_only: bool,
2890 pub addresses_only: bool,
2892 pub decrypt: bool,
2894 pub unsafe_show_secret: bool,
2896}
2897
2898#[derive(Clone, Debug)]
2900pub struct KeyAddressFind {
2901 pub alias: Option<String>,
2903 pub address: Option<Address>,
2905 pub public_key: Option<common::PublicKey>,
2907 pub public_key_hash: Option<String>,
2909 pub payment_address: Option<PaymentAddress>,
2911 pub keys_only: bool,
2913 pub addresses_only: bool,
2915 pub decrypt: bool,
2917 pub unsafe_show_secret: bool,
2919}
2920#[derive(Clone, Debug)]
2922pub struct KeyExport {
2923 pub alias: String,
2925}
2926
2927#[derive(Clone, Debug)]
2929pub struct KeyConvert {
2930 pub alias: String,
2932}
2933
2934#[derive(Clone, Debug)]
2936pub struct KeyImport {
2937 pub file_path: String,
2939 pub alias: String,
2941 pub alias_force: bool,
2943 pub unsafe_dont_encrypt: bool,
2945}
2946
2947#[derive(Clone, Debug)]
2949pub struct KeyAddressAdd {
2950 pub alias: String,
2952 pub alias_force: bool,
2954 pub value: String,
2956 pub birthday: Option<BlockHeight>,
2959 pub unsafe_dont_encrypt: bool,
2961}
2962
2963#[derive(Clone, Debug)]
2965pub struct KeyAddressRemove {
2966 pub alias: String,
2968 pub do_it: bool,
2970}
2971
2972#[derive(Clone, Debug)]
2974pub struct PayAddressGen {
2975 pub alias: String,
2977 pub alias_force: bool,
2979 pub viewing_key: String,
2981 pub diversifier_index: Option<DiversifierIndex>,
2983}
2984
2985#[derive(Clone, Debug)]
2987pub struct RecommendBatch<C: NamadaTypes = SdkTypes> {
2988 pub query: Query<C>,
2990 pub max_gas: Option<u64>,
2992 pub gas: Option<u64>,
2995 pub conversion_table: C::BpConversionTable,
2997}
2998
2999#[derive(Clone, Debug)]
3001pub struct EthereumBridgePool<C: NamadaTypes = SdkTypes> {
3002 pub nut: bool,
3007 pub tx: Tx<C>,
3009 pub asset: EthAddress,
3011 pub recipient: EthAddress,
3013 pub sender: C::Address,
3015 pub amount: InputAmount,
3017 pub fee_amount: InputAmount,
3019 pub fee_payer: Option<C::Address>,
3023 pub fee_token: C::AddrOrNativeToken,
3025 pub code_path: PathBuf,
3027}
3028
3029impl<C: NamadaTypes> TxBuilder<C> for EthereumBridgePool<C> {
3030 fn tx<F>(self, func: F) -> Self
3031 where
3032 F: FnOnce(Tx<C>) -> Tx<C>,
3033 {
3034 EthereumBridgePool {
3035 tx: func(self.tx),
3036 ..self
3037 }
3038 }
3039}
3040
3041impl<C: NamadaTypes> EthereumBridgePool<C> {
3042 pub fn nut(self, nut: bool) -> Self {
3047 Self { nut, ..self }
3048 }
3049
3050 pub fn asset(self, asset: EthAddress) -> Self {
3052 Self { asset, ..self }
3053 }
3054
3055 pub fn recipient(self, recipient: EthAddress) -> Self {
3057 Self { recipient, ..self }
3058 }
3059
3060 pub fn sender(self, sender: C::Address) -> Self {
3062 Self { sender, ..self }
3063 }
3064
3065 pub fn amount(self, amount: InputAmount) -> Self {
3067 Self { amount, ..self }
3068 }
3069
3070 pub fn fee_amount(self, fee_amount: InputAmount) -> Self {
3072 Self { fee_amount, ..self }
3073 }
3074
3075 pub fn fee_payer(self, fee_payer: C::Address) -> Self {
3079 Self {
3080 fee_payer: Some(fee_payer),
3081 ..self
3082 }
3083 }
3084
3085 pub fn fee_token(self, fee_token: C::Address) -> Self {
3087 Self {
3088 fee_token: fee_token.into(),
3089 ..self
3090 }
3091 }
3092
3093 pub fn code_path(self, code_path: PathBuf) -> Self {
3095 Self { code_path, ..self }
3096 }
3097}
3098
3099impl EthereumBridgePool {
3100 pub async fn build(
3102 self,
3103 context: &impl Namada,
3104 ) -> crate::error::Result<(namada_tx::Tx, SigningData)> {
3105 bridge_pool::build_bridge_pool_tx(context, self).await
3106 }
3107}
3108
3109#[derive(Debug, Clone)]
3111pub struct BridgePoolProof<C: NamadaTypes = SdkTypes> {
3112 pub ledger_address: C::TendermintAddress,
3114 pub transfers: Vec<KeccakHash>,
3117 pub relayer: Address,
3124}
3125
3126#[derive(Debug, Clone)]
3128pub struct RelayBridgePoolProof<C: NamadaTypes = SdkTypes> {
3129 pub ledger_address: C::TendermintAddress,
3131 pub transfers: Vec<KeccakHash>,
3133 pub relayer: Address,
3135 pub confirmations: u64,
3137 pub eth_rpc_endpoint: C::EthereumAddress,
3139 pub gas: Option<u64>,
3142 pub gas_price: Option<u64>,
3145 pub eth_addr: Option<EthAddress>,
3148 pub sync: bool,
3151}
3152
3153#[derive(Debug, Clone)]
3155pub struct BridgeValidatorSet<C: NamadaTypes = SdkTypes> {
3156 pub ledger_address: C::TendermintAddress,
3158 pub epoch: Option<Epoch>,
3160}
3161
3162#[derive(Debug, Clone)]
3164pub struct GovernanceValidatorSet<C: NamadaTypes = SdkTypes> {
3165 pub ledger_address: C::TendermintAddress,
3167 pub epoch: Option<Epoch>,
3169}
3170
3171#[derive(Debug, Clone)]
3173pub struct ValidatorSetProof<C: NamadaTypes = SdkTypes> {
3174 pub ledger_address: C::TendermintAddress,
3176 pub epoch: Option<Epoch>,
3178}
3179
3180#[derive(Debug, Clone)]
3182pub struct ValidatorSetUpdateRelay<C: NamadaTypes = SdkTypes> {
3183 pub daemon: bool,
3186 pub ledger_address: C::TendermintAddress,
3188 pub confirmations: u64,
3190 pub eth_rpc_endpoint: C::EthereumAddress,
3192 pub epoch: Option<Epoch>,
3194 pub gas: Option<u64>,
3197 pub gas_price: Option<u64>,
3200 pub eth_addr: Option<EthAddress>,
3203 pub sync: bool,
3206 pub retry_dur: Option<StdDuration>,
3209 pub success_dur: Option<StdDuration>,
3212}
3213
3214#[derive(Clone, Debug)]
3216pub struct GenIbcShieldingTransfer<C: NamadaTypes = SdkTypes> {
3217 pub query: Query<C>,
3219 pub output_folder: Option<PathBuf>,
3221 pub target: C::PaymentAddress,
3223 pub amount: InputAmount,
3225 pub expiration: TxExpiration,
3227 pub asset: IbcShieldingTransferAsset<C>,
3229 pub frontend_sus_fee: Option<(C::PaymentAddress, Dec)>,
3235}
3236
3237#[derive(Clone, Debug)]
3239pub enum IbcShieldingTransferAsset<C: NamadaTypes = SdkTypes> {
3240 LookupNamadaAddress {
3242 token: String,
3244 port_id: PortId,
3246 channel_id: ChannelId,
3248 },
3249 Address(C::Address),
3251}