Skip to content

Commit

Permalink
Merge pull request #158 from UnitapApp/feature/gastap_dynamic_round_d…
Browse files Browse the repository at this point in the history
…uration

Feature/gastap dynamic round duration
  • Loading branch information
Mohamad Bastin authored Oct 27, 2023
2 parents da0a3c7 + f8e8752 commit 01e4cd4
Show file tree
Hide file tree
Showing 31 changed files with 862 additions and 729 deletions.
90 changes: 48 additions & 42 deletions core/utils.py
Original file line number Diff line number Diff line change
@@ -1,57 +1,64 @@
import datetime

import pytz
from time import time
from web3 import Web3
from web3.middleware import geth_poa_middleware
from web3.contract.contract import Contract, ContractFunction
from web3.types import Type, TxParams
from django.utils import timezone
from web3.middleware import geth_poa_middleware
from web3.types import TxParams, Type


class TimeUtils:
@staticmethod
def get_last_monday():
now = int(time())
day = 86400 # seconds in a day
week = 7 * day
weeks = now // week # number of weeks since epoch
monday = 345600 # first monday midnight
last_monday_midnight = monday + (weeks * week)

# last monday could be off by one week
if last_monday_midnight > now:
last_monday_midnight -= week

return timezone.make_aware(
datetime.datetime.fromtimestamp(last_monday_midnight)
)

@staticmethod
def get_second_last_monday():
now = int(time())
day = 86400 # seconds in a day
week = 7 * day
weeks = now // week # number of weeks since epoch
monday = 345600 # first monday midnight
last_monday_midnight = monday + (weeks * week)

# last monday could be off by one week
if last_monday_midnight > now:
last_monday_midnight -= week

return timezone.make_aware(
datetime.datetime.fromtimestamp(last_monday_midnight - week)
)
# @staticmethod
# def get_last_monday():
# now = int(time())
# day = 86400 # seconds in a day
# week = 7 * day
# weeks = now // week # number of weeks since epoch
# monday = 345600 # first monday midnight
# last_monday_midnight = monday + (weeks * week)

# # last monday could be off by one week
# if last_monday_midnight > now:
# last_monday_midnight -= week

# return timezone.make_aware(
# datetime.datetime.fromtimestamp(last_monday_midnight)
# )

# @staticmethod
# def get_second_last_monday():
# now = int(time())
# day = 86400 # seconds in a day
# week = 7 * day
# weeks = now // week # number of weeks since epoch
# monday = 345600 # first monday midnight
# last_monday_midnight = monday + (weeks * week)

# # last monday could be off by one week
# if last_monday_midnight > now:
# last_monday_midnight -= week

# return timezone.make_aware(
# datetime.datetime.fromtimestamp(last_monday_midnight - week)
# )

@staticmethod
def get_first_day_of_the_month():
now = datetime.datetime.now(pytz.timezone("UTC"))
first_day = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
return first_day

@staticmethod
def get_first_day_of_last_month():
now = datetime.datetime.now(pytz.timezone("UTC"))
first_day = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
last_month = first_day - datetime.timedelta(days=1)
first_day_of_last_month = last_month.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
return first_day_of_last_month


class Web3Utils:
def __init__(self, rpc_url, poa = False) -> None:
def __init__(self, rpc_url, poa=False) -> None:
self._rpc_url = rpc_url
self._w3 = None
self._account = None
Expand All @@ -71,7 +78,7 @@ def w3(self) -> Web3:
return self._w3

raise Exception(f"RPC provider is not connected ({self._rpc_url})")

@property
def poa(self):
return self._poa
Expand Down Expand Up @@ -102,8 +109,7 @@ def contract_call(self, func: Type[ContractFunction], from_address=None):

def build_contract_txn(self, func: Type[ContractFunction]):
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})
return self.sign_tx(tx_data)

def sign_tx(self, tx_data: TxParams):
Expand All @@ -117,6 +123,6 @@ def wait_for_transaction_receipt(self, tx_hash):

def current_block(self):
return self.w3.eth.block_number

def get_transaction_by_hash(self, hash):
return self.w3.eth.get_transaction(hash)
33 changes: 18 additions & 15 deletions faucet/admin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
from django.contrib import admin
from .models import *

from .models import (
BrightUser,
Chain,
ClaimReceipt,
DonationReceipt,
GlobalSettings,
LightningConfig,
TransactionBatch,
WalletAccount,
)


class ChainAdmin(admin.ModelAdmin):
Expand Down Expand Up @@ -28,8 +38,8 @@ def last_updated_with_seconds(obj):


class TXHashFilter(admin.SimpleListFilter):
title = 'has tx hash' # or use _('country') for translated title
parameter_name = 'has_tx_hash'
title = "has tx hash" # or use _('country') for translated title
parameter_name = "has_tx_hash"

def lookups(self, request, model_admin):
return (
Expand Down Expand Up @@ -66,8 +76,8 @@ class WalletAccountAdmin(admin.ModelAdmin):


class GlobalSettingsAdmin(admin.ModelAdmin):
list_display = ["pk", "weekly_chain_claim_limit", "tokentap_weekly_claim_limit"]
list_editable = ["weekly_chain_claim_limit", "tokentap_weekly_claim_limit"]
list_display = ["pk", "gastap_round_claim_limit", "tokentap_round_claim_limit"]
list_editable = ["gastap_round_claim_limit", "tokentap_round_claim_limit"]


class TransactionBatchAdmin(admin.ModelAdmin):
Expand All @@ -92,16 +102,9 @@ class LightningConfigAdmin(admin.ModelAdmin):


class DonationReceiptAdmin(admin.ModelAdmin):
list_display = [
'tx_hash',
'user_profile',
'chain',
'value',
'total_price',
'datetime'
]
search_fields = ['tx_hash']
list_filter = ['chain', 'user_profile']
list_display = ["tx_hash", "user_profile", "chain", "value", "total_price", "datetime"]
search_fields = ["tx_hash"]
list_filter = ["chain", "user_profile"]


admin.site.register(WalletAccount, WalletAccountAdmin)
Expand Down
35 changes: 20 additions & 15 deletions faucet/constraints.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import logging

import requests
from core.constraints import *

from core.constraints import ConstraintParam, ConstraintVerification
from core.utils import Web3Utils
from faucet.faucet_manager.credit_strategy import WeeklyCreditStrategy
from .models import DonationReceipt, Chain, ClaimReceipt
from faucet.faucet_manager.credit_strategy import RoundCreditStrategy

from .models import Chain, ClaimReceipt, DonationReceipt


class DonationConstraint(ConstraintVerification):
Expand All @@ -24,7 +28,8 @@ class OptimismDonationConstraint(DonationConstraint):
def is_observed(self, *args, **kwargs):
try:
chain = Chain.objects.get(chain_id=10)
except:
except Exception as e:
logging.error(e)
return False
self._param_values[ConstraintParam.CHAIN] = chain.pk
return super().is_observed(*args, **kwargs)
Expand All @@ -38,12 +43,11 @@ def is_observed(self, *args, **kwargs):
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}"
f"{chain.explorer_api_url}/api?module=account&action=txlistinternal&address={user_address}&start"
f"block=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":
Expand All @@ -54,16 +58,15 @@ def is_observed(self, *args, **kwargs):
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}"
f"{chain.explorer_api_url}/api?module=account&action=txlist&address={user_address}&startblock=0&"
f"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"]:
return True
first_tx = first_tx["result"][0]
claiming_gas_tx = w3.get_transaction_by_hash(
first_internal_tx["hash"]
)
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
Expand All @@ -75,7 +78,8 @@ class OptimismClaimingGasConstraint(EvmClaimingGasConstraint):
def is_observed(self, *args, **kwargs):
try:
chain = Chain.objects.get(chain_id=10)
except:
except Exception as e:
logging.error(e)
return False
self._param_values[ConstraintParam.CHAIN] = chain.pk
return super().is_observed(*args, **kwargs)
Expand All @@ -91,7 +95,7 @@ def is_observed(self, *args, **kwargs):
user_profile=self.user_profile,
chain=chain,
_status=ClaimReceipt.VERIFIED,
datetime__gte=WeeklyCreditStrategy.get_last_monday(),
datetime__gte=RoundCreditStrategy.get_start_of_the_round(),
).exists()


