1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use super::{DB_POOL, MOSTRO_CONFIG};
use crate::config::types::{
AntiAbuseBondSettings, DatabaseSettings, ExpirationSettings, LightningSettings, MostroSettings,
NostrSettings, RpcSettings,
};
use crate::price::PriceSettings;
use mostro_core::transport::Transport;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
// Mostro configuration settings struct
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct Settings {
/// Url of database for Mostro
pub database: DatabaseSettings,
/// Nostr configuration settings
pub nostr: NostrSettings,
/// Mostro daemon configuration settings
pub mostro: MostroSettings,
/// Lightning configuration settings
pub lightning: LightningSettings,
/// RPC configuration settings
pub rpc: RpcSettings,
/// Event expiration configuration settings
pub expiration: Option<ExpirationSettings>,
/// Anti-abuse bond configuration (issue #711). Absent section ≡ disabled.
#[serde(default)]
pub anti_abuse_bond: Option<AntiAbuseBondSettings>,
/// Multi-source price configuration (see `docs/PRICE_PROVIDERS.md`).
/// Absent section ≡ legacy single-source behaviour (synthesised in
/// Phase 1's migration).
#[serde(default)]
pub price: Option<PriceSettings>,
}
/// Initialize the global MOSTRO_CONFIG struct
pub fn init_mostro_settings(s: Settings) {
MOSTRO_CONFIG
.set(s)
.expect("Failed to set Mostro global settings");
}
/// Get database pool for Mostro db operations to share across the thread
pub fn get_db_pool() -> Arc<sqlx::SqlitePool> {
DB_POOL.get().expect("No database pool found").clone()
}
impl Settings {
/// This function retrieves the Lightning configuration from the global MOSTRO_CONFIG struct.
pub fn get_ln() -> &'static LightningSettings {
&MOSTRO_CONFIG
.get()
.expect("No Lightning settings found")
.lightning
}
/// This function retrieves the Mostro configuration from the global MOSTRO_CONFIG struct.
pub fn get_mostro() -> &'static MostroSettings {
&MOSTRO_CONFIG
.get()
.expect("No Mostro settings found")
.mostro
}
/// This function retrieves the Database configuration from the global MOSTRO_CONFIG struct.
pub fn get_db() -> &'static DatabaseSettings {
&MOSTRO_CONFIG
.get()
.expect("No Database settings found")
.database
}
/// This function retrieves the Nostr configuration from the global MOSTRO_CONFIG struct.
pub fn get_nostr() -> &'static NostrSettings {
&MOSTRO_CONFIG.get().expect("No Nostr settings found").nostr
}
/// This function retrieves the RPC configuration from the global MOSTRO_CONFIG struct.
pub fn get_rpc() -> &'static RpcSettings {
&MOSTRO_CONFIG.get().expect("No RPC settings found").rpc
}
/// This function retrieves the Expiration configuration from the global MOSTRO_CONFIG struct.
pub fn get_expiration() -> Option<&'static ExpirationSettings> {
MOSTRO_CONFIG
.get()
.expect("No settings found")
.expiration
.as_ref()
}
/// This function retrieves the anti-abuse bond configuration from the
/// global `MOSTRO_CONFIG`. Returns `None` when the `[anti_abuse_bond]`
/// block is absent (treated as disabled), and also when the global
/// settings haven't been initialized yet — unlike the other accessors
/// in this file, the bond gate is on the hot path of the take flow and
/// must never panic in unit tests that don't bring up the full
/// configuration.
pub fn get_bond() -> Option<&'static AntiAbuseBondSettings> {
MOSTRO_CONFIG.get()?.anti_abuse_bond.as_ref()
}
/// Wire transport for protocol messages. Falls back to the default
/// (`gift-wrap`, protocol v1) when the global settings haven't been
/// initialized yet — `send_dm()` sits on every reply path and must
/// degrade to v1 behavior rather than panic in unit tests that don't
/// bring up the full configuration, mirroring [`Settings::get_bond`].
///
/// DEPRECATED(v0.19.0, #786): goes away with the `transport` setting —
/// v0.19.0 hardcodes the protocol-v2 (`nip44`) wire format.
#[deprecated(
since = "0.18.0",
note = "transitional v1/v2 transport selection; removed in v0.19.0 (protocol v2 only) — see issue #786"
)]
pub fn get_transport() -> Transport {
#[allow(deprecated)]
MOSTRO_CONFIG
.get()
.map(|s| s.mostro.transport)
.unwrap_or_default()
}
/// Retrieve the multi-source price configuration from the global
/// `MOSTRO_CONFIG`. Returns `None` when the `[price]` block is absent
/// (Phase 1 synthesises a legacy default in that case) and also when the
/// global settings haven't been initialized yet, so it never panics on
/// the price hot path or in unit tests that don't bring up the full
/// configuration — mirroring [`Settings::get_bond`].
pub fn get_price() -> Option<&'static PriceSettings> {
MOSTRO_CONFIG.get()?.price.as_ref()
}
/// True when the feature is configured AND explicitly enabled. This is
/// the single gate every bond-related code path must check before
/// running. Keeps the opt-in guarantee simple to audit. Returns
/// `false` when settings haven't been initialized.
pub fn is_bond_enabled() -> bool {
Self::get_bond().is_some_and(|cfg| cfg.enabled)
}
}