layer_climb_core/
signing.rs1pub mod authz;
2pub mod contract;
3pub mod ibc;
4pub mod middleware;
5pub mod msg;
6
7use crate::{
8 cache::ClimbCache,
9 prelude::*,
10 querier::Connection,
11 transaction::{SequenceStrategy, SequenceStrategyKind},
12};
13use layer_climb_signer::TxSigner;
14use middleware::{SigningMiddlewareMapBody, SigningMiddlewareMapResp};
15use std::sync::Arc;
16use tracing::instrument;
17
18#[derive(Clone)]
20pub struct SigningClient {
21 pub querier: QueryClient,
22 pub signer: Arc<dyn TxSigner>,
23 pub addr: Address,
24 pub account_number: u64,
25 pub middleware_map_body: Arc<Vec<SigningMiddlewareMapBody>>,
27 pub middleware_map_resp: Arc<Vec<SigningMiddlewareMapResp>>,
29 pub sequence_strategy: SequenceStrategy,
34}
35
36impl std::fmt::Debug for SigningClient {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 f.debug_struct("SigningClient")
39 .field("chain_id", &self.querier.chain_config.chain_id)
40 .field("addr", &self.addr)
41 .finish()
42 }
43}
44
45impl SigningClient {
46 pub async fn new(
47 chain_config: ChainConfig,
48 signer: impl TxSigner + 'static,
49 connection: Option<Connection>,
50 ) -> Result<Self> {
51 let connection = connection.unwrap_or_default();
52
53 Self::new_with_cache(
54 chain_config,
55 signer,
56 ClimbCache::new(connection.rpc.clone()),
57 Some(connection),
58 )
59 .await
60 }
61
62 pub async fn new_with_cache(
63 chain_config: ChainConfig,
64 signer: impl TxSigner + 'static,
65 cache: ClimbCache,
66 connection: Option<Connection>,
67 ) -> Result<Self> {
68 let addr = chain_config.address_from_pub_key(&signer.public_key().await?)?;
69
70 let querier = QueryClient::new_with_cache(chain_config.clone(), cache, connection).await?;
71
72 let base_account = querier.base_account(&addr).await?;
73
74 Ok(Self {
75 signer: Arc::new(signer),
76 querier,
77 addr,
78 account_number: base_account.account_number,
79 middleware_map_body: Arc::new(middleware::SigningMiddlewareMapBody::default_list()),
80 middleware_map_resp: Arc::new(middleware::SigningMiddlewareMapResp::default_list()),
81 sequence_strategy: SequenceStrategy::new(SequenceStrategyKind::Query),
82 })
83 }
84
85 #[instrument]
88 pub async fn refresh_signer(&mut self) -> Result<()> {
89 self.addr = self
90 .querier
91 .chain_config
92 .address_from_pub_key(&self.signer.public_key().await?)?;
93
94 self.account_number = self.querier.base_account(&self.addr).await?.account_number;
95
96 Ok(())
97 }
98
99 pub fn chain_id(&self) -> &ChainId {
100 &self.querier.chain_config.chain_id
101 }
102
103 pub fn sequence_strategy_kind(&self) -> &SequenceStrategyKind {
104 &self.sequence_strategy.kind
105 }
106
107 pub fn tx_builder(&self) -> TxBuilder<'_> {
108 let mut tx_builder = TxBuilder::new(&self.querier, self.signer.as_ref());
109
110 tx_builder
111 .set_sender(self.addr.clone())
112 .set_account_number(self.account_number)
113 .set_sequence_strategy(self.sequence_strategy.clone());
114
115 if !self.middleware_map_body.is_empty() {
116 tx_builder.set_middleware_map_body(self.middleware_map_body.clone());
117 }
118
119 if !self.middleware_map_resp.is_empty() {
120 tx_builder.set_middleware_map_resp(self.middleware_map_resp.clone());
121 }
122
123 tx_builder
124 }
125
126 pub async fn transfer<'a, D: Into<Option<&'a str>> + std::fmt::Debug>(
127 &self,
128 amount: u128,
129 recipient: &Address,
130 denom: D,
131 tx_builder: Option<TxBuilder<'_>>,
132 ) -> Result<layer_climb_proto::abci::TxResponse> {
133 tracing::debug!("transfering {} to {} from {}", amount, recipient, self.addr);
134
135 let res = tx_builder
136 .unwrap_or_else(|| self.tx_builder())
137 .broadcast([proto_into_any(
138 &self.transfer_msg(amount, recipient, denom)?,
139 )?])
140 .await?;
141
142 Ok(res)
143 }
144}