Skip to content

Commit

Permalink
Merge pull request #202 from UnitapApp/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
Mohamad Bastin authored Nov 30, 2023
2 parents 0300cd2 + e5c27bb commit 6bc7d8d
Show file tree
Hide file tree
Showing 39 changed files with 926 additions and 287 deletions.
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,14 @@ docker-build-dev:
docker-up-dev:
docker-compose up -d --force-recreate --build

docker-up-dev-log:
docker-compose up --force-recreate --build

docker-down-dev:
docker-compose down

docker-coverage-report:
docker-compose exec -i backend bash -c "coverage run manage.py test; coverage report"

docker-coverage-report-no-i:
docker-compose exec backend bash -c "coverage run manage.py test; coverage report"
4 changes: 0 additions & 4 deletions authentication/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
from rest_framework.authtoken.models import Token

from authentication.models import UserProfile, Wallet
from faucet.faucet_manager.claim_manager import LimitedChainClaimManager
from faucet.models import GlobalSettings


class UsernameRequestSerializer(serializers.Serializer):
Expand Down Expand Up @@ -88,8 +86,6 @@ class Meta:
fields = [
"pk",
"username",
"is_meet_verified",
"is_aura_verified",
"wallets",
]

Expand Down
1 change: 1 addition & 0 deletions brightIDfaucet/celery.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"set-raffle-random-words": {"task": "prizetap.tasks.set_raffle_random_words", "schedule": 120},
"set-raffle-winners": {"task": "prizetap.tasks.set_raffle_winners", "schedule": 300},
"get-raffle-winners": {"task": "prizetap.tasks.get_raffle_winners", "schedule": 300},
"set-raffle-ids": {"task": "prizetap.tasks.set_raffle_ids", "schedule": 300},
}

# Load task modules from all registered Django apps.
Expand Down
24 changes: 4 additions & 20 deletions core/admin.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,15 @@
from django.contrib import admin

from .models import TokenPrice


class UserConstraintBaseAdmin(admin.ModelAdmin):
fields = [
'name',
'title',
'type',
'description',
'response',
"icon_url"
]
list_display = [
"pk",
"name",
"description"
]
fields = ["name", "title", "type", "description", "explanation", "response", "icon_url"]
list_display = ["pk", "name", "description"]


class TokenPriceAdmin(admin.ModelAdmin):
list_display = [
'symbol',
'usd_price',
'price_url',
'datetime',
'last_updated'
]
list_display = ["symbol", "usd_price", "price_url", "datetime", "last_updated"]
list_filter = ["symbol"]


Expand Down
57 changes: 35 additions & 22 deletions core/constraints.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
import copy
from enum import Enum
import importlib
from abc import ABC, abstractmethod
from enum import Enum

from django.core.exceptions import ImproperlyConfigured

from authentication.models import UserProfile


class ConstraintParam(Enum):
CHAIN='chain'
ADDRESS='address'
ID='id'
USERNAME='username'
FROM_DATE='from_date'
TO_DATE='to_date'
CHAIN = "chain"
ADDRESS = "address"
ID = "id"
USERNAME = "username"
FROM_DATE = "from_date"
TO_DATE = "to_date"

@classmethod
def choices(cls):
return [(key.value, key.name) for key in cls]


class ConstraintVerification(ABC):
_param_keys = []
__response_text = ""
def __init__(self, user_profile:UserProfile) -> None:

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

Expand All @@ -30,11 +36,11 @@ def is_observed(self, *args, **kwargs) -> bool:
@classmethod
def param_keys(cls) -> list:
return cls._param_keys

@property
def param_values(self):
return self._param_values

@param_values.setter
def param_values(self, values: dict):
self.is_valid_param_keys(values.keys())
Expand All @@ -56,7 +62,7 @@ def is_valid_param_keys(cls, keys):
@property
def response(self) -> str:
return self.__response_text or f"{self.__class__.__name__} constraint is violated"

@response.setter
def response(self, text: str):
self.__response_text = text
Expand All @@ -70,19 +76,26 @@ def is_observed(self, *args, **kwargs):
class BrightIDAuraVerification(ConstraintVerification):
def is_observed(self, *args, **kwargs):
return self.user_profile.is_aura_verified



class HasNFTVerification(ConstraintVerification):
_param_keys = [
ConstraintParam.CHAIN,
ConstraintParam.ADDRESS,
ConstraintParam.ID
]
_param_keys = [ConstraintParam.CHAIN, ConstraintParam.ADDRESS, ConstraintParam.ID]

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

def is_observed(self, *args, **kwargs):
chain_id = self._param_values[ConstraintParam.CHAIN]
collection = self._param_values[ConstraintParam.ADDRESS]
nft_id = self._param_values[ConstraintParam.ID]

self.chain_id = self._param_values[ConstraintParam.CHAIN]
self.collection = self._param_values[ConstraintParam.ADDRESS]
self.nft_id = self._param_values[ConstraintParam.ID]


def get_constraint(constraint_label: str) -> ConstraintVerification:
app_name, constraint_name = constraint_label.split(".")
constraints_module_name = f"{app_name}.constraints"
try:
constraints_module = importlib.import_module(constraints_module_name)
constraint_class = getattr(constraints_module, constraint_name)
return constraint_class
except (ModuleNotFoundError, AttributeError):
raise ImproperlyConfigured(f"Constraint '{constraint_name}' not found in any app.")
7 changes: 5 additions & 2 deletions core/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import inspect

from django.db import models
from django.utils.translation import gettext_lazy as _

