Skip to content

Commit

Permalink
LBP Swaps
Browse files Browse the repository at this point in the history
  • Loading branch information
igorsereda committed Feb 11, 2025
1 parent f2c38a9 commit 3d76b37
Show file tree
Hide file tree
Showing 13 changed files with 22,293 additions and 0 deletions.
22,086 changes: 22,086 additions & 0 deletions dex_screener/abi/hydradx/v176.json

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions dex_screener/dipdup.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ indexes:
- callback: hydradx.on_swap_executed
name: XYK.SellExecuted

- callback: hydradx.lbp.on_pool_created
name: LBP.PoolCreated
- callback: hydradx.on_swap_executed
name: LBP.BuyExecuted
- callback: hydradx.on_swap_executed
name: LBP.SellExecuted

- callback: hydradx.omnipool.on_token_added
name: Omnipool.TokenAdded
- callback: hydradx.on_swap_executed
Expand Down
13 changes: 13 additions & 0 deletions dex_screener/handlers/hydradx/lbp/on_pool_created.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from dipdup.context import HandlerContext
from dipdup.models.substrate import SubstrateEvent

from dex_screener.service.dex.lbp.lbp_service import LBPService
from dex_screener.types.hydradx.substrate_events.lbp_pool_created import LBPPoolCreatedPayload


async def on_pool_created(
ctx: HandlerContext,
event: SubstrateEvent[LBPPoolCreatedPayload],
) -> None:
pool = await LBPService.register_pool(event)
await LBPService.register_pair(pool, event)
1 change: 1 addition & 0 deletions dex_screener/models/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
class DexKey(StrEnum):
IsolatedPool: str = 'hydradx_xyk'
Omnipool: str = 'hydradx_omnipool'
LBP: str = 'hydradx_lbp'
StableSwap: str = 'hydradx_stableswap'
58 changes: 58 additions & 0 deletions dex_screener/service/dex/lbp/lbp_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from __future__ import annotations

import logging
from typing import TYPE_CHECKING

from dex_screener.models import Asset
from dex_screener.models import DexKey
from dex_screener.models import Pair
from dex_screener.models import Pool
from dex_screener.models.dto import DexScreenerEventInfoDTO

if TYPE_CHECKING:
from dipdup.models.substrate import SubstrateEvent

from dex_screener.types.hydradx.substrate_events.lbp_pool_created import LBPPoolCreatedPayload


class LBPService:
logger = logging.getLogger('lbp_service')

@classmethod
async def register_pool(cls, event: SubstrateEvent[LBPPoolCreatedPayload]):
pool, _ = await Pool.update_or_create(
id=event.payload['pool'],
defaults={
'account': event.payload['pool'],
'dex_key': DexKey.LBP,
},
)
cls.logger.info('Pool registered: %r.', pool)

return pool

@classmethod
async def register_pair(cls, pool: Pool, event: SubstrateEvent[LBPPoolCreatedPayload]):
pair_id = pool.account
if await Pair.exists(id=pair_id):
cls.logger.warning('Pair already exists: %s.', pair_id)
return

asset_a = await Asset.get(id=event.payload['data']['assets'][0])
asset_b = await Asset.get(id=event.payload['data']['assets'][1])
event_info = DexScreenerEventInfoDTO.from_event(event)

pair = await Pair.create(
id=pair_id,
dex_key=DexKey.LBP,
asset_0_id=min(asset_a.id, asset_b.id),
asset_1_id=max(asset_a.id, asset_b.id),
pool=pool,
created_at_block_id=event_info.block_id,
created_at_txn_id=event_info.tx_id,
fee_bps=event.payload['data']['fee'][1],
)
cls.logger.info('Pair registered in pool %r: %r.', pool, pair)

await pool.assets.add(asset_a, asset_b)
cls.logger.info('Pair Assets added to pool %r: %s, %s.', pool, asset_a, asset_b)
64 changes: 64 additions & 0 deletions dex_screener/service/event/entity/swap/lbp_swap_event_entity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from __future__ import annotations

from typing import TYPE_CHECKING

