charli3_dendrite 1.4.9.dev0__tar.gz → 1.4.10.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.
Files changed (41) hide show
  1. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/PKG-INFO +1 -1
  2. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/pyproject.toml +2 -2
  3. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dataclasses/datums.py +7 -2
  4. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/amm/amm_base.py +1 -1
  5. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/amm/minswap.py +12 -4
  6. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/amm/sundae.py +24 -9
  7. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/amm/wingriders.py +37 -4
  8. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/LICENSE +0 -0
  9. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/README.md +0 -0
  10. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/__init__.py +0 -0
  11. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/backend/__init__.py +0 -0
  12. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/backend/backend_base.py +0 -0
  13. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/backend/blockfrost/__init__.py +0 -0
  14. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/backend/blockfrost/models.py +0 -0
  15. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/backend/dbsync/__init__.py +0 -0
  16. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/backend/dbsync/models.py +0 -0
  17. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/backend/ogmios_kupo/__init__.py +0 -0
  18. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/backend/ogmios_kupo/models.py +0 -0
  19. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/backend/utils.py +0 -0
  20. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dataclasses/__init__.py +0 -0
  21. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dataclasses/models.py +0 -0
  22. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/__init__.py +0 -0
  23. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/amm/__init__.py +0 -0
  24. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/amm/amm_types.py +0 -0
  25. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/amm/cswap.py +0 -0
  26. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/amm/dano.py +0 -0
  27. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/amm/muesli.py +0 -0
  28. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/amm/spectrum.py +0 -0
  29. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/amm/splash.py +0 -0
  30. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/amm/vyfi.py +0 -0
  31. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/core/__init__.py +0 -0
  32. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/core/base.py +0 -0
  33. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/core/errors.py +0 -0
  34. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/ob/__init__.py +0 -0
  35. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/ob/axo.py +0 -0
  36. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/ob/chadswap.py +0 -0
  37. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/ob/djed.py +0 -0
  38. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/ob/geniusyield.py +0 -0
  39. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/ob/ob_base.py +0 -0
  40. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/dexs/ob/saturnswap.py +0 -0
  41. {charli3_dendrite-1.4.9.dev0 → charli3_dendrite-1.4.10.dev0}/src/charli3_dendrite/utility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: charli3_dendrite
3
- Version: 1.4.9.dev0
3
+ Version: 1.4.10.dev0
4
4
  Summary:
5
5
  License-File: LICENSE
6
6
  Author: Elder Millenial
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "charli3_dendrite"
3
- version = "1.4.9-dev0"
3
+ version = "1.4.10-dev0"
4
4
  description = ""
5
5
  authors = ["Elder Millenial <eldermillenial@protonmail.com>"]
6
6
  readme = "README.md"
@@ -49,7 +49,7 @@ module = ["pycardano", "pycardano.*", "dotenv", "nox"]
49
49
  ignore_missing_imports = true
50
50
 
51
51
  [tool.bumpversion]
52
- current_version = "1.4.9-dev0"
52
+ current_version = "1.4.10-dev0"
53
53
  parse = """(?x)
54
54
  (?P<major>\\d+)\\.
55
55
  (?P<minor>\\d+)\\.
@@ -64,8 +64,13 @@ class PlutusFullAddress(PlutusData):
64
64
  @classmethod
65
65
  def from_address(cls, address: Address) -> "PlutusFullAddress":
66
66
  """Parse an Address object to a PlutusFullAddress."""
67
- error_msg = "Only addresses with staking and payment parts are accepted."
68
- if None in [address.staking_part, address.payment_part]:
67
+ # Enterprise (no-stake) addresses are valid the staking part is
68
+ # encoded as PlutusNone below (Plutus `Nothing`). Swap-forwarding
69
+ # targets are sometimes enterprise script addresses (e.g. an order
70
+ # forwarding to a bare order script address), so only a payment part
71
+ # is required.
72
+ error_msg = "Only addresses with a payment part are accepted."
73
+ if address.payment_part is None:
69
74
  raise ValueError(error_msg)
70
75
  stake: _PlutusConstrWrapper | PlutusNone = PlutusNone()
71
76
  if address.staking_part is not None:
@@ -99,7 +99,7 @@ class AbstractPoolState(AbstractPairState):
99
99
  Raises:
100
100
  ValueError: If more than one asset is supplied as input or output.
101
101
  """
102
- if self.swap_forward and address_target is not None:
102
+ if not self.swap_forward and address_target is not None:
103
103
  print( # noqa: T201
104
104
  f"{self.__class__.__name__} does not support swap forwarding.",
105
105
  )