Expand All @@ -17,11 +19,12 @@ class Type(models.TextChoices):
name = models.CharField(
max_length=255,
unique=True,
choices=[(c.__name__, c.__name__) for c in constraints],
choices=[(f'{inspect.getmodule(c).__name__.split(".")[0]}.{c.__name__}', c.__name__) for c in constraints],
)
title = models.CharField(max_length=255)
type = models.CharField(max_length=10, choices=Type.choices, default=Type.VERIFICATION)
description = models.TextField(null=True, blank=True)
explanation = models.TextField(null=True, blank=True)
response = models.TextField(null=True, blank=True)
icon_url = models.CharField(max_length=255, null=True, blank=True)

Expand All @@ -33,7 +36,7 @@ def create_name_field(cls, constraints):
return models.CharField(
max_length=255,
unique=True,
choices=[(c.__name__, c.__name__) for c in constraints],
choices=[(f'{inspect.getmodule(c).__name__.split(".")[0]}.{c.__name__}', c.__name__) for c in constraints],
)


Expand Down
28 changes: 11 additions & 17 deletions core/serializers.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,35 @@
from rest_framework import serializers
from .constraints import *

from core.constraints import ConstraintVerification, get_constraint

from .models import UserConstraint


class UserConstraintBaseSerializer(serializers.Serializer):
pk = serializers.IntegerField()
name = serializers.CharField()
title = serializers.CharField()
type = serializers.ChoiceField(
choices=UserConstraint.Type.choices
)
type = serializers.ChoiceField(choices=UserConstraint.Type.choices)
description = serializers.CharField()
explanation = serializers.CharField()
response = serializers.CharField()
icon_url = serializers.CharField()
params = serializers.SerializerMethodField()

class Meta:
fields = [
"pk",
"name",
"title",
"type",
"description",
"response",
"icon_url",
"params"
]
fields = ["pk", "name", "title", "type", "description", "explanation", "response", "icon_url", "params"]
read_only_fields = [
"pk",
"name",
"title",
"type",
"description",
"explanation",
"response",
"icon_url",
"params"
"params",
]

def get_params(self, constraint: UserConstraint):
c_class: ConstraintVerification = eval(constraint.name)
return [p.name for p in c_class.param_keys()]
c_class: ConstraintVerification = get_constraint(constraint.name)
return [p.name for p in c_class.param_keys()]
37 changes: 33 additions & 4 deletions core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pytz
from web3 import Web3
from web3.contract.contract import Contract, ContractFunction
from web3.logs import DISCARD, IGNORE, STRICT, WARN
from web3.middleware import geth_poa_middleware
from web3.types import TxParams, Type

Expand Down Expand Up @@ -58,6 +59,11 @@ def get_first_day_of_last_month():


class Web3Utils:
LOG_STRICT = STRICT
LOG_IGNORE = IGNORE
LOG_DISCARD = DISCARD
LOG_WARN = WARN

def __init__(self, rpc_url, poa=False) -> None:
self._rpc_url = rpc_url
self._w3 = None
Expand Down Expand Up @@ -97,8 +103,12 @@ def contract(self) -> Type[Contract]:
def set_contract(self, address, abi):
self._contract = self.w3.eth.contract(address=address, abi=abi)

def contract_txn(self, func: Type[ContractFunction]):
signed_tx = self.build_contract_txn(func)
def get_contract_function(self, func_name: str):
func = getattr(self.contract.functions, func_name)
return func

def contract_txn(self, func: Type[ContractFunction], **kwargs):
signed_tx = self.build_contract_txn(func, **kwargs)
txn_hash = self.send_raw_tx(signed_tx)
return txn_hash.hex()

Expand All @@ -107,9 +117,12 @@ def contract_call(self, func: Type[ContractFunction], from_address=None):
return func.call({"from": from_address})
return func.call()

def build_contract_txn(self, func: Type[ContractFunction]):
def get_gas_estimate(self, func: Type[ContractFunction]):
return func.estimate_gas({"from": self.account.address})

def build_contract_txn(self, func: Type[ContractFunction], **kwargs):
nonce = self.w3.eth.get_transaction_count(self.account.address)
tx_data = func.build_transaction({"from": self.account.address, "nonce": nonce})
tx_data = func.build_transaction({"from": self.account.address, "nonce": nonce, **kwargs})
return self.sign_tx(tx_data)

def sign_tx(self, tx_data: TxParams):
Expand All @@ -126,3 +139,19 @@ def current_block(self):

def get_transaction_by_hash(self, hash):
return self.w3.eth.get_transaction(hash)

def get_gas_price(self):
return self.w3.eth.gas_price

def from_wei(self, value: int, unit: str = "ether"):
return self.w3.from_wei(value, unit)

@staticmethod
def to_checksum_address(address: str):
return Web3.to_checksum_address(address.lower())

def get_transaction_receipt(self, hash):
return self.w3.eth.get_transaction_receipt(hash)

def get_balance(self, address):
self.w3.eth.get_balance(address)
2 changes: 1 addition & 1 deletion faucet/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def is_observed(self, *args, **kwargs):
return (
DonationReceipt.objects.filter(chain__pk=chain_pk)
.filter(user_profile=self.user_profile)
.filter(status=ClaimReceipt.PROCESSED_FOR_TOKENTAP)
.filter(status=ClaimReceipt.VERIFIED)
.exists()
)

Expand Down
Loading

0 comments on commit 6bc7d8d

Please sign in to comment.