Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/delea #66

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,21 @@ with [EvaaWithdrawAndLiquidationParser](./parser/parsers/message/evaa.py).
Contains decoded EVAA liquidation events. Produced from messages table stream
with [EvaaWithdrawAndLiquidationParser](./parser/parsers/message/evaa.py).

### delea_deposit

Contains decoded Delea deposit events. Produced from messages table stream
with [DeleaDepositParser](./parser/parsers/message/delea.py).

### delea_withdraw

Contains decoded Delea withdraw events. Produced from messages table stream
with [DeleaWithdrawAndLiquidationParser](./parser/parsers/message/delea.py).

### delea_liquidation

Contains decoded Delea liquidation events. Produced from messages table stream
with [DeleaWithdrawAndLiquidationParser](./parser/parsers/message/delea.py).

## prices

Tables related to DeFi - DEX trades, TVL, LSD prices, etc..
Expand Down
44 changes: 44 additions & 0 deletions database/createdb.sql
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,50 @@ ALTER TYPE public.dex_name ADD VALUE 'megaton' AFTER 'ston.fi_v2';
-- required for megaton parser
CREATE INDEX jetton_transfers_trace_id_idx ON public.jetton_transfers (trace_id);


-- Delea

CREATE TABLE parsed.delea_deposit (
tx_hash bpchar(44) NULL primary key,
msg_hash bpchar(44) NULL,
trace_id bpchar(44) NULL,
utime int4 NULL,
successful boolean NULL,
query_id numeric NULL,
amount numeric NULL,
owner_address varchar NULL,
created timestamp NULL,
updated timestamp NULL
);

CREATE TABLE parsed.delea_withdraw (
tx_hash bpchar(44) NULL primary key,
msg_hash bpchar(44) NULL,
trace_id bpchar(44) NULL,
utime int4 NULL,
successful boolean NULL,
query_id numeric NULL,
amount numeric NULL,
owner_address varchar NULL,
recipient_address varchar NULL,
created timestamp NULL,
updated timestamp NULL
);

CREATE TABLE parsed.delea_liquidation (
tx_hash bpchar(44) NULL primary key,
msg_hash bpchar(44) NULL,
trace_id bpchar(44) NULL,
utime int4 NULL,
successful boolean NULL,
query_id numeric NULL,
amount numeric NULL,
owner_address varchar NULL,
liquidator_address varchar NULL,
created timestamp NULL,
updated timestamp NULL
);

