fedimint_client/client/
global_ctx.rs
1use std::sync::Arc;
2
3use fedimint_api_client::api::{DynGlobalApi, DynModuleApi};
4use fedimint_client_module::module::OutPointRange;
5use fedimint_client_module::sm::{ClientSMDatabaseTransaction, DynState, IState};
6use fedimint_client_module::transaction::{TransactionBuilder, TxSubmissionStatesSM};
7use fedimint_client_module::{
8 AddStateMachinesResult, IGlobalClientContext, InstancelessDynClientInputBundle,
9 InstancelessDynClientOutputBundle,
10};
11use fedimint_core::config::ClientConfig;
12use fedimint_core::core::{IntoDynInstance, ModuleInstanceId, ModuleKind, OperationId};
13use fedimint_core::module::registry::ModuleDecoderRegistry;
14use fedimint_core::util::BoxStream;
15use fedimint_core::{apply, async_trait_maybe_send, maybe_add_send_sync};
16use fedimint_eventlog::EventKind;
17
18use super::Client;
19
20#[derive(Clone, Debug)]
24pub(crate) struct ModuleGlobalClientContext {
25 pub(crate) client: Arc<Client>,
26 pub(crate) module_instance_id: ModuleInstanceId,
27 pub(crate) operation: OperationId,
28}
29
30#[apply(async_trait_maybe_send!)]
31impl IGlobalClientContext for ModuleGlobalClientContext {
32 fn module_api(&self) -> DynModuleApi {
33 self.api().with_module(self.module_instance_id)
34 }
35
36 fn api(&self) -> &DynGlobalApi {
37 &self.client.api
38 }
39
40 fn decoders(&self) -> &ModuleDecoderRegistry {
41 self.client.decoders()
42 }
43
44 async fn client_config(&self) -> ClientConfig {
45 self.client.config().await
46 }
47
48 async fn claim_inputs_dyn(
49 &self,
50 dbtx: &mut ClientSMDatabaseTransaction<'_, '_>,
51 inputs: InstancelessDynClientInputBundle,
52 ) -> anyhow::Result<OutPointRange> {
53 let tx_builder =
54 TransactionBuilder::new().with_inputs(inputs.into_dyn(self.module_instance_id));
55
56 self.client
57 .finalize_and_submit_transaction_inner(
58 &mut dbtx.global_tx().to_ref_nc(),
59 self.operation,
60 tx_builder,
61 )
62 .await
63 }
64
65 async fn fund_output_dyn(
66 &self,
67 dbtx: &mut ClientSMDatabaseTransaction<'_, '_>,
68 outputs: InstancelessDynClientOutputBundle,
69 ) -> anyhow::Result<OutPointRange> {
70 let tx_builder =
71 TransactionBuilder::new().with_outputs(outputs.into_dyn(self.module_instance_id));
72
73 self.client
74 .finalize_and_submit_transaction_inner(
75 &mut dbtx.global_tx().to_ref_nc(),
76 self.operation,
77 tx_builder,
78 )
79 .await
80 }
81
82 async fn add_state_machine_dyn(
83 &self,
84 dbtx: &mut ClientSMDatabaseTransaction<'_, '_>,
85 sm: Box<maybe_add_send_sync!(dyn IState)>,
86 ) -> AddStateMachinesResult {
87 let state = DynState::from_parts(self.module_instance_id, sm);
88
89 self.client
90 .executor
91 .add_state_machines_dbtx(&mut dbtx.global_tx().to_ref_nc(), vec![state])
92 .await
93 }
94
95 async fn transaction_update_stream(&self) -> BoxStream<TxSubmissionStatesSM> {
96 self.client.transaction_update_stream(self.operation).await
97 }
98
99 async fn log_event_json(
100 &self,
101 dbtx: &mut ClientSMDatabaseTransaction<'_, '_>,
102 kind: EventKind,
103 module: Option<(ModuleKind, ModuleInstanceId)>,
104 payload: serde_json::Value,
105 persist: bool,
106 ) {
107 self.client
108 .log_event_raw_dbtx(
109 dbtx.global_tx(),
110 kind,
111 module,
112 serde_json::to_vec(&payload).expect("Serialization can't fail"),
113 persist,
114 )
115 .await;
116 }
117}