Auradefi
The library's public surface (SPEC §8).
source must structurally satisfy BOTH
portfolio.holdings.BalanceSource (balances, for holdings) and
embed.sync.PageFetcher (fetch_txlist, for history): one
object, two seams, so a host writes one adapter.
__init__
__init__(self, ledger: LedgerPort, source: BalanceSource | PageFetcher, prices: PriceOracle, clock: Clock | None = None, settings: Settings | None = None, *, sync_state: SyncStatePort | None = None, decoder: Decoder | None = None, sync_page_size: int = 1000) -> None
Bind the host's ports. ZERO I/O happens here.
clock=None means SystemClock(), settings=None means
Settings(), sync_state=None means MemorySyncState()
(in-process; a host that wants durable cursors binds its own). A
pre-seeded ChainRegistry, per instance, it is mutable, is
built here and gates connect_address.
decoder=None binds the default composition LAZILY, at first
use, sources.evm.txlist.parse_normal_row per row ->
decode.pipeline.decode_account -> ledger.bridge, so
importing this module stays cheap and dependency-light.
Raises auradefi.errors.ValidationError when source does
not satisfy both seams: the failure belongs at bind time, not at
the first background tick.
Parameters
ledgerrequired, LedgerPortWhere transactions are stored. Four methods, tenant-scoped.
sourcerequired, BalanceSource | PageFetcherYour chain data. Must satisfy BOTH seams: balances and fetch_txlist: or binding raises immediately.
pricesrequired, PriceOracleYour price feed. Returning nothing for an asset is allowed and means unpriced, never zero.
clockoptional, Clock | None, default NoneNone means SystemClock(). Time is a port so quota windows and throttling are testable.
settingsoptional, Settings | None, default NoneNone means Settings(). Carries the sync interval and the project id that tenant ids derive under.
sync_stateoptional, SyncStatePort | None, default NoneConnections and cursors. None means in-process, which forgets every connection on restart.
decoderoptional, Decoder | None, default NoneRow-format seam. None binds the EVM txlist decoder lazily.
sync_page_sizeoptional, int, default 1000How many rows to ask a source for per page.
Raises
sandbox
sandbox(cls, *, connect: bool = True, **overrides: object) -> Auradefi
A working instance over a bundled recording, no keys, no network.
Production code paths, RECORDED data: answers are constants (5025
USD, seven transactions) and anything unrecorded raises
CassetteMissError. The address arrives connected unless
connect=False; ports override by keyword. See
sandbox_ports.
Parameters
connectoptional, bool, default TrueWhether to return with the sandbox address already connected. False to call connect_address yourself.
overridesoptional, objectAny port, by keyword, replacing that default.
Raises
from_env
from_env(cls, **overrides: object) -> Auradefi
A live instance wired from the environment (SPEC §8).
Reads AURADEFI_ETHERSCAN_API_KEY (optional) and
AURADEFI_HTTP_TIMEOUT_S. Storage is in-memory and NOT durable:
pass ledger=SqlModelLedger(...) to keep data, since the host
owns the engine and the migrations. See
env_ports.
Parameters
overridesoptional, objectAny port, by keyword. ledger= is the one most hosts set, since the default is not durable.
user
user(self, external_user_id: str) -> UserHandle
Get-or-create the handle for one opaque host user id.
Pure: no I/O and no persistence. The tenant id is DERIVED from
the id (embed.models.derive_tenant_id) under
settings.project_id, so the same string always resolves to the
same tenant, and to the SAME one that project's HTTP API resolves
it to (RELEASE_0.1.1 §5 #19). Raises
auradefi.errors.ValidationError for anything outside the pinned
opaque-id charset (an email is guessable and this is
bearer-equivalent, so @ cannot appear).
Parameters
external_user_idrequired, strYour opaque id for the person. The tenant id is derived from it; @ is refused because this is bearer-equivalent.
Raises
sync
sync(self, budget: int = 5) -> SyncReport
One tick across every known connection, in creation order.
ONE shared budget of page requests is spent connection by
connection until it runs out; connections beyond that point are
not visited this tick. budget < 1 raises
auradefi.errors.ValidationError. The aggregate sums the
per-connection counts, and no_op is True exactly when every
VISITED connection was a no-op: vacuously True with zero
connections. Self-throttling comes from
settings.sync_min_interval_s.
Parameters
budgetoptional, int, default 5Maximum source pages this ONE call may spend across every connection. Cursors make the next call resume.
Raises
holdings
holdings(self) -> tuple[HoldingsReport, ...]
One priced HoldingsReport per connection, creation order.
scalar_metrics
scalar_metrics(self) -> tuple[scalar_projection.Metric, ...]
(name, ms, float) triples per connection, concatenated.
Each connection contributes project.scalar.scalar_metrics
over its own holdings report and its own transactions: the
non-removed ADDED-kind ledger rows whose account_id is that
connection's id, read by paging ledger.sync until
has_more is False.