charli3_dendrite 1.6.7.dev0__tar.gz → 1.6.7.dev1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/PKG-INFO +1 -1
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/pyproject.toml +2 -2
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/backend/dbsync/__init__.py +2 -0
- charli3_dendrite-1.6.7.dev1/src/charli3_dendrite/lending/builtins.py +20 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/oracles/forward.py +72 -15
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/oracles/locator.py +2 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/oracles/reproduce.py +2 -2
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/_common.py +11 -12
- charli3_dendrite-1.6.7.dev1/src/charli3_dendrite/lending/fetch.py +58 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/indexing.py +2 -41
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/loader.py +11 -29
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/market.py +21 -25
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/rates.py +2 -17
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/state.py +5 -18
- charli3_dendrite-1.6.7.dev1/src/charli3_dendrite/lending/liqwid/datums.py +657 -0
- charli3_dendrite-1.6.7.dev1/src/charli3_dendrite/lending/liqwid/deployment.py +926 -0
- charli3_dendrite-1.6.7.dev1/src/charli3_dendrite/lending/liqwid/indexing.py +363 -0
- charli3_dendrite-1.6.7.dev1/src/charli3_dendrite/lending/liqwid/lifecycle.py +405 -0
- charli3_dendrite-1.6.7.dev1/src/charli3_dendrite/lending/liqwid/loader.py +104 -0
- charli3_dendrite-1.6.7.dev1/src/charli3_dendrite/lending/liqwid/market.py +459 -0
- charli3_dendrite-1.6.7.dev1/src/charli3_dendrite/lending/liqwid/math.py +415 -0
- charli3_dendrite-1.6.7.dev1/src/charli3_dendrite/lending/liqwid/oracles.py +327 -0
- charli3_dendrite-1.6.7.dev1/src/charli3_dendrite/lending/liqwid/rates.py +179 -0
- charli3_dendrite-1.6.7.dev1/src/charli3_dendrite/lending/liqwid/registry_v6.json +5739 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/markets.py +151 -17
- charli3_dendrite-1.6.7.dev1/src/charli3_dendrite/lending/math.py +85 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/normalized.py +176 -18
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/oracles/models.py +4 -2
- charli3_dendrite-1.6.7.dev1/src/charli3_dendrite/lending/oracles/qtoken.py +150 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/rates.py +63 -6
- charli3_dendrite-1.6.7.dev1/src/charli3_dendrite/lending/units.py +182 -0
- charli3_dendrite-1.6.7.dev0/src/charli3_dendrite/lending/liqwid/datums.py +0 -112
- charli3_dendrite-1.6.7.dev0/src/charli3_dendrite/lending/math.py +0 -34
- charli3_dendrite-1.6.7.dev0/src/charli3_dendrite/lending/oracles/qtoken.py +0 -50
- charli3_dendrite-1.6.7.dev0/src/charli3_dendrite/lending/units.py +0 -83
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/LICENSE +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/README.md +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/backend/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/backend/backend_base.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/backend/blockfrost/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/backend/blockfrost/models.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/backend/dbsync/models.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/backend/ogmios_kupo/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/backend/ogmios_kupo/models.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/backend/utils.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dataclasses/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dataclasses/datums.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dataclasses/models.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/amm_base.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/amm_types.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/cswap.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/dano.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/minswap.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/muesli.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/multi_asset.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/spectrum.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/splash.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/sundae.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/sundae_v4.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/sundae_v4_banded_cl_math.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/sundae_v4_deployments.json +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/sundae_v4_stableswap_math.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/vyfi.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/amm/wingriders.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/core/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/core/base.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/core/errors.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/ob/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/ob/axo.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/ob/cardanoswaps.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/ob/chadswap.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/ob/djed.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/ob/geniusyield.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/ob/ob_base.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/dexs/ob/saturnswap.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/base.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/constants.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/datums.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/loader.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/market.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/math.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/oracles/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/oracles/aggregator.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/oracles/aggregator_datums.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/oracles/deployments.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/oracles/leaves.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/oracles/lp_pricing.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/oracles/recipes.json +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/oracles/redeemer.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/oracles/structured_datums.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/state.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/build.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/builder.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/context.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/create_loan.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/datum_synth.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/increase_loan.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/loan_ids.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/modify_collateral.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/oracle_redeemer.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/oracle_synth.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/redeemers.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/repay.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/topup_withdraw.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/danogo/transactions/verify.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/constants.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/datums.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/loader.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/market.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/math.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/oracles/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/oracles/feeds.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/oracles/fluid_api.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/oracles/witness.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/state.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/_common.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/borrow.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/borrow_terms.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/builder.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/change_collateral.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/context.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/datum_synth.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/lend.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/pool.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/recast.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/redeemers.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/repay.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/request.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/resolve.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens/transactions/utxos.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/constants.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/datums.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/borrow.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/builder.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/change_collateral.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/claim.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/common.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/lender_bond.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/loan_action.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/loan_terms.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/oracle.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/pool_action.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/pool_cancel.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/pool_create.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/pool_edit.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/pool_terms.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/recast.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/redeemers.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/repay.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/fluidtokens_v4/transactions/resolve.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/liqwid/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/oracles/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/oracles/charli3.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/oracles/dex_pooled.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/oracles/fluid.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/oracles/orcfax.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/plutus.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/registry.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/transactions/__init__.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/transactions/base.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/transactions/infra.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/lending/transactions/snapshot.py +0 -0
- {charli3_dendrite-1.6.7.dev0 → charli3_dendrite-1.6.7.dev1}/src/charli3_dendrite/utility.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "charli3_dendrite"
|
|
3
|
-
version = "1.6.7-
|
|
3
|
+
version = "1.6.7-dev1"
|
|
4
4
|
description = ""
|
|
5
5
|
authors = ["Elder Millenial <eldermillenial@protonmail.com>"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -50,7 +50,7 @@ module = ["pycardano", "pycardano.*", "dotenv", "nox", "uplc", "uplc.*"]
|
|
|
50
50
|
ignore_missing_imports = true
|
|
51
51
|
|
|
52
52
|
[tool.bumpversion]
|
|
53
|
-
current_version = "1.6.7-
|
|
53
|
+
current_version = "1.6.7-dev1"
|
|
54
54
|
parse = """(?x)
|
|
55
55
|
(?P<major>\\d+)\\.
|
|
56
56
|
(?P<minor>\\d+)\\.
|
|
@@ -214,7 +214,9 @@ AND txo.consumed_by_tx_id IS NULL"""
|
|
|
214
214
|
datum_selector += """
|
|
215
215
|
AND ma.policy = ANY(%(policies)b) AND ma.name = ANY(%(names)b)"""
|
|
216
216
|
|
|
217
|
+
# A stable order, so LIMIT / OFFSET pages neither skip nor repeat a row.
|
|
217
218
|
datum_selector += """
|
|
219
|
+
ORDER BY txo.id
|
|
218
220
|
LIMIT %(limit)s
|
|
219
221
|
OFFSET %(offset)s"""
|
|
220
222
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""The protocol modules shipped with the lending package, in one table.
|
|
2
|
+
|
|
3
|
+
Each entry names the module that registers a protocol (never its bare package), and
|
|
4
|
+
that module provides:
|
|
5
|
+
|
|
6
|
+
- ``RATE_MODELS: tuple[type[RateModel], ...]``, the protocol's rate models, which
|
|
7
|
+
:mod:`charli3_dendrite.lending.rates` registers on its first lookup; and
|
|
8
|
+
- ``market_source() -> MarketSource``, the protocol's market source, which
|
|
9
|
+
:mod:`charli3_dendrite.lending.markets` registers on its first use.
|
|
10
|
+
|
|
11
|
+
Both registries keep a caller's own registration under the same key. No entry is
|
|
12
|
+
imported until a registry is first used.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
BUILTIN_PROTOCOL_PACKAGES: tuple[str, ...] = (
|
|
18
|
+
"charli3_dendrite.lending.fluidtokens_v4.market",
|
|
19
|
+
"charli3_dendrite.lending.liqwid.market",
|
|
20
|
+
)
|
|
@@ -17,8 +17,8 @@ from charli3_dendrite.lending.danogo.oracles.redeemer import OracleUtxoType
|
|
|
17
17
|
from charli3_dendrite.lending.danogo.oracles.reproduce import OracleLeaf
|
|
18
18
|
from charli3_dendrite.lending.danogo.oracles.reproduce import leaf_forward_rates
|
|
19
19
|
from charli3_dendrite.lending.danogo.oracles.reproduce import splash_lp_candidate
|
|
20
|
-
from charli3_dendrite.lending.liqwid.datums import
|
|
21
|
-
from charli3_dendrite.lending.liqwid.datums import
|
|
20
|
+
from charli3_dendrite.lending.liqwid.datums import POLICY_KEY_PREFIX
|
|
21
|
+
from charli3_dendrite.lending.liqwid.datums import decode_oracle_feed
|
|
22
22
|
from charli3_dendrite.lending.oracles.models import OraclePrice
|
|
23
23
|
from charli3_dendrite.lending.oracles.models import OracleSource
|
|
24
24
|
from charli3_dendrite.lending.oracles.models import PriceMap
|
|
@@ -57,9 +57,10 @@ def leaf_discriminator(otype: str, datum: str | None) -> str:
|
|
|
57
57
|
Some source kinds live many-to-one behind a shared marker token at a common
|
|
58
58
|
address, so the value alone cannot pin a UTxO; a stable datum field can:
|
|
59
59
|
|
|
60
|
-
* Liqwid V2 oracles ->
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
* Liqwid V2 oracles -> the priced asset's key (``OracleFeedDatum.asset_key``:
|
|
61
|
+
the asset unit, or ``policy:<policy>`` for a policy-wide feed). Each priced
|
|
62
|
+
asset has exactly one unspent feed carrying the oracle token; the updater key
|
|
63
|
+
rotates and is not part of the identity.
|
|
63
64
|
* Minswap pools -> the ``asset_a|asset_b`` pair (all pools carry one MSP token).
|
|
64
65
|
|
|
65
66
|
Returns "" for kinds already pinned by a unique NFT (no datum disambiguation
|
|
@@ -69,7 +70,7 @@ def leaf_discriminator(otype: str, datum: str | None) -> str:
|
|
|
69
70
|
return ""
|
|
70
71
|
try:
|
|
71
72
|
if otype == OracleUtxoType.TLIQWID_ORACLE_V2.name:
|
|
72
|
-
return
|
|
73
|
+
return decode_oracle_feed(datum).asset_key
|
|
73
74
|
if otype == OracleUtxoType.TMINSWAP_LP.name:
|
|
74
75
|
asset_a, _, asset_b, _ = parse_minswap_lp(datum)
|
|
75
76
|
return f"{asset_a}|{asset_b}"
|
|
@@ -78,6 +79,32 @@ def leaf_discriminator(otype: str, datum: str | None) -> str:
|
|
|
78
79
|
return ""
|
|
79
80
|
|
|
80
81
|
|
|
82
|
+
def _handle_key(handle: LeafHandle) -> str:
|
|
83
|
+
"""The identity ``handle.datum_key`` pins, in `leaf_discriminator`'s form.
|
|
84
|
+
|
|
85
|
+
A Liqwid oracle key in the earlier ``<updater>:<asset>`` form pins its asset
|
|
86
|
+
part; a ``policy:<policy>`` key is already in the current form.
|
|
87
|
+
"""
|
|
88
|
+
key = handle.datum_key
|
|
89
|
+
if handle.otype == OracleUtxoType.TLIQWID_ORACLE_V2.name and not key.startswith(
|
|
90
|
+
POLICY_KEY_PREFIX,
|
|
91
|
+
):
|
|
92
|
+
return key.rpartition(":")[2]
|
|
93
|
+
return key
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def leaf_matches_handle(handle: LeafHandle, datum: str | None) -> bool:
|
|
97
|
+
"""Whether a leaf's datum carries the identity ``handle.datum_key`` pins.
|
|
98
|
+
|
|
99
|
+
True for every datum when the handle has no ``datum_key`` (its NFT alone pins
|
|
100
|
+
the UTxO). Otherwise the leaf's `leaf_discriminator` must equal the handle's key;
|
|
101
|
+
a Liqwid oracle key captured as ``<updater>:<asset>`` is compared by its asset.
|
|
102
|
+
"""
|
|
103
|
+
if not handle.datum_key:
|
|
104
|
+
return True
|
|
105
|
+
return leaf_discriminator(handle.otype, datum) == _handle_key(handle)
|
|
106
|
+
|
|
107
|
+
|
|
81
108
|
@dataclass(frozen=True)
|
|
82
109
|
class LiveLeaf:
|
|
83
110
|
"""A source leaf as currently read on-chain: its parser type, datum, and value."""
|
|
@@ -206,6 +233,35 @@ def compose_cross_quote(
|
|
|
206
233
|
return collat_price, intermediate_to_quote
|
|
207
234
|
|
|
208
235
|
|
|
236
|
+
def _leaf_addresses(handle: LeafHandle) -> list[str]:
|
|
237
|
+
"""The addresses a handle's leaf is read from.
|
|
238
|
+
|
|
239
|
+
A Liqwid oracle leaf is read at ``handle.address`` and at every Liqwid oracle
|
|
240
|
+
validator of the bundled deployment, captured address first, each address once:
|
|
241
|
+
Liqwid binds a feed by oracle token and asset, whatever its validator, and the
|
|
242
|
+
captured address stays read when the deployment no longer lists it. Every other
|
|
243
|
+
kind is read at ``handle.address`` only.
|
|
244
|
+
"""
|
|
245
|
+
if handle.otype != OracleUtxoType.TLIQWID_ORACLE_V2.name:
|
|
246
|
+
return [handle.address]
|
|
247
|
+
# Imported here so that importing this module loads no Liqwid deployment.
|
|
248
|
+
from charli3_dendrite.lending.liqwid.indexing import LiqwidKind
|
|
249
|
+
from charli3_dendrite.lending.liqwid.indexing import liqwid_selectors
|
|
250
|
+
|
|
251
|
+
return list(
|
|
252
|
+
dict.fromkeys(
|
|
253
|
+
[
|
|
254
|
+
handle.address,
|
|
255
|
+
*(
|
|
256
|
+
selector.address
|
|
257
|
+
for selector in liqwid_selectors()
|
|
258
|
+
if selector.kind is LiqwidKind.ORACLE
|
|
259
|
+
),
|
|
260
|
+
],
|
|
261
|
+
),
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
|
|
209
265
|
def resolve_leaf_info(
|
|
210
266
|
backend: AbstractBackend,
|
|
211
267
|
handle: LeafHandle,
|
|
@@ -214,7 +270,9 @@ def resolve_leaf_info(
|
|
|
214
270
|
|
|
215
271
|
A unique identifying NFT yields a single match; kinds that share a marker token
|
|
216
272
|
across many feeds at one address (e.g. Liqwid V2 oracles) are narrowed by
|
|
217
|
-
`handle.datum_key` -- the stable asset-identity parsed from each candidate's datum
|
|
273
|
+
`handle.datum_key` -- the stable asset-identity parsed from each candidate's datum
|
|
274
|
+
(`leaf_matches_handle`). A Liqwid oracle leaf is looked up at ``handle.address``
|
|
275
|
+
and at every Liqwid oracle validator (`_leaf_addresses`).
|
|
218
276
|
Returns None unless exactly one UTxO matches, so the caller never reads the wrong
|
|
219
277
|
feed. This is the shared resolution both `read_live_leaf` (forward pricing) and the
|
|
220
278
|
create-loan snapshot (full-UTxO assembly) rely on.
|
|
@@ -222,18 +280,17 @@ def resolve_leaf_info(
|
|
|
222
280
|
want = (handle.nft_policy + handle.nft_name) if handle.nft_policy else None
|
|
223
281
|
rows = list(
|
|
224
282
|
backend.get_pool_utxos(
|
|
225
|
-
addresses=
|
|
283
|
+
addresses=_leaf_addresses(handle),
|
|
226
284
|
assets=[want] if want else None,
|
|
227
285
|
historical=False,
|
|
228
286
|
),
|
|
229
287
|
)
|
|
230
|
-
matches = [
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
]
|
|
288
|
+
matches = [
|
|
289
|
+
info
|
|
290
|
+
for info in rows
|
|
291
|
+
if (want is None or want in info.assets.root)
|
|
292
|
+
and leaf_matches_handle(handle, info.datum_cbor)
|
|
293
|
+
]
|
|
237
294
|
if len(matches) != 1:
|
|
238
295
|
return None
|
|
239
296
|
return matches[0]
|
|
@@ -50,6 +50,8 @@ class LeafHandle:
|
|
|
50
50
|
`datum_key` is a further discriminator for kinds that share one marker token across
|
|
51
51
|
many feeds (e.g. Liqwid V2 oracles): the stable asset-identity parsed from the leaf
|
|
52
52
|
datum (see `forward.leaf_discriminator`). Empty when the NFT alone pins the UTxO.
|
|
53
|
+
A Liqwid oracle leaf is identified by its token and `datum_key` alone and is read
|
|
54
|
+
at every Liqwid oracle validator; its `address` is where it was captured.
|
|
53
55
|
"""
|
|
54
56
|
|
|
55
57
|
otype: str
|
|
@@ -47,8 +47,8 @@ from charli3_dendrite.lending.danogo.oracles.leaves import parse_minswap_lp
|
|
|
47
47
|
from charli3_dendrite.lending.danogo.oracles.leaves import parse_splash_cpamm_g3
|
|
48
48
|
from charli3_dendrite.lending.danogo.oracles.leaves import splash_lp_token_price
|
|
49
49
|
from charli3_dendrite.lending.danogo.oracles.redeemer import OracleUtxoType
|
|
50
|
+
from charli3_dendrite.lending.liqwid.datums import decode_oracle_feed
|
|
50
51
|
from charli3_dendrite.lending.liqwid.datums import parse_liqwid_market_state
|
|
51
|
-
from charli3_dendrite.lending.liqwid.datums import parse_liqwid_oracle_v2
|
|
52
52
|
|
|
53
53
|
# Liqwid market qToken: the on-chain price divides the field-9 exchange rate by the
|
|
54
54
|
# underlying's (cent-denominated) price; that constant is folded into the leaf rate so
|
|
@@ -96,7 +96,7 @@ def leaf_forward_rates(leaf: OracleLeaf) -> List[Tuple[str, Fraction]]:
|
|
|
96
96
|
num, den = parse_danogo_staking_rate(datum)
|
|
97
97
|
out.append(("stake", Fraction(num, den)))
|
|
98
98
|
elif leaf.otype == OracleUtxoType.TLIQWID_ORACLE_V2 and datum is not None:
|
|
99
|
-
|
|
99
|
+
num, den = decode_oracle_feed(datum).price
|
|
100
100
|
out.append(("liqv2", Fraction(num, den)))
|
|
101
101
|
elif leaf.otype == OracleUtxoType.TDJED and datum is not None:
|
|
102
102
|
_, (num, den) = parse_djed(datum)
|
|
@@ -47,7 +47,7 @@ from charli3_dendrite.lending.danogo.oracles.deployments import (
|
|
|
47
47
|
from charli3_dendrite.lending.danogo.oracles.forward import INTERMEDIATE_QUOTE
|
|
48
48
|
from charli3_dendrite.lending.danogo.oracles.forward import LiveLeaf
|
|
49
49
|
from charli3_dendrite.lending.danogo.oracles.forward import compose_cross_quote
|
|
50
|
-
from charli3_dendrite.lending.danogo.oracles.forward import
|
|
50
|
+
from charli3_dendrite.lending.danogo.oracles.forward import leaf_matches_handle
|
|
51
51
|
from charli3_dendrite.lending.danogo.oracles.forward import replay_recipe
|
|
52
52
|
from charli3_dendrite.lending.danogo.oracles.leaves import parse_orcfax_fs
|
|
53
53
|
from charli3_dendrite.lending.danogo.oracles.locator import Recipe
|
|
@@ -145,18 +145,17 @@ def _leaf_for_handle(leaves: list[Utxo], handle: LeafHandle) -> Utxo | None:
|
|
|
145
145
|
"""Find the resolved source leaf a recipe step's handle points at.
|
|
146
146
|
|
|
147
147
|
Matches by the handle's identifying NFT (policy + name) and, when present, the
|
|
148
|
-
datum discriminator that pins kinds sharing one marker token across many feeds
|
|
148
|
+
datum discriminator that pins kinds sharing one marker token across many feeds
|
|
149
|
+
(`leaf_matches_handle`, as `resolve_leaf_info`). None unless exactly one leaf
|
|
150
|
+
matches.
|
|
149
151
|
"""
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
continue
|
|
158
|
-
return u
|
|
159
|
-
return None
|
|
152
|
+
matches = [
|
|
153
|
+
u
|
|
154
|
+
for u in leaves
|
|
155
|
+
if (not handle.nft_policy or u.holds(handle.nft_policy, handle.nft_name))
|
|
156
|
+
and leaf_matches_handle(handle, u.datum)
|
|
157
|
+
]
|
|
158
|
+
return matches[0] if len(matches) == 1 else None
|
|
160
159
|
|
|
161
160
|
|
|
162
161
|
def _resolve_recipe(
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Backend reads shared by the protocol loaders.
|
|
2
|
+
|
|
3
|
+
A protocol loader fetches every unspent UTxO at a script address and classifies each
|
|
4
|
+
row with its own parser; the paging, the out-ref de-duplication and the default
|
|
5
|
+
evaluation time are the same for every protocol and live here.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import time
|
|
11
|
+
from typing import TYPE_CHECKING
|
|
12
|
+
from typing import Final
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from charli3_dendrite.backend.backend_base import AbstractBackend
|
|
16
|
+
from charli3_dendrite.dataclasses.models import PoolStateInfo
|
|
17
|
+
|
|
18
|
+
PAGE_SIZE: Final[int] = 1000
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def unspent_utxos(
|
|
22
|
+
backend: AbstractBackend,
|
|
23
|
+
address: str,
|
|
24
|
+
*,
|
|
25
|
+
page_size: int = PAGE_SIZE,
|
|
26
|
+
) -> list[PoolStateInfo]:
|
|
27
|
+
"""Every unspent UTxO the backend returns for ``address``, once per out-ref.
|
|
28
|
+
|
|
29
|
+
Pages through ``get_pool_utxos`` and terminates on a short page or on a page that
|
|
30
|
+
adds no new out-ref, so a backend that ignores ``page`` and returns the same rows
|
|
31
|
+
again ends the loop. Rows are de-duplicated by out-ref, keeping the first row
|
|
32
|
+
returned, since the backend pages with LIMIT / OFFSET. Rows keep the backend's
|
|
33
|
+
order.
|
|
34
|
+
"""
|
|
35
|
+
rows_by_ref: dict[tuple[str, int], PoolStateInfo] = {}
|
|
36
|
+
page = 0
|
|
37
|
+
while True:
|
|
38
|
+
rows = list(
|
|
39
|
+
backend.get_pool_utxos(
|
|
40
|
+
addresses=[address],
|
|
41
|
+
limit=page_size,
|
|
42
|
+
page=page,
|
|
43
|
+
historical=False,
|
|
44
|
+
),
|
|
45
|
+
)
|
|
46
|
+
before = len(rows_by_ref)
|
|
47
|
+
for info in rows:
|
|
48
|
+
rows_by_ref.setdefault((info.tx_hash, info.tx_index), info)
|
|
49
|
+
if len(rows) < page_size or len(rows_by_ref) == before:
|
|
50
|
+
return list(rows_by_ref.values())
|
|
51
|
+
page += 1
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def resolve_now_ms(now_ms: int | None) -> int:
|
|
55
|
+
"""``now_ms`` (POSIX ms), or the current time when it is None."""
|
|
56
|
+
if now_ms is None:
|
|
57
|
+
return int(time.time() * 1000)
|
|
58
|
+
return now_ms
|
|
@@ -13,13 +13,6 @@ from dataclasses import dataclass
|
|
|
13
13
|
from enum import Enum
|
|
14
14
|
from typing import Union
|
|
15
15
|
|
|
16
|
-
import cbor2 # type: ignore[import-not-found]
|
|
17
|
-
from pycardano import Address
|
|
18
|
-
from pycardano import ScriptHash
|
|
19
|
-
from pycardano.exception import DecodingException
|
|
20
|
-
from pycardano.exception import DeserializeException
|
|
21
|
-
from pycardano.exception import InvalidAddressInputException
|
|
22
|
-
|
|
23
16
|
from charli3_dendrite.dataclasses.models import PoolSelector
|
|
24
17
|
from charli3_dendrite.dataclasses.models import PoolStateInfo
|
|
25
18
|
from charli3_dendrite.lending.fluidtokens_v4 import constants as c
|
|
@@ -32,6 +25,8 @@ from charli3_dendrite.lending.fluidtokens_v4.state import FluidV4PoolManagerStat
|
|
|
32
25
|
from charli3_dendrite.lending.fluidtokens_v4.state import FluidV4PoolState
|
|
33
26
|
from charli3_dendrite.lending.fluidtokens_v4.state import FluidV4RequestState
|
|
34
27
|
from charli3_dendrite.lending.fluidtokens_v4.state import identity_name
|
|
28
|
+
from charli3_dendrite.lending.units import DECODE_ERRORS
|
|
29
|
+
from charli3_dendrite.lending.units import script_credential
|
|
35
30
|
from charli3_dendrite.lending.units import script_payment_address
|
|
36
31
|
|
|
37
32
|
FluidV4State = Union[
|
|
@@ -67,18 +62,6 @@ _STATE_CLASS: dict[EntityKind, type[FluidV4State]] = {
|
|
|
67
62
|
EntityKind.LOCKED_BORROWER_MANAGER: FluidV4LockedBorrowerState,
|
|
68
63
|
}
|
|
69
64
|
|
|
70
|
-
# Everything a malformed record can raise while its datum is decoded. Truncated CBOR
|
|
71
|
-
# raises cbor2's end-of-stream error, which is not a ValueError.
|
|
72
|
-
DECODE_ERRORS = (
|
|
73
|
-
cbor2.CBORDecodeError,
|
|
74
|
-
DeserializeException,
|
|
75
|
-
ValueError,
|
|
76
|
-
TypeError,
|
|
77
|
-
KeyError,
|
|
78
|
-
IndexError,
|
|
79
|
-
AttributeError,
|
|
80
|
-
)
|
|
81
|
-
|
|
82
65
|
|
|
83
66
|
@dataclass(frozen=True)
|
|
84
67
|
class EntitySelector:
|
|
@@ -138,28 +121,6 @@ def entity_selectors(
|
|
|
138
121
|
}
|
|
139
122
|
|
|
140
123
|
|
|
141
|
-
def script_credential(address: str) -> str | None:
|
|
142
|
-
"""Payment script hash (hex) of a bech32 address; None for any other address.
|
|
143
|
-
|
|
144
|
-
Every V4 entity sits at a script credential, so a key-hash payment part (even one
|
|
145
|
-
whose bytes equal a V4 script hash) returns None, as does an unparseable address.
|
|
146
|
-
pycardano asserts key-hash sizes and decodes a bech32 Byron header as CBOR, so a
|
|
147
|
-
malformed address can also raise ``AssertionError`` or ``DeserializeException``.
|
|
148
|
-
"""
|
|
149
|
-
try:
|
|
150
|
-
part = Address.decode(address).payment_part
|
|
151
|
-
except (
|
|
152
|
-
AssertionError,
|
|
153
|
-
DecodingException,
|
|
154
|
-
DeserializeException,
|
|
155
|
-
InvalidAddressInputException,
|
|
156
|
-
TypeError,
|
|
157
|
-
ValueError,
|
|
158
|
-
):
|
|
159
|
-
return None
|
|
160
|
-
return part.payload.hex() if isinstance(part, ScriptHash) else None
|
|
161
|
-
|
|
162
|
-
|
|
163
124
|
def parse_utxo(
|
|
164
125
|
info: PoolStateInfo,
|
|
165
126
|
selectors: Mapping[EntityKind, EntitySelector] | None = None,
|
|
@@ -12,12 +12,14 @@ that matches exact addresses the snapshot comes back empty.
|
|
|
12
12
|
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
|
|
15
|
-
import time
|
|
16
15
|
from dataclasses import dataclass
|
|
17
16
|
from typing import TYPE_CHECKING
|
|
18
17
|
from typing import TypeVar
|
|
19
18
|
|
|
20
19
|
from charli3_dendrite.lending.base import LendingBook
|
|
20
|
+
from charli3_dendrite.lending.fetch import PAGE_SIZE
|
|
21
|
+
from charli3_dendrite.lending.fetch import resolve_now_ms
|
|
22
|
+
from charli3_dendrite.lending.fetch import unspent_utxos
|
|
21
23
|
from charli3_dendrite.lending.fluidtokens_v4.constants import resolve_config
|
|
22
24
|
from charli3_dendrite.lending.fluidtokens_v4.indexing import EntityKind
|
|
23
25
|
from charli3_dendrite.lending.fluidtokens_v4.indexing import EntitySelector
|
|
@@ -37,8 +39,6 @@ if TYPE_CHECKING:
|
|
|
37
39
|
from charli3_dendrite.lending.fluidtokens_v4.datums import ConfigDatum
|
|
38
40
|
from charli3_dendrite.lending.oracles.models import PriceMap
|
|
39
41
|
|
|
40
|
-
PAGE_SIZE = 1000
|
|
41
|
-
|
|
42
42
|
_T = TypeVar("_T")
|
|
43
43
|
|
|
44
44
|
|
|
@@ -50,33 +50,16 @@ def fetch_entities(
|
|
|
50
50
|
) -> list[FluidV4State]:
|
|
51
51
|
"""Every unspent UTxO at ``selector``'s credential that parses as its kind.
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
again ends the loop. Pages are de-duplicated by out-ref, since the backend pages
|
|
56
|
-
with LIMIT / OFFSET. Sorted by out-ref.
|
|
53
|
+
The rows are those of :func:`~charli3_dendrite.lending.fetch.unspent_utxos`: every
|
|
54
|
+
page, once per out-ref. Sorted by out-ref.
|
|
57
55
|
"""
|
|
58
56
|
only = {selector.kind: selector}
|
|
59
57
|
found: dict[str, FluidV4State] = {}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
addresses=[selector.address],
|
|
66
|
-
limit=page_size,
|
|
67
|
-
page=page,
|
|
68
|
-
historical=False,
|
|
69
|
-
),
|
|
70
|
-
)
|
|
71
|
-
before = len(seen)
|
|
72
|
-
for info in rows:
|
|
73
|
-
seen.add((info.tx_hash, info.tx_index))
|
|
74
|
-
state = parse_utxo(info, only)
|
|
75
|
-
if state is not None:
|
|
76
|
-
found.setdefault(state.out_ref, state)
|
|
77
|
-
if len(rows) < page_size or len(seen) == before:
|
|
78
|
-
return [found[ref] for ref in sorted(found)]
|
|
79
|
-
page += 1
|
|
58
|
+
for info in unspent_utxos(backend, selector.address, page_size=page_size):
|
|
59
|
+
state = parse_utxo(info, only)
|
|
60
|
+
if state is not None:
|
|
61
|
+
found.setdefault(state.out_ref, state)
|
|
62
|
+
return [found[ref] for ref in sorted(found)]
|
|
80
63
|
|
|
81
64
|
|
|
82
65
|
def link_loans(
|
|
@@ -134,8 +117,7 @@ def snapshot(
|
|
|
134
117
|
|
|
135
118
|
``now_ms`` (POSIX ms) is the loans' evaluation time; it defaults to now.
|
|
136
119
|
"""
|
|
137
|
-
|
|
138
|
-
now_ms = int(time.time() * 1000)
|
|
120
|
+
now_ms = resolve_now_ms(now_ms)
|
|
139
121
|
config = resolve_config(backend)
|
|
140
122
|
fetched = {
|
|
141
123
|
kind: fetch_entities(backend, selector)
|
|
@@ -7,7 +7,6 @@ number comes from the datum and the contract-exact maths.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
import time
|
|
11
10
|
from fractions import Fraction
|
|
12
11
|
from typing import TYPE_CHECKING
|
|
13
12
|
from typing import Any
|
|
@@ -22,6 +21,7 @@ from charli3_dendrite.lending.fluidtokens_v4.indexing import EntityKind
|
|
|
22
21
|
from charli3_dendrite.lending.fluidtokens_v4.indexing import entity_selectors
|
|
23
22
|
from charli3_dendrite.lending.fluidtokens_v4.indexing import parse_utxo
|
|
24
23
|
from charli3_dendrite.lending.fluidtokens_v4.rates import PROTOCOL_NAME
|
|
24
|
+
from charli3_dendrite.lending.fluidtokens_v4.rates import RATE_MODELS # noqa: F401
|
|
25
25
|
from charli3_dendrite.lending.fluidtokens_v4.rates import FluidAmortizedRate
|
|
26
26
|
from charli3_dendrite.lending.fluidtokens_v4.rates import FluidFlatTermRate
|
|
27
27
|
from charli3_dendrite.lending.fluidtokens_v4.rates import FluidPerpetualRate
|
|
@@ -37,6 +37,7 @@ from charli3_dendrite.lending.fluidtokens_v4.state import names_under
|
|
|
37
37
|
from charli3_dendrite.lending.fluidtokens_v4.transactions.oracle import has_oracle
|
|
38
38
|
from charli3_dendrite.lending.markets import LendingSnapshot
|
|
39
39
|
from charli3_dendrite.lending.markets import WatchSpec
|
|
40
|
+
from charli3_dendrite.lending.markets import convertible_views
|
|
40
41
|
from charli3_dendrite.lending.normalized import BorrowRequest
|
|
41
42
|
from charli3_dendrite.lending.normalized import CollateralHolding
|
|
42
43
|
from charli3_dendrite.lending.normalized import CollateralTerms
|
|
@@ -47,6 +48,7 @@ from charli3_dendrite.lending.normalized import LendingPosition
|
|
|
47
48
|
from charli3_dendrite.lending.normalized import Origin
|
|
48
49
|
from charli3_dendrite.lending.normalized import Party
|
|
49
50
|
from charli3_dendrite.lending.normalized import PartyKind
|
|
51
|
+
from charli3_dendrite.lending.normalized import as_parse_error
|
|
50
52
|
from charli3_dendrite.lending.oracles.models import OracleRef
|
|
51
53
|
from charli3_dendrite.lending.oracles.models import OracleSource
|
|
52
54
|
from charli3_dendrite.lending.units import constr
|
|
@@ -58,6 +60,8 @@ if TYPE_CHECKING:
|
|
|
58
60
|
from charli3_dendrite.lending.fluidtokens_v4.datums import CollateralAsset
|
|
59
61
|
from charli3_dendrite.lending.fluidtokens_v4.datums import ConfigDatum
|
|
60
62
|
from charli3_dendrite.lending.fluidtokens_v4.state import FluidV4PoolManagerState
|
|
63
|
+
from charli3_dendrite.lending.markets import ParseContext
|
|
64
|
+
from charli3_dendrite.lending.markets import PositionLifecycle
|
|
61
65
|
from charli3_dendrite.lending.rates import RateModel
|
|
62
66
|
|
|
63
67
|
# Constructor alternatives of RepaymentMode, LiquidationMode and Option.
|
|
@@ -212,12 +216,6 @@ def lendable_principal(pool: FluidV4PoolState) -> int:
|
|
|
212
216
|
return max(pool.assets["lovelace"] - floor, 0)
|
|
213
217
|
|
|
214
218
|
|
|
215
|
-
def _converted(what: str, exc: Exception) -> LendingParseError:
|
|
216
|
-
if isinstance(exc, LendingParseError):
|
|
217
|
-
return exc
|
|
218
|
-
return LendingParseError(f"{what}: {exc}")
|
|
219
|
-
|
|
220
|
-
|
|
221
219
|
def pool_to_market(
|
|
222
220
|
pool: FluidV4PoolState,
|
|
223
221
|
pool_manager: FluidV4PoolManagerState | None = None,
|
|
@@ -267,7 +265,7 @@ def pool_to_market(
|
|
|
267
265
|
permissioned=pool.is_permissioned,
|
|
268
266
|
)
|
|
269
267
|
except _CONVERSION_ERRORS as exc:
|
|
270
|
-
raise
|
|
268
|
+
raise as_parse_error(f"pool {pool.out_ref}", exc) from exc
|
|
271
269
|
|
|
272
270
|
|
|
273
271
|
def _origin(loan: FluidV4LoanState) -> Origin | None:
|
|
@@ -303,7 +301,7 @@ def loan_to_position(loan: FluidV4LoanState) -> LendingPosition:
|
|
|
303
301
|
opened_ms=int(datum.lend_date), # type: ignore[attr-defined]
|
|
304
302
|
)
|
|
305
303
|
except _CONVERSION_ERRORS as exc:
|
|
306
|
-
raise
|
|
304
|
+
raise as_parse_error(f"loan {loan.out_ref}", exc) from exc
|
|
307
305
|
|
|
308
306
|
|
|
309
307
|
def request_to_borrow_request(request: FluidV4RequestState) -> BorrowRequest:
|
|
@@ -343,7 +341,7 @@ def request_to_borrow_request(request: FluidV4RequestState) -> BorrowRequest:
|
|
|
343
341
|
!= PERMISSIONLESS_MARKER,
|
|
344
342
|
)
|
|
345
343
|
except _CONVERSION_ERRORS as exc:
|
|
346
|
-
raise
|
|
344
|
+
raise as_parse_error(f"request {request.out_ref}", exc) from exc
|
|
347
345
|
|
|
348
346
|
|
|
349
347
|
_VIEW_KINDS = (EntityKind.POOL, EntityKind.LOAN, EntityKind.REQUEST)
|
|
@@ -353,6 +351,8 @@ class FluidTokensV4MarketSource:
|
|
|
353
351
|
"""FluidTokens V4 pools, loans and requests as common views."""
|
|
354
352
|
|
|
355
353
|
name = PROTOCOL_NAME
|
|
354
|
+
# Every V4 loan holds its own identity token, so positions need no chaining.
|
|
355
|
+
lifecycle: PositionLifecycle | None = None
|
|
356
356
|
|
|
357
357
|
def __init__(self, config: ConfigDatum | None = None) -> None:
|
|
358
358
|
"""Watch the deployment ``config`` names; mainnet by default."""
|
|
@@ -369,9 +369,13 @@ class FluidTokensV4MarketSource:
|
|
|
369
369
|
def parse(
|
|
370
370
|
self,
|
|
371
371
|
info: PoolStateInfo,
|
|
372
|
+
*,
|
|
373
|
+
context: ParseContext | None = None,
|
|
372
374
|
) -> LendingMarket | LendingPosition | BorrowRequest | None:
|
|
373
375
|
"""One UTxO as its view; None when it is not a V4 pool, loan or request.
|
|
374
376
|
|
|
377
|
+
A V4 view reads only its own UTxO, so ``context`` is ignored.
|
|
378
|
+
|
|
375
379
|
Raises LendingParseError for a pool, loan or request it cannot convert.
|
|
376
380
|
"""
|
|
377
381
|
state = parse_utxo(info, self._selectors)
|
|
@@ -394,26 +398,18 @@ class FluidTokensV4MarketSource:
|
|
|
394
398
|
"""
|
|
395
399
|
from charli3_dendrite.lending.fluidtokens_v4.loader import snapshot
|
|
396
400
|
|
|
397
|
-
found = snapshot(
|
|
398
|
-
backend,
|
|
399
|
-
now_ms=int(time.time() * 1000) if now_ms is None else now_ms,
|
|
400
|
-
)
|
|
401
|
+
found = snapshot(backend, now_ms=now_ms)
|
|
401
402
|
managers = {manager.pool_id: manager for manager in found.pool_managers}
|
|
402
403
|
return LendingSnapshot(
|
|
403
|
-
markets=
|
|
404
|
+
markets=convertible_views(
|
|
404
405
|
lambda pool: pool_to_market(pool, managers.get(pool.pool_id)),
|
|
405
406
|
found.pools,
|
|
406
407
|
),
|
|
407
|
-
positions=
|
|
408
|
-
requests=
|
|
408
|
+
positions=convertible_views(loan_to_position, found.loans),
|
|
409
|
+
requests=convertible_views(request_to_borrow_request, found.requests),
|
|
409
410
|
)
|
|
410
411
|
|
|
411
412
|
|
|
412
|
-
def
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
try:
|
|
416
|
-
out.append(convert(state))
|
|
417
|
-
except LendingParseError:
|
|
418
|
-
continue
|
|
419
|
-
return tuple(out)
|
|
413
|
+
def market_source() -> FluidTokensV4MarketSource:
|
|
414
|
+
"""The mainnet FluidTokens V4 source, as ``lending.builtins`` registers it."""
|
|
415
|
+
return FluidTokensV4MarketSource()
|
|
@@ -12,12 +12,9 @@ headline rate annualizes it over the term.
|
|
|
12
12
|
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
|
|
15
|
-
import dataclasses
|
|
16
15
|
from abc import abstractmethod
|
|
17
16
|
from dataclasses import dataclass
|
|
18
17
|
from fractions import Fraction
|
|
19
|
-
from typing import TYPE_CHECKING
|
|
20
|
-
from typing import Any
|
|
21
18
|
from typing import ClassVar
|
|
22
19
|
|
|
23
20
|
from charli3_dendrite.lending.fluidtokens.math import amortization_installment
|
|
@@ -28,19 +25,17 @@ from charli3_dendrite.lending.fluidtokens.math import perpetual_debt
|
|
|
28
25
|
from charli3_dendrite.lending.fluidtokens.math import perpetual_outstanding_debt
|
|
29
26
|
from charli3_dendrite.lending.normalized import LendingParseError
|
|
30
27
|
from charli3_dendrite.lending.rates import HOURS_PER_YEAR
|
|
28
|
+
from charli3_dendrite.lending.rates import DataclassIntParams
|
|
31
29
|
from charli3_dendrite.lending.rates import RateKind
|
|
32
30
|
from charli3_dendrite.lending.rates import RateModel
|
|
33
31
|
|
|
34
|
-
if TYPE_CHECKING:
|
|
35
|
-
from collections.abc import Mapping
|
|
36
|
-
|
|
37
32
|
PROTOCOL_NAME = "FluidTokensV4"
|
|
38
33
|
|
|
39
34
|
_RATE_BASIS = 10_000
|
|
40
35
|
|
|
41
36
|
|
|
42
37
|
@dataclass(frozen=True)
|
|
43
|
-
class _FluidRate(
|
|
38
|
+
class _FluidRate(DataclassIntParams):
|
|
44
39
|
"""Terms every FluidTokens repayment mode carries."""
|
|
45
40
|
|
|
46
41
|
interest_rate: int
|
|
@@ -69,16 +64,6 @@ class _FluidRate(RateModel):
|
|
|
69
64
|
repayment_time_window=self.repayment_time_window,
|
|
70
65
|
)
|
|
71
66
|
|
|
72
|
-
def params(self) -> dict[str, int]:
|
|
73
|
-
"""The datum integers, by field name."""
|
|
74
|
-
return dataclasses.asdict(self)
|
|
75
|
-
|
|
76
|
-
@classmethod
|
|
77
|
-
def from_params(cls, params: Mapping[str, Any]) -> RateModel:
|
|
78
|
-
"""Rebuild from :meth:`params`."""
|
|
79
|
-
names = [field.name for field in dataclasses.fields(cls)]
|
|
80
|
-
return cls(**{name: int(params[name]) for name in names})
|
|
81
|
-
|
|
82
67
|
|
|
83
68
|
@dataclass(frozen=True)
|
|
84
69
|
class FluidPerpetualRate(_FluidRate):
|