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