Skip to content

Commit

Permalink
Merge pull request #221 from UnitapApp/refactor/relocate-chain-configs
Browse files Browse the repository at this point in the history
Move NetworkTypes to core
  • Loading branch information
ShayanShiravani authored Dec 16, 2023
2 parents 159ea0c + e2a7d22 commit 528357e
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 62 deletions.
31 changes: 10 additions & 21 deletions authentication/models.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from django.db import models
from django.contrib.auth.models import User
from authentication.helpers import BRIGHTID_SOULDBOUND_INTERFACE
from django.utils import timezone
from django.core.validators import RegexValidator
from django.core.cache import cache
from django.core.validators import RegexValidator
from django.db import models
from django.utils import timezone

from authentication.helpers import BRIGHTID_SOULDBOUND_INTERFACE
from core.models import NetworkTypes


class ProfileManager(models.Manager):
Expand Down Expand Up @@ -83,22 +85,6 @@ def user_count():
return count


class NetworkTypes:
EVM = "EVM"
SOLANA = "Solana"
LIGHTNING = "Lightning"
NONEVM = "NONEVM"
NONEVMXDC = "NONEVMXDC"

networks = (
(EVM, "EVM"),
(SOLANA, "Solana"),
(LIGHTNING, "Lightning"),
(NONEVM, "NONEVM"),
(NONEVMXDC, "NONEVMXDC"),
)