from dex_screener.models import DexKey
from dex_screener.models import Pair
from dex_screener.service.event.entity.swap.dto import MarketDataArgsDTO
from dex_screener.service.event.entity.swap.dto import SwapEventMarketDataDTO
from dex_screener.service.event.entity.swap.dto import SwapEventPoolDataDTO
from dex_screener.service.event.entity.swap.exception import InvalidSwapEventMarketDataError
from dex_screener.service.event.entity.swap.swap_event_entity import SwapEventEntity

if TYPE_CHECKING:
from dipdup.models.substrate import SubstrateEvent


class LBPSwapEventEntity(SwapEventEntity):
def __init__(self, event: SubstrateEvent):
self._event = event

async def resolve_pool_data(self) -> SwapEventPoolDataDTO:
asset_a_id = self._event.payload['asset_in']
asset_b_id = self._event.payload['asset_out']
pair = await Pair.filter(
dex_key=DexKey.LBP,
asset_0_id=min(asset_a_id, asset_b_id),
asset_1_id=max(asset_a_id, asset_b_id),
).first()
return SwapEventPoolDataDTO(
pair_id=pair.id,
# asset_0_reserve=None,
# asset_1_reserve=None,
)

async def resolve_market_data(self) -> SwapEventMarketDataDTO:
match self._event.payload:
case {
'who': str(maker),
'asset_in': int(asset_in_id),
'asset_out': int(asset_out_id),
'buy_price': int(minor_amount_in),
'amount': int(minor_amount_out),
}:
pass
case {
'who': str(maker),
'asset_in': int(asset_in_id),
'asset_out': int(asset_out_id),
'sale_price': int(minor_amount_out),
'amount': int(minor_amount_in),
}:
pass
case _:
raise InvalidSwapEventMarketDataError(f'Unhandled LBP Swap Event Payload: {self._event.payload}.')

resolved_args = MarketDataArgsDTO(
maker=maker,
asset_in_id=asset_in_id,
asset_out_id=asset_out_id,
minor_amount_in=minor_amount_in,
minor_amount_out=minor_amount_out,
)

return await self._market_data_from_args(resolved_args)
3 changes: 3 additions & 0 deletions dex_screener/service/event/event_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import TYPE_CHECKING

from dex_screener.service.event.entity.swap.isolated_pool_swap_event_entity import IsolatedPoolSwapEventEntity
from dex_screener.service.event.entity.swap.lbp_swap_event_entity import LBPSwapEventEntity
from dex_screener.service.event.entity.swap.omnipool_swap_event_entity import OmnipoolSwapEventEntity

if TYPE_CHECKING:
Expand All @@ -26,6 +27,8 @@ def build_swap_event_entity(cls, event: SubstrateEvent) -> SwapEventEntity:
return IsolatedPoolSwapEventEntity(event)
case 'Omnipool.BuyExecuted' | 'Omnipool.SellExecuted':
return OmnipoolSwapEventEntity(event)
case 'LBP.BuyExecuted' | 'LBP.SellExecuted':
return LBPSwapEventEntity(event)

@classmethod
async def register_join_exit(cls, event): ...
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .v176 import V176

type LBPBuyExecutedPayload = V176
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# generated by DipDup 8.2.0rc1

from __future__ import annotations

from typing import TypedDict


class V176(TypedDict):
"""
Purchase executed.
"""

who: str
asset_out: int
asset_in: int
amount: int
buy_price: int
fee_asset: int
fee_amount: int
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .v176 import V176

type LBPPoolCreatedPayload = V176
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# generated by DipDup 8.2.0rc1

from __future__ import annotations

from typing import TypedDict


class V176(TypedDict):
"""
Pool was created by the `CreatePool` origin.
"""

pool: str
data: str
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .v176 import V176

type LBPSellExecutedPayload = V176
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# generated by DipDup 8.2.0rc1

from __future__ import annotations

from typing import TypedDict


class V176(TypedDict):
"""
Sale executed.
"""

who: str
asset_in: int
asset_out: int
amount: int
sale_price: int
fee_asset: int
fee_amount: int

0 comments on commit 3d76b37

Please sign in to comment.