@@ -546,11 +546,16 @@ class MinswapV2OrderDatum(OrderDatum):
546
546
  full_address_source = PlutusFullAddress.from_address(address_source)
547
547
  step = SwapExactInV2.from_assets(in_asset=in_assets, out_asset=out_assets)
548
548
 
549
+ # `datum_target` is the INNER next-hop order datum (consistent with
550
+ # Sundae / WingRiders); wrap it as the receiver's inline datum. No
551
+ # target (or no datum) -> no receiver datum.
549
552
  if address_target is None:
550
553
  address_target = address_source
551
- datum_target = SundaeV3PlutusNone()
554
+ receiver_datum = SundaeV3PlutusNone()
552
555
  elif datum_target is None:
553
- datum_target = SundaeV3PlutusNone()
556
+ receiver_datum = SundaeV3PlutusNone()
557
+ else:
558
+ receiver_datum = SundaeV3ReceiverInlineDatum(datum=datum_target)
554
559
 
555
560
  full_address_target = PlutusFullAddress.from_address(address_target)
556
561
 
@@ -574,9 +579,12 @@ class MinswapV2OrderDatum(OrderDatum):
574
579
  return cls(
575
580
  owner=OAMSignature(address_source.payment_part.payload),
576
581
  refund_address=full_address_source,
577
- refund_datum_hash=datum_target,
582
+ # The refund goes back to the source wallet and carries NO datum —
583
+ # only the receiver (next hop) gets the forward datum, so
584
+ # refund_datum_hash is always PlutusNone.
585
+ refund_datum_hash=SundaeV3PlutusNone(),
578
586
  receiver_address=full_address_target,
579
- receiver_datum_hash=datum_target,
587
+ receiver_datum_hash=receiver_datum,
580
588
  lp_asset=lp_asset,
581
589
  step=step,
582
590
  max_batcher_fee=batcher_fee.quantity(),
@@ -307,8 +307,25 @@ class SundaeV3OrderDatum(OrderDatum):
307
307
  in_assets: Assets,
308
308
  out_assets: Assets,
309
309
  fee: int,
310
+ address_target: Address | None = None,
311
+ datum_target: PlutusData | None = None,
310
312
  ):
311
- full_address = SundaeV3AddressWithDatum.from_address(address_source)
313
+ # Swap forwarding: when a target address is supplied the filled output
314
+ # is sent there with an optional inline receiver datum (so it can fund
315
+ # the next order in a cross-protocol chain) instead of returning to the
316
+ # source wallet. No target -> source, no inline datum.
317
+ if address_target is None:
318
+ full_address = SundaeV3AddressWithDatum.from_address(address_source)
319
+ else:
320
+ receiver_datum = (
321
+ SundaeV3ReceiverInlineDatum(datum=datum_target)
322
+ if datum_target is not None
323
+ else SundaeV3PlutusNone()
324
+ )
325
+ full_address = SundaeV3AddressWithDatum(
326
+ address=PlutusFullAddress.from_address(address_target),
327
+ datum=receiver_datum,
328
+ )
312
329
  merged = in_assets + out_assets
313
330
  if in_assets.unit() == merged.unit():
314
331
  direction = AtoB()
@@ -642,7 +659,7 @@ class SundaeSwapV3CPPState(AbstractConstantProductPoolState):
642
659
 
643
660
  @property
644
661
  def swap_forward(self) -> bool:
645
- return False
662
+ return True
646
663
 
647
664
  @property
648
665
  def stake_address(self) -> Address:
@@ -738,9 +755,6 @@ class SundaeSwapV3CPPState(AbstractConstantProductPoolState):
738
755
  address_target: Address | None = None,
739
756
  datum_target: PlutusData | None = None,
740
757
  ) -> PlutusData:
741
- if self.swap_forward and address_target is not None:
742
- print(f"{self.__class__.__name__} does not support swap forwarding.")
743
-
744
758
  ident = bytes.fromhex(self.pool_nft.unit()[64:])
745
759
 
746
760
  datum = SundaeV3OrderDatum.create_datum(
@@ -749,6 +763,8 @@ class SundaeSwapV3CPPState(AbstractConstantProductPoolState):
749
763
  in_assets=in_assets,
750
764
  out_assets=out_assets,
751
765
  fee=self.batcher_fee(in_assets=in_assets, out_assets=out_assets).quantity(),
766
+ address_target=address_target,
767
+ datum_target=datum_target,
752
768
  )
753
769
 
754
770
  return datum
