charli3_dendrite 1.5.12.dev0__tar.gz → 1.5.13.dev0__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.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/PKG-INFO +1 -1
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/pyproject.toml +2 -2
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/__init__.py +2 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/backend/backend_base.py +20 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/backend/blockfrost/__init__.py +26 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/backend/dbsync/__init__.py +27 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/backend/ogmios_kupo/__init__.py +12 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dataclasses/models.py +16 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/amm/amm_types.py +0 -191
- charli3_dendrite-1.5.13.dev0/src/charli3_dendrite/dexs/amm/multi_asset.py +170 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/amm/sundae_v4.py +817 -173
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/core/errors.py +8 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/LICENSE +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/README.md +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/backend/__init__.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/backend/blockfrost/models.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/backend/dbsync/models.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/backend/ogmios_kupo/models.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/backend/utils.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dataclasses/__init__.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dataclasses/datums.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/__init__.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/amm/__init__.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/amm/amm_base.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/amm/cswap.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/amm/dano.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/amm/minswap.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/amm/muesli.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/amm/spectrum.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/amm/splash.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/amm/sundae.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/amm/sundae_v4_deployments.json +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/amm/vyfi.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/amm/wingriders.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/core/__init__.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/core/base.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/ob/__init__.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/ob/axo.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/ob/cardanoswaps.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/ob/chadswap.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/ob/djed.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/ob/geniusyield.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/ob/ob_base.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/dexs/ob/saturnswap.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/__init__.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/base.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/__init__.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/constants.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/datums.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/loader.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/market.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/math.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/oracles/__init__.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/oracles/aggregator.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/oracles/aggregator_datums.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/oracles/deployments.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/oracles/forward.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/oracles/leaves.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/oracles/locator.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/oracles/lp_pricing.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/oracles/recipes.json +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/oracles/redeemer.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/oracles/reproduce.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/oracles/structured_datums.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/state.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/__init__.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/_common.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/build.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/builder.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/context.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/create_loan.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/datum_synth.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/increase_loan.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/loan_ids.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/modify_collateral.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/oracle_redeemer.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/oracle_synth.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/redeemers.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/repay.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/topup_withdraw.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/danogo/transactions/verify.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/__init__.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/constants.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/datums.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/loader.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/market.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/math.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/oracles/__init__.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/oracles/feeds.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/oracles/fluid_api.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/oracles/witness.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/state.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/transactions/__init__.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/transactions/_common.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/transactions/borrow.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/transactions/builder.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/transactions/change_collateral.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/transactions/context.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/transactions/datum_synth.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/transactions/lend.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/transactions/pool.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/transactions/recast.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/transactions/redeemers.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/transactions/repay.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/transactions/request.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/fluidtokens/transactions/resolve.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/math.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/oracles/__init__.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/oracles/charli3.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/oracles/dex_pooled.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/oracles/fluid.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/oracles/models.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/oracles/orcfax.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/oracles/qtoken.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/registry.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/transactions/__init__.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/transactions/base.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/transactions/infra.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/transactions/snapshot.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/lending/units.py +0 -0
- {charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/utility.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "charli3_dendrite"
|
|
3
|
-
version = "1.5.
|
|
3
|
+
version = "1.5.13-dev0"
|
|
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.5.
|
|
53
|
+
current_version = "1.5.13-dev0"
|
|
54
54
|
parse = """(?x)
|
|
55
55
|
(?P<major>\\d+)\\.
|
|
56
56
|
(?P<minor>\\d+)\\.
|
{charli3_dendrite-1.5.12.dev0 → charli3_dendrite-1.5.13.dev0}/src/charli3_dendrite/__init__.py
RENAMED
|
@@ -19,6 +19,8 @@ from charli3_dendrite.dexs.amm.splash import SplashSSPState
|
|
|
19
19
|
from charli3_dendrite.dexs.amm.sundae import SundaeSwapCPPState
|
|
20
20
|
from charli3_dendrite.dexs.amm.sundae import SundaeSwapV3CPPState
|
|
21
21
|
from charli3_dendrite.dexs.amm.sundae import SundaeSwapV3StableSwap
|
|
22
|
+
from charli3_dendrite.dexs.amm.sundae_v4 import SundaeV4ConstantSumPool
|
|
23
|
+
from charli3_dendrite.dexs.amm.sundae_v4 import SundaeV4Vault
|
|
22
24
|
from charli3_dendrite.dexs.amm.vyfi import VyFiCPPState
|
|
23
25
|
from charli3_dendrite.dexs.amm.wingriders import WingRidersCPPState
|
|
24
26
|
from charli3_dendrite.dexs.amm.wingriders import WingRidersSSPState
|
|
@@ -10,6 +10,7 @@ from pycardano import Address # type: ignore
|
|
|
10
10
|
from charli3_dendrite.dataclasses.models import Assets
|
|
11
11
|
from charli3_dendrite.dataclasses.models import BlockList
|
|
12
12
|
from charli3_dendrite.dataclasses.models import PoolStateList
|
|
13
|
+
from charli3_dendrite.dataclasses.models import RedeemerRecord
|
|
13
14
|
from charli3_dendrite.dataclasses.models import ScriptReference
|
|
14
15
|
from charli3_dendrite.dataclasses.models import SwapTransactionList
|
|
15
16
|
|
|
@@ -205,6 +206,25 @@ class AbstractBackend(ABC):
|
|
|
205
206
|
"""
|
|
206
207
|
pass
|
|
207
208
|
|
|
209
|
+
def get_redeemers(self, tx_hash: str) -> list[RedeemerRecord]:
|
|
210
|
+
"""Every redeemer supplied in transaction ``tx_hash``.
|
|
211
|
+
|
|
212
|
+
Backends that cannot index redeemers leave this unimplemented.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
tx_hash: The transaction hash (hex).
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
The transaction's redeemers, in implementation-defined order
|
|
219
|
+
(db-sync orders by purpose then index). ``script_hash`` is ``""``
|
|
220
|
+
for a redeemer with no script, never ``None``.
|
|
221
|
+
|
|
222
|
+
Raises:
|
|
223
|
+
NotImplementedError: if the backend has no redeemer index.
|
|
224
|
+
"""
|
|
225
|
+
msg = f"{type(self).__name__} cannot read transaction redeemers."
|
|
226
|
+
raise NotImplementedError(msg)
|
|
227
|
+
|
|
208
228
|
@abstractmethod
|
|
209
229
|
def get_axo_target(
|
|
210
230
|
self,
|
|
@@ -18,6 +18,7 @@ from charli3_dendrite.dataclasses.models import Assets
|
|
|
18
18
|
from charli3_dendrite.dataclasses.models import BlockList
|
|
19
19
|
from charli3_dendrite.dataclasses.models import PoolStateInfo
|
|
20
20
|
from charli3_dendrite.dataclasses.models import PoolStateList
|
|
21
|
+
from charli3_dendrite.dataclasses.models import RedeemerRecord
|
|
21
22
|
from charli3_dendrite.dataclasses.models import ScriptReference
|
|
22
23
|
from charli3_dendrite.dataclasses.models import SwapTransactionList
|
|
23
24
|
|
|
@@ -283,6 +284,31 @@ class BlockFrostBackend(AbstractBackend):
|
|
|
283
284
|
)
|
|
284
285
|
return None
|
|
285
286
|
|
|
287
|
+
def get_redeemers(self, tx_hash: str) -> list[RedeemerRecord]:
|
|
288
|
+
"""Every redeemer of ``tx_hash``, resolving each datum by its hash.
|
|
289
|
+
|
|
290
|
+
Args:
|
|
291
|
+
tx_hash: The transaction hash (hex).
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
The redeemers in the order the API lists them. ``script_hash`` is
|
|
295
|
+
``""`` for a redeemer the API reports with no script, never
|
|
296
|
+
``None``.
|
|
297
|
+
"""
|
|
298
|
+
records = []
|
|
299
|
+
for item in self.api.transaction_redeemers(tx_hash, gather_pages=True):
|
|
300
|
+
cbor = self.api.script_datum_cbor(item.redeemer_data_hash).cbor
|
|
301
|
+
records.append(
|
|
302
|
+
RedeemerRecord(
|
|
303
|
+
tx_hash=tx_hash,
|
|
304
|
+
purpose=item.purpose,
|
|
305
|
+
index=item.tx_index,
|
|
306
|
+
script_hash=item.script_hash or "",
|
|
307
|
+
data_cbor=cbor,
|
|
308
|
+
),
|
|
309
|
+
)
|
|
310
|
+
return records
|
|
311
|
+
|
|
286
312
|
def get_axo_target(
|
|
287
313
|
self,
|
|
288
314
|
assets: Assets,
|
|
@@ -20,6 +20,7 @@ from charli3_dendrite.backend.dbsync.models import UTxOSelector
|
|
|
20
20
|
from charli3_dendrite.dataclasses.models import Assets
|
|
21
21
|
from charli3_dendrite.dataclasses.models import BlockList
|
|
22
22
|
from charli3_dendrite.dataclasses.models import PoolStateList
|
|
23
|
+
from charli3_dendrite.dataclasses.models import RedeemerRecord
|
|
23
24
|
from charli3_dendrite.dataclasses.models import ScriptReference
|
|
24
25
|
from charli3_dendrite.dataclasses.models import SwapTransactionList
|
|
25
26
|
|
|
@@ -575,6 +576,32 @@ LIMIT 1
|
|
|
575
576
|
|
|
576
577
|
return UTxOSelector.parse(r[0])
|
|
577
578
|
|
|
579
|
+
def get_redeemers(self, tx_hash: str) -> list[RedeemerRecord]:
|
|
580
|
+
"""Every redeemer of ``tx_hash`` with its datum bytes.
|
|
581
|
+
|
|
582
|
+
Args:
|
|
583
|
+
tx_hash: The transaction hash (hex).
|
|
584
|
+
|
|
585
|
+
Returns:
|
|
586
|
+
The redeemers in ``(purpose, index)`` order. ``script_hash`` is
|
|
587
|
+
``""`` for a redeemer with no script (db-sync's
|
|
588
|
+
``redeemer.script_hash`` is nullable), never ``None``.
|
|
589
|
+
"""
|
|
590
|
+
query = """
|
|
591
|
+
SELECT encode(tx.hash, 'hex') AS tx_hash,
|
|
592
|
+
r.purpose::text AS purpose,
|
|
593
|
+
r.index AS index,
|
|
594
|
+
COALESCE(encode(r.script_hash, 'hex'), '') AS script_hash,
|
|
595
|
+
encode(rd.bytes, 'hex') AS data_cbor
|
|
596
|
+
FROM redeemer r
|
|
597
|
+
JOIN tx ON tx.id = r.tx_id
|
|
598
|
+
JOIN redeemer_data rd ON rd.id = r.redeemer_data_id
|
|
599
|
+
WHERE tx.hash = %(tx_hash)b
|
|
600
|
+
ORDER BY r.purpose, r.index
|
|
601
|
+
"""
|
|
602
|
+
rows = self.db_query(query, {"tx_hash": bytes.fromhex(tx_hash)})
|
|
603
|
+
return [RedeemerRecord.model_validate(row) for row in rows]
|
|
604
|
+
|
|
578
605
|
def _get_historical_order_utxos(
|
|
579
606
|
self,
|
|
580
607
|
stake_addresses: list[str],
|
|
@@ -22,6 +22,7 @@ from charli3_dendrite.dataclasses.models import BlockInfo
|
|
|
22
22
|
from charli3_dendrite.dataclasses.models import BlockList
|
|
23
23
|
from charli3_dendrite.dataclasses.models import PoolStateInfo
|
|
24
24
|
from charli3_dendrite.dataclasses.models import PoolStateList
|
|
25
|
+
from charli3_dendrite.dataclasses.models import RedeemerRecord
|
|
25
26
|
from charli3_dendrite.dataclasses.models import ScriptReference
|
|
26
27
|
from charli3_dendrite.dataclasses.models import SwapTransactionList
|
|
27
28
|
|
|
@@ -50,6 +51,8 @@ class OgmiosKupoBackend(AbstractBackend):
|
|
|
50
51
|
ogmios_url (str): URL for the Ogmios service.
|
|
51
52
|
kupo_url (str): URL for the Kupo service.
|
|
52
53
|
network (Network): The Cardano network to use.
|
|
54
|
+
path (str): URL path segment appended after the host:port when
|
|
55
|
+
building the Ogmios websocket connection string.
|
|
53
56
|
"""
|
|
54
57
|
_, ws_string = ogmios_url.split("ws://")
|
|
55
58
|
self.ws_url, self.port = ws_string.split(":")
|
|
@@ -478,6 +481,15 @@ class OgmiosKupoBackend(AbstractBackend):
|
|
|
478
481
|
)
|
|
479
482
|
return None
|
|
480
483
|
|
|
484
|
+
def get_redeemers(self, tx_hash: str) -> list[RedeemerRecord]:
|
|
485
|
+
"""Kupo indexes outputs, not redeemers.
|
|
486
|
+
|
|
487
|
+
Raises:
|
|
488
|
+
NotImplementedError: always.
|
|
489
|
+
"""
|
|
490
|
+
msg = "The Ogmios/Kupo backend has no redeemer index."
|
|
491
|
+
raise NotImplementedError(msg)
|
|
492
|
+
|
|
481
493
|
def get_axo_target(
|
|
482
494
|
self,
|
|
483
495
|
assets: Assets,
|
|
@@ -310,6 +310,22 @@ class ScriptReference(DendriteBaseModel):
|
|
|
310
310
|
return None
|
|
311
311
|
|
|
312
312
|
|
|
313
|
+
class RedeemerRecord(DendriteBaseModel):
|
|
314
|
+
"""One redeemer of a transaction.
|
|
315
|
+
|
|
316
|
+
``purpose`` is the ledger purpose (``spend`` / ``mint`` / ``cert`` /
|
|
317
|
+
``reward`` / ``vote`` / ``propose``), ``index`` the redeemer's index within
|
|
318
|
+
that purpose, ``script_hash`` the hex script it was supplied for and
|
|
319
|
+
``data_cbor`` the hex CBOR of the redeemer datum.
|
|
320
|
+
"""
|
|
321
|
+
|
|
322
|
+
tx_hash: str
|
|
323
|
+
purpose: str
|
|
324
|
+
index: int
|
|
325
|
+
script_hash: str
|
|
326
|
+
data_cbor: str
|
|
327
|
+
|
|
328
|
+
|
|
313
329
|
class BlockInfo(DendriteBaseModel):
|
|
314
330
|
epoch_slot_no: int
|
|
315
331
|
block_no: int
|
|
@@ -136,197 +136,6 @@ class AbstractConstantProductPoolState(AbstractPoolState):
|
|
|
136
136
|
return amount_in, price_impact
|
|
137
137
|
|
|
138
138
|
|
|
139
|
-
class AbstractConstantSumPoolState(AbstractPoolState):
|
|
140
|
-
"""State of a constant-sum AMM pool priced on a fixed integer value vector.
|
|
141
|
-
|
|
142
|
-
A constant-sum pool conserves total *value* ``V = Sum(price_i * reserve_i)`` on a
|
|
143
|
-
fixed integer price vector (positionally aligned to the pool assets), with NO
|
|
144
|
-
amplification — it is the linear-curve sibling of
|
|
145
|
-
:class:`AbstractConstantProductPoolState` (``x*y=k``) and
|
|
146
|
-
:class:`AbstractStableSwapPoolState` (the amplified Curve invariant), and is NOT a
|
|
147
|
-
stable-swap variant. Within a routable 2-asset ``(i, j)`` leg a swap of ``dx`` of
|
|
148
|
-
asset ``i`` preserves ``V`` minus the floored LP fee: the pool retains
|
|
149
|
-
``floor(dx * p_i * fee_num / fee_den)`` of value and pays the remainder out in
|
|
150
|
-
asset ``j`` at the fixed price ratio ``p_i : p_j``. Output is bounded by the
|
|
151
|
-
out-side reserve ``reserve_j`` — a constant-sum leg cannot pay out more of an
|
|
152
|
-
asset than it holds.
|
|
153
|
-
|
|
154
|
-
The returned output is the unique maximum that satisfies the on-chain constant-sum
|
|
155
|
-
swap-step relation (the value increase ``v_increase`` is pinned to exactly
|
|
156
|
-
``floor(input_value * fee_num / fee_den)``): a larger output over-pays (fails the
|
|
157
|
-
tightness bound) and a smaller output over-charges (fails the achievable bound).
|
|
158
|
-
|
|
159
|
-
Concrete constant-sum DEXs supply only the per-leg price weights and fee via the
|
|
160
|
-
two hooks below (:meth:`_cs_price_pair` and :meth:`_cs_fee`), mirroring how
|
|
161
|
-
:class:`AbstractStableSwapPoolState` exposes ``amp``/``_get_ann`` and
|
|
162
|
-
:class:`AbstractConstantLiquidityPoolState` exposes ``_sqrt_price_bounds`` — the
|
|
163
|
-
standard ``reserve_a`` / ``reserve_b`` / ``unit_a`` / ``unit_b`` interface drives
|
|
164
|
-
the math.
|
|
165
|
-
"""
|
|
166
|
-
|
|
167
|
-
fee_basis: int = 10000
|
|
168
|
-
|
|
169
|
-
# -- per-DEX hooks (the analogue of the stable base's amp/_get_ann) --------
|
|
170
|
-
def _cs_price_pair(self) -> tuple[int, int]:
|
|
171
|
-
"""Integer price weights ``(price_a, price_b)`` aligned to ``(unit_a, unit_b)``.
|
|
172
|
-
|
|
173
|
-
The constant-sum value vector restricted to this 2-asset leg. Defaults to an
|
|
174
|
-
equal-price ``(1, 1)`` leg (the common stable-pair case); override when a leg
|
|
175
|
-
carries non-unit integer price weights.
|
|
176
|
-
"""
|
|
177
|
-
return (1, 1)
|
|
178
|
-
|
|
179
|
-
def _cs_fee(self) -> tuple[int, int]:
|
|
180
|
-
"""LP swap fee as an exact integer ratio ``(fee_num, fee_den)``.
|
|
181
|
-
|
|
182
|
-
Defaults to ``volume_fee / fee_basis``; override to supply the on-chain
|
|
183
|
-
``fee_num`` / ``fee_den`` directly (the on-chain check floors
|
|
184
|
-
``input_value * fee_num / fee_den``).
|
|
185
|
-
"""
|
|
186
|
-
fee = self.volume_fee
|
|
187
|
-
if fee is None:
|
|
188
|
-
return (0, self.fee_basis)
|
|
189
|
-
if isinstance(fee, (list, tuple)):
|
|
190
|
-
return (int(fee[0]), self.fee_basis)
|
|
191
|
-
return (int(fee), self.fee_basis)
|
|
192
|
-
|
|
193
|
-
# -- generic constant-sum value-conservation math -------------------------
|
|
194
|
-
def get_amount_out(
|
|
195
|
-
self,
|
|
196
|
-
asset: Assets,
|
|
197
|
-
precise: bool = True,
|
|
198
|
-
) -> tuple[Assets, float]:
|
|
199
|
-
"""Output amount + price impact for an input ``asset`` (capped at the reserve).
|
|
200
|
-
|
|
201
|
-
Value-conservation forward quote: the pool retains the floored fee on the input
|
|
202
|
-
value and pays out the remaining value at the fixed price ratio, capped at the
|
|
203
|
-
out-side reserve. This is the unique maximum output that satisfies the on-chain
|
|
204
|
-
constant-sum step relation.
|
|
205
|
-
|
|
206
|
-
Args:
|
|
207
|
-
asset (Assets): The input asset amount for the swap.
|
|
208
|
-
precise (bool): Accepted for interface parity; the output is always the
|
|
209
|
-
integer floor.
|
|
210
|
-
|
|
211
|
-
Returns:
|
|
212
|
-
tuple[Assets, float]: The output asset and the price-impact ratio.
|
|
213
|
-
"""
|
|
214
|
-
if len(asset) != 1 or asset.unit() not in (self.unit_a, self.unit_b):
|
|
215
|
-
error_msg = f"Invalid input asset for pool: {asset}"
|
|
216
|
-
raise ValueError(error_msg)
|
|
217
|
-
|
|
218
|
-
price_a, price_b = self._cs_price_pair()
|
|
219
|
-
fee_num, fee_den = self._cs_fee()
|
|
220
|
-
if asset.unit() == self.unit_a:
|
|
221
|
-
price_in, price_out, out_real, out_unit = (
|
|
222
|
-
price_a,
|
|
223
|
-
price_b,
|
|
224
|
-
self.reserve_b,
|
|
225
|
-
self.unit_b,
|
|
226
|
-
)
|
|
227
|
-
else:
|
|
228
|
-
price_in, price_out, out_real, out_unit = (
|
|
229
|
-
price_b,
|
|
230
|
-
price_a,
|
|
231
|
-
self.reserve_a,
|
|
232
|
-
self.unit_a,
|
|
233
|
-
)
|
|
234
|
-
|
|
235
|
-
amount_in = asset.quantity()
|
|
236
|
-
input_value = amount_in * price_in
|
|
237
|
-
# Floor the fee — the pool wins the dust, exactly as the on-chain check pins
|
|
238
|
-
# v_increase = floor(input_value * fee_num / fee_den).
|
|
239
|
-
fee_value = input_value * fee_num // fee_den
|
|
240
|
-
out_value = input_value - fee_value
|
|
241
|
-
expected_out = min(out_value // price_out, out_real)
|
|
242
|
-
out_assets = Assets(**{out_unit: expected_out})
|
|
243
|
-
if not precise:
|
|
244
|
-
out_assets.root[out_unit] = expected_out
|
|
245
|
-
|
|
246
|
-
if amount_in == 0 or expected_out == 0:
|
|
247
|
-
return out_assets, 0.0
|
|
248
|
-
# Spot (out per in) is the fixed ratio price_in/price_out; on an uncapped leg
|
|
249
|
-
# the only wedge is the fee, so the impact equals the fee fraction (it grows
|
|
250
|
-
# once the output saturates the reserve cap).
|
|
251
|
-
effective = (expected_out * price_out) / (amount_in * price_in)
|
|
252
|
-
return out_assets, 1.0 - effective
|
|
253
|
-
|
|
254
|
-
def get_amount_in(
|
|
255
|
-
self,
|
|
256
|
-
asset: Assets,
|
|
257
|
-
precise: bool = True,
|
|
258
|
-
) -> tuple[Assets, float]:
|
|
259
|
-
"""Minimum input + price impact to obtain a desired output ``asset``.
|
|
260
|
-
|
|
261
|
-
Algebraic inverse of :meth:`get_amount_out`: the least input whose post-fee
|
|
262
|
-
value covers the requested output value at the fixed price ratio.
|
|
263
|
-
|
|
264
|
-
Args:
|
|
265
|
-
asset (Assets): The desired output asset amount for the swap.
|
|
266
|
-
precise (bool): Accepted for interface parity; the input is the integer
|
|
267
|
-
ceiling (the minimal whole-unit input).
|
|
268
|
-
|
|
269
|
-
Returns:
|
|
270
|
-
tuple[Assets, float]: The required input asset and the price-impact ratio.
|
|
271
|
-
|
|
272
|
-
Raises:
|
|
273
|
-
InvalidPoolError: If the desired output exceeds the leg's reserve.
|
|
274
|
-
"""
|
|
275
|
-
if len(asset) != 1 or asset.unit() not in (self.unit_a, self.unit_b):
|
|
276
|
-
error_msg = f"Invalid output asset for pool: {asset}"
|
|
277
|
-
raise ValueError(error_msg)
|
|
278
|
-
desired_out = asset.quantity()
|
|
279
|
-
if desired_out <= 0:
|
|
280
|
-
error_msg = "desired output must be positive"
|
|
281
|
-
raise ValueError(error_msg)
|
|
282
|
-
|
|
283
|
-
price_a, price_b = self._cs_price_pair()
|
|
284
|
-
fee_num, fee_den = self._cs_fee()
|
|
285
|
-
if asset.unit() == self.unit_b:
|
|
286
|
-
out_real, price_in, price_out, in_unit = (
|
|
287
|
-
self.reserve_b,
|
|
288
|
-
price_a,
|
|
289
|
-
price_b,
|
|
290
|
-
self.unit_a,
|
|
291
|
-
)
|
|
292
|
-
else:
|
|
293
|
-
out_real, price_in, price_out, in_unit = (
|
|
294
|
-
self.reserve_a,
|
|
295
|
-
price_b,
|
|
296
|
-
price_a,
|
|
297
|
-
self.unit_b,
|
|
298
|
-
)
|
|
299
|
-
if desired_out >= out_real:
|
|
300
|
-
error_msg = (
|
|
301
|
-
f"Desired output {desired_out} exceeds available reserve {out_real}"
|
|
302
|
-
)
|
|
303
|
-
raise InvalidPoolError(error_msg)
|
|
304
|
-
|
|
305
|
-
out_value = desired_out * price_out
|
|
306
|
-
net = fee_den - fee_num
|
|
307
|
-
|
|
308
|
-
def _produced(amount: int) -> int:
|
|
309
|
-
value = amount * price_in
|
|
310
|
-
return (value - value * fee_num // fee_den) // price_out
|
|
311
|
-
|
|
312
|
-
# Closed-form ceil is a valid upper bound (it ignores the fee-flooring that
|
|
313
|
-
# makes small inputs cheaper); flooring can move the true minimum down a few
|
|
314
|
-
# units, so search down to the minimum, then back up to guarantee coverage.
|
|
315
|
-
amount_in = max(1, -(-(out_value * fee_den) // (price_in * net)))
|
|
316
|
-
while amount_in > 1 and _produced(amount_in - 1) >= desired_out:
|
|
317
|
-
amount_in -= 1
|
|
318
|
-
while _produced(amount_in) < desired_out:
|
|
319
|
-
amount_in += 1
|
|
320
|
-
in_assets = Assets(**{in_unit: amount_in})
|
|
321
|
-
if not precise:
|
|
322
|
-
in_assets.root[in_unit] = amount_in
|
|
323
|
-
|
|
324
|
-
if amount_in == 0:
|
|
325
|
-
return in_assets, 0.0
|
|
326
|
-
effective = (desired_out * price_out) / (amount_in * price_in)
|
|
327
|
-
return in_assets, 1.0 - effective
|
|
328
|
-
|
|
329
|
-
|
|
330
139
|
class AbstractStableSwapPoolState(AbstractPoolState):
|
|
331
140
|
"""Represents the state of a stable swap automated market maker (AMM) pool."""
|
|
332
141
|
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""Abstract base for pools whose reserves are an N-asset vector.
|
|
2
|
+
|
|
3
|
+
Every quote names its units explicitly: for ``N > 2`` there is no "other"
|
|
4
|
+
asset, so nothing on this base defaults or enumerates pairs.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from abc import ABC
|
|
10
|
+
from abc import abstractmethod
|
|
11
|
+
|
|
12
|
+
from pycardano import Address
|
|
13
|
+
from pycardano import PlutusData
|
|
14
|
+
from pycardano import TransactionOutput
|
|
15
|
+
from pydantic import ConfigDict
|
|
16
|
+
|
|
17
|
+
from charli3_dendrite.dataclasses.models import Assets
|
|
18
|
+
from charli3_dendrite.dataclasses.models import DendriteBaseModel
|
|
19
|
+
from charli3_dendrite.dataclasses.models import PoolSelector
|
|
20
|
+
from charli3_dendrite.utility import asset_to_value
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class AbstractMultiAssetPoolState(DendriteBaseModel, ABC):
|
|
24
|
+
"""State of a pool priced over an N-entry reserve vector.
|
|
25
|
+
|
|
26
|
+
``reserves`` is keyed by dendrite unit in canonical order (lovelace first,
|
|
27
|
+
then policy + name). Subclasses own the curve math and the order builders.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
model_config = ConfigDict(
|
|
31
|
+
alias_generator=None,
|
|
32
|
+
populate_by_name=True,
|
|
33
|
+
arbitrary_types_allowed=True,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
reserves: Assets
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
@abstractmethod
|
|
40
|
+
def dex(cls) -> str:
|
|
41
|
+
"""The DEX name."""
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
@abstractmethod
|
|
45
|
+
def pool_selector(cls) -> PoolSelector:
|
|
46
|
+
"""How pool UTxOs are found."""
|
|
47
|
+
|
|
48
|
+
@classmethod
|
|
49
|
+
@abstractmethod
|
|
50
|
+
def order_selector(cls) -> list[str]:
|
|
51
|
+
"""The order submission addresses."""
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
@abstractmethod
|
|
55
|
+
def pool_id(self) -> str:
|
|
56
|
+
"""A unique identifier for the pool type."""
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
@abstractmethod
|
|
60
|
+
def stake_address(self) -> Address:
|
|
61
|
+
"""The address an order UTxO is locked at."""
|
|
62
|
+
|
|
63
|
+
@abstractmethod
|
|
64
|
+
def get_amount_out(
|
|
65
|
+
self,
|
|
66
|
+
asset: Assets,
|
|
67
|
+
out_unit: str,
|
|
68
|
+
precise: bool = True,
|
|
69
|
+
) -> tuple[Assets, float]:
|
|
70
|
+
"""Output of ``out_unit`` for offering ``asset`` (one or more reserves)."""
|
|
71
|
+
|
|
72
|
+
@abstractmethod
|
|
73
|
+
def get_amount_in(
|
|
74
|
+
self,
|
|
75
|
+
asset: Assets,
|
|
76
|
+
in_unit: str,
|
|
77
|
+
precise: bool = True,
|
|
78
|
+
) -> tuple[Assets, float]:
|
|
79
|
+
"""Minimum ``in_unit`` to obtain the single-asset ``asset``."""
|
|
80
|
+
|
|
81
|
+
@abstractmethod
|
|
82
|
+
def price(self, unit_in: str, unit_out: str) -> tuple[int, int]:
|
|
83
|
+
"""The exact ``(price_in, price_out)`` weights between two reserves."""
|
|
84
|
+
|
|
85
|
+
@abstractmethod
|
|
86
|
+
def apply_swap(self, asset_in: Assets, asset_out: Assets) -> None:
|
|
87
|
+
"""Move the reserves as if the swap settled."""
|
|
88
|
+
|
|
89
|
+
@abstractmethod
|
|
90
|
+
def batcher_fee(
|
|
91
|
+
self,
|
|
92
|
+
in_assets: Assets | None = None,
|
|
93
|
+
out_assets: Assets | None = None,
|
|
94
|
+
extra_assets: Assets | None = None,
|
|
95
|
+
) -> Assets:
|
|
96
|
+
"""The lovelace an order locks for its execution fee."""
|
|
97
|
+
|
|
98
|
+
@abstractmethod
|
|
99
|
+
def deposit(
|
|
100
|
+
self,
|
|
101
|
+
in_assets: Assets | None = None,
|
|
102
|
+
out_assets: Assets | None = None,
|
|
103
|
+
) -> Assets:
|
|
104
|
+
"""The lovelace rider an order carries and gets back."""
|
|
105
|
+
|
|
106
|
+
@abstractmethod
|
|
107
|
+
def swap_datum(
|
|
108
|
+
self,
|
|
109
|
+
address_source: Address,
|
|
110
|
+
in_assets: Assets,
|
|
111
|
+
out_assets: Assets,
|
|
112
|
+
extra_assets: Assets | None = None,
|
|
113
|
+
address_target: Address | None = None,
|
|
114
|
+
datum_target: PlutusData | None = None,
|
|
115
|
+
) -> PlutusData:
|
|
116
|
+
"""The order datum for a swap of ``in_assets`` into at least ``out_assets``."""
|
|
117
|
+
|
|
118
|
+
def units(self) -> list[str]:
|
|
119
|
+
"""The reserve units in canonical order."""
|
|
120
|
+
return list(self.reserves.root)
|
|
121
|
+
|
|
122
|
+
def reserve(self, unit: str) -> int:
|
|
123
|
+
"""The declared reserve of ``unit``.
|
|
124
|
+
|
|
125
|
+
Raises:
|
|
126
|
+
KeyError: ``unit`` is not a reserve of this pool.
|
|
127
|
+
"""
|
|
128
|
+
return self.reserves.root[unit]
|
|
129
|
+
|
|
130
|
+
def swap_utxo(
|
|
131
|
+
self,
|
|
132
|
+
address_source: Address,
|
|
133
|
+
in_assets: Assets,
|
|
134
|
+
out_assets: Assets,
|
|
135
|
+
extra_assets: Assets | None = None,
|
|
136
|
+
address_target: Address | None = None,
|
|
137
|
+
datum_target: PlutusData | None = None,
|
|
138
|
+
) -> tuple[TransactionOutput, PlutusData]:
|
|
139
|
+
"""The order output for a swap: value = input + fee + rider, inline datum.
|
|
140
|
+
|
|
141
|
+
Raises:
|
|
142
|
+
ValueError: more than one asset offered or asked.
|
|
143
|
+
"""
|
|
144
|
+
if len(in_assets) != 1 or len(out_assets) != 1:
|
|
145
|
+
msg = "Only one asset can be supplied as input, and one asset as output."
|
|
146
|
+
raise ValueError(msg)
|
|
147
|
+
order_datum = self.swap_datum(
|
|
148
|
+
address_source=address_source,
|
|
149
|
+
in_assets=in_assets,
|
|
150
|
+
out_assets=out_assets,
|
|
151
|
+
extra_assets=extra_assets,
|
|
152
|
+
address_target=address_target,
|
|
153
|
+
datum_target=datum_target,
|
|
154
|
+
)
|
|
155
|
+
value = Assets(**dict(in_assets.root))
|
|
156
|
+
value.root["lovelace"] = (
|
|
157
|
+
value.root.get("lovelace", 0)
|
|
158
|
+
+ self.batcher_fee(
|
|
159
|
+
in_assets=in_assets,
|
|
160
|
+
out_assets=out_assets,
|
|
161
|
+
extra_assets=extra_assets,
|
|
162
|
+
).quantity()
|
|
163
|
+
+ self.deposit(in_assets=in_assets, out_assets=out_assets).quantity()
|
|
164
|
+
)
|
|
165
|
+
output = TransactionOutput(
|
|
166
|
+
address=self.stake_address,
|
|
167
|
+
amount=asset_to_value(value),
|
|
168
|
+
datum=order_datum,
|
|
169
|
+
)
|
|
170
|
+
return output, order_datum
|