Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
AccountsListAPI,
DonorsAPI,
)
from base.api import StatsAPI
from base.api import StatsAPI, ReclaimProofRequestView
from donations.api import DonationContractConfigAPI
from grantpicks.api import AccountProjectListAPI, ProjectListAPI, ProjectRoundVotesAPI, ProjectStatsAPI, RoundApplicationsAPI, RoundDetailAPI, RoundsListAPI
from lists.api import (
Expand Down Expand Up @@ -143,6 +143,7 @@
),
# stats
path("v1/stats", StatsAPI.as_view(), name="stats_api"),
path("v1/reclaim/generate-request", ReclaimProofRequestView.as_view(), name="stats_api"),

# grantpicks
path("v1/rounds", RoundsListAPI.as_view(), name="rounds_api"),
Expand Down
53 changes: 49 additions & 4 deletions base/api.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
from django.db.models import Count, Exists, OuterRef, Sum
from django.utils import timezone
from django.db.models import Sum
from django.http import JsonResponse
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from drf_spectacular.utils import (
OpenApiExample,
OpenApiParameter,
OpenApiResponse,
extend_schema,
)
from django.conf import settings
from asgiref.sync import async_to_sync
from rest_framework import serializers
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView

from reclaim_python_sdk import ReclaimProofRequest
from accounts.models import Account
from donations.models import Donation
from pots.models import PotPayout
Expand All @@ -25,6 +26,8 @@ class StatsResponseSerializer(serializers.Serializer):
total_donors_count = serializers.IntegerField()
total_recipients_count = serializers.IntegerField()

class ReclaimProofRequestConfigSerializer(serializers.Serializer):
reclaimProofRequestConfig = serializers.CharField()

class StatsAPI(APIView):
def dispatch(self, request, *args, **kwargs):
Expand Down Expand Up @@ -87,3 +90,45 @@ def get(self, request: Request, *args, **kwargs):
"total_recipients_count": total_recipients_count,
}
)


class ReclaimProofRequestView(APIView):

@extend_schema(
responses={
200: OpenApiResponse(
response=ReclaimProofRequestConfigSerializer,
description="Returns Reclaim proof request configuration",
examples=[
OpenApiExample(
"example-1",
summary="Simple example",
description="Example response for Reclaim proof request config",
value={
"reclaimProofRequestConfig": "{}"
},
response_only=True,
),
],
),
500: OpenApiResponse(description="Internal server error"),
}
)
def post(self, request: Request, *args, **kwargs):
APP_ID = settings.RECLAIM_APP_ID
APP_SECRET = settings.RECLAIM_APP_SECRET
PROVIDER_ID = settings.RECLAIM_TWITTER_PROVIDER_ID

platform = request.query_params.get("platform")
handle = request.query_params.get("handle")

try:
reclaim_proof_func = async_to_sync(ReclaimProofRequest.init)
reclaim_proof_request = reclaim_proof_func(APP_ID, APP_SECRET, PROVIDER_ID, {"context": {"handle": handle}})
# reclaim_proof_request.set_app_callback_url("https://your-backend.com/receive-proofs")
reclaim_proof_request_config = reclaim_proof_request.to_json_string()

return JsonResponse({"reclaimProofRequestConfig": reclaim_proof_request_config})
except Exception as error:
print(f"Error generating request config: {error}")
return JsonResponse({"error": "Failed to generate request config"}, status=500)
11 changes: 8 additions & 3 deletions base/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,16 @@
REDIS_HOST = os.environ.get("PL_REDIS_HOST", "localhost")
REDIS_PORT = os.environ.get("PL_REDIS_PORT", 6379)
SENTRY_DSN = os.environ.get("PL_SENTRY_DSN")
RECLAIM_APP_ID = os.environ.get("PL_RECLAIM_APP_ID")
RECLAIM_APP_SECRET = os.environ.get("PL_RECLAIM_APP_SECRET")
RECLAIM_TWITTER_PROVIDER_ID = os.environ.get("PL_RECLAIM_TWITTER_PROVIDER_ID")

# POTLOCK_TLA = "potlock.testnet" if ENVIRONMENT == "testnet" else "potlock.near"
POTLOCK_TLA = "potlock.testnet" if ENVIRONMENT == "testnet" else ("staging.potlock.near" if ENVIRONMENT == "dev" else "potlock.near")
# NADABOT_TLA = "nadabot.testnet" if ENVIRONMENT == "testnet" else "nadabot.near"
NADABOT_TLA = "nadabot.testnet" if ENVIRONMENT == "testnet" else ("staging.nadabot.near" if ENVIRONMENT == "dev" else "nadabot.near")
STELLAR_CONTRACT_ID = "CBEW52FEWIFWK4LCSMX5FAAG2MYB36C2RLKS5YEIF5AOJEDMCGYU3ZGB" if ENVIRONMENT == "testnet" else ("" if ENVIRONMENT == "dev" else "")
STELLAR_PROJECTS_REGISTRY_CONTRACT = "CBG2JAGBYUAM3YLQFNFR3ZSWVR7XR5BEQHQ6XGUA3HCWVCHWO3RS3YUD" if ENVIRONMENT == "testnet" else ("" if ENVIRONMENT == "dev" else "")
STELLAR_CONTRACT_ID = "CA7A2776JYIOYXPAJFONDC7BVPDWWLZU524UTGIJIQH6HWWOR6LKYQQT" if ENVIRONMENT == "testnet" else ("" if ENVIRONMENT == "dev" else "")
STELLAR_PROJECTS_REGISTRY_CONTRACT = "CA56XSY7YEZ7CJ5FYG7YODQIWE3JNRGZ5S7E7VJAQ675KDS4BLZJ5NJH" if ENVIRONMENT == "testnet" else ("" if ENVIRONMENT == "dev" else "")
NEAR_SOCIAL_CONTRACT_ADDRESS = (
"v1.social08.testnet" if ENVIRONMENT == "testnet" else "social.near"
)
Expand Down Expand Up @@ -234,7 +237,9 @@

