charli3_dendrite 1.5.0.dev1__tar.gz → 1.5.1.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.0.dev1 → charli3_dendrite-1.5.1.dev0}/PKG-INFO +1 -1
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/pyproject.toml +2 -2
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/ob/saturnswap.py +407 -8
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/LICENSE +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/README.md +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/backend/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/backend/backend_base.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/backend/blockfrost/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/backend/blockfrost/models.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/backend/dbsync/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/backend/dbsync/models.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/backend/ogmios_kupo/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/backend/ogmios_kupo/models.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/backend/utils.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dataclasses/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dataclasses/datums.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dataclasses/models.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/amm_base.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/amm_types.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/cswap.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/dano.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/minswap.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/muesli.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/spectrum.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/splash.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/sundae.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/vyfi.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/wingriders.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/core/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/core/base.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/core/errors.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/ob/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/ob/axo.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/ob/cardanoswaps.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/ob/chadswap.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/ob/djed.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/ob/geniusyield.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/ob/ob_base.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/base.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/constants.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/datums.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/loader.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/market.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/math.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/oracles/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/oracles/aggregator.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/oracles/aggregator_datums.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/oracles/deployments.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/oracles/forward.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/oracles/leaves.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/oracles/locator.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/oracles/lp_pricing.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/oracles/recipes.json +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/oracles/redeemer.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/oracles/reproduce.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/oracles/structured_datums.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/state.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/_common.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/build.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/builder.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/context.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/create_loan.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/datum_synth.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/increase_loan.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/loan_ids.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/modify_collateral.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/oracle_redeemer.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/oracle_synth.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/redeemers.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/repay.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/topup_withdraw.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/danogo/transactions/verify.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/math.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/oracles/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/oracles/charli3.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/oracles/dex_pooled.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/oracles/fluid.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/oracles/models.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/oracles/orcfax.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/oracles/qtoken.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/registry.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/transactions/__init__.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/transactions/base.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/transactions/infra.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/transactions/snapshot.py +0 -0
- {charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.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.1-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.1-dev0"
|
|
54
54
|
parse = """(?x)
|
|
55
55
|
(?P<major>\\d+)\\.
|
|
56
56
|
(?P<minor>\\d+)\\.
|
|
@@ -17,6 +17,7 @@ from pycardano import PaymentSigningKey
|
|
|
17
17
|
from pycardano import PaymentVerificationKey
|
|
18
18
|
from pycardano import PlutusData
|
|
19
19
|
from pycardano import PlutusV2Script
|
|
20
|
+
from pycardano import PlutusV3Script
|
|
20
21
|
from pycardano import Redeemer
|
|
21
22
|
from pycardano import TransactionBuilder
|
|
22
23
|
from pycardano import TransactionId
|
|
@@ -63,6 +64,12 @@ SATURNSWAP_LEGACY_ORDER_ADDRESS = (
|
|
|
63
64
|
"addr1zyd0sj57d9lpu7cy9g9qdurpazqc9l4eaxk6j59nd2gkh4"
|
|
64
65
|
"275jq4yvpskgayj55xegdp30g5rfynax66r8vgn9fldndsqzf5tn"
|
|
65
66
|
)
|
|
67
|
+
# V3 (PlutusV3) contract; script hash
|
|
68
|
+
# 6023f59dce0064f1d6d27594dbea25bc4305a9f6a10f3a064037553a.
|
|
69
|
+
SATURNSWAP_V3_ORDER_ADDRESS = (
|
|
70
|
+
"addr1z9sz8avaecqxfuwk6f6efkl2yk7yxpdf76ss7wsxgqm42w"
|
|
71
|
+
"h2l9cdyhc0eja9mxq0lgeer90edhlfymnxv2ym3szcetqsp0ume8"
|
|
72
|
+
)
|
|
66
73
|
|
|
67
74
|
# When the protocol shares its authorize hot-key, set this env var to the signing
|
|
68
75
|
# key and dendrite builds the fee-free authorized fill on either contract.
|
|
@@ -199,6 +206,199 @@ class SaturnSwapSwapDatum(OrderDatum):
|
|
|
199
206
|
return OrderType.swap
|
|
200
207
|
|
|
201
208
|
|
|
209
|
+
@dataclass
|
|
210
|
+
class SaturnSwapOutputReferenceV3(PlutusData):
|
|
211
|
+
"""Flat OutputReference: Constr0[tx_id: bytes(32), index]. No TxId wrapper."""
|
|
212
|
+
|
|
213
|
+
CONSTR_ID = 0
|
|
214
|
+
tx_id: bytes
|
|
215
|
+
index: int
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
@dataclass
|
|
219
|
+
class SaturnSwapPaymentDatumV3(PlutusData):
|
|
220
|
+
"""PaymentDatum { output_reference } with the flat V3 OutputReference."""
|
|
221
|
+
|
|
222
|
+
CONSTR_ID = 0
|
|
223
|
+
output_reference: SaturnSwapOutputReferenceV3
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
@dataclass
|
|
227
|
+
class SaturnSwapCoverage(PlutusData):
|
|
228
|
+
"""Aegis coverage { vault, premium_bps, policy_ref }."""
|
|
229
|
+
|
|
230
|
+
CONSTR_ID = 0
|
|
231
|
+
vault: PlutusFullAddress
|
|
232
|
+
premium_bps: int
|
|
233
|
+
policy_ref: SaturnSwapOutputReferenceV3
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
@dataclass
|
|
237
|
+
class SaturnSwapSomeCoverage(PlutusData):
|
|
238
|
+
"""Some(Coverage) wrapper for Option<Coverage>."""
|
|
239
|
+
|
|
240
|
+
CONSTR_ID = 0
|
|
241
|
+
value: SaturnSwapCoverage
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
@dataclass
|
|
245
|
+
class SaturnSwapSwapDatumV3(OrderDatum):
|
|
246
|
+
"""V3 SwapDatum (11 fields).
|
|
247
|
+
|
|
248
|
+
Extends the V2 layout with ``min_partial_fill`` and optional Aegis
|
|
249
|
+
``coverage``, and uses the flat :class:`SaturnSwapOutputReferenceV3`.
|
|
250
|
+
"""
|
|
251
|
+
|
|
252
|
+
CONSTR_ID = 0
|
|
253
|
+
owner: PlutusFullAddress
|
|
254
|
+
policy_id_sell: bytes
|
|
255
|
+
asset_name_sell: bytes
|
|
256
|
+
amount_sell: int
|
|
257
|
+
policy_id_buy: bytes
|
|
258
|
+
asset_name_buy: bytes
|
|
259
|
+
amount_buy: int
|
|
260
|
+
valid_before_time: Union[PlutusNone, SaturnSwapSomeInt]
|
|
261
|
+
output_reference: SaturnSwapOutputReferenceV3
|
|
262
|
+
min_partial_fill: int
|
|
263
|
+
coverage: Union[SaturnSwapSomeCoverage, PlutusNone]
|
|
264
|
+
|
|
265
|
+
def pool_pair(self) -> Assets | None:
|
|
266
|
+
"""Return the asset pair for this swap datum."""
|
|
267
|
+
sell_unit = (
|
|
268
|
+
"lovelace"
|
|
269
|
+
if self.policy_id_sell == b""
|
|
270
|
+
else self.policy_id_sell.hex() + self.asset_name_sell.hex()
|
|
271
|
+
)
|
|
272
|
+
buy_unit = (
|
|
273
|
+
"lovelace"
|
|
274
|
+
if self.policy_id_buy == b""
|
|
275
|
+
else self.policy_id_buy.hex() + self.asset_name_buy.hex()
|
|
276
|
+
)
|
|
277
|
+
return Assets(**{sell_unit: 0}) + Assets(**{buy_unit: 0})
|
|
278
|
+
|
|
279
|
+
def address_source(self) -> str | None:
|
|
280
|
+
"""Return the maker address as a bech32 string."""
|
|
281
|
+
return self.owner.to_address().encode()
|
|
282
|
+
|
|
283
|
+
def requested_amount(self) -> Assets:
|
|
284
|
+
"""Return the requested buy asset amount."""
|
|
285
|
+
buy_unit = (
|
|
286
|
+
"lovelace"
|
|
287
|
+
if self.policy_id_buy == b""
|
|
288
|
+
else self.policy_id_buy.hex() + self.asset_name_buy.hex()
|
|
289
|
+
)
|
|
290
|
+
return Assets(**{buy_unit: self.amount_buy})
|
|
291
|
+
|
|
292
|
+
def order_type(self) -> OrderType | None:
|
|
293
|
+
"""Return the order type classification."""
|
|
294
|
+
return OrderType.swap
|
|
295
|
+
|
|
296
|
+
def is_covered(self) -> bool:
|
|
297
|
+
"""Return whether the order carries Aegis coverage."""
|
|
298
|
+
return isinstance(self.coverage, SaturnSwapSomeCoverage)
|
|
299
|
+
|
|
300
|
+
def premium_bps(self) -> int | None:
|
|
301
|
+
"""Coverage premium in basis points, or None when uncovered."""
|
|
302
|
+
return self.coverage.value.premium_bps if self.is_covered() else None
|
|
303
|
+
|
|
304
|
+
def coverage_vault(self) -> str | None:
|
|
305
|
+
"""Aegis vault bech32 address, or None when uncovered."""
|
|
306
|
+
if not self.is_covered():
|
|
307
|
+
return None
|
|
308
|
+
return self.coverage.value.vault.to_address().encode()
|
|
309
|
+
|
|
310
|
+
def premium_for_fill(self, user_sell_amount: int) -> int:
|
|
311
|
+
"""Out-of-pocket premium (buy asset) for a fill of ``user_sell_amount``.
|
|
312
|
+
|
|
313
|
+
``max(1, user_sell_amount * premium_bps // 10000)`` for covered orders;
|
|
314
|
+
``0`` when uncovered.
|
|
315
|
+
"""
|
|
316
|
+
if not self.is_covered():
|
|
317
|
+
return 0
|
|
318
|
+
base = (user_sell_amount * self.coverage.value.premium_bps) // 10_000
|
|
319
|
+
return max(1, base)
|
|
320
|
+
|
|
321
|
+
def check_min_partial_fill(self, user_sell_amount: int) -> None:
|
|
322
|
+
"""Reject a partial fill below the min_partial_fill floor.
|
|
323
|
+
|
|
324
|
+
A partial fill (``user_sell_amount < amount_buy``) must deliver at least
|
|
325
|
+
``min_partial_fill`` of the buy asset; a full fill is always allowed.
|
|
326
|
+
"""
|
|
327
|
+
is_partial = user_sell_amount < self.amount_buy
|
|
328
|
+
if is_partial and user_sell_amount < self.min_partial_fill:
|
|
329
|
+
msg = (
|
|
330
|
+
f"partial fill {user_sell_amount} below min_partial_fill "
|
|
331
|
+
f"{self.min_partial_fill}"
|
|
332
|
+
)
|
|
333
|
+
raise ValueError(msg)
|
|
334
|
+
|
|
335
|
+
def build_relist_datum(
|
|
336
|
+
self,
|
|
337
|
+
spent_tx_hash: str,
|
|
338
|
+
spent_index: int,
|
|
339
|
+
user_sell_amount: int,
|
|
340
|
+
) -> "SaturnSwapSwapDatumV3":
|
|
341
|
+
"""Continuation (relist) datum for a partial fill of ``user_sell_amount``.
|
|
342
|
+
|
|
343
|
+
Owner, pair, ``valid_before_time``, ``min_partial_fill`` and ``coverage``
|
|
344
|
+
carry forward unchanged; the flat ``output_reference`` points to the spent
|
|
345
|
+
order. Mirrors the residual-amount math in
|
|
346
|
+
:meth:`SaturnSwapV3OrderState.swap_utxo` (including the ADA-sell carve).
|
|
347
|
+
"""
|
|
348
|
+
two_ada = 2_000_000
|
|
349
|
+
new_amount_buy = self.amount_buy - user_sell_amount
|
|
350
|
+
new_amount_sell = _ratio_amount(
|
|
351
|
+
self.amount_buy,
|
|
352
|
+
new_amount_buy,
|
|
353
|
+
self.amount_sell,
|
|
354
|
+
)
|
|
355
|
+
if self.policy_id_sell == b"" and new_amount_sell > two_ada:
|
|
356
|
+
new_amount_sell -= two_ada
|
|
357
|
+
new_amount_buy = _ratio_amount(
|
|
358
|
+
self.amount_sell,
|
|
359
|
+
new_amount_sell,
|
|
360
|
+
self.amount_buy,
|
|
361
|
+
)
|
|
362
|
+
return SaturnSwapSwapDatumV3(
|
|
363
|
+
owner=self.owner,
|
|
364
|
+
policy_id_sell=self.policy_id_sell,
|
|
365
|
+
asset_name_sell=self.asset_name_sell,
|
|
366
|
+
amount_sell=new_amount_sell,
|
|
367
|
+
policy_id_buy=self.policy_id_buy,
|
|
368
|
+
asset_name_buy=self.asset_name_buy,
|
|
369
|
+
amount_buy=new_amount_buy,
|
|
370
|
+
valid_before_time=self.valid_before_time,
|
|
371
|
+
output_reference=SaturnSwapOutputReferenceV3(
|
|
372
|
+
tx_id=bytes.fromhex(spent_tx_hash),
|
|
373
|
+
index=spent_index,
|
|
374
|
+
),
|
|
375
|
+
min_partial_fill=self.min_partial_fill,
|
|
376
|
+
coverage=self.coverage,
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
def premium_payment(
|
|
380
|
+
self,
|
|
381
|
+
user_sell_amount: int,
|
|
382
|
+
) -> tuple[str, Assets] | None:
|
|
383
|
+
"""Aegis premium owed for a fill: ``(vault_bech32, buy-asset premium)``.
|
|
384
|
+
|
|
385
|
+
``None`` for uncovered orders. The premium is out-of-pocket for the filler,
|
|
386
|
+
denominated in the BUY asset, and paid to the coverage vault as a real
|
|
387
|
+
output the validator requires on a covered fill.
|
|
388
|
+
"""
|
|
389
|
+
if not self.is_covered():
|
|
390
|
+
return None
|
|
391
|
+
buy_unit = (
|
|
392
|
+
"lovelace"
|
|
393
|
+
if self.policy_id_buy == b""
|
|
394
|
+
else self.policy_id_buy.hex() + self.asset_name_buy.hex()
|
|
395
|
+
)
|
|
396
|
+
return (
|
|
397
|
+
self.coverage.value.vault.to_address().encode(),
|
|
398
|
+
Assets(**{buy_unit: self.premium_for_fill(user_sell_amount)}),
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
|
|
202
402
|
@dataclass
|
|
203
403
|
class SaturnSwapSwapAction(PlutusData):
|
|
204
404
|
"""SwapAction(user_sell_amount, input_index, output_index)."""
|
|
@@ -243,12 +443,20 @@ class SaturnSwapSwapAction(PlutusData):
|
|
|
243
443
|
input_index = input_utxo.input.index
|
|
244
444
|
|
|
245
445
|
for i, txo in enumerate(tx_builder.outputs):
|
|
246
|
-
|
|
446
|
+
datum = txo.datum
|
|
447
|
+
if isinstance(datum, SaturnSwapPaymentDatum):
|
|
448
|
+
# V2: nested OutputReference -> TxId -> bytes.
|
|
449
|
+
ref_tx_id = datum.output_reference.tx_id.value
|
|
450
|
+
ref_index = datum.output_reference.index
|
|
451
|
+
elif isinstance(datum, SaturnSwapPaymentDatumV3):
|
|
452
|
+
# V3: flat OutputReference (tx_id is bare bytes).
|
|
453
|
+
ref_tx_id = datum.output_reference.tx_id
|
|
454
|
+
ref_index = datum.output_reference.index
|
|
455
|
+
else:
|
|
247
456
|
continue
|
|
248
|
-
output_ref = txo.datum.output_reference
|
|
249
457
|
if (
|
|
250
|
-
|
|
251
|
-
and
|
|
458
|
+
ref_tx_id == bytes.fromhex(str(input_tx_id))
|
|
459
|
+
and ref_index == input_index
|
|
252
460
|
and txo.address == owner_address
|
|
253
461
|
):
|
|
254
462
|
self.output_index = i
|
|
@@ -311,8 +519,8 @@ class _SaturnSwapOrderStateBase(AbstractOrderState):
|
|
|
311
519
|
return SaturnSwapSwapDatum
|
|
312
520
|
|
|
313
521
|
@classmethod
|
|
314
|
-
def default_script_class(cls) -> type[PlutusV2Script]:
|
|
315
|
-
"""Return default script type."""
|
|
522
|
+
def default_script_class(cls) -> type[PlutusV2Script] | type[PlutusV3Script]:
|
|
523
|
+
"""Return default script type (V2 base; the V3 leaf overrides)."""
|
|
316
524
|
return PlutusV2Script
|
|
317
525
|
|
|
318
526
|
@property
|
|
@@ -464,7 +672,7 @@ class _SaturnSwapOrderStateBase(AbstractOrderState):
|
|
|
464
672
|
tx_builder: TransactionBuilder,
|
|
465
673
|
sell_unit: str,
|
|
466
674
|
new_amount_sell: int,
|
|
467
|
-
payment_datum: "SaturnSwapPaymentDatum",
|
|
675
|
+
payment_datum: "SaturnSwapPaymentDatum | SaturnSwapPaymentDatumV3",
|
|
468
676
|
) -> None:
|
|
469
677
|
"""Add the taker-fee output, or require the authorize hot-key signature.
|
|
470
678
|
|
|
@@ -699,9 +907,200 @@ class SaturnSwapLegacyOrderState(_SaturnSwapOrderStateBase):
|
|
|
699
907
|
return [SATURNSWAP_LEGACY_ORDER_ADDRESS]
|
|
700
908
|
|
|
701
909
|
|
|
910
|
+
class SaturnSwapV3OrderState(_SaturnSwapOrderStateBase):
|
|
911
|
+
"""V3 (PlutusV3) SaturnSwap order state — 1% taker-fee contract.
|
|
912
|
+
|
|
913
|
+
Orders resting at :data:`SATURNSWAP_V3_ORDER_ADDRESS` (script hash
|
|
914
|
+
``6023f59d…``). Same 1% non-auth taker fee as the live V2 contract; the datum
|
|
915
|
+
is the 11-field :class:`SaturnSwapSwapDatumV3` (flat OutputReference +
|
|
916
|
+
``min_partial_fill`` + optional coverage) and the script is PlutusV3.
|
|
917
|
+
"""
|
|
918
|
+
|
|
919
|
+
TAKER_FEE_BPS: ClassVar[int] = SATURNSWAP_TAKER_FEE_BPS
|
|
920
|
+
|
|
921
|
+
@classmethod
|
|
922
|
+
def dex(cls) -> str:
|
|
923
|
+
"""Return the DEX name."""
|
|
924
|
+
return "SaturnSwap"
|
|
925
|
+
|
|
926
|
+
@classmethod
|
|
927
|
+
def order_selector(cls) -> list[str]:
|
|
928
|
+
"""Return order script addresses (V3 contract)."""
|
|
929
|
+
return [SATURNSWAP_V3_ORDER_ADDRESS]
|
|
930
|
+
|
|
931
|
+
@classmethod
|
|
932
|
+
def order_datum_class(cls) -> type[PlutusData]:
|
|
933
|
+
"""Return the V3 order datum class."""
|
|
934
|
+
return SaturnSwapSwapDatumV3
|
|
935
|
+
|
|
936
|
+
@classmethod
|
|
937
|
+
def default_script_class(cls) -> type[PlutusV3Script]:
|
|
938
|
+
"""V3 orders are spent via a PlutusV3 reference script."""
|
|
939
|
+
return PlutusV3Script
|
|
940
|
+
|
|
941
|
+
def swap_utxo(
|
|
942
|
+
self,
|
|
943
|
+
address_source: Address,
|
|
944
|
+
in_assets: Assets,
|
|
945
|
+
out_assets: Assets,
|
|
946
|
+
tx_builder: TransactionBuilder,
|
|
947
|
+
extra_assets: Assets | None = None,
|
|
948
|
+
address_target: Address | None = None,
|
|
949
|
+
datum_target: PlutusData | None = None,
|
|
950
|
+
) -> tuple[TransactionOutput | None, PlutusData]:
|
|
951
|
+
"""Build a V3 taker-fill for this order.
|
|
952
|
+
|
|
953
|
+
Uses the flat :class:`SaturnSwapPaymentDatumV3` and the V3 relist datum
|
|
954
|
+
(:meth:`SaturnSwapSwapDatumV3.build_relist_datum`), enforces the
|
|
955
|
+
``min_partial_fill`` floor, and preserves the authorized fee-free path.
|
|
956
|
+
Covered orders require the out-of-pocket premium output and are handled
|
|
957
|
+
separately.
|
|
958
|
+
|
|
959
|
+
TODO(dry): the owner-output / fee / partial-residual scaffold mirrors the
|
|
960
|
+
V2 base ``swap_utxo``; fold the shared body into an order-book mixin so V2
|
|
961
|
+
and V3 stop duplicating it.
|
|
962
|
+
"""
|
|
963
|
+
two_ada = 2_000_000
|
|
964
|
+
user_sell_amount = int(in_assets.quantity())
|
|
965
|
+
|
|
966
|
+
# Reject a partial below the on-chain min_partial_fill floor.
|
|
967
|
+
self.order_datum.check_min_partial_fill(user_sell_amount)
|
|
968
|
+
|
|
969
|
+
if self.reference_utxo is not None:
|
|
970
|
+
tx_builder.reference_inputs.add(self.reference_utxo)
|
|
971
|
+
|
|
972
|
+
order_address = (
|
|
973
|
+
get_backend()
|
|
974
|
+
.get_pool_in_tx(
|
|
975
|
+
self.tx_hash,
|
|
976
|
+
addresses=self.pool_selector().addresses,
|
|
977
|
+
)[0]
|
|
978
|
+
.address
|
|
979
|
+
)
|
|
980
|
+
input_utxo = UTxO(
|
|
981
|
+
TransactionInput(
|
|
982
|
+
transaction_id=TransactionId(bytes.fromhex(self.tx_hash)),
|
|
983
|
+
index=self.tx_index,
|
|
984
|
+
),
|
|
985
|
+
output=TransactionOutput(
|
|
986
|
+
address=order_address,
|
|
987
|
+
amount=asset_to_value(self.assets),
|
|
988
|
+
datum_hash=self.order_datum.hash(),
|
|
989
|
+
),
|
|
990
|
+
)
|
|
991
|
+
script_input_lovelace = input_utxo.output.amount.coin
|
|
992
|
+
|
|
993
|
+
# Flat V3 payment datum stamped on every output (owner/fee/relist).
|
|
994
|
+
output_ref = SaturnSwapOutputReferenceV3(
|
|
995
|
+
tx_id=bytes.fromhex(self.tx_hash),
|
|
996
|
+
index=self.tx_index,
|
|
997
|
+
)
|
|
998
|
+
payment_datum = SaturnSwapPaymentDatumV3(output_reference=output_ref)
|
|
999
|
+
|
|
1000
|
+
partial = user_sell_amount < self.order_datum.amount_buy
|
|
1001
|
+
sell_unit = out_assets.unit()
|
|
1002
|
+
buy_unit = in_assets.unit()
|
|
1003
|
+
sell_is_ada = sell_unit == "lovelace"
|
|
1004
|
+
|
|
1005
|
+
owner_address = self.order_datum.owner.to_address()
|
|
1006
|
+
owner_assets = Assets(**{buy_unit: user_sell_amount})
|
|
1007
|
+
new_amount_sell = _ratio_amount(
|
|
1008
|
+
self.order_datum.amount_buy,
|
|
1009
|
+
user_sell_amount,
|
|
1010
|
+
self.order_datum.amount_sell,
|
|
1011
|
+
)
|
|
1012
|
+
if partial and sell_is_ada and new_amount_sell > two_ada:
|
|
1013
|
+
owner_assets.root["lovelace"] = (
|
|
1014
|
+
owner_assets.root.get("lovelace", 0) + two_ada
|
|
1015
|
+
)
|
|
1016
|
+
elif not partial and not sell_is_ada:
|
|
1017
|
+
owner_assets.root["lovelace"] = (
|
|
1018
|
+
owner_assets.root.get("lovelace", 0) + script_input_lovelace
|
|
1019
|
+
)
|
|
1020
|
+
|
|
1021
|
+
owner_output = TransactionOutput(
|
|
1022
|
+
address=owner_address,
|
|
1023
|
+
amount=asset_to_value(owner_assets),
|
|
1024
|
+
datum=payment_datum,
|
|
1025
|
+
)
|
|
1026
|
+
owner_output.amount.coin = max(
|
|
1027
|
+
owner_output.amount.coin,
|
|
1028
|
+
min_lovelace(tx_builder.context, output=owner_output),
|
|
1029
|
+
)
|
|
1030
|
+
tx_builder.add_output(owner_output)
|
|
1031
|
+
|
|
1032
|
+
self._add_fee_or_authorize(
|
|
1033
|
+
tx_builder,
|
|
1034
|
+
sell_unit,
|
|
1035
|
+
new_amount_sell,
|
|
1036
|
+
payment_datum,
|
|
1037
|
+
)
|
|
1038
|
+
|
|
1039
|
+
# Covered orders owe an out-of-pocket premium output (buy asset) to the
|
|
1040
|
+
# Aegis vault; the validator requires it and enforces vault distinctness.
|
|
1041
|
+
premium = self.order_datum.premium_payment(user_sell_amount)
|
|
1042
|
+
if premium is not None:
|
|
1043
|
+
vault_bech32, premium_assets = premium
|
|
1044
|
+
vault_address = Address.decode(vault_bech32)
|
|
1045
|
+
if vault_address.payment_part == owner_address.payment_part:
|
|
1046
|
+
msg = "coverage vault must differ from the order owner"
|
|
1047
|
+
raise ValueError(msg)
|
|
1048
|
+
premium_output = TransactionOutput(
|
|
1049
|
+
address=vault_address,
|
|
1050
|
+
amount=asset_to_value(premium_assets),
|
|
1051
|
+
datum=payment_datum,
|
|
1052
|
+
)
|
|
1053
|
+
premium_output.amount.coin = max(
|
|
1054
|
+
premium_output.amount.coin,
|
|
1055
|
+
min_lovelace(tx_builder.context, output=premium_output),
|
|
1056
|
+
)
|
|
1057
|
+
tx_builder.add_output(premium_output)
|
|
1058
|
+
|
|
1059
|
+
action = SaturnSwapSwapAction(
|
|
1060
|
+
user_sell_amount=user_sell_amount,
|
|
1061
|
+
input_index=0,
|
|
1062
|
+
output_index=0,
|
|
1063
|
+
)
|
|
1064
|
+
redeemer = Redeemer(action)
|
|
1065
|
+
tx_builder.add_script_input(
|
|
1066
|
+
utxo=input_utxo,
|
|
1067
|
+
script=self.reference_utxo,
|
|
1068
|
+
redeemer=redeemer,
|
|
1069
|
+
)
|
|
1070
|
+
tx_builder.datums.update({self.order_datum.hash(): self.order_datum})
|
|
1071
|
+
|
|
1072
|
+
if partial:
|
|
1073
|
+
new_datum = self.order_datum.build_relist_datum(
|
|
1074
|
+
self.tx_hash,
|
|
1075
|
+
self.tx_index,
|
|
1076
|
+
user_sell_amount,
|
|
1077
|
+
)
|
|
1078
|
+
residual_assets = Assets(**{sell_unit: new_datum.amount_sell})
|
|
1079
|
+
residual_output = TransactionOutput(
|
|
1080
|
+
address=order_address,
|
|
1081
|
+
amount=asset_to_value(residual_assets),
|
|
1082
|
+
datum=new_datum,
|
|
1083
|
+
)
|
|
1084
|
+
if sell_is_ada:
|
|
1085
|
+
residual_output.amount.coin = max(
|
|
1086
|
+
residual_output.amount.coin,
|
|
1087
|
+
min_lovelace(tx_builder.context, output=residual_output),
|
|
1088
|
+
)
|
|
1089
|
+
else:
|
|
1090
|
+
residual_output.amount.coin = max(
|
|
1091
|
+
script_input_lovelace,
|
|
1092
|
+
min_lovelace(tx_builder.context, output=residual_output),
|
|
1093
|
+
)
|
|
1094
|
+
tx_builder.datums.update({new_datum.hash(): new_datum})
|
|
1095
|
+
return residual_output, new_datum
|
|
1096
|
+
|
|
1097
|
+
return None, self.order_datum
|
|
1098
|
+
|
|
1099
|
+
|
|
702
1100
|
# Concrete SaturnSwap contracts, newest first. The order book walks all of these
|
|
703
|
-
# so
|
|
1101
|
+
# so the V3, live 1%, and legacy 4% contracts are aggregated.
|
|
704
1102
|
_SATURNSWAP_ORDER_STATE_CLASSES: list[type[_SaturnSwapOrderStateBase]] = [
|
|
1103
|
+
SaturnSwapV3OrderState,
|
|
705
1104
|
SaturnSwapOrderState,
|
|
706
1105
|
SaturnSwapLegacyOrderState,
|
|
707
1106
|
]
|
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/__init__.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/backend/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/backend/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/cswap.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/dano.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/minswap.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/muesli.py
RENAMED
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/splash.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/sundae.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/amm/vyfi.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/core/base.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/core/errors.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/ob/__init__.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/ob/axo.py
RENAMED
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/ob/chadswap.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/ob/djed.py
RENAMED
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/dexs/ob/ob_base.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/__init__.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/math.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.5.0.dev1 → charli3_dendrite-1.5.1.dev0}/src/charli3_dendrite/lending/registry.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|