Skip to main content

auradefi

Open-source, multi-tenant crypto data aggregator. It takes the tenancy model from Vezgo, the DeFi position depth from DeBank and the transaction decomposition from Zerion, then emits Plaid's wire format, so crypto lands in the same downstream schema as bank and exchange data.

It is a library first and a service second. A Python host imports auradefi directly and pays no serialisation or network cost. The HTTP API is a thin shell over the same importable core.

Status: alpha, and 0.1.2 is the release to use. It is 3,426 tests green offline on a fresh clone with no API keys, its notebooks execute clean, and every example under examples/ runs against the published wheel. Work towards 0.2.0 is on main ahead of that release: the EVM node path landed first (a JSON-RPC client, a Multicall3 batcher, a log scanner and a concrete on-chain reader), so this page describes a tree that is not yet a release. STATUS.md carries the live gate state, including which gates are red today.

Do not use 0.1.0. A separate adversarial review of it found nineteen verified defects, of which five were security and four were silent data loss. None of them failed a test. docs/internal/RELEASE_0.1.1.md is the full accounting. 0.1.1 fixes all nineteen and deliberately breaks one id derivation, so read Upgrading in CHANGELOG.md before you move library-ingested data across.

Alpha means the gaps in What is not there are real; read that section before you budget work against this. STATUS.md carries the live gate state, and docs/internal/SPEC.md is the design contract.

Documentation site → carries the examples, the thirteen executable notebooks and the full reference, rendered with every example's real output.

Install

pip install auradefi                # core; httpx is the only dependency
pip install 'auradefi[sql]'         # + the SQLModel ledger backend
pip install 'auradefi[api]'         # + the FastAPI HTTP surface

From a clone (if your system python has no pip, scripts/bootstrap.sh handles it):

git clone https://github.com/auracarehq/auradefi
cd auradefi && bash scripts/bootstrap.sh
.venv/bin/pytest                           # the whole suite, offline, no keys
.venv/bin/python examples/quickstart.py    # every capability, end to end
bash scripts/run_examples.sh               # all thirteen examples

Examples

examples/ holds one file per question. Each one is self-contained, reads nothing from this repository, and runs offline without API keys. Each asserts its own output, and CI executes all of them, so a stale example fails the build.

Example What it answers
quickstart.py the whole library in one file; start here
01_holdings_for_an_address.py a priced portfolio, exactly, with unpriced assets named
02_embed_in_your_backend.py your ports, your tick, your database, and restart resume
03_write_a_source_adapter.py point it at your own chain data (two methods)
04_persist_to_your_database.py host-owned DDL, a resumable cursor feed, a reorg
05_serve_the_http_api.py Plaid's envelope over HTTP, and batch partial success
06_isolate_two_tenants.py one deployment, many customers, attacked four ways
07_read_defi_positions.py an LP and a loan that still add up to net worth
08_report_cost_basis_and_pnl.py FIFO/LIFO/HIFO/ACB, any instant, Plaid tax_lots[]
09_deliver_signed_webhooks.py signing, the pinned retry schedule, replay
10_scan_bitcoin_and_solana.py an xpub that never leaves the process, and Token-2022
11_provoke_every_error.py every error on purpose, so you can test your handler
12_read_a_contract_from_a_node.py eth_call, a batch, five reads in one round trip, and logs

examples/README.md annotates the index, and the documentation site renders every example with its real output.

Using it

As a library, where the host owns storage, transport, prices and the tick:

from auradefi import Auradefi

auradefi = Auradefi(
    ledger=SqlModelLedger(session_factory=my_session_factory),  # your database
    source=MySource(),        # your transport: .balances() + .fetch_txlist()
    prices=MyPrices(),        # your price feed: .usd_prices()
)
user = auradefi.user("opaque-host-user-id")   # get-or-create, id is derived
user.connect_address("eip155:1", "0x…")       # validated now, not on a later tick
report = auradefi.sync(budget=5)              # budgeted, resumable, self-throttling
holdings, metrics = auradefi.holdings(), auradefi.scalar_metrics()

As a service, where create_app takes ports you already built:

from auradefi.api.app import create_app
from auradefi.api.deps import Deps

