Skip to content

Commit

Permalink
Merge pull request #148 from UnitapApp/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
Mohamad Bastin authored Oct 22, 2023
2 parents 36cfe7c + c9b2480 commit f8150e1
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 33 deletions.
81 changes: 58 additions & 23 deletions faucet/constraints.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import requests
from core.constraints import *
from core.utils import Web3Utils
from faucet.faucet_manager.credit_strategy import WeeklyCreditStrategy
from .models import DonationReceipt, Chain, ClaimReceipt


class DonationConstraint(ConstraintVerification):
_param_keys = [
ConstraintParam.CHAIN
]
_param_keys = [ConstraintParam.CHAIN]

def is_observed(self, *args, **kwargs):
chain_pk = self._param_values[ConstraintParam.CHAIN]
return DonationReceipt.objects\
.filter(chain__pk=chain_pk)\
.filter(user_profile = self.user_profile)\
.filter(status=ClaimReceipt.PROCESSED_FOR_TOKENTAP)\
.exists()

return (
DonationReceipt.objects.filter(chain__pk=chain_pk)
.filter(user_profile=self.user_profile)
.filter(status=ClaimReceipt.PROCESSED_FOR_TOKENTAP)
.exists()
)


class OptimismDonationConstraint(DonationConstraint):
_param_keys = []

Expand All @@ -27,39 +29,46 @@ def is_observed(self, *args, **kwargs):
self._param_values[ConstraintParam.CHAIN] = chain.pk
return super().is_observed(*args, **kwargs)


class EvmClaimingGasConstraint(ConstraintVerification):
_param_keys = [
ConstraintParam.CHAIN
]
_param_keys = [ConstraintParam.CHAIN]

def is_observed(self, *args, **kwargs):
chain_pk = self._param_values[ConstraintParam.CHAIN]
chain = Chain.objects.get(pk=chain_pk)
w3 = Web3Utils(chain.rpc_url_private, chain.poa)
current_block = w3.current_block()
user_address = self.user_profile.wallets.get(wallet_type=chain.chain_type).address
user_address = self.user_profile.wallets.get(
wallet_type=chain.chain_type
).address

first_internal_tx = requests.get(
f"{chain.explorer_api_url}/api?module=account&action=txlistinternal&address={user_address}&startblock=0&endblock={current_block}&page=1&offset=1&sort=asc&apikey={chain.explorer_api_key}"
)
first_internal_tx = first_internal_tx.json()
if first_internal_tx and first_internal_tx['status'] == '1':
first_internal_tx = first_internal_tx['result'][0]
if first_internal_tx and first_internal_tx['from'] == chain.fund_manager_address.lower()\
and first_internal_tx['isError'] == '0':
if first_internal_tx and first_internal_tx["status"] == "1":
first_internal_tx = first_internal_tx["result"][0]
if (
first_internal_tx
and first_internal_tx["from"] == chain.fund_manager_address.lower()
and first_internal_tx["isError"] == "0"
):
first_tx = requests.get(
f"{chain.explorer_api_url}/api?module=account&action=txlist&address={user_address}&startblock=0&endblock={current_block}&page=1&offset=1&sort=asc&apikey={chain.explorer_api_key}"
)
first_tx = first_tx.json()
if first_tx:
if not first_tx['result']:
if not first_tx["result"]:
return True
first_tx = first_tx['result'][0]
claiming_gas_tx = w3.get_transaction_by_hash(first_internal_tx['hash'])
web3_first_tx = w3.get_transaction_by_hash(first_tx['hash'])
return web3_first_tx['blockNumber'] > claiming_gas_tx['blockNumber']
first_tx = first_tx["result"][0]
claiming_gas_tx = w3.get_transaction_by_hash(
first_internal_tx["hash"]
)
web3_first_tx = w3.get_transaction_by_hash(first_tx["hash"])
return web3_first_tx["blockNumber"] > claiming_gas_tx["blockNumber"]
return False


class OptimismClaimingGasConstraint(EvmClaimingGasConstraint):
_param_keys = []

Expand All @@ -69,4 +78,30 @@ def is_observed(self, *args, **kwargs):
except:
return False
self._param_values[ConstraintParam.CHAIN] = chain.pk
return super().is_observed(*args, **kwargs)
return super().is_observed(*args, **kwargs)


class HasClaimedGasInThisRound(ConstraintVerification):
_param_keys = [ConstraintParam.CHAIN]

def is_observed(self, *args, **kwargs):
chain_pk = self._param_values[ConstraintParam.CHAIN]
chain = Chain.objects.get(pk=chain_pk)
return ClaimReceipt.objects.filter(
user_profile=self.user_profile,
chain=chain,
_status=ClaimReceipt.VERIFIED,
datetime__gte=WeeklyCreditStrategy.get_last_monday(),
).exists()


class OptimismHasClaimedGasInThisRound(HasClaimedGasInThisRound):
_param_keys = []

def is_observed(self, *args, **kwargs):
try:
chain = Chain.objects.get(chain_id=10)
except:
return False
self._param_values[ConstraintParam.CHAIN] = chain.pk
return super().is_observed(*args, **kwargs)
11 changes: 7 additions & 4 deletions tokenTap/constraints.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
from core.constraints import *
from core.utils import TimeUtils
from faucet.constraints import OptimismHasClaimedGasInThisRound
from faucet.models import ClaimReceipt



