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