From 351e6e5f37c349474e15f48ac35d542ff95904eb Mon Sep 17 00:00:00 2001 From: rolandpo Date: Tue, 11 Jul 2023 19:26:00 +0200 Subject: [PATCH 1/3] add wousd/woeth history endpoints --- eagleproject/core/blockchain/addresses.py | 2 + .../blockchain/harvest/transaction_history.py | 43 +++++++++++++------ .../core/blockchain/harvest/transactions.py | 18 ++++++-- eagleproject/core/models.py | 2 + 4 files changed, 49 insertions(+), 16 deletions(-) diff --git a/eagleproject/core/blockchain/addresses.py b/eagleproject/core/blockchain/addresses.py index ca464f9..b65c62f 100644 --- a/eagleproject/core/blockchain/addresses.py +++ b/eagleproject/core/blockchain/addresses.py @@ -53,6 +53,7 @@ GOVERNORV2 = "0x830622bdd79cc677ee6594e20bbda5b26568b781" GOVERNORV3 = "0x72426ba137dec62657306b12b1e869d43fec6ec7" OUSD = "0x2a8e1e676ec238d8a992307b495b45b3feaa5e86" +WOUSD = "0xd2af830e8cbdfed6cc11bab697bb25496ed6fa62" TIMELOCK = "0x52bebd3d7f37ec4284853fd5861ae71253a7f428" COMPENSATION_CLAIMS = "0x9c94df9d594ba1eb94430c006c269c314b1a8281" GOVERNANCE = "0x3cdd07c16614059e66344a7b579dab4f9516c0b6" @@ -81,6 +82,7 @@ # OETH OETH = "0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3" +WOETH = "0xdcee70654261af21c44c093c300ed3bb97b78192" OETH_ZAPPER = "0x8c135f50c7317a93cc95bb208a494e5ade5b66b0" OETH_ETH_AMO_METAPOOL = "0x94b17476a93b3262d87b9a326965d1e91f9c13e7" OETH_CURVE_AMO_REWARDS_POOL = "0x24b65DC1cf053A8D96872c323d29e86ec43eB33A" diff --git a/eagleproject/core/blockchain/harvest/transaction_history.py b/eagleproject/core/blockchain/harvest/transaction_history.py index a14e4bd..c5d6fbc 100644 --- a/eagleproject/core/blockchain/harvest/transaction_history.py +++ b/eagleproject/core/blockchain/harvest/transaction_history.py @@ -91,6 +91,8 @@ VEOGV, OUSD, OETH, + WOUSD, + WOETH, OETH_ETH_AMO_METAPOOL, OETH_ETH_AMO_CURVE_GUAGE, ) @@ -1122,7 +1124,7 @@ def process_transaction(transaction): for log in logs: if log.topic_0 == TRANSFER: transfer_log_count += 1 - is_origin_token = (log.address == OUSD and project == OriginTokens.OUSD) or (log.address == OETH and project == OriginTokens.OETH) + is_origin_token = (log.address == OUSD and project == OriginTokens.OUSD) or (log.address == OETH and project == OriginTokens.OETH) or (log.address == WOUSD and project == OriginTokens.WOUSD) or (log.address == WOETH and project == OriginTokens.WOETH) from_address = "0x" + log.topic_1[-40:] to_address = "0x" + log.topic_2[-40:] @@ -1157,9 +1159,23 @@ def process_transaction(transaction): classification = 'unknown_transfer' if swap_receive_origin_token: - classification = 'swap_gain_ousd' if project == OriginTokens.OUSD else 'swap_gain_oeth' + if project == OriginTokens.WOUSD: + classification = 'swap_gain_wousd' + elif project == OriginTokens.WOETH: + classification = 'swap_gain_woeth' + elif project == OriginTokens.OUSD: + classification = 'swap_gain_ousd' + else: + classification = 'swap_gain_oeth' elif swap_send_origin_token: - classification = 'swap_give_ousd' if project == OriginTokens.OUSD else 'swap_give_oeth' + if project == OriginTokens.WOUSD: + classification = 'swap_give_wousd' + elif project == OriginTokens.WOETH: + classification = 'swap_give_woeth' + elif project == OriginTokens.OUSD: + classification = 'swap_give_ousd' + else: + classification = 'swap_give_oeth' analyzed_transaction_hashes.append(transaction.tx_hash) analyzed_transactions.append(transaction_analysis( @@ -1317,6 +1333,8 @@ def get_history_for_address(address, transaction_filter, project=OriginTokens.OU if transaction_filter != None: transaction_filter = transaction_filter.replace('swap_ousd', 'swap_gain_ousd swap_give_ousd') transaction_filter = transaction_filter.replace('swap_oeth', 'swap_gain_oeth swap_give_oeth') + transaction_filter = transaction_filter.replace('swap_wousd', 'swap_gain_wousd swap_give_wousd') + transaction_filter = transaction_filter.replace('swap_woeth', 'swap_gain_woeth swap_give_woeth') tx_history_filtered = [] # find last non rebase transaction, and remove later transactions @@ -1328,15 +1346,16 @@ def get_history_for_address(address, transaction_filter, project=OriginTokens.OU for i in range(0, (last_non_yield_tx_idx + 1) if last_non_yield_tx_idx != -1 else 1, 1): if isinstance(tx_history[i], rebase_log): - if transaction_filter == None or 'yield' in transaction_filter: - tx_history_filtered.append({ - 'block_number': tx_history[i].block_number, - 'time': tx_history[i].block_time, - 'balance': "{:.18f}".format(float(tx_history[i].balance)), - 'tx_hash': tx_history[i].tx_hash, - 'amount': "{:.18f}".format(float(tx_history[i].amount)), - 'type': 'yield' - }) + if project != 'wousd' and project != 'woeth': + if transaction_filter == None or 'yield' in transaction_filter: + tx_history_filtered.append({ + 'block_number': tx_history[i].block_number, + 'time': tx_history[i].block_time, + 'balance': "{:.18f}".format(float(tx_history[i].balance)), + 'tx_hash': tx_history[i].tx_hash, + 'amount': "{:.18f}".format(float(tx_history[i].amount)), + 'type': 'yield' + }) else: tx_hash = tx_history[i].tx_hash.tx_hash tx_classification = hash_to_classification[tx_hash] if tx_hash in hash_to_classification else 'unknown_transaction_not_found' diff --git a/eagleproject/core/blockchain/harvest/transactions.py b/eagleproject/core/blockchain/harvest/transactions.py index f04faa5..de3765c 100644 --- a/eagleproject/core/blockchain/harvest/transactions.py +++ b/eagleproject/core/blockchain/harvest/transactions.py @@ -16,8 +16,10 @@ OGN_STAKING, STORY_STAKING_SERIES, STORY_STAKING_SEASONS, + OUSD, OETH, - OUSD + WOUSD, + WOETH, ) from core.blockchain.const import ( E_18, @@ -113,10 +115,18 @@ def maybe_store_transfer_record(log, block): return None # Must be on OUSD - if log["address"] != OUSD and log["address"] != OETH: + if log["address"] != OUSD and log["address"] != OETH and log["address"] != WOUSD and log["address"] != WOETH: return None - project = OriginTokens.OUSD if log["address"] == OUSD else OriginTokens.OETH + if log["address"] == WOUSD: + project = OriginTokens.WOUSD + elif log["address"] == WOETH: + project = OriginTokens.WOETH + elif log["address"] == OUSD: + project = OriginTokens.OUSD + else: + project = OriginTokens.OETH + tx_hash = log["transactionHash"] log_index = int(log["logIndex"], 16) @@ -166,7 +176,7 @@ def get_earliest_rebase_block_number(block_number, project): address=address, ).order_by('block_number').first() - return rebase_log.block_number if rebase_log.block_number > block_number else block_number + return rebase_log.block_number if rebase_log and rebase_log.block_number > block_number else block_number # get rebasing credits per token log at block number def get_rebasing_credits_per_token(block_number, project): diff --git a/eagleproject/core/models.py b/eagleproject/core/models.py index 5c827d5..c3c3029 100644 --- a/eagleproject/core/models.py +++ b/eagleproject/core/models.py @@ -16,6 +16,8 @@ class OriginTokens(models.TextChoices): OUSD = "ousd", "ousd" OETH = "oeth", "oeth" + WOUSD = "wousd", "wousd" + WOETH = "woeth", "woeth" class AssetBlock(models.Model): symbol = models.CharField(max_length=8, db_index=True) From 088362d031cf15589c856507d728825b69c249b5 Mon Sep 17 00:00:00 2001 From: rolandpo Date: Tue, 8 Aug 2023 15:37:09 +0200 Subject: [PATCH 2/3] error handling --- .../blockchain/harvest/transaction_history.py | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/eagleproject/core/blockchain/harvest/transaction_history.py b/eagleproject/core/blockchain/harvest/transaction_history.py index c5d6fbc..ddcf484 100644 --- a/eagleproject/core/blockchain/harvest/transaction_history.py +++ b/eagleproject/core/blockchain/harvest/transaction_history.py @@ -1159,23 +1159,27 @@ def process_transaction(transaction): classification = 'unknown_transfer' if swap_receive_origin_token: - if project == OriginTokens.WOUSD: + if project == OriginTokens.OUSD: + classification = 'swap_gain_ousd' + elif project == OriginTokens.OETH: + classification = 'swap_gain_oeth' + elif project == OriginTokens.WOUSD: classification = 'swap_gain_wousd' elif project == OriginTokens.WOETH: classification = 'swap_gain_woeth' - elif project == OriginTokens.OUSD: - classification = 'swap_gain_ousd' else: - classification = 'swap_gain_oeth' + raise Exception('Unexpected project id', project) elif swap_send_origin_token: - if project == OriginTokens.WOUSD: + if project == OriginTokens.OUSD: + classification = 'swap_give_ousd' + elif project == OriginTokens.OETH: + classification = 'swap_give_oeth' + elif project == OriginTokens.WOUSD: classification = 'swap_give_wousd' elif project == OriginTokens.WOETH: classification = 'swap_give_woeth' - elif project == OriginTokens.OUSD: - classification = 'swap_give_ousd' else: - classification = 'swap_give_oeth' + raise Exception('Unexpected project id', project) analyzed_transaction_hashes.append(transaction.tx_hash) analyzed_transactions.append(transaction_analysis( @@ -1346,7 +1350,7 @@ def get_history_for_address(address, transaction_filter, project=OriginTokens.OU for i in range(0, (last_non_yield_tx_idx + 1) if last_non_yield_tx_idx != -1 else 1, 1): if isinstance(tx_history[i], rebase_log): - if project != 'wousd' and project != 'woeth': + if project != OriginTokens.WOUSD and project != OriginTokens.WOETH: if transaction_filter == None or 'yield' in transaction_filter: tx_history_filtered.append({ 'block_number': tx_history[i].block_number, From 76e27baf06a08a0c30368556f6342abedb83ba9f Mon Sep 17 00:00:00 2001 From: Shahul Hameed <10547529+shahthepro@users.noreply.github.com> Date: Tue, 29 Aug 2023 18:34:48 +0400 Subject: [PATCH 3/3] Add Dripper endpoints --- eagleproject/core/blockchain/dripper.py | 62 +++++++++++++++++++++++++ eagleproject/core/blockchain/rpc.py | 19 ++++---- eagleproject/core/views.py | 11 +++++ eagleproject/eagleproject/urls.py | 1 + 4 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 eagleproject/core/blockchain/dripper.py diff --git a/eagleproject/core/blockchain/dripper.py b/eagleproject/core/blockchain/dripper.py new file mode 100644 index 0000000..1006828 --- /dev/null +++ b/eagleproject/core/blockchain/dripper.py @@ -0,0 +1,62 @@ +from datetime import datetime, timedelta + +from core.models import OriginTokens + +from core.blockchain.addresses import ( + DRIPPER, + OETH_DRIPPER, + USDT, + WETH, +) + +from core.blockchain.rpc import ( + balanceOf, + dripper_available, + dripper_drip_rate, +) + +LOCAL_DRIPPER_CACHE = { + OriginTokens.OUSD: None, + OriginTokens.OETH: None, +} + +def get_dripper_stats(project): + global LOCAL_DRIPPER_CACHE + + cached_data = LOCAL_DRIPPER_CACHE.get(project) + if cached_data is not None: + valid_until, stats = cached_data + if valid_until > datetime.today(): + return stats + + token = USDT if project == OriginTokens.OUSD else WETH + token_decimals = 6 if project == OriginTokens.OUSD else 18 + dripper_addr = DRIPPER if project == OriginTokens.OUSD else OETH_DRIPPER + + token_balance = balanceOf(token, dripper_addr, token_decimals) + collectable = dripper_available(project=project) + rate = dripper_drip_rate(project=project) + + rate_per_minute = rate * 60 + rate_per_hour = rate * 60 * 60 + rate_per_day = rate * 24 * 60 * 60 + + data = { + "token": token, + "drip_rate": rate, + "rate_per_minute": rate_per_minute, + "rate_per_hour": rate_per_hour, + "rate_per_day": rate_per_day, + "token_balance": token_balance, + "collectable": collectable, + "updated_at": datetime.today(), + } + + LOCAL_DRIPPER_CACHE[project] = [ + # Cache stuff for 30m + datetime.today() + timedelta(minutes=30), + data + ] + + return data + diff --git a/eagleproject/core/blockchain/rpc.py b/eagleproject/core/blockchain/rpc.py index 3891f7b..8e19ebb 100644 --- a/eagleproject/core/blockchain/rpc.py +++ b/eagleproject/core/blockchain/rpc.py @@ -466,20 +466,19 @@ def staking_durationRewardRate(address, duration, block="latest"): def dripper_available(block="latest", project=OriginTokens.OUSD): signature = SIG_DRIPPER_AVAILABLE_FUNDS[:10] + dripper_addr = OETH_DRIPPER if project == OriginTokens.OETH else DRIPPER + decimals = E_18 if project == OriginTokens.OETH else E_6 - if project == OriginTokens.OETH: - data = call(OETH_DRIPPER, signature, "", block) - return Decimal(int(data["result"], 16)) / E_18 - else: - data = call(DRIPPER, signature, "", block) - return Decimal(int(data["result"], 16)) / E_6 + data = call(dripper_addr, signature, "", block) + return Decimal(int(data["result"], 16)) / decimals - -def dripper_drip_rate(block="latest"): +def dripper_drip_rate(block="latest", project=OriginTokens.OUSD): signature = SIG_DRIPPER_CONFIG[:10] - data = call(DRIPPER, signature, "", block) - return Decimal(int(data["result"][64 + 2 :], 16)) / E_6 + dripper_addr = OETH_DRIPPER if project == OriginTokens.OETH else DRIPPER + decimals = E_18 if project == OriginTokens.OETH else E_6 + data = call(dripper_addr, signature, "", block) + return Decimal(int(data["result"][64 + 2 :], 16)) / decimals class AaveLendingPoolCore: """ LendingPoolCore calls """ diff --git a/eagleproject/core/views.py b/eagleproject/core/views.py index 66a594c..ee9e382 100644 --- a/eagleproject/core/views.py +++ b/eagleproject/core/views.py @@ -15,6 +15,7 @@ from django.db.models import Q from core.blockchain.addresses import ( DRIPPER, + OETH_DRIPPER, OUSD, OETH, USDT, @@ -69,6 +70,10 @@ OUSDMetaStrategy, ) +from core.blockchain.dripper import ( + get_dripper_stats +) + from core.channels.email import Email from core.coingecko import get_price from core.common import dict_append @@ -1180,3 +1185,9 @@ def coingecko_pools(request, project): safe=False, ), ) + +def api_dripper(request, project): + response = JsonResponse(get_dripper_stats(project)) + + response.setdefault("Access-Control-Allow-Origin", "*") + return _cache(60 * 30, response) diff --git a/eagleproject/eagleproject/urls.py b/eagleproject/eagleproject/urls.py index 9ae08fe..4dbfc15 100644 --- a/eagleproject/eagleproject/urls.py +++ b/eagleproject/eagleproject/urls.py @@ -82,6 +82,7 @@ path("api/v2//strategies", core_views.strategies), path("api/v2//collateral", core_views.collateral), path("api/v2//apr/trailing_history/", core_views.api_apr_trailing_history), + path("api/v2//dripper", core_views.api_dripper), # Deprecated v1 API endpoints (exists for backward compatibility) path("api/v1/apr/trailing", RedirectView.as_view(url="/api/v2/ousd/apr/trailing", permanent=True)),