app = create_app(Deps(tenancy=, keys=, ledger=, webhooks=, clock=))
# POST /auth/token, POST /connections, GET /crypto/sync  (Plaid's envelope)
# GET /coverage, POST /webhooks/endpoints, POST /webhooks/…/replay

docs/books/ walks both surfaces executably and offline.

What works today

Coverage is published as data (rule #10). Every row below has an executable notebook under docs/books/ that runs offline and asserts its own outputs, plus a gate test under tests/.

Capability Limits, and what proves it
Quantity/Money: exact at 10^77, four-field wire form, raw always a JSON string, strict wire grammar 02_money
CAIP-2/CAIP-19 parse + canonicalize, deterministic ast_… ids, both-ways asset registry 5 seed chains (Ethereum, Polygon, Base, Bitcoin, Solana); 03_assets_chains
Asset groups (decimals-equality law, single fallback) + additive spam scoring (score + numbers, caller threshold) 03_assets_chains
Ledger port: idempotent upsert, cursor sync with has_more paging, reorg as removed + re-added, resurrection, tenant isolation memory and SQLModel backends; 04_ledger
Cassette replay harness (CassetteMissError offline guarantee) 01_foundation
Style gates: size, structure, placement, layering (tests/style) no allowlist
EVM balances to holdings, exact-Decimal USD totals, unpriced assets named Etherscan V2 source + DefiLlama prices; 05_holdings
Tenancy: org/project/end-user, scoped adk_ keys, authEndpoint JWT mint, three-window quota, audit log the isolation gate actively tries to leak; 06_tenancy
Rich transactions: parts[]/acts[], fees as siblings carrying borne_by, derived type, ledger bridge, reorg + resurrection EVM only, one act per transaction; 07_transactions
DeFi positions: adapter protocol, drill-down, group totals + health factor, signed synthetic-Holdings projection Uniswap v2/v3, Aave v3, Lido/Rocket Pool; 08_positions
EVM node path: keccak256, a static ABI codec, JSON-RPC single calls and id-matched batches, Multicall3 aggregate3 with per-call failure declared, chunked eth_getLogs, and EvmContractReader as the adapters' seam Ethereum-shaped chains, static ABI types only, no async; 13_evm_node
Embedding: from auradefi import Auradefi, host-owned session, budgeted two-phase sync, 26-metric scalar projection chain-scoped connection ids, restart resume enumerated from the state port, one connection's failure contained to its own row (0.1.1 #18/#21/#24/#26); 09_embedding, 02_embed_in_your_backend.py
Bitcoin: pure-Python BIP32 xpub derivation, gap-20 scan, confirmed-only UTXO balances p2wpkh + Esplora only; the extended key never reaches HTTP; 10_bitcoin_solana
Solana: SPL + Token-2022 balances, ScaledUiAmount carried both ways, signature history balances only, no decode; 10_bitcoin_solana
HTTP API: Plaid /crypto/sync envelope, connections, /coverage generated as data, nine quota headers, batch holdings 12_http_api
Webhooks: HMAC-SHA256 signed, durable over a pinned retry schedule, dead letter + replay 12_http_api
Accounting: lot ledger, FIFO/LIFO/HIFO/ACB, realised + unrealised PnL, arbitrary-date PnL, Plaid tax_lots 50,000-event gate; 11_accounting

What is not there

Rule #10 applies to the absences too.

  • There are no live network adapters beyond what the cassettes cover. Every I/O path is exercised against committed recordings. Pointing a source at the real Etherscan, Esplora or Solana RPC needs your own keys and endpoints, and CI has not reconciled the output against an incumbent.
  • The EVM node path has never met a real node. EvmContractReader, EvmRpc, Multicall3 and scan_logs ship and the five position adapters resolve through them, but every vector that proves it is a hand-authored cassette: the block-20,450,000 words were packed from the integers the existing goldens pin, not recorded from an archive node, and tests/golden/test_phase11_reader.py says so in its own docstring. What is proven is the selector derivation, the word packing, the tuple decode, the block pin and the JSON-RPC path end to end. Agreement with mainnet state at that block is not proven by anything here.
  • The codec is static types only: uint<N>, int<N>, address and bool, plus Multicall3's own two dynamic shapes as named special cases. No string, no bytes, no arrays and no nested tuples, and it raises on them instead of guessing. Every function the shipped adapters call fits, and a contract of yours that does not will be refused rather than mis-encoded.
  • Nothing in the package constructs an EvmContractReader for you. It is wired by a host, and the block a ResolveContext names is not threaded into the reader: the reader carries its own pin, chosen at construction, so a host that wants a report at block N builds the reader at block N.
  • One price oracle (DefiLlama), current prices only. There is no fallback feed and no historical price service: prices/historian.py and prices/store.py are declared in the module layout and absent, as are the coingecko, manual and onchain_amm oracles, so accounting marks are the caller's.
  • No scheduler and no background worker. The host owns every tick, and a backfill is a sync() budget you spend yourself. This is the design, not a gap: 0.2.0 removed jobs/ from the declared layout after finding four of its five modules already shipped under other names, and the fifth was a cron evaluator wearing a domain's clothes. What is genuinely missing is a reprocess path for re-decoding stored rows after the decoder improves; the decoder_version it would select on is already persisted.
  • Five of the nine declared api/routes/ modules are absent: accounts.py, holdings.py, positions.py, transactions.py and webhooks.py. What ships is auth, connections, sync and admin, so holdings and positions have no HTTP surface of their own, and the webhook admin routes live in admin.py.
  • project/ ships only scalar.py. project/plaid.py and project/native.py are declared and absent. The Plaid envelope is projected in api/wire.py instead, so that projection is not reusable outside the HTTP shell the way the layer contract intends.
  • Two ledger backends: in-memory and SQLModel/sqlite. Postgres should work through the same port; only sqlite is exercised. The tenancy, keys, quota, audit and webhook stores are in-memory only.
  • Cosmos is absent, as is every EVM chain the registry does not seed. So are exchange connections, NFTs and protocol-specific decoders (acts[] is always one act, and protocol is always None).
  • Solana transaction decode is not implemented. Balances and signature history only.
  • No async surface, no background worker and no scheduler. The host owns the tick.
  • There is no migration for the 0.1.1 embed id break. Library-ingested embed connection ids, and every transaction_id hashed over them, re-derive in 0.1.1, so 0.1.0 rows written through Auradefi stop matching. A host either re-derives them itself or accepts the old rows as orphaned history (CHANGELOG.md, Upgrading). Data written through the HTTP API is unaffected.
  • SyncStatePort is a five-method Protocol in 0.1.1 (tenants() was added). A host store written against the 0.1.0 four-method shape is refused at bind time, so it cannot silently sync nothing.

The rules the code lives by

  • Money is a tagged decimal string, and a raw amount is never a JSON integer.
  • Asset ids are deterministic CAIP-19 and permanently stable.
  • Every movement is a part[]; fees are siblings of movements.
  • Multi-tenancy is designed in. Two tenants can never see each other's data.
  • pytest passes on a fresh clone with no API keys, because the cassettes are committed.
  • Files cap at 400 lines with no allowlist, and tests/style/ enforces the layer contract.

Docker

docker compose run --rm test    # full offline suite in a network-less container
docker compose run --rm demo    # quickstart against the installed wheel

Docs

auradefi.info is built from this repository, with every example executed at build time and every signature generated from the code.

Start here:

Also in the repository:

Licence

Apache-2.0. See LICENSE.

Release files for auradefi 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for auradefi 0.1.2
File Size Uploaded
auradefi-0.1.2.tar.gz 1.0 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for auradefi 0.1.2
File Interpreter ABI Platform
auradefi-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 1.4 MB

Release files / auradefi-0.1.2.tar.gz

Download URL auradefi-0.1.2.tar.gz
Size 1.0 MB
Tags Source
SHA-256 checksum
How to use checksums
fa195c4fd1b653d810fbe33acbb53bee8709557c28b1ea626e6fa7fbead96eb6
BLAKE2b-256 checksum
How to use checksums
39c40ef5d57621ca6cc451ff12788c07e643eec6d757105db1d79784b06dbfa8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Pop!_OS","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / auradefi-0.1.2-py3-none-any.whl

Download URL auradefi-0.1.2-py3-none-any.whl
Size 327.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
25704b38560704cc1d349d26908b691f670eb0d83251527bc634dba918cda365
BLAKE2b-256 checksum
How to use checksums
85f96b60fa5ffbf71e422a5f727ccd783dc75292a5ffb9dda12a092505da3853
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Pop!_OS","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page