pub trait ClientModule:
Debug
+ MaybeSend
+ MaybeSync
+ 'static {
type Init: ClientModuleInit;
type Common: ModuleCommon;
type Backup: ModuleBackup;
type ModuleStateMachineContext: Context;
type States: State<ModuleContext = Self::ModuleStateMachineContext> + IntoDynInstance<DynType = DynState>;
Show 16 methods
// Required methods
fn context(&self) -> Self::ModuleStateMachineContext;
fn input_fee(
&self,
amount: Amount,
input: &<Self::Common as ModuleCommon>::Input,
) -> Option<Amount>;
fn output_fee(
&self,
amount: Amount,
output: &<Self::Common as ModuleCommon>::Output,
) -> Option<Amount>;
// Provided methods
fn decoder() -> Decoder { ... }
fn kind() -> ModuleKind { ... }
fn start<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: Sync + 'async_trait,
'life0: 'async_trait { ... }
fn handle_cli_command<'life0, 'life1, 'async_trait>(
&'life0 self,
_args: &'life1 [OsString],
) -> Pin<Box<dyn Future<Output = Result<Value>> + Send + 'async_trait>>
where Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn handle_rpc<'life0, 'async_trait>(
&'life0 self,
_method: String,
_request: Value,
) -> Pin<Box<dyn Future<Output = BoxStream<'_, Result<Value>>> + Send + 'async_trait>>
where Self: Sync + 'async_trait,
'life0: 'async_trait { ... }
fn supports_backup(&self) -> bool { ... }
fn backup<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Self::Backup>> + Send + 'async_trait>>
where Self: Sync + 'async_trait,
'life0: 'async_trait { ... }
fn supports_being_primary(&self) -> bool { ... }
fn create_final_inputs_and_outputs<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_dbtx: &'life1 mut DatabaseTransaction<'life2>,
_operation_id: OperationId,
_input_amount: Amount,
_output_amount: Amount,
) -> Pin<Box<dyn Future<Output = Result<(ClientInputBundle<<Self::Common as ModuleCommon>::Input, Self::States>, ClientOutputBundle<<Self::Common as ModuleCommon>::Output, Self::States>)>> + Send + 'async_trait>>
where Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn await_primary_module_output<'life0, 'async_trait>(
&'life0 self,
_operation_id: OperationId,
_out_point: OutPoint,
) -> Pin<Box<dyn Future<Output = Result<Amount>> + Send + 'async_trait>>
where Self: Sync + 'async_trait,
'life0: 'async_trait { ... }
fn get_balance<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_dbtx: &'life1 mut DatabaseTransaction<'life2>,
) -> Pin<Box<dyn Future<Output = Amount> + Send + 'async_trait>>
where Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn subscribe_balance_changes<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = BoxStream<'static, ()>> + Send + 'async_trait>>
where Self: Sync + 'async_trait,
'life0: 'async_trait { ... }
fn leave<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_dbtx: &'life1 mut DatabaseTransaction<'life2>,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
}
Expand description
Fedimint module client
Required Associated Types§
type Init: ClientModuleInit
Sourcetype Common: ModuleCommon
type Common: ModuleCommon
Common module types shared between client and server
Sourcetype Backup: ModuleBackup
type Backup: ModuleBackup
Data stored in regular backups so that restoring doesn’t have to start from epoch 0
Sourcetype ModuleStateMachineContext: Context
type ModuleStateMachineContext: Context
Data and API clients available to state machine transitions of this module
Sourcetype States: State<ModuleContext = Self::ModuleStateMachineContext> + IntoDynInstance<DynType = DynState>
type States: State<ModuleContext = Self::ModuleStateMachineContext> + IntoDynInstance<DynType = DynState>
All possible states this client can submit to the executor
Required Methods§
fn context(&self) -> Self::ModuleStateMachineContext
Sourcefn input_fee(
&self,
amount: Amount,
input: &<Self::Common as ModuleCommon>::Input,
) -> Option<Amount>
fn input_fee( &self, amount: Amount, input: &<Self::Common as ModuleCommon>::Input, ) -> Option<Amount>
Returns the fee the processing of this input requires.
If the semantics of a given input aren’t known this function returns
None
, this only happens if a future version of Fedimint introduces a
new input variant. For clients this should only be the case when
processing transactions created by other users, so the result of
this function can be unwrap
ped whenever dealing with inputs
generated by ourselves.
Sourcefn output_fee(
&self,
amount: Amount,
output: &<Self::Common as ModuleCommon>::Output,
) -> Option<Amount>
fn output_fee( &self, amount: Amount, output: &<Self::Common as ModuleCommon>::Output, ) -> Option<Amount>
Returns the fee the processing of this output requires.
If the semantics of a given output aren’t known this function returns
None
, this only happens if a future version of Fedimint introduces a
new output variant. For clients this should only be the case when
processing transactions created by other users, so the result of
this function can be unwrap
ped whenever dealing with inputs
generated by ourselves.
Provided Methods§
fn decoder() -> Decoder
fn kind() -> ModuleKind
Sourcefn start<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
fn start<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
Initialize client.
Called by the core client code on start, after ClientContext
is
fully initialized, so unlike during ClientModuleInit::init
,
access to global client is allowed.
fn handle_cli_command<'life0, 'life1, 'async_trait>(
&'life0 self,
_args: &'life1 [OsString],
) -> Pin<Box<dyn Future<Output = Result<Value>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn handle_rpc<'life0, 'async_trait>(
&'life0 self,
_method: String,
_request: Value,
) -> Pin<Box<dyn Future<Output = BoxStream<'_, Result<Value>>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
fn supports_backup(&self) -> bool
fn backup<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Self::Backup>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
Sourcefn supports_being_primary(&self) -> bool
fn supports_being_primary(&self) -> bool
Does this module support being a primary module
If it does it must implement:
Sourcefn create_final_inputs_and_outputs<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_dbtx: &'life1 mut DatabaseTransaction<'life2>,
_operation_id: OperationId,
_input_amount: Amount,
_output_amount: Amount,
) -> Pin<Box<dyn Future<Output = Result<(ClientInputBundle<<Self::Common as ModuleCommon>::Input, Self::States>, ClientOutputBundle<<Self::Common as ModuleCommon>::Output, Self::States>)>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn create_final_inputs_and_outputs<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_dbtx: &'life1 mut DatabaseTransaction<'life2>,
_operation_id: OperationId,
_input_amount: Amount,
_output_amount: Amount,
) -> Pin<Box<dyn Future<Output = Result<(ClientInputBundle<<Self::Common as ModuleCommon>::Input, Self::States>, ClientOutputBundle<<Self::Common as ModuleCommon>::Output, Self::States>)>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Creates all inputs and outputs necessary to balance the transaction. The function returns an error if and only if the client’s funds are not sufficient to create the inputs necessary to fully fund the transaction.
A returned input also contains:
- A set of private keys belonging to the input for signing the transaction
- A closure that generates states belonging to the input. This closure
takes the transaction id of the transaction in which the input was
used and the input index as input since these cannot be known at time
of calling
create_funding_input
and have to be injected later.
A returned output also contains:
- A closure that generates states belonging to the output. This closure
takes the transaction id of the transaction in which the output was
used and the output index as input since these cannot be known at time
of calling
create_change_output
and have to be injected later.
Sourcefn await_primary_module_output<'life0, 'async_trait>(
&'life0 self,
_operation_id: OperationId,
_out_point: OutPoint,
) -> Pin<Box<dyn Future<Output = Result<Amount>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
fn await_primary_module_output<'life0, 'async_trait>(
&'life0 self,
_operation_id: OperationId,
_out_point: OutPoint,
) -> Pin<Box<dyn Future<Output = Result<Amount>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
Waits for the funds from an output created by
Self::create_final_inputs_and_outputs
to become available. This
function returning typically implies a change in the output of
Self::get_balance
.
Sourcefn get_balance<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_dbtx: &'life1 mut DatabaseTransaction<'life2>,
) -> Pin<Box<dyn Future<Output = Amount> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_balance<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_dbtx: &'life1 mut DatabaseTransaction<'life2>,
) -> Pin<Box<dyn Future<Output = Amount> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Returns the balance held by this module and available for funding transactions.
Sourcefn subscribe_balance_changes<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = BoxStream<'static, ()>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
fn subscribe_balance_changes<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = BoxStream<'static, ()>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
Returns a stream that will output the updated module balance each time it changes.
Sourcefn leave<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_dbtx: &'life1 mut DatabaseTransaction<'life2>,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn leave<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_dbtx: &'life1 mut DatabaseTransaction<'life2>,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Leave the federation
While technically there’s nothing stopping the client from just abandoning Federation at any point by deleting all the related local data, it is useful to make sure it’s safe beforehand.
This call indicates the desire of the caller client code to orderly and safely leave the Federation by this module instance. The goal of the implementations is to fulfil that wish, giving prompt and informative feedback if it’s not yet possible.
The client module implementation should handle the request and return as fast as possible avoiding blocking for longer than necessary. This would usually involve some combination of:
- recording the state of being in process of leaving the Federation to prevent initiating new conditions that could delay its completion;
- performing any fast to complete cleanup/exit logic;
- initiating any time-consuming logic (e.g. canceling outstanding contracts), as background jobs, tasks machines, etc.
- checking for any conditions indicating it might not be safe to leave at the moment.
This function should return Ok
only if from the perspective
of this module instance, it is safe to delete client data and
stop using it, with no further actions (like background jobs) required
to complete.
This function should return an error if it’s not currently possible to safely (e.g. without loosing funds) leave the Federation. It should avoid running indefinitely trying to complete any cleanup actions necessary to reach a clean state, preferring spawning new state machines and returning an informative error about cleanup still in progress.
If any internal task needs to complete, any user action is required,
or even external condition needs to be met this function
should return a Err
.
Notably modules should not disable interaction that might be necessary for the user (possibly through other modules) to leave the Federation. In particular a Mint module should retain ability to create new notes, and LN module should retain ability to send funds out.
Calling code must NOT assume that a module that once returned Ok
,
will not return Err
at later point. E.g. a Mint module might have
no outstanding balance at first, but other modules winding down
might “cash-out” to Ecash.
Before leaving the Federation and deleting any state the calling code
must collect a full round of Ok
from all the modules.
Calling code should allow the user to override and ignore any outstanding errors, after sufficient amount of warnings. Ideally, this should be done on per-module basis, to avoid mistakes.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.