@@ -801,7 +817,7 @@ class SundaeSwapV3StableSwap(AbstractStableSwapPoolState):
801
817
 
802
818
  @property
803
819
  def swap_forward(self) -> bool:
804
- return False
820
+ return True
805
821
 
806
822
  @property
807
823
  def stake_address(self) -> Address:
@@ -917,9 +933,6 @@ class SundaeSwapV3StableSwap(AbstractStableSwapPoolState):
917
933
  address_target: Address | None = None,
918
934
  datum_target: PlutusData | None = None,
919
935
  ) -> PlutusData:
920
- if self.swap_forward and address_target is not None:
921
- print(f"{self.__class__.__name__} does not support swap forwarding.")
922
-
923
936
  ident = bytes.fromhex(self.pool_nft.unit()[64:])
924
937
 
925
938
  datum = SundaeV3OrderDatum.create_datum(
@@ -928,6 +941,8 @@ class SundaeSwapV3StableSwap(AbstractStableSwapPoolState):
928
941
  in_assets=in_assets,
929
942
  out_assets=out_assets,
930
943
  fee=self.batcher_fee(in_assets=in_assets, out_assets=out_assets).quantity(),
944
+ address_target=address_target,
945
+ datum_target=datum_target,
931
946
  )
932
947
 
933
948
  return datum
@@ -11,6 +11,7 @@ from pycardano import PlutusData
11
11
  from pycardano import PlutusV1Script
12
12
  from pycardano import PlutusV2Script
13
13
  from pycardano.plutus import RawDatum
14
+ from pycardano.plutus import RawPlutusData
14
15
 
15
16
  from charli3_dendrite.dataclasses.datums import AssetClass
16
17
  from charli3_dendrite.dataclasses.datums import OrderDatum
@@ -354,13 +355,45 @@ class WingRidersV2OrderDatum(OrderDatum):
354
355
  direction = BtoA()
355
356
 
356
357
  plutus_address = PlutusFullAddress.from_address(address_source)
358
+ # Swap forwarding: send the fill to the target (next order) address with
359
+ # an optional inline compensation datum so it can fund the next order in
360
+ # a cross-protocol chain; no target -> back to the owner.
361
+ if address_target is None:
362
+ beneficiary = plutus_address
363
+ compensation_datum = b""
364
+ compensation_datum_type = NoDatum()
365
+ elif datum_target is not None:
366
+ beneficiary = PlutusFullAddress.from_address(address_target)
367
+ # WR-V2 stores the inline compensation datum as the RAW datum
368
+ # structure (a CBORTag/PlutusData), not its CBOR bytes — storing
369
+ # datum_target directly serializes to the matching structure.
370
+ #
371
+ # The next-hop datum may be a typed OrderDatum (a PlutusData
372
+ # subclass) or a RawPlutusData wrapper (e.g. a multi-leg inner datum
373
+ # parsed from CBOR). WR's compensation_datum Union accepts PlutusData
374
+ # + raw CBOR primitives but NOT the RawPlutusData *class*, so it
375
+ # rejects RawPlutusData at serialization — unlike Sundae / Minswap,
376
+ # whose receiver field is a plain PlutusData and accepts either. To
377
+ # keep forwarding uniform across the three DEXes, unwrap RawPlutusData
378
+ # to its raw ``.data`` (a CBORTag for any order datum): byte-identical
379
+ # and Union-valid.
380
+ compensation_datum = (
381
+ datum_target.data
382
+ if isinstance(datum_target, RawPlutusData)
383
+ else datum_target
384
+ )
385
+ compensation_datum_type = InlineDatum()
386
+ else:
387
+ beneficiary = PlutusFullAddress.from_address(address_target)
388
+ compensation_datum = b""
389
+ compensation_datum_type = NoDatum()
357
390
 
358
391
  return WingRidersV2OrderDatum(
359
392
  oil=2000000,
360
- beneficiary=plutus_address,
393
+ beneficiary=beneficiary,
361
394
  owner_address=plutus_address,
362
- compensation_datum=b"",
363
- compensation_datum_type=NoDatum(),
395
+ compensation_datum=compensation_datum,
396
+ compensation_datum_type=compensation_datum_type,
364
397
  deadline=timeout,
365
398
  asset_a_symbol=(
366
399
  bytes.fromhex(merged.unit()[:56])
@@ -685,7 +718,7 @@ class WingRidersV2CPPState(AbstractConstantProductPoolState):
685
718
 
686
719
  @property
687
720
  def swap_forward(self) -> bool:
688
- return False
721
+ return True
689
722
 
690
723
  @property
691
724
  def pool_id(self) -> str: