Skip to content

Commit

Permalink
StableSwap Pool Swaps
Browse files Browse the repository at this point in the history
  • Loading branch information
igorsereda committed Feb 12, 2025
1 parent 47f18ed commit 7f7e812
Show file tree
Hide file tree
Showing 18 changed files with 230 additions and 272 deletions.
25 changes: 14 additions & 11 deletions dex_screener/dipdup.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,20 @@ indexes:
- callback: hydradx.asset.on_location_set
name: AssetRegistry.LocationSet

- callback: hydradx.omnipool.on_token_added
name: Omnipool.TokenAdded
- callback: hydradx.on_swap_executed
name: Omnipool.BuyExecuted
- callback: hydradx.on_swap_executed
name: Omnipool.SellExecuted

- callback: hydradx.stableswap.on_pool_created
name: Stableswap.PoolCreated
- callback: hydradx.on_swap_executed
name: Stableswap.BuyExecuted
- callback: hydradx.on_swap_executed
name: Stableswap.SellExecuted

- callback: hydradx.isolated_pool.on_pool_created
name: XYK.PoolCreated
- callback: hydradx.on_swap_executed
Expand All @@ -69,17 +83,6 @@ indexes:
- callback: hydradx.on_swap_executed
name: LBP.SellExecuted

- callback: hydradx.omnipool.on_token_added
name: Omnipool.TokenAdded
- callback: hydradx.on_swap_executed
name: Omnipool.BuyExecuted
- callback: hydradx.on_swap_executed
name: Omnipool.SellExecuted

# - callback: hydradx.on_swap_executed
# name: Stableswap.BuyExecuted
# - callback: hydradx.on_swap_executed
# name: Stableswap.SellExecuted

advanced:
reindex:
Expand Down
45 changes: 0 additions & 45 deletions dex_screener/handlers/hydradx/stableswap/on_buy_executed.py

This file was deleted.

13 changes: 13 additions & 0 deletions dex_screener/handlers/hydradx/stableswap/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.stableswap.stableswap_service import StableSwapService
from dex_screener.types.hydradx.substrate_events.stableswap_pool_created import StableswapPoolCreatedPayload


async def on_pool_created(
ctx: HandlerContext,
event: SubstrateEvent[StableswapPoolCreatedPayload],
) -> None:
pool = await StableSwapService.register_pool(event)
await StableSwapService.register_pair(pool, event)
45 changes: 0 additions & 45 deletions dex_screener/handlers/hydradx/stableswap/on_sell_executed.py

This file was deleted.

8 changes: 5 additions & 3 deletions dex_screener/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,12 @@ class Pool(Model):
class Meta:
table = 'dex_pool'
model = 'models.Pool'
unique_together = ('dex_key', 'dex_pool_id')

id = fields.TextField(primary_key=True)
account = AccountField(null=True)
id = fields.IntField(primary_key=True)
dex_key = fields.EnumField(enum_type=DexKey, db_index=True)
dex_pool_id = fields.TextField(db_index=True)
account = AccountField(null=True)
assets: ManyToManyFieldInstance[Asset] = ManyToManyField(
model_name=Asset.Meta.model,
# through='models.AssetPoolReserve',
Expand All @@ -102,7 +104,7 @@ class Meta:
)

def __repr__(self) -> str:
return f'<Pool[{self.dex_key}](id={self.id}, account={self.account})>'
return f'<Pool[{self.dex_key}](id={self.dex_pool_id}, account={self.account})>'


class AssetPoolReserve(Model):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ class IsolatedPoolService:
@classmethod
async def register_pool(cls, event: SubstrateEvent[XYKPoolCreatedPayload]):
pool, _ = await Pool.update_or_create(
id=event.payload['pool'],
dex_key=DexKey.IsolatedPool,
dex_pool_id=event.payload['pool'],
defaults={
'account': event.payload['pool'],
'dex_key': DexKey.IsolatedPool,
'lp_token_id': event.payload['share_token'],
},
)
Expand Down
4 changes: 2 additions & 2 deletions dex_screener/service/dex/lbp/lbp_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ class LBPService:
@classmethod
async def register_pool(cls, event: SubstrateEvent[LBPPoolCreatedPayload]):
pool, _ = await Pool.update_or_create(
id=event.payload['pool'],
dex_key = DexKey.LBP,
dex_pool_id = event.payload['pool'],
defaults={
'account': event.payload['pool'],
'dex_key': DexKey.LBP,
},
)
cls.logger.info('Pool registered: %r.', pool)
Expand Down
62 changes: 2 additions & 60 deletions dex_screener/service/dex/omnipool/omnipool_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,17 @@
import logging
from typing import TYPE_CHECKING

from dex_screener.handlers.hydradx.asset.asset_type.exception import InvalidEventDataError
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 import SwapEvent
from dex_screener.models.dto import DexScreenerEventInfoDTO
from dex_screener.service.dex.omnipool.const import OMNIPOOL_HUB_ASSET_ID
from dex_screener.service.dex.omnipool.const import OMNIPOOL_SYSTEM_ACCOUNT

if TYPE_CHECKING:
from dipdup.models.substrate import SubstrateEvent

from dex_screener.types.hydradx.substrate_events.omnipool_buy_executed import OmnipoolBuyExecutedPayload
from dex_screener.types.hydradx.substrate_events.omnipool_sell_executed import OmnipoolSellExecutedPayload
from dex_screener.types.hydradx.substrate_events.omnipool_token_added import OmnipoolTokenAddedPayload


