auradefi
Open-source, multi-tenant crypto data aggregator. The tenancy model of Vezgo, the DeFi position depth of DeBank, the transaction decomposition of Zerion, and Plaid's wire format — so crypto merges with bank and exchange data in one schema downstream.
Library first, service second. A Python host imports auradefi
directly and pays no serialisation or network cost; the HTTP API is a thin
shell over the importable core.
Status: alpha. All ten SPEC phases are implemented and the 0.1.0 release gate was green offline on a fresh clone with no API keys.
Do not use 0.1.0. An independent adversarial review found nineteen verified defects in it — five security, four silent data loss — none of which failed a test.
docs/RELEASE_0.1.1.mdis the full accounting and 0.1.1 is the fix release, in progress.STATUS.mdcarries the live test count and which of those fixes have landed; the capability table below says what works today, anddocs/SPEC.mdis the full design contract.
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 (no pip on your system python? 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 docs/examples/quickstart.py # every phase, end to end
Using it
As a library — the host owns storage, transport, prices and the tick (SPEC §8):
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 — 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
Both surfaces are walked — executably, offline — in
docs/books/.
What works today
Coverage published as data, not prose optimism (rule #10). Every row marked
works has an executable notebook under docs/books/ that
runs offline and asserts its own outputs, plus a gate test under tests/.
| Capability | Phase | Status |
|---|---|---|
Quantity/Money: exact at 10^77, four-field wire form, raw always a JSON string, strict wire grammar |
0 | works — 02_money |
CAIP-2/CAIP-19 parse + canonicalize, deterministic ast_… ids, both-ways asset registry |
0 | works — 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) |
0 | works — 03_assets_chains |
Ledger port: idempotent upsert, cursor sync with has_more paging, reorg = removed + re-added, resurrection, tenant isolation |
0 | works — memory and SQLModel backends; 04_ledger |
Cassette replay harness (CassetteMissError offline guarantee) |
0 | works — 01_foundation |
Style gates: size, structure, placement, layering (tests/style) |
0 | works — no allowlist |
EVM balances → holdings, exact-Decimal USD totals, unpriced assets named not guessed |
1 | works — Etherscan V2 source + DefiLlama prices; 05_holdings |
Tenancy: org/project/end-user, scoped adk_ keys, authEndpoint JWT mint, three-window quota, audit log |
2 | works — isolation gate actively tries to leak; 06_tenancy |
Rich transactions: parts[]/acts[], fees as siblings carrying borne_by, derived type, ledger bridge, reorg + resurrection |
3 | works — EVM only, one act per transaction; 07_transactions |
| DeFi positions: adapter protocol, drill-down, group totals + health factor, signed synthetic-Holdings projection | 4 | works — Uniswap v2/v3, Aave v3, Lido/Rocket Pool; fixture-driven, see below; 08_positions |
Embedding: from auradefi import Auradefi, host-owned session, budgeted two-phase sync, 26-metric scalar projection |
5 | RED on this branch — the 0.1.1 sync fixes (#18/#21/#24) are in embed/ and their recorded fixture has not been re-recorded to match the new backfill window, so the engine is currently losing rows against it; see STATUS.md. Chain-scoped connection ids, restart resume and per-connection failure isolation are demonstrated in docs/examples/quickstart.py; 09_embedding does not execute clean |
| Bitcoin: pure-Python BIP32 xpub derivation, gap-20 scan, confirmed-only UTXO balances | 6 | works — p2wpkh + Esplora only; the extended key never reaches HTTP; 10_bitcoin_solana |
| Solana: SPL + Token-2022 balances, ScaledUiAmount carried both ways, signature history | 7 | works — balances only, no decode; 10_bitcoin_solana |
HTTP API: Plaid /crypto/sync envelope, connections, /coverage generated as data, nine quota headers, batch holdings |
8 | works — 12_http_api |
| Webhooks: HMAC-SHA256 signed, durable over a pinned retry schedule, dead letter + replay | 8 | works — 12_http_api |
Accounting: lot ledger, FIFO/LIFO/HIFO/ACB, realised + unrealised PnL, arbitrary-date PnL, Plaid tax_lots |
9 | works — 50,000-event gate; 11_accounting |
What is not there
Stated plainly, because rule #10 cuts both ways.
- 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 / Solana RPC needs your own keys and endpoints, and has not been reconciled against an incumbent in CI.
- Positions are fixture-driven. The
ContractReaderseam ships and every adapter is pinned to block-20,450,000 golden vectors, but no concrete on-chain reader ships — there is noeth_calltransport and no multicall batcher in the package. A host must supply its own reader to run the adapters against a live chain. - No multicall anywhere. Token balances cost one request each.
- One price oracle (DefiLlama), current prices only. No fallback feed and
no historical price service:
prices/historian.pyandprices/store.pyare declared in the spec's layout and absent, along with thecoingecko,manualandonchain_ammoracles, so accounting marks are the caller's. - No
jobs/package. The spec declaresscheduler.py,discover.py,refresh.py,reprocess.pyandbackfill.py; none of them ship. There is no scheduler, no background worker and no reprocess path — the host owns every tick, and a backfill is async()budget you spend yourself. - Five of the nine declared
api/routes/modules are absent:accounts.py,holdings.py,positions.py,transactions.pyandwebhooks.py. What ships isauth,connections,syncandadmin— so holdings and positions have no HTTP surface of their own, and the webhook admin routes live inadmin.pyrather than in awebhooks.py. project/ships onlyscalar.py.project/plaid.pyandproject/native.pyare declared and absent; the Plaid envelope is projected inapi/wire.pyinstead, which means 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. Tenancy, keys, quota, audit and webhook stores are in-memory only.
- Cosmos is absent, as is every EVM chain the registry does not seed,
along with exchange connections, NFTs and protocol-specific decoders
(
acts[]is always one act andprotocolis alwaysNone). - Solana transaction decode is not implemented — balances and signature history only.
- No async surface, no background worker, no scheduler: the host owns the tick.
- No migration for the 0.1.1 embed id break. Library-ingested embed
connection ids — and every
transaction_idhashed over them — re-derive in 0.1.1, so 0.1.0 rows written throughAuradefistop 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. SyncStatePortis 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 rather than silently syncing nothing.
The rules the code lives by
- Money is a tagged decimal string; 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, never movements. - Multi-tenancy is designed in; two tenants can never see each other's data.
pytestpasses on a fresh clone with no API keys — cassettes committed.- Files cap at 400 lines with no allowlist; the layer contract is enforced
by tests (
tests/style/), not by convention.
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
docs/SPEC.md— the design contractdocs/books/— twelve executable notebooks, run headlessly in CI so they cannot rotdocs/DECISIONS.md— every pinned algorithm and id formulaSTATUS.md— phase gates and known caveatsdocs/AGENT_PROMPTS.md— the agent loop that builds this repo, with copy-paste promptsdocs/RELEASING.md— pip + Docker release proceduredocs/RELEASE_0.1.1.md— every defect found in 0.1.0, its fix and the regression-test protocolCHANGELOG.md— what changed per release, including the 0.1.1 upgrade note
Licence
Apache-2.0 — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file auradefi-0.1.1.tar.gz.
File metadata
- Download URL: auradefi-0.1.1.tar.gz
- Upload date:
- Size: 651.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
21113758a0feaf1e476143d1870ab3206499998d3244ef937ff83c6ad9ea227e
|
|
| MD5 |
42622b2aeadf32baef33a7b2dc20bcc8
|
|
| BLAKE2b-256 |
5efa7a6596e73f572c04579d6f6ff43e4fc6a90d8cb4466bbb30192f3d7906c2
|
File details
Details for the file auradefi-0.1.1-py3-none-any.whl.
File metadata
- Download URL: auradefi-0.1.1-py3-none-any.whl
- Upload date:
- Size: 259.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc946b1f3958d2a94dbba54ccd6a0b9c2099113e9dc922cfa8a4a2d6c4c9536c
|
|
| MD5 |
c56ceb838e8af8a41054f87d21b6a6ed
|
|
| BLAKE2b-256 |
d46aeea7c6b5e9a2789de97bb8b2eb4937b15be135647a5dac75ee67b5b315bc
|