The observer could read headers, events, extrinsics, metadata and difficulty, and not a single pallet storage item. Answering "which address is this chain's treasury" meant going outside it and hand-deriving twox128 prefixes, which is a gap in the tool rather than an answer. The treasury is the case that shows why. `set_treasury_account` reads *never* on the call index and `TreasuryAccountUpdated` reads *never* on the event index — both true, because the address was set at genesis, so no extrinsic ever carried it and no event ever announced it. It exists only in state. It is qzjsuLN7Nhu4bjvmUbjSTr2ZTeZ7oRxXpQP9fdv6PcHUCRrVR, and it has never been funded. `Runtime::storage_key` builds a key entirely from the runtime's own description — the pallet's storage prefix, the item name, and each key's declared hasher — because a wrong hasher yields a key that reads as *absent* rather than as an error, and nothing would catch it. Its test pins two keys against ones read off the live chain by hand. Keys are SCALE-encoded against the type the entry declares, so a map on an account, a u32 or a tuple all work without this knowing which it is. Absent is not zero, and only the modifier knows which: an `optional` entry holding nothing means nothing, a `default` entry means the runtime's default, and the state page marks the latter rather than passing it off as something the chain wrote. `read_balance` deliberately does not apply the default — `AccountInfo` zeroes, Substrate reaps empty accounts, and falling back would turn "does not exist" into "holds nothing", which is the treasury's exact case. /:chain/state lists all 40 keyless entries decoded, and an account page now carries a real balance beside the flows it already summed. Those are different numbers: rewards say what an account was paid, a balance says what it has, and they differ by every transfer out. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jp6a8EDar9ueEhAxzep4V5
77 lines
2.5 KiB
TypeScript
77 lines
2.5 KiB
TypeScript
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
import type { AccountEvent } from "./AccountEvent";
|
|
import type { BigUintDec } from "./BigUintDec";
|
|
import type { ChainId } from "./ChainId";
|
|
import type { MinerId } from "./MinerId";
|
|
import type { RewardSummary } from "./RewardSummary";
|
|
|
|
/**
|
|
* Everything the observer holds about one account.
|
|
*/
|
|
export type AccountDetail = {
|
|
/**
|
|
* Which chain.
|
|
*/
|
|
chain: ChainId,
|
|
/**
|
|
* The address as asked for, re-encoded canonically.
|
|
*/
|
|
address: string,
|
|
/**
|
|
* The raw account id, `0x` hex — what the events are keyed on.
|
|
*/
|
|
account: string,
|
|
/**
|
|
* The reward preimage this address derives from, when a block the observer
|
|
* recorded was authored by it.
|
|
*
|
|
* The derivation runs one way only: a preimage gives an address, and no
|
|
* amount of arithmetic gives the preimage back. So this is a *lookup*
|
|
* among preimages already seen, and its absence means only that this
|
|
* observer has not watched this account win a block — not that it never
|
|
* has.
|
|
*/
|
|
miner: MinerId | null,
|
|
/**
|
|
* The telemetry name held for that miner, if one is.
|
|
*/
|
|
display: string | null,
|
|
/**
|
|
* The account's free balance right now, read from chain state rather than
|
|
* inferred from the flows below.
|
|
*
|
|
* `null` when the node would not answer, and — importantly — also when the
|
|
* account does not exist. On Substrate an account with nothing in it is
|
|
* not an account with zero, it is absent, and those read differently: the
|
|
* treasury address this chain has configured has never been funded, and
|
|
* showing it a zero would imply it had been and spent.
|
|
*/
|
|
balance: BigUintDec | null,
|
|
/**
|
|
* The whole `System::Account` entry as the runtime describes it — nonce,
|
|
* consumers, providers, and the balance breakdown. Carried alongside the
|
|
* single number above because the number is what a reader came for and the
|
|
* rest is what makes it checkable.
|
|
*/
|
|
state: Record<string, unknown> | null,
|
|
/**
|
|
* Mining rewards, over the whole indexed record.
|
|
*/
|
|
rewards: RewardSummary,
|
|
/**
|
|
* Everything involving this account, newest first.
|
|
*/
|
|
activity: Array<AccountEvent>,
|
|
/**
|
|
* The lowest and highest block whose events have been read for this chain.
|
|
*
|
|
* Reported because it is the honest scope of every number above: an
|
|
* account page is a claim about a range of history, and a backfill still
|
|
* working its way toward genesis has not made that claim yet.
|
|
*/
|
|
indexed_from: number,
|
|
/**
|
|
* The highest block whose events have been read.
|
|
*/
|
|
indexed_to: number, };
|