Expand All @@ -40,9 +36,9 @@ async def get_pool(cls):
@classmethod
async def register_pool(cls):
pool = await Pool.create(
id=OMNIPOOL_SYSTEM_ACCOUNT,
account=OMNIPOOL_SYSTEM_ACCOUNT,
dex_key=DexKey.Omnipool,
dex_pool_id = OMNIPOOL_SYSTEM_ACCOUNT,
account=OMNIPOOL_SYSTEM_ACCOUNT,
)
cls.logger.info('Omnipool registered: %r.', pool)

Expand Down Expand Up @@ -80,57 +76,3 @@ async def register_pair(cls, pool: Pool, event: SubstrateEvent[OmnipoolTokenAdde

await pool.assets.add(new_asset)
cls.logger.info('Pair Asset added to pool %r: %s.', pool, new_asset)

@classmethod
async def register_swap(cls, event: SubstrateEvent[OmnipoolBuyExecutedPayload | OmnipoolSellExecutedPayload]):
match event.payload:
case {
'who': str(maker),
'asset_in': int(asset_in_id),
'asset_out': int(asset_out_id),
'amount_in': int(minor_amount_in),
'amount_out': int(minor_amount_out),
}:
pass

case _:
raise InvalidEventDataError(f'Unhandled Omnipool Swap Event: {event}.')
if minor_amount_in * minor_amount_out == 0:
cls.logger.warning('Invalid Swap Event: minor amount must be natural!')
return

asset_in = await Asset.get(id=asset_in_id)
asset_out = await Asset.get(id=asset_out_id)
asset_amount_in = asset_in.from_minor(minor_amount_in)
asset_amount_out = asset_out.from_minor(minor_amount_out)

if asset_in.id < asset_out.id:
swap_data = {
'amount_0_in': asset_amount_in,
'amount_1_out': asset_amount_out,
'price': asset_amount_out / asset_amount_in,
}
else:
swap_data = {
'amount_0_out': asset_amount_out,
'amount_1_in': asset_amount_in,
'price': asset_amount_in / asset_amount_out,
}

swap_data.update(
{
'maker': maker,
'pair_id': cls.get_pair_id(asset_in.id, asset_out.id),
'event_type': 'swap',
}
)

event_info = DexScreenerEventInfoDTO.from_event(event)

swap = await SwapEvent.create(
**event_info.model_dump(),
**swap_data,
)
cls.logger.info('Swap Event %s registered: %s [%s].', event_info.name, swap.id, event_info.get_explorer_url())

# await event_info.update_latest_block()
5 changes: 5 additions & 0 deletions dex_screener/service/dex/stableswap/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
DEX_PULL_ACCOUNT_MAPPING: dict[int, str] = {
100: '0x22bb00df7706a5965728b60f96406ee59ce675fd5fd10652a4ed6f618856ccfe',
101: '0xaffeef2e0ccac1986d8ac3b557e1e0d682d649bf61aee81e1a7faaab7eae35e0',
102: '0x7fe7d370617e793b178de6efc9bc5813382f2e2866ee298ea1917d8b8dce436b',
}
63 changes: 63 additions & 0 deletions dex_screener/service/dex/stableswap/stableswap_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from __future__ import annotations

import logging
from itertools import combinations
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
from dex_screener.service.dex.stableswap.const import DEX_PULL_ACCOUNT_MAPPING

if TYPE_CHECKING:
from dipdup.models.substrate import SubstrateEvent

from dex_screener.types.hydradx.substrate_events.stableswap_pool_created import StableswapPoolCreatedPayload


class StableSwapService:
logger = logging.getLogger('stableswap_service')

@classmethod
def get_pair_id(cls, pool_account: str, asset_a_id: int, asset_b_id: int) -> str:
asset_id_list = [str(asset_id) for asset_id in sorted([int(asset_a_id), int(asset_b_id)])]

return '-'.join([pool_account, *asset_id_list])

@classmethod
async def register_pool(cls, event: SubstrateEvent[StableswapPoolCreatedPayload]):
dex_pool_id = event.payload['pool_id']
account = DEX_PULL_ACCOUNT_MAPPING[int(dex_pool_id)]
pool = await Pool.create(
dex_key=DexKey.StableSwap,
dex_pool_id=dex_pool_id,
account=account,
)
cls.logger.info('StableSwap Pool registered: %r.', pool)

return pool

@classmethod
async def register_pair(cls, pool: Pool, event: SubstrateEvent[StableswapPoolCreatedPayload]):

for asset_a_id, asset_b_id in combinations(event.payload['assets'], 2):
pair_id = cls.get_pair_id(pool.account, asset_a_id, asset_b_id)

event_info = DexScreenerEventInfoDTO.from_event(event)

pair = await Pair.create(
id=pair_id,
dex_key=DexKey.StableSwap,
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['fee'],
)
cls.logger.info('Pair registered in pool %r: %r.', pool, pair)
pool_assets: list[Asset] = await Asset.filter(id__in=event.payload['assets'])
await pool.assets.add(*pool_assets)
cls.logger.info('Assets added to pool %r: %s.', pool, pool_assets)
Loading

0 comments on commit 7f7e812

Please sign in to comment.