-- TonFun
CREATE TABLE parsed.tonfun_bcl_trade (
tx_hash bpchar(44) NULL primary key,
Expand Down
2 changes: 1 addition & 1 deletion parser/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ services:
restart: always
environment:
- KAFKA_GROUP_ID=messages_parsers
- SUPPORTED_PARSERS=StonfiSwap,StonfiSwapV2,DedustSwap,TradoorPerpOrder,TradoorOptionOrder,GasPumpTrade,TradoorPerpPositionChange,EvaaSupplyParser,EvaaWithdrawAndLiquidationParser,JettonMintParser,HipoTokensMinted,TonFunTrade,TONCOSwap
- SUPPORTED_PARSERS=StonfiSwap,StonfiSwapV2,DedustSwap,TradoorPerpOrder,TradoorOptionOrder,GasPumpTrade,TradoorPerpPositionChange,EvaaSupplyParser,EvaaWithdrawAndLiquidationParser,JettonMintParser,HipoTokensMinted,DeleaDepositParser,DeleaWithdrawAndLiquidationParse,TonFunTrade,TONCOSwap
- KAFKA_TOPICS=ton.public.messages
- MIN_MATURITY_SECONDS=300
env_file:
Expand Down
50 changes: 50 additions & 0 deletions parser/model/delea.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from dataclasses import dataclass
from pytoniq_core import Address


@dataclass
class DeleaDeposit:
__tablename__ = "delea_deposit"
__schema__ = "parsed"

tx_hash: str
msg_hash: str
trace_id: str
utime: int
successful: bool
query_id: int
amount: int # amount_supplied
owner_address: Address


@dataclass
class DeleaWithdraw:
__tablename__ = "delea_withdraw"
__schema__ = "parsed"

tx_hash: str
msg_hash: str
trace_id: str
utime: int
successful: bool
query_id: int
amount: int # withdraw_amount_current
owner_address: Address
recipient_address: Address


@dataclass
class DeleaLiquidation:
__tablename__ = "delea_liquidation"
__schema__ = "parsed"

tx_hash: str
msg_hash: str
trace_id: str
utime: int
successful: bool
query_id: int
amount: int # liquidatable_amount
owner_address: Address
liquidator_address: Address

3 changes: 3 additions & 0 deletions parser/parsers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from parsers.message.dedust_swap import DedustSwap
from parsers.message.stonfi_swap import StonfiSwap
from parsers.message.evaa import EvaaSupplyParser, EvaaWithdrawAndLiquidationParser
from parsers.message.delea import DeleaDepositParser, DeleaWithdrawAndLiquidationParser
from parsers.message.jetton_mint import JettonMintParser, HipoTokensMinted
from parsers.nft_transfer.nft_history import NftHistoryParser
from parsers.jetton_wallets.jetton_wallet_balances import JettonWalletBalancesParser
Expand Down Expand Up @@ -46,6 +47,8 @@
EvaaWithdrawAndLiquidationParser(),
JettonMintParser(),
HipoTokensMinted(),
DeleaDepositParser(),
DeleaWithdrawAndLiquidationParser(),

PriceDiscovery(MIN_SWAP_VOLUME_FOR_PRICE),

Expand Down
137 changes: 137 additions & 0 deletions parser/parsers/message/delea.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
from loguru import logger
from pytoniq_core import Cell, Address
import traceback

from db import DB
from model.parser import Parser, TOPIC_MESSAGES
from model.delea import DeleaDeposit, DeleaLiquidation, DeleaWithdraw


DELEA_CONTRACTS = [
Parser.uf2raw("EQB6rkS8xt3Ey4XugdVqQDe1vt4KJDh813_k2ceoONTCBnyD"),
Parser.uf2raw("EQCwIIRKpuV9fQpQxdTMhLAO30MNHa6GOYd00TsySOOYtA9n"),
Parser.uf2raw("EQA2OzCuP8-d_lN2MYxLv5WCNfpLH1NUuugppOZBZgNYn-aa"),
Parser.uf2raw("EQA6Xba1d30QeSTVW7-cIAq-WHD9ZBFg90dQ7CB8mQ2Cxx25"),
Parser.uf2raw("EQADnjMkZBCS7-zKAPGHwFXGdd8b85m3bRDm52AX__ORLey-"),
]

DEPOSIT_TON_EVENT = Parser.opcode_signed(0x00bbdf19)
DEPOSIT_JETTON_EVENT = Parser.opcode_signed(0x7362d09c)
WITHDRAW_EVENT = Parser.opcode_signed(0x000a2c32)
LIQUIDATION_EVENT = Parser.opcode_signed(0x000a2c38)


class DeleaDepositParser(Parser):
def topics(self):
return [TOPIC_MESSAGES]

def predicate(self, obj) -> bool:
return (
obj.get("opcode", None) in [DEPOSIT_JETTON_EVENT, DEPOSIT_TON_EVENT]
and obj.get("direction", None) == "in"
and obj.get("destination", None) in DELEA_CONTRACTS
)

def handle_internal(self, obj, db: DB):
logger.info(f"Parsing Delea deposit message {Parser.require(obj.get('msg_hash', None))}")
cell = Parser.message_body(obj, db).begin_parse()
deposit_type = cell.load_uint(32) # 0x11a
amount = 0
query_id = 0
owner_address = Parser.require(obj.get("source", None))
try:
if deposit_type == DEPOSIT_TON_EVENT:
query_id = cell.load_uint(64)
amount = cell.load_coins()
elif deposit_type == DEPOSIT_JETTON_EVENT:
query_id = cell.load_uint(64)
amount = cell.load_coins()
owner_address = cell.load_address()
else :
logger.info(f"Skipping message with opcode {deposit_type}")
return
except Exception as e:
logger.error(f"Unable to parse deposit event {e}: {traceback.format_exc()}")
raise Exception(f"Unable to parse deposit event {e}: {traceback.format_exc()}")

event = DeleaDeposit(
tx_hash=Parser.require(obj.get("tx_hash", None)),
msg_hash=Parser.require(obj.get("msg_hash", None)),
trace_id=Parser.require(obj.get("trace_id", None)),
utime=Parser.require(obj.get("created_at", None)),
successful=Parser.require(db.is_tx_successful(Parser.require(obj.get("tx_hash", None)))),
query_id=query_id,
owner_address=owner_address,
amount=amount,
)
logger.info(f"Adding Delea deposit {event}")
db.serialize(event)


class DeleaWithdrawAndLiquidationParser(Parser):
def topics(self):
return [TOPIC_MESSAGES]

def predicate(self, obj) -> bool:
return (
obj.get("opcode", None) in [WITHDRAW_EVENT, LIQUIDATION_EVENT]
and obj.get("direction", None) == "in"
and obj.get("destination", None) in DELEA_CONTRACTS
)

def handle_internal(self, obj, db: DB):
cell = Parser.message_body(obj, db).begin_parse()
op = cell.load_uint(32)
event = None
if op == WITHDRAW_EVENT:
query_id = cell.load_uint(64)
amount = cell.load_coins()
cell.load_coins()
cell.load_coins()
cell.load_coins()
cell.load_uint(64)
owner_address = cell.load_address()
sc_1 = cell.load_ref().begin_parse()
recipient_address = sc_1.load_address()
event = DeleaWithdraw(
tx_hash=Parser.require(obj.get("tx_hash", None)),
msg_hash=Parser.require(obj.get("msg_hash", None)),
trace_id=Parser.require(obj.get("trace_id", None)),
utime=Parser.require(obj.get("created_at", None)),
successful=Parser.require(db.is_tx_successful(Parser.require(obj.get("tx_hash", None)))),
query_id=query_id,
owner_address=owner_address,
amount=amount,
recipient_address=recipient_address,
)
logger.info(f"Adding Delea withdraw {event}")
elif op == LIQUIDATION_EVENT:
query_id = cell.load_uint(64)
failed = cell.load_bool()
if failed:
logger.info(f"Delea liquidation is not successfull {Parser.require(obj.get('msg_hash', None))}")
return
amount = cell.load_coins()
cell.load_coins()
cell.load_coins()
cell.load_uint(64)
if cell.load_bool():
cell.load_address()
sc_1 = cell.load_ref().begin_parse()
liquidator_address = sc_1.loadAddress()
event = DeleaLiquidation(
tx_hash=Parser.require(obj.get("tx_hash", None)),
msg_hash=Parser.require(obj.get("msg_hash", None)),
trace_id=Parser.require(obj.get("trace_id", None)),
utime=Parser.require(obj.get("created_at", None)),
successful=Parser.require(db.is_tx_successful(Parser.require(obj.get("tx_hash", None)))),
query_id=query_id,
owner_address=owner_address,
amount=amount,
liquidator_address=liquidator_address,
)
logger.info(f"Adding Delea liquidation {event}")
if event is None :
logger.error(f"Unable to serialize event {Parser.require(obj.get('msg_hash', None))}: {traceback.format_exc()}")
raise Exception(f"Unable to serialize event {Parser.require(obj.get('msg_hash', None))}: {traceback.format_exc()}")
db.serialize(event)