Expand All @@ -101,7 +105,8 @@ class OptimismHasClaimedGasInThisRound(HasClaimedGasInThisRound):
def is_observed(self, *args, **kwargs):
try:
chain = Chain.objects.get(chain_id=10)
except:
except Exception as e:
logging.error(e)
return False
self._param_values[ConstraintParam.CHAIN] = chain.pk
return super().is_observed(*args, **kwargs)
68 changes: 34 additions & 34 deletions faucet/faucet_manager/brightid_user_registry.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
from eth_account.signers.local import LocalAccount
from web3 import Web3
from web3.exceptions import TimeExhausted
from web3.gas_strategies.rpc import rpc_gas_price_strategy
from web3.middleware import geth_poa_middleware
from faucet.faucet_manager.brightid_user_registry_abi import bright_id_user_registry_abi
from faucet.models import Chain, BrightUser
# from eth_account.signers.local import LocalAccount
# from web3 import Web3
# from web3.exceptions import TimeExhausted
# from web3.gas_strategies.rpc import rpc_gas_price_strategy
# from web3.middleware import geth_poa_middleware
# from faucet.faucet_manager.brightid_user_registry_abi import bright_id_user_registry_abi
# from faucet.models import Chain, BrightUser


class BrightIdUserRegistry:
def __init__(self, chain: Chain, bright_id_user_registry_address: str):
self.chain = chain
self.abi = bright_id_user_registry_abi
self.bright_id_user_registry_address = bright_id_user_registry_address
# class BrightIdUserRegistry:
# def __init__(self, chain: Chain, bright_id_user_registry_address: str):
# self.chain = chain
# self.abi = bright_id_user_registry_abi
# self.bright_id_user_registry_address = bright_id_user_registry_address

@property
def w3(self) -> Web3:
assert self.chain.rpc_url_private is not None
_w3 = Web3(Web3.HTTPProvider(self.chain.rpc_url_private))
if self.chain.poa:
_w3.middleware_onion.inject(geth_poa_middleware, layer=0)
if _w3.isConnected():
_w3.eth.set_gas_price_strategy(rpc_gas_price_strategy)
return _w3
raise Exception(f"Could not connect to rpc {self.chain.rpc_url_private}")
# @property
# def w3(self) -> Web3:
# assert self.chain.rpc_url_private is not None
# _w3 = Web3(Web3.HTTPProvider(self.chain.rpc_url_private))
# if self.chain.poa:
# _w3.middleware_onion.inject(geth_poa_middleware, layer=0)
# if _w3.isConnected():
# _w3.eth.set_gas_price_strategy(rpc_gas_price_strategy)
# return _w3
# raise Exception(f"Could not connect to rpc {self.chain.rpc_url_private}")

@property
def contract(self):
return self.w3.eth.contract(
address=self.get_checksum_address(self.bright_id_user_registry_address),
abi=self.abi,
)
# @property
# def contract(self):
# return self.w3.eth.contract(
# address=self.get_checksum_address(self.bright_id_user_registry_address),
# abi=self.abi,
# )

def get_checksum_address(self, address):
return Web3.toChecksumAddress(address.lower())
# def get_checksum_address(self, address):
# return Web3.toChecksumAddress(address.lower())

def is_verified_user(self, address):
return self.contract.functions.isVerifiedUser(
self.get_checksum_address(address)
).call()
# def is_verified_user(self, address):
# return self.contract.functions.isVerifiedUser(
# self.get_checksum_address(address)
# ).call()
Loading

0 comments on commit 01e4cd4

Please sign in to comment.