CORS_ALLOWED_ORIGIN_REGEXES = [
"^https:\/\/potlock-next-[\w-]+-potlock\.vercel\.app\/?$",
"^https?:\/\/.*\.?grantpicks\.com$"
"^https?:\/\/.*\.?grantpicks\.com$",
"^https:\/\/staging\.app\.potlock\.(org|io|xyz|app)\/?$",
"^https:\/\/staging\.alpha\.potlock\.(org|io|xyz|app)\/?$"
]

# REDIS / CACHE CONFIGS
Expand Down
55 changes: 55 additions & 0 deletions grantpicks/migrations/0007_remove_round_use_whitelist_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Generated by Django 5.0.6 on 2025-05-07 15:53

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("grantpicks", "0006_alter_round_compliance_period_ms_and_more"),
]

operations = [
migrations.RemoveField(
model_name="round",
name="use_whitelist",
),
migrations.AddField(
model_name="round",
name="application_wl_list_id",
field=models.IntegerField(
help_text="list for applicants",
null=True,
verbose_name="list for applicants",
),
),
migrations.AddField(
model_name="round",
name="use_whitelist_application",
field=models.BooleanField(
default=False,
help_text="Use whitelist for application.",
verbose_name="use whitelist",
),
preserve_default=False,
),
migrations.AddField(
model_name="round",
name="use_whitelist_voting",
field=models.BooleanField(
default=False,
help_text="Use whitelist for voting.",
verbose_name="use whitelist",
),
preserve_default=False,
),
migrations.AddField(
model_name="round",
name="voting_wl_list_id",
field=models.IntegerField(
help_text="list for voter whitelist",
null=True,
verbose_name="list for voter whitelist",
),
),
]
19 changes: 17 additions & 2 deletions grantpicks/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,25 @@ class Round(models.Model):
null=False,
help_text=_("Round voting end date."),
)
use_whitelist = models.BooleanField(
use_whitelist_voting = models.BooleanField(
_("use whitelist"),
null=False,
help_text=_("Use whitelist."),
help_text=_("Use whitelist for voting."),
)
use_whitelist_application = models.BooleanField(
_("use whitelist"),
null=False,
help_text=_("Use whitelist for application."),
)
application_wl_list_id = models.IntegerField(
_("list for applicants"),
null=True,
help_text=_("list for applicants"),
)
voting_wl_list_id = models.IntegerField(
_("list for voter whitelist"),
null=True,
help_text=_("list for voter whitelist"),
)
use_vault = models.BooleanField(
_("use vault"),
Expand Down
10 changes: 8 additions & 2 deletions grantpicks/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ class Meta:
"application_end",
"voting_start",
"voting_end",
"use_whitelist",
"use_whitelist_voting",
"use_whitelist_voting",
"application_wl_list_id",
"voting_wl_list_id",
"use_vault",
"num_picks_per_voter",
"max_participants",
Expand Down Expand Up @@ -190,7 +193,10 @@ class Meta:
],
"use_vault": True,
"description": "This is a test round",
"use_whitelist": False,
"use_whitelist_voting": False,
"use_whitelist_application": True,
"application_wl_list_id": 1,
"voting_wl_list_id": 2,
"voting_start": "2024-06-25T00:00:00Z",
"voting_end": "2024-06-30T00:00:00Z",
"cooldown_end": None,
Expand Down
7 changes: 5 additions & 2 deletions indexer_app/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1647,8 +1647,11 @@ def create_or_update_round(event_data, contract_id, timestamp, chain_id="stellar
'application_end': datetime.fromtimestamp(event_data.get('application_end_ms') / 1000) if event_data.get('application_end_ms') else None,
'voting_start': datetime.fromtimestamp(event_data.get('voting_start_ms') / 1000),
'voting_end': datetime.fromtimestamp(event_data.get('voting_end_ms') / 1000),
'use_whitelist': event_data.get('use_whitelist'),
'use_vault': use_vault,
'use_whitelist_voting': event_data.get('use_whitelist_voting', False),
'use_whitelist_application': event_data.get('use_whitelist_application', False),
'application_wl_list_id': event_data.get('application_wl_list_id'),
'voting_wl_list_id': event_data.get('voting_wl_list_id'),
'use_vault': use_vault or False,
'num_picks_per_voter': event_data.get('num_picks_per_voter'),
'max_participants': event_data.get('max_participants'),
'allow_applications': event_data.get('allow_applications'),
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ drf-spectacular = "^0.27.2"
django-extensions = "^3.2.3"
psutil = "^6.0.0"
stellar-sdk = "^11.0.0"
reclaim-python-sdk = "^0.2.1"

[tool.poetry.group.dev.dependencies]
black = "^24.3.0"
Expand Down
Loading