class Wallet(models.Model):
wallet_type = models.CharField(choices=NetworkTypes.networks, max_length=10)
user_profile = models.ForeignKey(
Expand All @@ -110,4 +96,7 @@ class Meta:
unique_together = (("wallet_type", "user_profile"),)

def __str__(self):
return f"{self.wallet_type} Wallet for profile with contextId {self.user_profile.initial_context_id}"
return (
f"{self.wallet_type} Wallet for profile with contextId "
f"{self.user_profile.initial_context_id}"
)
14 changes: 8 additions & 6 deletions core/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

from django.core.exceptions import ImproperlyConfigured

from authentication.models import UserProfile


class ConstraintParam(Enum):
CHAIN = "chain"
Expand All @@ -25,7 +23,7 @@ class ConstraintVerification(ABC):
_param_keys = []
__response_text = ""

def __init__(self, user_profile: UserProfile) -> None:
def __init__(self, user_profile) -> None:
self.user_profile = user_profile
self._param_values = {}

Expand Down Expand Up @@ -61,7 +59,9 @@ def is_valid_param_keys(cls, keys):

@property
def response(self) -> str:
return self.__response_text or f"{self.__class__.__name__} constraint is violated"
return (
self.__response_text or f"{self.__class__.__name__} constraint is violated"
)

@response.setter
def response(self, text: str):
Expand All @@ -81,7 +81,7 @@ def is_observed(self, *args, **kwargs):
class HasNFTVerification(ConstraintVerification):
_param_keys = [ConstraintParam.CHAIN, ConstraintParam.ADDRESS, ConstraintParam.ID]

def __init__(self, user_profile: UserProfile, response: str = None) -> None:
def __init__(self, user_profile, response: str = None) -> None:
super().__init__(user_profile, response)

def is_observed(self, *args, **kwargs):
Expand All @@ -98,4 +98,6 @@ def get_constraint(constraint_label: str) -> ConstraintVerification:
constraint_class = getattr(constraints_module, constraint_name)
return constraint_class
except (ModuleNotFoundError, AttributeError):
raise ImproperlyConfigured(f"Constraint '{constraint_name}' not found in any app.")
raise ImproperlyConfigured(
f"Constraint '{constraint_name}' not found in any app."
)
7 changes: 5 additions & 2 deletions faucet/faucet_manager/claim_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
from django.db import transaction
from django.utils import timezone

from authentication.models import NetworkTypes, UserProfile
from authentication.models import UserProfile
from core.models import NetworkTypes
from faucet.faucet_manager.credit_strategy import (
CreditStrategy,
CreditStrategyFactory,
Expand Down Expand Up @@ -36,7 +37,9 @@ def fund_manager(self):

def claim(self, amount, passive_address=None):
with transaction.atomic():
user_profile = UserProfile.objects.select_for_update().get(pk=self.credit_strategy.user_profile.pk)
user_profile = UserProfile.objects.select_for_update().get(
pk=self.credit_strategy.user_profile.pk
)
self.assert_pre_claim_conditions(amount, user_profile)
return self.create_pending_claim_receipt(
amount, passive_address
Expand Down
4 changes: 2 additions & 2 deletions faucet/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
from solders.keypair import Keypair
from solders.pubkey import Pubkey

from authentication.models import NetworkTypes, UserProfile
from authentication.models import UserProfile
from brightIDfaucet.settings import BRIGHT_ID_INTERFACE
from core.models import BigNumField
from core.models import BigNumField, NetworkTypes
from faucet.faucet_manager.lnpay_client import LNPayClient


Expand Down
89 changes: 66 additions & 23 deletions faucet/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
from django.utils import timezone
from sentry_sdk import capture_exception

from authentication.models import NetworkTypes, Wallet
from core.models import TokenPrice
from authentication.models import Wallet
from core.models import NetworkTypes, TokenPrice
from core.utils import Web3Utils
from tokenTap.models import TokenDistributionClaim

Expand Down Expand Up @@ -46,7 +46,9 @@ def memcache_lock(lock_id, oid, lock_expire=60):


def has_pending_batch(chain):
return TransactionBatch.objects.filter(chain=chain, _status=ClaimReceipt.PENDING).exists()
return TransactionBatch.objects.filter(
chain=chain, _status=ClaimReceipt.PENDING
).exists()


def passive_address_is_not_none(address):
Expand Down Expand Up @@ -101,10 +103,16 @@ def process_batch(self, batch_pk):
manager = SolanaFundManager(batch.chain)
elif batch.chain.chain_type == NetworkTypes.LIGHTNING:
manager = LightningFundManager(batch.chain)
elif batch.chain.chain_type == NetworkTypes.EVM or batch.chain.chain_type == NetworkTypes.NONEVMXDC:
elif (
batch.chain.chain_type == NetworkTypes.EVM
or batch.chain.chain_type == NetworkTypes.NONEVMXDC
):
manager = EVMFundManager(batch.chain)
else:
raise Exception(f"Invalid chain type to process batch, chain type {batch.chain.chain_type}")
raise Exception(
"Invalid chain type to process batch, chain type "
f"{batch.chain.chain_type}"
)
tx_hash = manager.multi_transfer(data)
batch.tx_hash = tx_hash
batch.save()
Expand All @@ -123,7 +131,9 @@ def process_batch(self, batch_pk):

@shared_task
def process_pending_batches():
batches = TransactionBatch.objects.filter(_status=ClaimReceipt.PENDING, tx_hash=None)
batches = TransactionBatch.objects.filter(
_status=ClaimReceipt.PENDING, tx_hash=None
)
for _batch in batches:
process_batch.delay(_batch.pk)

Expand All @@ -148,10 +158,16 @@ def update_pending_batch_with_tx_hash(self, batch_pk):
manager = SolanaFundManager(batch.chain)
elif batch.chain.chain_type == NetworkTypes.LIGHTNING:
manager = LightningFundManager(batch.chain)
elif batch.chain.chain_type == NetworkTypes.EVM or batch.chain.chain_type == NetworkTypes.NONEVMXDC:
elif (
batch.chain.chain_type == NetworkTypes.EVM
or batch.chain.chain_type == NetworkTypes.NONEVMXDC
):
manager = EVMFundManager(batch.chain)
else:
raise Exception(f"Invalid chain type to update pending batch, chain type {batch.chain.chain_type}")
raise Exception(
"Invalid chain type to update pending batch, chain type "
f"{batch.chain.chain_type}"
)

if manager.is_tx_verified(batch.tx_hash):
batch._status = ClaimReceipt.VERIFIED
Expand All @@ -174,14 +190,17 @@ def reject_expired_pending_claims():
ClaimReceipt.objects.filter(
batch=None,
_status=ClaimReceipt.PENDING,
datetime__lte=timezone.now() - timezone.timedelta(minutes=ClaimReceipt.MAX_PENDING_DURATION),
datetime__lte=timezone.now()
- timezone.timedelta(minutes=ClaimReceipt.MAX_PENDING_DURATION),
).update(_status=ClaimReceipt.REJECTED)


@shared_task
def update_pending_batches_with_tx_hash_status():
batches_queryset = (
TransactionBatch.objects.filter(_status=ClaimReceipt.PENDING).exclude(tx_hash=None).exclude(updating=True)
TransactionBatch.objects.filter(_status=ClaimReceipt.PENDING)
.exclude(tx_hash=None)
.exclude(updating=True)
)
for _batch in batches_queryset:
update_pending_batch_with_tx_hash.delay(_batch.pk)
Expand All @@ -190,15 +209,19 @@ def update_pending_batches_with_tx_hash_status():
@shared_task
def process_chain_pending_claims(chain_id): # locks chain
with transaction.atomic():
chain = Chain.objects.select_for_update().get(pk=chain_id) # lock based on chain
chain = Chain.objects.select_for_update().get(
pk=chain_id
) # lock based on chain

# all pending batches must be resolved before new transactions can be made
if has_pending_batch(chain):
return

# get all pending receipts for this chain
# pending receipts are receipts that have not been batched yet
receipts = ClaimReceipt.objects.filter(chain=chain, _status=ClaimReceipt.PENDING, batch=None)
receipts = ClaimReceipt.objects.filter(
chain=chain, _status=ClaimReceipt.PENDING, batch=None
)

if receipts.count() == 0:
return
Expand Down Expand Up @@ -334,30 +357,39 @@ def update_tokens_price():
update token.usd_price for all TokenPrice records in DB
"""

# TODO: we can make this function performance better by using aiohttp and asyncio or Threads
# TODO: we can make this function performance better
# by using aiohttp and asyncio or Threads
tokens = TokenPrice.objects.exclude(price_url__isnull=True).exclude(price_url="")
res_gen = map(lambda token: (token, requests.get(token.price_url, timeout=5)), tokens)
res_gen = map(
lambda token: (token, requests.get(token.price_url, timeout=5)), tokens
)

def parse_request(token: TokenPrice, request_res: requests.Response):
try:
request_res.raise_for_status()
json_data = request_res.json()
token.usd_price = json_data["data"]["rates"]["USD"]
# TODO: save all change when this function ended for all url done for better performance
# TODO: save all change when this function ended for
# all url done for better performance
token.save()
except requests.HTTPError as e:
logging.exception(
f"requests for url: {request_res.url} can not fetched with status_code: {request_res.status_code}. \
f"requests for url: {request_res.url} can not fetched with "
f"status_code: {request_res.status_code}. \
{str(e)}"
)

except KeyError as e:
logging.exception(
f"requests for url: {request_res.url} data do not have property keys for loading data. {str(e)}"
f"requests for url: {request_res.url} data do not have property "
f"keys for loading data. {str(e)}"
)

except Exception as e:
logging.exception(f"requests for url: {request_res.url} got error {type(e).__name__}. {str(e)}")
logging.exception(
f"requests for url: {request_res.url} got error "
f"{type(e).__name__}. {str(e)}"
)

[parse_request(*res) for res in res_gen]

Expand All @@ -383,18 +415,27 @@ def process_donation_receipt(self, donation_receipt_pk):
).values_list("lower_address", flat=True):
donation_receipt.delete()
return
if Web3Utils.to_checksum_address(tx.get("to")) != evm_fund_manager.get_fund_manager_checksum_address():
if (
Web3Utils.to_checksum_address(tx.get("to"))
!= evm_fund_manager.get_fund_manager_checksum_address()
):
donation_receipt.delete()
return
donation_receipt.value = str(evm_fund_manager.from_wei(tx.get("value")))
if donation_receipt.chain.is_testnet is False:
try:
token_price = TokenPrice.objects.get(symbol=donation_receipt.chain.symbol)
token_price = TokenPrice.objects.get(
symbol=donation_receipt.chain.symbol
)
donation_receipt.total_price = str(
decimal.Decimal(donation_receipt.value) * decimal.Decimal(token_price.usd_price)
decimal.Decimal(donation_receipt.value)
* decimal.Decimal(token_price.usd_price)
)
except TokenPrice.DoesNotExist:
logging.error(f"TokenPrice for Chain: {donation_receipt.chain.chain_name} did not defined")
logging.error(
f"TokenPrice for Chain: {donation_receipt.chain.chain_name} "
"did not defined"
)
donation_receipt.status = ClaimReceipt.REJECTED
donation_receipt.save()
return
Expand All @@ -412,6 +453,8 @@ def update_donation_receipt_pending_status():
"""
update status of pending donation receipt
"""
pending_donation_receipts = DonationReceipt.objects.filter(status=ClaimReceipt.PENDING)
pending_donation_receipts = DonationReceipt.objects.filter(
status=ClaimReceipt.PENDING
)
for pending_donation_receipt in pending_donation_receipts:
process_donation_receipt.delay(pending_donation_receipt.pk)
4 changes: 2 additions & 2 deletions prizetap/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from authentication.models import NetworkTypes, UserProfile
from core.models import BigNumField, Chain, UserConstraint
from authentication.models import UserProfile
from core.models import BigNumField, Chain, NetworkTypes, UserConstraint
from faucet.constraints import OptimismClaimingGasConstraint, OptimismDonationConstraint

from .constraints import HaveUnitapPass, NotHaveUnitapPass
Expand Down
3 changes: 1 addition & 2 deletions tokenTap/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
from eth_account.messages import encode_defunct
from web3 import Account, Web3

from authentication.models import NetworkTypes
from core.models import WalletAccount
from core.models import NetworkTypes, WalletAccount
from faucet.faucet_manager.credit_strategy import RoundCreditStrategy
from faucet.models import GlobalSettings

Expand Down
4 changes: 2 additions & 2 deletions tokenTap/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
from django.db import models
from django.utils import timezone

from authentication.models import NetworkTypes, UserProfile
from core.models import Chain, UserConstraint
from authentication.models import UserProfile
from core.models import Chain, NetworkTypes, UserConstraint
from faucet.constraints import OptimismHasClaimedGasInThisRound
from faucet.models import ClaimReceipt

Expand Down
4 changes: 2 additions & 2 deletions tokenTap/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from django.utils import timezone
from rest_framework.test import APITestCase, override_settings

from authentication.models import NetworkTypes, UserProfile, Wallet
from core.models import Chain, WalletAccount
from authentication.models import UserProfile, Wallet
from core.models import Chain, NetworkTypes, WalletAccount
from faucet.models import Chain as FaucetChain
from faucet.models import ClaimReceipt, GlobalSettings, TransactionBatch
from faucet.models import WalletAccount as FaucetWalletAccount
Expand Down

0 comments on commit 528357e

Please sign in to comment.