Skip to content

Commit

Permalink
fetch usd prices for payouts
Browse files Browse the repository at this point in the history
  • Loading branch information
lachlanglen committed Jun 20, 2024
1 parent cbc8497 commit a5aab5d
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 1 deletion.
1 change: 1 addition & 0 deletions donations/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ async def fetch_usd_prices_async(self):

### Fetches USD prices for the Donation record and saves USD totals
def fetch_usd_prices(self):
# TODO: remove duplicate logic with PotPayout.fetch_usd_prices
# get existing values for stats adjustments later
existing_total_amount_usd = self.total_amount_usd
existing_net_amount_usd = self.net_amount_usd
Expand Down
12 changes: 12 additions & 0 deletions indexer_app/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,18 @@ def fetch_usd_prices():
)
jobs_logger.info(f"USD prices fetched for {donations_count} donations.")

# payouts
payouts = PotPayout.objects.filter(amount_paid_usd__isnull=True)
payouts_count = payouts.count()
jobs_logger.info(f"Fetching USD prices for {payouts_count} payouts...")
for payout in payouts:
try:
payout.fetch_usd_prices()
except Exception as e:
jobs_logger.error(f"Failed to fetch USD prices for payout {payout.id}: {e}")

jobs_logger.info(f"USD prices fetched for {payouts_count} payouts.")


@shared_task
def update_pot_statistics():
Expand Down
72 changes: 71 additions & 1 deletion pots/models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
from datetime import timedelta
from decimal import Decimal

import requests
from django.conf import settings
from django.db import models
from django.utils.translation import gettext_lazy as _

from accounts.models import Account
from tokens.models import Token
from base.logging import logger
from base.utils import format_date
from tokens.models import Token, TokenHistoricalPrice


class PotFactory(models.Model):
Expand Down Expand Up @@ -440,6 +447,69 @@ class PotPayout(models.Model):
help_text=_("Transaction hash."),
)

### Fetches USD prices for the Donation record and saves USD totals
def fetch_usd_prices(self):
# first, see if there is a TokenHistoricalPrice within 1 day (or HISTORICAL_PRICE_QUERY_HOURS) of self.paid_at
token = self.token
time_window = timedelta(hours=settings.HISTORICAL_PRICE_QUERY_HOURS or 24)
token_prices = TokenHistoricalPrice.objects.filter(
token=token,
timestamp__gte=self.paid_at - time_window,
timestamp__lte=self.paid_at + time_window,
)
existing_token_price = token_prices.first()
amount = token.format_price(self.amount)
if existing_token_price:
try:
price_usd = existing_token_price.price_usd
self.amount_paid_usd = amount * price_usd
self.save()
except Exception as e:
logger.error(
f"Failed to calculate and save USD prices for payout using existing TokenHistoricalPrice: {e}"
)
else:
# no existing price within acceptable time period; fetch from coingecko
try:
logger.info(
"No existing price within acceptable time period; fetching historical price..."
)
endpoint = f"{settings.COINGECKO_URL}/coins/{self.token.id.id}/history?date={format_date(self.paid_at)}&localization=false"
if settings.COINGECKO_API_KEY:
endpoint += f"&x_cg_pro_api_key={settings.COINGECKO_API_KEY}"
response = requests.get(endpoint)
logger.info(f"coingecko response: {response}")
if response.status_code == 429:
logger.warning("Coingecko rate limit exceeded")
price_data = response.json()
except Exception as e:
logger.warning(f"Failed to fetch coingecko price data: {e}")
logger.info(f"coingecko price data: {price_data}")
price_usd = (
price_data.get("market_data", {}).get("current_price", {}).get("usd")
)
logger.info(f"unit price: {price_usd}")
if price_usd:
try:
# convert price_usd to decimal
price_usd = Decimal(price_usd)
self.amount_paid_usd = amount * price_usd
self.save()
except Exception as e:
logger.error(
f"Failed to calculate and save USD prices using fetched price: {e}"
)
try:
TokenHistoricalPrice.objects.create(
token=token,
price_usd=price_usd,
timestamp=self.paid_at,
)
except Exception as e:
logger.warning(
f"Error creating TokenHistoricalPrice: {e} token: {token} price_usd: {price_usd}"
)


class PotPayoutChallenge(models.Model):
id = models.AutoField(
Expand Down

0 comments on commit a5aab5d

Please sign in to comment.