pub enum MirrorBondStatesResult {
Known {
entries: Vec<MirrorBondEntry>,
complete: bool,
cursor: Option<MirrorBondKey>,
locked_dig_base_units: u64,
epoch: u64,
funding_wallet: WalletOperatorAddressResult,
url_reconcile: Box<UrlReconcileStatus>,
},
Unknown {
reason: MirrorBondStatesUnknownReason,
},
}Expand description
control.mirror.bondStates — the per-(store, root) state of every mirror bond this node
holds, and the $DIG those bonds have locked.
§“No bond” and “cannot tell” are different answers, at different levels
Every per-row MirrorBondState is a DEFINITE statement, including the six that mean “no coin
yet”: each names WHY, and each has its own remedy. A node that could not read a fact it needs
does not report a row at all — it answers Unknown for the WHOLE call, with
the reason. There is deliberately no per-row “unknown” and no empty-list fallback: a short list
and a complete one look the same, and the rows a broken read would drop are precisely the bonds
an operator most needs to see.
entries: [] with complete: true is therefore an ANSWER — this node holds no mirror bonds —
and it is never what a caller gets when something could not be read.
§The locked total is the node’s, and a client MUST NOT sum the page
locked_dig_base_units covers the WHOLE bond set, not this page, and includes
Reclaiming coins because their money is still locked. A client
that summed entries instead would under-report the locked total by exactly one page boundary
and would show money as available that cannot be spent — the money lie this method’s paging
makes easiest to tell. It is what dig-app#289’s locked-total surface reads.
§Every amount is DIG BASE UNITS
$DIG carries 3 decimals, so one base unit is 0.001 DIG. It is NOT a mojo — XCH’s 1e-12 base
unit, nine orders of magnitude away. A mirror amount is never quoted in mojos.
§A page, and it says so
Rows come in ASCENDING (store_id, root), a total order over the LOWERCASE unprefixed hex
spelling of both halves, stable across the pages of one walk. complete states whether the page is the whole set and is never inferred from the
page’s length: a node may return a short page for its own reasons, and a set that is an exact
multiple of the page size makes the last full page indistinguishable from a truncated one.
Resume from cursor — the key of the last row you were actually HANDED.
Variants§
Known
The node can state every bond’s state.
Fields
entries: Vec<MirrorBondEntry>One page of bonds, ascending by (store_id, root), possibly empty.
complete: boolIs this page the WHOLE bond set?
Required on the wire, and stated positively so the reading a caller falls into when the
field is absent or defaulted is the SAFE one — complete defaults to “there may be
more”, which costs at worst one redundant request, whereas a truncated spelling would
default to “this is everything” and end a walk early.
cursor: Option<MirrorBondKey>The key of the LAST row in this page — the value to resume from — or null for an empty
page.
The key the caller was HANDED, never a position the node “got to”. Pass it as
MirrorBondStatesParams::after.
The key MUST be present; null is meaningful and an absent key must NOT decode into it.
locked_dig_base_units: u64The $DIG this node has LOCKED in mirror coins across the whole bond set, in DIG base units.
Authoritative and node-computed. Includes reclaiming coins. Spans every page.
epoch: u64The epoch in force when this answer was taken, one-based.
Carried so a client can tell a bond at the current epoch from one it is reading across a rollover, without consulting a second method whose answer may have moved in between.
funding_wallet: WalletOperatorAddressResultWHICH WALLET every figure on this page is about.
§Why an answer about money must name the wallet
Every amount here — each Unfunded shortfall,
locked_dig_base_units, each bonded amount — is a
statement about the node’s own MACHINE-custody operator wallet, not about the user’s. A
node reported three bonds unfunded, short 1010 while its operator’s own wallet held
1,015,000 base units of $DIG: both statements were true, each was about a different
wallet, and the payload named an amount and no wallet, so nobody could tell. Naming it
here is what makes the page self-describing rather than merely correct.
§On the ANSWER, not on each row — and the distinction is not cosmetic
The funding wallet is node-wide, so a per-row copy would be the same string repeated for every entry: a field that cannot vary, which reads as though it could. Worse, two rows of one answer could then be written to disagree, and a client would have to decide which to believe. One value per answer can be wrong; it cannot be inconsistent with itself.
Carried rather than left to control.wallet.operatorAddress for the same reason
epoch is carried: a second call is a second observation, and it
may have moved. A page of amounts that requires a follow-up call to learn whose amounts
they are can be rendered, screenshotted and acted on before that call returns.
The same type control.wallet.operatorAddress returns, reused rather than restated, so
the two surfaces cannot drift into two spellings of one fact — and so a node with no
wallet yet says NotInitialized
here too, instead of a blank string a client might render as a destination.
url_reconcile: Box<UrlReconcileStatus>This node’s URL-reconciliation standing: whether the daily pass is armed, when it next runs, what it last saw, and how many bonds are stale RIGHT NOW.
Without this a client cannot decide whether to show the “reset mirrors” button as
useful without a dry_run round trip on every render, and cannot tell whether a
submitted reconcile it kicked off earlier has landed — it would have to re-walk the
whole bond page and re-derive stale_bonds itself
from MirrorBondState::Bonded::url_current on every entry, on every page.
Boxed: UrlReconcileStatus carries two nested Options the way its sibling
Unknown variant carries only a bare reason, and inlining it here
widens the WHOLE enum to fit its largest variant — Box costs one wire-invisible
indirection (serde serializes through it transparently) rather than that.
Unknown
The node cannot state the bond states, and names which fact is missing.
Fields
reason: MirrorBondStatesUnknownReasonWhich fact the node is missing.
Trait Implementations§
Source§impl Clone for MirrorBondStatesResult
impl Clone for MirrorBondStatesResult
Source§fn clone(&self) -> MirrorBondStatesResult
fn clone(&self) -> MirrorBondStatesResult
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more