class OncePerWeekVerification(ConstraintVerification):
def is_observed(self, *args, **kwargs):
token_distribution = kwargs["token_distribution"]
token_distribution = kwargs["token_distribution"]
return not token_distribution.claims.filter(
user_profile=self.user_profile,
created_at__gte=TimeUtils.get_last_monday(),
).exists()



class OncePerMonthVerification(ConstraintVerification):
def is_observed(self, *args, **kwargs):
token_distribution = kwargs["token_distribution"]
Expand All @@ -25,4 +27,5 @@ def is_observed(self, *args, **kwargs):
token_distribution = kwargs["token_distribution"]
return not token_distribution.claims.filter(
user_profile=self.user_profile,
).exists()
status=ClaimReceipt.VERIFIED,
).exists()
2 changes: 2 additions & 0 deletions tokenTap/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.db import models
from authentication.models import NetworkTypes, UserProfile
from faucet.models import Chain, ClaimReceipt
from faucet.constraints import OptimismHasClaimedGasInThisRound
from core.models import UserConstraint
from .constraints import *
from django.core.cache import cache
Expand All @@ -12,6 +13,7 @@ class Constraint(UserConstraint):
OncePerWeekVerification,
OncePerMonthVerification,
OnceInALifeTimeVerification,
OptimismHasClaimedGasInThisRound,
]
name = UserConstraint.create_name_field(constraints)

Expand Down
3 changes: 1 addition & 2 deletions tokenTap/serializers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from faucet.serializers import SmallChainSerializer
from rest_framework import serializers
from core.serializers import UserConstraintBaseSerializer
from core.models import UserConstraint
from tokenTap.models import TokenDistribution, TokenDistributionClaim, Constraint
from tokenTap.models import *
from .constraints import *


Expand Down
5 changes: 5 additions & 0 deletions tokenTap/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@
TokenDistributionClaimStatusUpdateView.as_view(),
name="claim-update",
),
path(
"get-token-constraints/<int:td_id>/",
GetTokenDistributionConstraintsView.as_view(),
name="get-token-distribution-constraints",
),
]
60 changes: 56 additions & 4 deletions tokenTap/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import json
from django.shortcuts import get_object_or_404
import rest_framework.exceptions
from rest_framework.generics import CreateAPIView, RetrieveAPIView, ListAPIView
from rest_framework.response import Response
Expand All @@ -8,8 +10,10 @@
from authentication.serializers import MessageResponseSerializer
from faucet.models import Chain, ClaimReceipt, GlobalSettings
from permissions.models import Permission
from rest_framework.views import APIView
from tokenTap.models import TokenDistribution, TokenDistributionClaim
from tokenTap.serializers import (
ConstraintSerializer,
DetailResponseSerializer,
TokenDistributionClaimResponseSerializer,
TokenDistributionClaimSerializer,
Expand All @@ -32,14 +36,13 @@ class TokenDistributionListView(ListAPIView):
queryset = TokenDistribution.objects.filter(is_active=True)

def get_queryset(self):
q = TokenDistribution.objects.filter(is_active=True)
q = TokenDistribution.objects.filter(is_active=True)

sorted_queryset = sorted(
q, key=lambda obj: obj.total_claims_since_last_round, reverse=True
)

return sorted_queryset



class TokenDistributionClaimView(CreateAPIView):
Expand Down Expand Up @@ -99,11 +102,28 @@ def post(self, request, *args, **kwargs):

self.check_token_distribution_is_claimable(token_distribution)

self.check_user_weekly_credit(user_profile)
self.check_user_has_wallet(user_profile)

self.check_user_permissions(token_distribution, user_profile)

self.check_user_has_wallet(user_profile)
try:
tdc = TokenDistributionClaim.objects.get(
user_profile=user_profile,
token_distribution=token_distribution,
status=ClaimReceipt.PENDING,
)
return Response(
{
"detail": "Signature Was Already Created",
"signature": TokenDistributionClaimSerializer(tdc).data,
},
status=200,
)

except TokenDistributionClaim.DoesNotExist:
pass

self.check_user_weekly_credit(user_profile)

nonce = create_uint32_random_nonce()
if token_distribution.chain.chain_type == NetworkTypes.EVM:
Expand Down Expand Up @@ -148,6 +168,38 @@ def post(self, request, *args, **kwargs):
)


class GetTokenDistributionConstraintsView(APIView):
permission_classes = [IsAuthenticated]

def get(self, request, td_id):
user_profile = request.user.profile
td = get_object_or_404(TokenDistribution, pk=td_id)
try:
param_values = json.loads(td.constraint_params)
except:
param_values = {}

response_constraints = []

for c in td.permissions.all():
constraint: ConstraintVerification = eval(c.name)(user_profile)
constraint.response = c.response
try:
constraint.param_values = param_values[c.name]
except KeyError:
pass
is_verified = False
if constraint.is_observed(token_distribution=td):
is_verified = True
response_constraints.append(
{**ConstraintSerializer(c).data, "is_verified": is_verified}
)

return Response(
{"success": True, "constraints": response_constraints}, status=200
)


class TokenDistributionClaimStatusUpdateView(CreateAPIView):
permission_classes = [IsAuthenticated]

Expand Down

0 comments on commit f8150e1

Please sign in to comment.