diff --git a/brightIDfaucet/celery.py b/brightIDfaucet/celery.py index bfa25893..e1cf7a43 100644 --- a/brightIDfaucet/celery.py +++ b/brightIDfaucet/celery.py @@ -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. diff --git a/prizetap/migrations/0039_rename_nft_id_raffle_nft_ids.py b/prizetap/migrations/0039_rename_nft_id_raffle_nft_ids.py new file mode 100644 index 00000000..46da3485 --- /dev/null +++ b/prizetap/migrations/0039_rename_nft_id_raffle_nft_ids.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0.4 on 2023-11-09 07:02 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('prizetap', '0038_alter_constraint_name'), + ] + + operations = [ + migrations.RenameField( + model_name='raffle', + old_name='nft_id', + new_name='nft_ids', + ), + ] diff --git a/prizetap/migrations/0040_alter_raffle_nft_ids.py b/prizetap/migrations/0040_alter_raffle_nft_ids.py new file mode 100644 index 00000000..6dcc7973 --- /dev/null +++ b/prizetap/migrations/0040_alter_raffle_nft_ids.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0.4 on 2023-11-09 07:03 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('prizetap', '0039_rename_nft_id_raffle_nft_ids'), + ] + + operations = [ + migrations.AlterField( + model_name='raffle', + name='nft_ids', + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/prizetap/models.py b/prizetap/models.py index 3b8cc83a..913ea732 100644 --- a/prizetap/models.py +++ b/prizetap/models.py @@ -53,7 +53,7 @@ class Meta: decimals = models.IntegerField(default=18) is_prize_nft = models.BooleanField(default=False) - nft_id = models.CharField(max_length=256, null=True, blank=True) + nft_ids = models.TextField(null=True, blank=True) token_uri = models.TextField(null=True, blank=True) chain = models.ForeignKey(Chain, on_delete=models.CASCADE, related_name="raffles") diff --git a/prizetap/serializers.py b/prizetap/serializers.py index 91aedb0e..46acc61a 100644 --- a/prizetap/serializers.py +++ b/prizetap/serializers.py @@ -121,6 +121,8 @@ def validate(self, data): constraint_class.is_valid_param_keys(constraint_params[c.name]) except KeyError as e: raise serializers.ValidationError({"constraint_params": [{f"{c.name}": str(e)}]}) + if data["winners_count"] > data["max_number_of_entries"]: + raise serializers.ValidationError({"winners_count": "Invalid value"}) data["creator_profile"] = self.context["user_profile"] return data @@ -151,7 +153,7 @@ class Meta: "prize_symbol", "decimals", "is_prize_nft", - "nft_id", + "nft_ids", "token_uri", "chain", "contract", @@ -173,6 +175,7 @@ class Meta: "number_of_entries", "number_of_onchain_entries", "max_multiplier", + "winners_count", ] def get_user_entry(self, raffle: Raffle): diff --git a/prizetap/tasks.py b/prizetap/tasks.py index bfdc1d57..53bcbbfd 100644 --- a/prizetap/tasks.py +++ b/prizetap/tasks.py @@ -1,3 +1,4 @@ +import logging import time import requests @@ -149,3 +150,70 @@ def request_random_words(raffle: Raffle): if tx_hash: raffle.vrf_tx_hash = tx_hash raffle.save() + + +@shared_task(bind=True) +def set_raffle_ids(self): + id = f"{self.name}-LOCK" + + with memcache_lock(id, self.app.oid) as acquired: + if not acquired: + print(f"Could not acquire process lock at {self.name}") + return + raffles_queryset = ( + Raffle.objects.filter(status=Raffle.Status.PENDING).filter(raffleId__isnull=True).order_by("id") + ) + if raffles_queryset.count() > 0: + for raffle in raffles_queryset: + contract_client = PrizetapContractClient(raffle) + + receipt = contract_client.get_transaction_receipt(raffle.tx_hash) + raffle_created_log = receipt["logs"][1] + log = contract_client.contract.events.RaffleCreated().process_log(raffle_created_log) + + raffle.raffleId = log["args"]["raffleId"] + onchain_raffle = contract_client.get_raffle() + is_valid = True + if onchain_raffle["status"] != 0: + is_valid = False + logging.error(f"Mismatch raffle {raffle.raffleId} status") + if onchain_raffle["lastParticipantIndex"] != 0: + is_valid = False + logging.error(f"Mismatch raffle {raffle.raffleId} lastParticipantIndex") + if onchain_raffle["lastWinnerIndex"] != 0: + is_valid = False + logging.error(f"Mismatch raffle {raffle.raffleId} lastWinnerIndex") + if onchain_raffle["participantsCount"] != 0: + is_valid = False + logging.error(f"Mismatch raffle {raffle.raffleId} participantsCount") + if raffle.creator_address != onchain_raffle["initiator"]: + is_valid = False + logging.error(f"Mismatch raffle {raffle.raffleId} initiator") + if raffle.max_number_of_entries != onchain_raffle["maxParticipants"]: + is_valid = False + logging.error(f"Mismatch raffle {raffle.raffleId} maxParticipants") + if raffle.max_multiplier != onchain_raffle["maxMultiplier"]: + is_valid = False + logging.error(f"Mismatch raffle {raffle.raffleId} maxMultiplier") + if raffle.start_at != onchain_raffle["startTime"]: + is_valid = False + logging.error(f"Mismatch raffle {raffle.raffleId} startTime") + if raffle.deadline != onchain_raffle["endTime"]: + is_valid = False + logging.error(f"Mismatch raffle {raffle.raffleId} endTime") + if raffle.winners_count != onchain_raffle["winnersCount"]: + is_valid = False + logging.error(f"Mismatch raffle {raffle.raffleId} winnersCount") + if raffle.is_prize_nft: + if raffle.prize_asset != onchain_raffle["collection"]: + is_valid = False + logging.error(f"Mismatch raffle {raffle.raffleId} collection") + else: + if raffle.prize_amount != onchain_raffle["prizeAmount"]: + is_valid = False + logging.error(f"Mismatch raffle {raffle.raffleId} prizeAmount") + if raffle.prize_asset != onchain_raffle["currency"]: + is_valid = False + logging.error(f"Mismatch raffle {raffle.raffleId} currency") + if is_valid: + raffle.save() diff --git a/prizetap/utils.py b/prizetap/utils.py index 6c8b272b..8f905f9c 100644 --- a/prizetap/utils.py +++ b/prizetap/utils.py @@ -30,12 +30,12 @@ def set_raffle_random_words(self, expiration_time, random_words, reqId, muon_sig def get_raffle(self): func = self.contract.functions.raffles(self.raffle.raffleId) - return self.contract_call(func) + output = self.contract_call(func) + return self.__process_raffle(output) def get_last_winner_index(self): raffle = self.get_raffle() - last_index = raffle[8] if not self.raffle.is_prize_nft else raffle[7] - return last_index + return raffle["lastWinnerIndex"] def set_winners(self): winners_count = self.raffle.winners_count @@ -59,6 +59,15 @@ def get_raffle_winners_count(self): func = self.contract.functions.getWinnersCount(self.raffle.raffleId) return self.contract_call(func) + def __process_raffle(self, output): + raffles_abi = [item for item in self.contract.abi if item.get("name") == "raffles"] + assert len(raffles_abi) == 1, "The raffles abi not found" + raffles_abi = raffles_abi[0] + result = {} + for index, item in enumerate(raffles_abi["outputs"]): + result[item["name"]] = output[index] + return result + class VRFClientContractClient(Web3Utils): def __init__(self, chain) -> None: