# auradefi > Open-source multi-tenant crypto data aggregator for Python. Reads EVM, Bitcoin and Solana balances and history, prices them exactly, keeps tenants isolated, and emits Plaid's wire format. Library first: import it and pay no network cost. The HTTP API is a thin shell over the same core. Version 0.1.1, Apache-2.0, alpha. Install with `pip install auradefi`. This is the whole first program, and it needs no credentials: ```python from auradefi import Auradefi aura = Auradefi.sandbox() # no key, no network, no configuration for holding in aura.holdings()[0].holdings: print(holding.symbol, holding.quantity, holding.value) ``` What a reader coming from another library gets wrong: - Start in Sandbox. `Auradefi.sandbox()` needs no key, no network and no configuration: it replays a recording bundled inside the wheel, through the production source, decoder, ledger and pricing code. Going live is one line, `Auradefi.from_env()`. - Sandbox answers are constants: one address on `eip155:1`, 2 ETH and 25 USDC worth 5025 USD, seven transactions. Asking it for a different address, chain or page raises `CassetteMissError`, which means the recording does not hold that request. No credential is missing. - Amounts are exact. `Quantity` and `Money` wrap `Decimal` and go on the wire as tagged strings, never as JSON numbers. A float anywhere in this arithmetic is a bug. - An unpriced asset is never zero. It comes back in `report.holdings` with `price=None` and is named in `report.unpriced`, so a total is either right or visibly incomplete. - There are no Bitcoin or Solana prices. The one shipped oracle is DefiLlama: current prices, six EVM chains. Anything else needs your own `prices` port. - Chains are CAIP-2 strings. `user.connect_address("eip155:1", "0x…")` works; `"ethereum"` is refused, as is any chain the registry has not been given. - Configuration is prefixed. `Settings.from_env()` reads `AURADEFI_ETHERSCAN_API_KEY` and its siblings. A bare `ETHERSCAN_API_KEY` is ignored deliberately, so an unrelated variable cannot become this library's credential. - Nothing runs on its own. There is no scheduler, no worker and no background thread. You call `aura.sync(budget=n)` on your own tick, where `budget` caps the source pages that one call may spend; cursors make the next call resume. - The default ledger is memory and loses everything at exit. Production means `ledger=SqlModelLedger(session_factory=…)` or your own object. It takes a session factory, not a URL, because your application owns the engine and the migrations. - A source is one object satisfying two seams, `balances()` and `fetch_txlist()`. Binding one that has only the first raises at construction time. - Ports are structural protocols. There is no base class and no registration: an object with the right methods is the port. Five of them, all optional keyword arguments to `Auradefi.sandbox()` and `Auradefi.from_env()`. - Every failure inherits `auradefi.errors.AuradefiError`, so one `except` clause catches this library and nothing else. - The gaps are real and documented: no multicall, no on-chain reader for the position adapters, no historical prices, no async surface, no Solana transaction decode. If the reference does not name a symbol, it does not exist. Say so instead of inventing one. ## Get started - [Quickstart](https://auradefi.info/quickstart.html): Five lines, no credentials, working code. - [auradefi](https://auradefi.info/index.html): What it is, what works today, and what is not there. - [Authentication & keys](https://auradefi.info/authentication.html): What credentials you need: at most one, and it is optional. - [Bring your own](https://auradefi.info/bring-your-own.html): Your API, your database, your prices: every port and its methods. - [Database schema](https://auradefi.info/schema.html): Two tables, as SQL you can paste into your own migration. - [Build with an LLM](https://auradefi.info/llms.html): A prompt to paste in, and the docs as one file a model can hold. ## Guides - [All guides](https://auradefi.info/examples/index.html): Ten task-shaped recipes that run offline. - [auradefi in five lines, then the whole library in one file.](https://auradefi.info/examples/quickstart.html) - [How do I get a priced portfolio for one address?](https://auradefi.info/examples/01_holdings_for_an_address.html) - [How do I run this inside my own backend, with my own database?](https://auradefi.info/examples/02_embed_in_your_backend.html) - [How do I point this at MY chain data: my RPC, my vendor, my archive?](https://auradefi.info/examples/03_write_a_source_adapter.html) - [How do I store this in MY database, and stream changes to my clients?](https://auradefi.info/examples/04_persist_to_your_database.html) - [How do I expose this over HTTP, the way Plaid clients already expect?](https://auradefi.info/examples/05_serve_the_http_api.html) - [How do I serve many customers from one deployment without leaking?](https://auradefi.info/examples/06_isolate_two_tenants.html) - [How do I get DeFi positions, an LP, a loan, and not lie about them?](https://auradefi.info/examples/07_read_defi_positions.html) - [How do I answer "what did they make, and what tax lots are open"?](https://auradefi.info/examples/08_report_cost_basis_and_pnl.html) - [How do I get told when something changes, and trust what arrives?](https://auradefi.info/examples/09_deliver_signed_webhooks.html) - [How do I handle a Bitcoin xpub and Solana's token zoo?](https://auradefi.info/examples/10_scan_bitcoin_and_solana.html) ## Optional - [PyBooks](https://auradefi.info/books/index.html): Twelve executable notebooks, run in CI. - [01: Foundation](https://auradefi.info/books/01_foundation.html) - [02: Money & Quantity](https://auradefi.info/books/02_money.html) - [03: Assets & Chains](https://auradefi.info/books/03_assets_chains.html) - [04: The Ledger](https://auradefi.info/books/04_ledger.html) - [05: Balances to Holdings](https://auradefi.info/books/05_holdings.html) - [06: Tenancy](https://auradefi.info/books/06_tenancy.html) - [07: Transactions](https://auradefi.info/books/07_transactions.html) - [08: Positions](https://auradefi.info/books/08_positions.html) - [09: Embedding](https://auradefi.info/books/09_embedding.html) - [10: Bitcoin & Solana](https://auradefi.info/books/10_bitcoin_solana.html) - [11: Accounting](https://auradefi.info/books/11_accounting.html) - [12: The HTTP API](https://auradefi.info/books/12_http_api.html) ## API reference - [Overview](https://auradefi.info/reference/index.html): Every public symbol, grouped the way a host meets it. - [Auradefi](https://auradefi.info/reference/Auradefi.html) - [UserHandle](https://auradefi.info/reference/UserHandle.html) - [Settings](https://auradefi.info/reference/Settings.html) - [LedgerPort](https://auradefi.info/reference/LedgerPort.html) - [SyncStatePort](https://auradefi.info/reference/SyncStatePort.html) - [BalanceSource](https://auradefi.info/reference/BalanceSource.html) - [PageFetcher](https://auradefi.info/reference/PageFetcher.html) - [PriceOracle](https://auradefi.info/reference/PriceOracle.html) - [EtherscanSource](https://auradefi.info/reference/EtherscanSource.html) - [EtherscanV2](https://auradefi.info/reference/EtherscanV2.html) - [DefiLlamaOracle](https://auradefi.info/reference/DefiLlamaOracle.html) - [Inquirer](https://auradefi.info/reference/Inquirer.html) - [MemoryLedger](https://auradefi.info/reference/MemoryLedger.html) - [SqlModelLedger](https://auradefi.info/reference/SqlModelLedger.html) - [MemorySyncState](https://auradefi.info/reference/MemorySyncState.html) - [SystemClock](https://auradefi.info/reference/SystemClock.html) - [FrozenClock](https://auradefi.info/reference/FrozenClock.html) - [Quantity](https://auradefi.info/reference/Quantity.html) - [Money](https://auradefi.info/reference/Money.html) - [HoldingsReport](https://auradefi.info/reference/HoldingsReport.html) - [Holding](https://auradefi.info/reference/Holding.html) - [SyncReport](https://auradefi.info/reference/SyncReport.html) - [ConnectionSyncReport](https://auradefi.info/reference/ConnectionSyncReport.html) - [ConnectionRecord](https://auradefi.info/reference/ConnectionRecord.html) - [LedgerTransaction](https://auradefi.info/reference/LedgerTransaction.html) - [Entry](https://auradefi.info/reference/Entry.html) - [SyncPage](https://auradefi.info/reference/SyncPage.html) - [pnl_at](https://auradefi.info/reference/pnl_at.html) - [derive_events](https://auradefi.info/reference/derive_events.html) - [PnLReport](https://auradefi.info/reference/PnLReport.html) - [TaxLot](https://auradefi.info/reference/TaxLot.html) - [sign](https://auradefi.info/reference/sign.html) - [verify_signature](https://auradefi.info/reference/verify_signature.html) - [Deliverer](https://auradefi.info/reference/Deliverer.html) - [replay](https://auradefi.info/reference/replay.html) ## Reference - [Errors](https://auradefi.info/errors.html): Every exception, when it fires, and its HTTP status. - [HTTP API](https://auradefi.info/http.html): Plaid's wire format over your ports. - [Changelog](https://auradefi.info/changelog.html): What changed per release, and what breaks. ## Machine-readable - [llms-full.txt](https://auradefi.info/llms-full.txt): every page above as one plain-text file, with each example's full source. - [prompt.txt](https://auradefi.info/prompt.txt): a prompt to paste into a model before asking it for auradefi code. - [openapi.json](https://auradefi.info/openapi.json): the HTTP surface, generated from the app. - [Source](https://github.com/auracarehq/auradefi): Apache-2.0. Every example on this site is executed at build time.