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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
//! # Satellite Account Shards
//!
//! A high-performance library for managing sharded account state in Bitcoin-based blockchain programs.
//! This crate provides ergonomic tools for working with distributed UTXO sets
//! across multiple shards while maintaining atomicity and consistency.
//!
//! ## Overview
//!
//! This library is designed for applications that need to manage large amounts of Bitcoin UTXOs
//! and Rune tokens across multiple shards for scalability. It provides:
//!
//! - **Type-safe shard management** with compile-time state tracking
//! - **Efficient UTXO distribution** across shards
//! - **Atomic transaction building** with proper fee calculation
//! - **Rune token support** for managing fungible tokens on Bitcoin
//! - **Zero-copy serialization** for high-performance applications
//!
//! ## Quick start
//!
//! 1. **Add the dependency** to your `Cargo.toml` (defaults enable `runes` and
//! `utxo-consolidation`):
//!
//! ```toml
//! saturn-account-shards = "0.1"
//! ```
//!
//! 2. **Create a `ShardSet`, select shards, call helpers**:
//!
//! ```rust,no_run
//! use satellite_shard::{ShardSet, StateShard};
//! # use satellite_bitcoin::utxo_info::{UtxoInfo, SingleRuneSet};
//! # #[derive(Default, Clone)]
//! # struct DummyShard;
//! # impl StateShard<UtxoInfo<SingleRuneSet>, SingleRuneSet> for DummyShard {
//! # fn btc_utxos(&self) -> &[UtxoInfo<SingleRuneSet>] { &[] }
//! # fn btc_utxos_mut(&mut self) -> &mut [UtxoInfo<SingleRuneSet>] { &mut [] }
//! # fn btc_utxos_retain(&mut self, _: &mut dyn FnMut(&UtxoInfo<SingleRuneSet>) -> bool) {}
//! # fn add_btc_utxo(&mut self, _: UtxoInfo<SingleRuneSet>) -> Option<usize> { None }
//! # fn btc_utxos_len(&self) -> usize { 0 }
//! # fn btc_utxos_max_len(&self) -> usize { 0 }
//! # fn rune_utxo(&self) -> Option<&UtxoInfo<SingleRuneSet>> { None }
//! # fn rune_utxo_mut(&mut self) -> Option<&mut UtxoInfo<SingleRuneSet>> { None }
//! # fn clear_rune_utxo(&mut self) {}
//! # fn set_rune_utxo(&mut self, _: UtxoInfo<SingleRuneSet>) {}
//! # }
//! # let mut shards_storage = [DummyShard::default(), DummyShard::default()];
//! # let mut loaders: Vec<&mut DummyShard> = shards_storage.iter_mut().collect();
//!
//! // Build an *unselected* set and then pick the shards we need.
//! let shard_set = ShardSet::<SingleRuneSet, UtxoInfo<SingleRuneSet>, DummyShard, 2>::from_loaders(&mut loaders);
//! let mut selected = shard_set.select_with([0, 1]).unwrap();
//!
//! // Call any of the high-level helpers, e.g. redistribute BTC back to the shards.
//! // selected.redistribute_remaining_btc_to_shards(...);
//! ```
//!
//! ## Features
//!
//! | Feature flag | Purpose | Default |
//! |--------------|---------|---------|
//! | `runes` | Support for the Bitcoin **Runes** protocol (adds Rune-specific helpers) | ✅ |
//! | `utxo-consolidation` | Convenience helpers to combine many small UTXOs into fewer large ones | ✅ |
//! | `serde` | Enable `serde::{Serialize, Deserialize}` implementations where possible | ❌ |
//!
//! All items that require a feature are tagged on docs.rs via
//! **`cfg(feature = "…")`** in their rust-doc header.
//!
//! ## Glossary
//!
//! | Term | Meaning |
//! |------|---------|
//! | **Shard** | A single on-chain account that stores a portion of the global program state. |
//! | **Pool** | A collection of shards that together form one logical program state. |
//! | **UTXO** | *Unspent Transaction Output*: holds satoshis (and optionally Rune amounts) on the Bitcoin chain. |
//! | **Rune** | A fungible token defined by the Runes protocol and transported inside a Bitcoin UTXO. |
//!
//! ## Key Components
//!
//! ### ShardSet
//!
//! The central abstraction is [`ShardSet`], which provides a type-safe wrapper around
//! a collection of shards. It uses the typestate pattern to ensure proper usage:
//!
//! ```rust,ignore
//! # use saturn_account_shards::{ShardSet, StateShard};
//! # use satellite_bitcoin::utxo_info::{UtxoInfo, SingleRuneSet};
//! # #[derive(Default, Clone)]
//! # struct DummyShard;
//! # impl StateShard<UtxoInfo<SingleRuneSet>, SingleRuneSet> for DummyShard {
//! # fn btc_utxos(&self) -> &[UtxoInfo<SingleRuneSet>] { &[] }
//! # fn btc_utxos_mut(&mut self) -> &mut [UtxoInfo<SingleRuneSet>] { &mut [] }
//! # fn btc_utxos_retain(&mut self, _: &mut dyn FnMut(&UtxoInfo<SingleRuneSet>) -> bool) {}
//! # fn add_btc_utxo(&mut self, _: UtxoInfo<SingleRuneSet>) -> Option<usize> { None }
//! # fn btc_utxos_len(&self) -> usize { 0 }
//! # fn btc_utxos_max_len(&self) -> usize { 0 }
//! # fn rune_utxo(&self) -> Option<&UtxoInfo<SingleRuneSet>> { None }
//! # fn rune_utxo_mut(&mut self) -> Option<&mut UtxoInfo<SingleRuneSet>> { None }
//! # fn clear_rune_utxo(&mut self) {}
//! # fn set_rune_utxo(&mut self, _: UtxoInfo<SingleRuneSet>) {}
//! # }
//! # let mut shard1 = DummyShard::default();
//! # let mut shard2 = DummyShard::default();
//! # let mut shards = [&mut shard1, &mut shard2];
//! // Create an unselected shard set
//! let shard_set = ShardSet::<SingleRuneSet, UtxoInfo<SingleRuneSet>, DummyShard, 2>::new(&mut shards);
//!
//! // Select shards to work with
//! let selected = shard_set.select_with([0, 1]).unwrap();
//!
//! // Now high-level operations are available
//! // selected.redistribute_remaining_btc_to_shards(...);
//! ```
//!
//! ### StateShard Trait
//!
//! All shards must implement the [`StateShard`] trait, which provides a unified interface
//! for managing both Bitcoin UTXOs and Rune tokens:
//!
//! ```rust
//! # use saturn_account_shards::{StateShard};
//! # use satellite_bitcoin::utxo_info::{UtxoInfo, SingleRuneSet};
//! # use satellite_bitcoin::generic::fixed_set::FixedCapacitySet;
//! #
//! struct MyShard {
//! btc_utxos: Vec<UtxoInfo<SingleRuneSet>>,
//! rune_utxo: Option<UtxoInfo<SingleRuneSet>>,
//! }
//!
//! impl StateShard<UtxoInfo<SingleRuneSet>, SingleRuneSet> for MyShard {
//! fn btc_utxos(&self) -> &[UtxoInfo<SingleRuneSet>] {
//! &self.btc_utxos
//! }
//!
//! fn btc_utxos_mut(&mut self) -> &mut [UtxoInfo<SingleRuneSet>] {
//! &mut self.btc_utxos
//! }
//!
//! // ... implement other required methods
//! # fn btc_utxos_retain(&mut self, _: &mut dyn FnMut(&UtxoInfo<SingleRuneSet>) -> bool) {}
//! # fn add_btc_utxo(&mut self, _: UtxoInfo<SingleRuneSet>) -> Option<usize> { None }
//! # fn btc_utxos_len(&self) -> usize { 0 }
//! # fn btc_utxos_max_len(&self) -> usize { 0 }
//! # fn rune_utxo(&self) -> Option<&UtxoInfo<SingleRuneSet>> { None }
//! # fn rune_utxo_mut(&mut self) -> Option<&mut UtxoInfo<SingleRuneSet>> { None }
//! # fn clear_rune_utxo(&mut self) {}
//! # fn set_rune_utxo(&mut self, _: UtxoInfo<SingleRuneSet>) {}
//! # }
//! ```
//!
//! ## Common Operations
//!
//! ### Selecting Shards
//!
//! ```rust
//! # use satellite_shard::{ShardSet, StateShard};
//! # use satellite_bitcoin::utxo_info::{UtxoInfo, SingleRuneSet};
//! # #[derive(Default, Clone)]
//! # struct DummyShard;
//! # impl StateShard<UtxoInfo<SingleRuneSet>, SingleRuneSet> for DummyShard {
//! # fn btc_utxos(&self) -> &[UtxoInfo<SingleRuneSet>] { &[] }
//! # fn btc_utxos_mut(&mut self) -> &mut [UtxoInfo<SingleRuneSet>] { &mut [] }
//! # fn btc_utxos_retain(&mut self, _: &mut dyn FnMut(&UtxoInfo<SingleRuneSet>) -> bool) {}
//! # fn add_btc_utxo(&mut self, _: UtxoInfo<SingleRuneSet>) -> Option<usize> { None }
//! # fn btc_utxos_len(&self) -> usize { 0 }
//! # fn btc_utxos_max_len(&self) -> usize { 0 }
//! # fn rune_utxo(&self) -> Option<&UtxoInfo<SingleRuneSet>> { None }
//! # fn rune_utxo_mut(&mut self) -> Option<&mut UtxoInfo<SingleRuneSet>> { None }
//! # fn clear_rune_utxo(&mut self) {}
//! # fn set_rune_utxo(&mut self, _: UtxoInfo<SingleRuneSet>) {}
//! # }
//! # let mut shards: Vec<DummyShard> = vec![DummyShard::default(); 5];
//! # let mut shard_refs: Vec<&mut DummyShard> = shards.iter_mut().collect();
//! let shard_set = ShardSet::<SingleRuneSet, UtxoInfo<SingleRuneSet>, DummyShard, 5>::new(&mut shard_refs);
//!
//! // Select specific shards by index
//! let selected = shard_set.select_with([0, 2, 4]).unwrap();
//!
//! // Select the shard with minimum BTC
//! // let selected = shard_set.select_min_by(|s| s.total_btc()).unwrap();
//!
//! // Select shards that meet a condition
//! // let selected = shard_set.select_multiple_by(|s| s.btc_utxos_len() > 0).unwrap();
//! ```
//!
//! ### Redistributing Liquidity
//!
//! ```rust,no_run
//! # use satellite_shard::{ShardSet, StateShard};
//! # use satellite_bitcoin::{TransactionBuilder, fee_rate::FeeRate};
//! # use satellite_bitcoin::utxo_info::{UtxoInfo, SingleRuneSet};
//! # use std::str::FromStr;
//! # use bitcoin::ScriptBuf;
//! # #[derive(Default, Clone)]
//! # struct DummyShard;
//! # impl StateShard<UtxoInfo<SingleRuneSet>, SingleRuneSet> for DummyShard {
//! # fn btc_utxos(&self) -> &[UtxoInfo<SingleRuneSet>] { &[] }
//! # fn btc_utxos_mut(&mut self) -> &mut [UtxoInfo<SingleRuneSet>] { &mut [] }
//! # fn btc_utxos_retain(&mut self, _: &mut dyn FnMut(&UtxoInfo<SingleRuneSet>) -> bool) {}
//! # fn add_btc_utxo(&mut self, _: UtxoInfo<SingleRuneSet>) -> Option<usize> { None }
//! # fn btc_utxos_len(&self) -> usize { 0 }
//! # fn btc_utxos_max_len(&self) -> usize { 0 }
//! # fn rune_utxo(&self) -> Option<&UtxoInfo<SingleRuneSet>> { None }
//! # fn rune_utxo_mut(&mut self) -> Option<&mut UtxoInfo<SingleRuneSet>> { None }
//! # fn clear_rune_utxo(&mut self) {}
//! # fn set_rune_utxo(&mut self, _: UtxoInfo<SingleRuneSet>) {}
//! # }
//! # let mut shards: Vec<DummyShard> = vec![DummyShard::default(); 3];
//! # let mut shard_refs: Vec<&mut DummyShard> = shards.iter_mut().collect();
//! # let shard_set = ShardSet::<SingleRuneSet, UtxoInfo<SingleRuneSet>, DummyShard, 3>::new(&mut shard_refs);
//! # let mut selected = shard_set.select_with([0, 1, 2]).unwrap();
//! # let mut tx_builder = TransactionBuilder::<10, 3, SingleRuneSet>::new();
//! # let program_script = ScriptBuf::new();
//! # let fee_rate = FeeRate::from_str("1.0").unwrap();
//! # let removed_from_shards = 1000u64;
//! // Redistribute remaining BTC evenly across selected shards
//! let redistributed = selected.redistribute_remaining_btc_to_shards(
//! &mut tx_builder,
//! removed_from_shards,
//! program_script,
//! &fee_rate,
//! ).unwrap();
//! ```
pub use ;
pub use IntoShardIndices;
pub use *;
pub use *;
pub use *;
pub use DistributionError;