Пример #1
0
 def cart_payload(self, build_absolute_uri, user=None):
     return {
         'grant_id': str(self.id),
         'grant_slug': self.slug,
         'grant_url': self.url,
         'grant_title': self.title,
         'grant_contract_version': self.contract_version,
         'grant_contract_address': self.contract_address,
         'grant_token_symbol': self.token_symbol,
         'grant_admin_address': self.admin_address,
         'grant_token_address': self.token_address,
         'grant_logo': self.logo.url if self.logo and self.logo.url else build_absolute_uri(static(f'v2/images/grants/logos/{self.id % 3}.png')),
         'grant_clr_prediction_curve': self.clr_prediction_curve,
         'grant_image_css': self.image_css,
         'is_clr_eligible': self.is_clr_eligible,
         'clr_round_num': self.clr_round_num,
         'tenants': self.tenants,
         'zcash_payout_address': self.zcash_payout_address,
         'celo_payout_address': self.celo_payout_address,
         'zil_payout_address': self.zil_payout_address,
         'polkadot_payout_address': self.polkadot_payout_address,
         'harmony_payout_address': self.harmony_payout_address,
         'binance_payout_address': self.binance_payout_address,
         'kusama_payout_address': self.kusama_payout_address,
         'harmony_payout_address': self.harmony_payout_address,
         'rsk_payout_address': self.rsk_payout_address,
         'algorand_payout_address': self.algorand_payout_address,
         'is_on_team': is_grant_team_member(self, user.profile) if user and user.is_authenticated else False,
     }
Пример #2
0
Файл: views.py Проект: mul53/web
def milestones(request, grant_id, grant_slug):
    profile = get_profile(request)
    grant = Grant.objects.prefetch_related('milestones').get(pk=grant_id,
                                                             slug=grant_slug)

    if not is_grant_team_member(grant, profile):
        return redirect(reverse('grants:details', args=(grant.pk, grant.slug)))

    if request.method == "POST":
        method = request.POST.get('method')

        if method == "POST":
            form = MilestoneForm(request.POST)
            milestone = form.save(commit=False)
            milestone.grant = grant
            milestone.save()

        if method == "PUT":
            milestone_id = request.POST.get('milestone_id')
            milestone = Milestone.objects.get(pk=milestone_id)
            milestone.completion_date = request.POST.get('completion_date')
            milestone.save()

        if method == "DELETE":
            milestone_id = request.POST.get('milestone_id')
            milestone = grant.milestones.get(pk=milestone_id)
            milestone.delete()

        return redirect(
            reverse('grants:milestones', args=(grant.pk, grant.slug)))

    form = MilestoneForm()
    milestones = grant.milestones.order_by('due_date')

    params = {
        'active':
        'grant_milestones',
        'title':
        _('Grant Milestones'),
        'card_desc':
        _('Provide sustainable funding for Open Source with Gitcoin Grants'),
        'grant':
        grant,
        'milestones':
        milestones,
        'form':
        form,
        'keywords':
        get_keywords(),
    }
    return TemplateResponse(request, 'grants/milestones.html', params)
Пример #3
0
def grant_fund(request, grant_id, grant_slug):
    """Handle grant funding."""
    try:
        grant = Grant.objects.get(pk=grant_id, slug=grant_slug)
    except Grant.DoesNotExist:
        raise Http404

    profile = get_profile(request)

    if not grant.active:
        params = {
            'active': 'grant_error',
            'title': _('Fund - Grant Ended'),
            'grant': grant,
            'text': _('This Grant has ended.'),
            'subtext': _('Contributions can no longer be made this grant')
        }
        return TemplateResponse(request, 'grants/shared/error.html', params)

    if is_grant_team_member(grant, profile):
        params = {
            'active': 'grant_error',
            'title': _('Fund - Grant funding blocked'),
            'grant': grant,
            'text': _('This Grant cannot be funded'),
            'subtext': _('Grant team members cannot contribute to their own grant.')
        }
        return TemplateResponse(request, 'grants/shared/error.html', params)

    if grant.link_to_new_grant:
        params = {
            'active': 'grant_error',
            'title': _('Fund - Grant Migrated'),
            'grant': grant.link_to_new_grant,
            'text': f'This Grant has ended',
            'subtext': 'Contributions can no longer be made to this grant. <br> Visit the new grant to contribute.',
            'button_txt': 'View New Grant'
        }
        return TemplateResponse(request, 'grants/shared/error.html', params)

    active_subscription = Subscription.objects.select_related('grant').filter(
        grant=grant_id, active=True, error=False, contributor_profile=request.user.profile
    )

    if active_subscription:
        params = {
            'active': 'grant_error',
            'title': _('Subscription Exists'),
            'grant': grant,
            'text': _('You already have an active subscription for this grant.')
        }
        return TemplateResponse(request, 'grants/shared/error.html', params)

    if grant.contract_address == '0x0':
        messages.info(
            request,
            _('This grant is not configured to accept funding at this time.  Please contact [email protected] if you believe this message is in error!')
        )
        logger.error(f"Grant {grant.pk} is not properly configured for funding.  Please set grant.contract_address on this grant")
        return redirect(reverse('grants:details', args=(grant.pk, grant.slug)))

    if request.method == 'POST':
        if 'contributor_address' in request.POST:
            subscription = Subscription()

            subscription.active = False
            subscription.contributor_address = request.POST.get('contributor_address', '')
            subscription.amount_per_period = request.POST.get('amount_per_period', 0)
            subscription.real_period_seconds = request.POST.get('real_period_seconds', 2592000)
            subscription.frequency = request.POST.get('frequency', 30)
            subscription.frequency_unit = request.POST.get('frequency_unit', 'days')
            subscription.token_address = request.POST.get('token_address', '')
            subscription.token_symbol = request.POST.get('token_symbol', '')
            subscription.gas_price = request.POST.get('gas_price', 0)
            subscription.new_approve_tx_id = request.POST.get('sub_new_approve_tx_id', '0x0')
            subscription.num_tx_approved = request.POST.get('num_tx_approved', 1)
            subscription.network = request.POST.get('network', '')
            subscription.contributor_profile = profile
            subscription.grant = grant
            subscription.comments = request.POST.get('comment', '')
            subscription.save()

            # one time payments
            activity = None
            if int(subscription.num_tx_approved) == 1:
                subscription.successful_contribution(subscription.new_approve_tx_id);
                subscription.error = True #cancel subs so it doesnt try to bill again
                subscription.subminer_comments = "skipping subminer bc this is a 1 and done subscription, and tokens were alredy sent"
                subscription.save()
                activity = record_subscription_activity_helper('new_grant_contribution', subscription, profile)
            else:
                activity = record_subscription_activity_helper('new_grant_subscription', subscription, profile)

            if 'comment' in request.POST:
                comment = request.POST.get('comment')
                if comment and activity:
                    comment = Comment.objects.create(
                        profile=request.user.profile,
                        activity=activity,
                        comment=comment)

            # TODO - how do we attach the tweet modal WITH BULK TRANSFER COUPON next pageload??
            messages.info(
                request,
                _('Your subscription has been created. It will bill within the next 5 minutes or so. Thank you for supporting Open Source !')
            )

            return JsonResponse({
                'success': True,
            })

        if 'hide_wallet_address' in request.POST:
            profile.hide_wallet_address = bool(request.POST.get('hide_wallet_address', False))
            profile.save()

        if 'signature' in request.POST:
            sub_new_approve_tx_id = request.POST.get('sub_new_approve_tx_id', '')
            subscription = Subscription.objects.filter(new_approve_tx_id=sub_new_approve_tx_id).first()
            subscription.active = True
            subscription.subscription_hash = request.POST.get('subscription_hash', '')
            subscription.contributor_signature = request.POST.get('signature', '')
            if 'split_tx_id' in request.POST:
                subscription.split_tx_id = request.POST.get('split_tx_id', '')
                subscription.save_split_tx_to_contribution()
            if 'split_tx_confirmed' in request.POST:
                subscription.split_tx_confirmed = bool(request.POST.get('split_tx_confirmed', False))
                subscription.save_split_tx_to_contribution()
            subscription.save()

            value_usdt = subscription.get_converted_amount()
            if value_usdt:
                grant.monthly_amount_subscribed += subscription.get_converted_monthly_amount()

            grant.save()
            new_supporter(grant, subscription)
            thank_you_for_supporting(grant, subscription)
            return JsonResponse({
                'success': True,
                'url': reverse('grants:details', args=(grant.pk, grant.slug))
            })

    splitter_contract_address = settings.SPLITTER_CONTRACT_ADDRESS

    # handle phantom funding
    active_tab = 'normal'
    fund_reward = None
    round_number = 4
    can_phantom_fund = request.user.is_authenticated and request.user.groups.filter(name='phantom_funders').exists() and clr_active
    phantom_funds = PhantomFunding.objects.filter(profile=request.user.profile, round_number=round_number).order_by('created_on').nocache() if request.user.is_authenticated else PhantomFunding.objects.none()
    is_phantom_funding_this_grant = can_phantom_fund and phantom_funds.filter(grant=grant).exists()
    show_tweet_modal = False
    if can_phantom_fund:
        active_tab = 'phantom'
    if can_phantom_fund and request.POST.get('toggle_phantom_fund'):
        if is_phantom_funding_this_grant:
            msg = "You are no longer signaling for this grant."
            phantom_funds.filter(grant=grant).delete()
        else:
            msg = "You are now signaling for this grant."
            show_tweet_modal = True
            name_search = 'grants_round_4_contributor' if not settings.DEBUG else 'pogs_eth'
            fund_reward = BulkTransferCoupon.objects.filter(token__name__contains=name_search).order_by('?').first()
            PhantomFunding.objects.create(grant=grant, profile=request.user.profile, round_number=round_number)
            record_grant_activity_helper('new_grant_contribution', grant, request.user.profile)

        messages.info(
            request,
            msg
        )
        is_phantom_funding_this_grant = not is_phantom_funding_this_grant

    params = {
        'profile': profile,
        'active': 'fund_grant',
        'title': _('Fund Grant'),
        'card_desc': _('Provide sustainable funding for Open Source with Gitcoin Grants'),
        'subscription': {},
        'show_tweet_modal': show_tweet_modal,
        'grant_has_no_token': True if grant.token_address == '0x0000000000000000000000000000000000000000' else False,
        'grant': grant,
        'clr_prediction_curve': [c[1] for c in grant.clr_prediction_curve] if grant.clr_prediction_curve and len(grant.clr_prediction_curve[0]) > 1 else [0, 0, 0, 0, 0, 0],
        'keywords': get_keywords(),
        'recommend_gas_price': recommend_min_gas_price_to_confirm_in_time(4),
        'recommend_gas_price_slow': recommend_min_gas_price_to_confirm_in_time(120),
        'recommend_gas_price_avg': recommend_min_gas_price_to_confirm_in_time(15),
        'recommend_gas_price_fast': recommend_min_gas_price_to_confirm_in_time(1),
        'eth_usd_conv_rate': eth_usd_conv_rate(),
        'conf_time_spread': conf_time_spread(),
        'gas_advisories': gas_advisories(),
        'splitter_contract_address': settings.SPLITTER_CONTRACT_ADDRESS,
        'gitcoin_donation_address': settings.GITCOIN_DONATION_ADDRESS,
        'can_phantom_fund': can_phantom_fund,
        'is_phantom_funding_this_grant': is_phantom_funding_this_grant,
        'active_tab': active_tab,
        'fund_reward': fund_reward,
        'phantom_funds': phantom_funds,
        'clr_round': clr_round,
        'clr_active': clr_active,
        'total_clr_pot': total_clr_pot,
    }
    return TemplateResponse(request, 'grants/fund.html', params)
Пример #4
0
def grant_details(request, grant_id, grant_slug):
    """Display the Grant details page."""
    profile = get_profile(request)
    add_cancel_params = False
    try:
        grant = Grant.objects.prefetch_related('subscriptions', 'milestones', 'updates').get(
            pk=grant_id, slug=grant_slug
        )
        milestones = grant.milestones.order_by('due_date')
        updates = grant.updates.order_by('-created_on')
        subscriptions = grant.subscriptions.filter(active=True, error=False).order_by('-created_on')
        cancelled_subscriptions = grant.subscriptions.filter(active=False, error=False).order_by('-created_on')
        _contributions = Contribution.objects.filter(subscription__in=grant.subscriptions.all())
        phantom_funds = grant.phantom_funding.all()
        contributions = list(_contributions.order_by('-created_on'))
        voucher_fundings = [ele.to_mock_contribution() for ele in phantom_funds.order_by('-created_on')]
        contributors = list(_contributions.distinct('subscription__contributor_profile')) + list(phantom_funds.distinct('profile'))
        activity_count = len(cancelled_subscriptions) + len(contributions)
        user_subscription = grant.subscriptions.filter(contributor_profile=profile, active=True).first()
        user_non_errored_subscription = grant.subscriptions.filter(contributor_profile=profile, active=True, error=False).first()
        add_cancel_params = user_subscription
    except Grant.DoesNotExist:
        raise Http404

    is_admin = (grant.admin_profile.id == profile.id) if profile and grant.admin_profile else False
    if is_admin:
        add_cancel_params = True

    is_team_member = is_grant_team_member(grant, profile)

    if request.method == 'POST' and (is_team_member or request.user.is_staff):
        if request.FILES.get('input_image'):
            logo = request.FILES.get('input_image', None)
            grant.logo = logo
            grant.save()
            record_grant_activity_helper('update_grant', grant, profile)
            return redirect(reverse('grants:details', args=(grant.pk, grant.slug)))
        if 'contract_address' in request.POST:
            grant.cancel_tx_id = request.POST.get('grant_cancel_tx_id', '')
            grant.active = False
            grant.save()
            grant_cancellation(grant, user_subscription)
            for sub in subscriptions:
                subscription_terminated(grant, sub)
            record_grant_activity_helper('killed_grant', grant, profile)
        elif 'input-title' in request.POST:
            update_kwargs = {
                'title': request.POST.get('input-title', ''),
                'description': request.POST.get('description', ''),
                'grant': grant
            }
            Update.objects.create(**update_kwargs)
            record_grant_activity_helper('update_grant', grant, profile)
        elif 'edit-title' in request.POST:
            grant.title = request.POST.get('edit-title')
            grant.reference_url = request.POST.get('edit-reference_url')
            grant.amount_goal = Decimal(request.POST.get('edit-amount_goal'))
            team_members = request.POST.getlist('edit-grant_members[]')
            team_members.append(str(grant.admin_profile.id))
            grant.team_members.set(team_members)
            if 'edit-description' in request.POST:
                grant.description = request.POST.get('edit-description')
                grant.description_rich = request.POST.get('edit-description_rich')
            grant.save()
            record_grant_activity_helper('update_grant', grant, profile)
            return redirect(reverse('grants:details', args=(grant.pk, grant.slug)))

    # handle grant updates unsubscribe
    key = 'unsubscribed_profiles'
    is_unsubscribed_from_updates_from_this_grant = request.user.is_authenticated and request.user.profile.pk in grant.metadata.get(key, [])
    if request.GET.get('unsubscribe') and request.user.is_authenticated:
        ups = grant.metadata.get(key, [])
        ups.append(request.user.profile.pk)
        grant.metadata[key] = ups
        grant.save()
        messages.info(
                request,
                _('You have been unsubscribed from the updates from this grant.')
            )
        is_unsubscribed_from_updates_from_this_grant = True

    tab = request.GET.get('tab', 'activity')
    params = {
        'active': 'grant_details',
        'clr_matching_banners_style': clr_matching_banners_style,
        'grant': grant,
        'tab': tab,
        'title': matching_live + grant.title,
        'card_desc': grant.description,
        'avatar_url': grant.logo.url if grant.logo else None,
        'subscriptions': subscriptions,
        'cancelled_subscriptions': cancelled_subscriptions,
        'contributions': contributions,
        'user_subscription': user_subscription,
        'user_non_errored_subscription': user_non_errored_subscription,
        'is_admin': is_admin,
        'grant_is_inactive': not grant.active,
        'updates': updates,
        'milestones': milestones,
        'keywords': get_keywords(),
        'target': f'/activity?what=grant:{grant.pk}',
        'activity_count': activity_count,
        'contributors': contributors,
        'clr_active': clr_active,
        'show_clr_card': show_clr_card,
        'is_team_member': is_team_member,
        'voucher_fundings': voucher_fundings,
        'is_unsubscribed_from_updates_from_this_grant': is_unsubscribed_from_updates_from_this_grant,
        'tags': [(f'Email Grant Funders ({len(contributors)})', 'bullhorn')] if is_team_member else [],
    }

    if tab == 'stats':
        params['max_graph'] = grant.history_by_month_max
        params['history'] = json.dumps(grant.history_by_month)

    if add_cancel_params:
        add_in_params = {
            'recommend_gas_price': recommend_min_gas_price_to_confirm_in_time(4),
            'recommend_gas_price_slow': recommend_min_gas_price_to_confirm_in_time(120),
            'recommend_gas_price_avg': recommend_min_gas_price_to_confirm_in_time(15),
            'recommend_gas_price_fast': recommend_min_gas_price_to_confirm_in_time(1),
            'eth_usd_conv_rate': eth_usd_conv_rate(),
            'conf_time_spread': conf_time_spread(),
            'gas_advisories': gas_advisories(),
        }
        for key, value in add_in_params.items():
            params[key] = value

    return TemplateResponse(request, 'grants/detail/index.html', params)
Пример #5
0
def grant_fund(request, grant_id, grant_slug):
    """Handle grant funding."""
    try:
        grant = Grant.objects.get(pk=grant_id, slug=grant_slug)
    except Grant.DoesNotExist:
        raise Http404

    profile = get_profile(request)

    if not grant.active:
        params = {
            'active': 'grant_error',
            'title': _('Fund - Grant Ended'),
            'grant': grant,
            'text': _('This Grant has ended.'),
            'subtext': _('Contributions can no longer be made this grant')
        }
        return TemplateResponse(request, 'grants/shared/error.html', params)

    if is_grant_team_member(grant, profile):
        params = {
            'active':
            'grant_error',
            'title':
            _('Fund - Grant funding blocked'),
            'grant':
            grant,
            'text':
            _('This Grant cannot be funded'),
            'subtext':
            _('Grant team members cannot contribute to their own grant.')
        }
        return TemplateResponse(request, 'grants/shared/error.html', params)

    if grant.link_to_new_grant:
        params = {
            'active': 'grant_error',
            'title': _('Fund - Grant Migrated'),
            'grant': grant.link_to_new_grant,
            'text': f'This Grant has ended',
            'subtext':
            'Contributions can no longer be made to this grant. <br> Visit the new grant to contribute.',
            'button_txt': 'View New Grant'
        }
        return TemplateResponse(request, 'grants/shared/error.html', params)

    active_subscription = Subscription.objects.select_related('grant').filter(
        grant=grant_id,
        active=True,
        error=False,
        contributor_profile=request.user.profile,
        is_postive_vote=True)

    if active_subscription:
        params = {
            'active': 'grant_error',
            'title': _('Subscription Exists'),
            'grant': grant,
            'text':
            _('You already have an active subscription for this grant.')
        }
        return TemplateResponse(request, 'grants/shared/error.html', params)

    if not grant.configured_to_receieve_funding:
        messages.info(
            request,
            _('This grant is not configured to accept funding at this time.  Please contact [email protected] if you believe this message is in error!'
              ))
        logger.error(
            f"Grant {grant.pk} is not properly configured for funding.  Please set grant.contract_address on this grant"
        )
        return redirect(reverse('grants:details', args=(grant.pk, grant.slug)))

    if request.method == 'POST':
        from grants.tasks import process_grant_contribution
        process_grant_contribution.delay(grant_id, grant_slug, profile.pk,
                                         request.POST)

        return JsonResponse({
            'success': True,
        })

    raise Http404
Пример #6
0
def grant_details(request, grant_id, grant_slug):
    """Display the Grant details page."""
    tab = request.GET.get('tab', 'description')
    profile = get_profile(request)
    add_cancel_params = False
    try:
        grant = None
        try:
            grant = Grant.objects.prefetch_related(
                'subscriptions', 'team_members').get(pk=grant_id,
                                                     slug=grant_slug)
        except Grant.DoesNotExist:
            grant = Grant.objects.prefetch_related(
                'subscriptions', 'team_members').get(pk=grant_id)

        increment_view_count.delay([grant.pk], grant.content_type,
                                   request.user.id, 'individual')
        subscriptions = grant.subscriptions.filter(
            active=True, error=False,
            is_postive_vote=True).order_by('-created_on')
        cancelled_subscriptions = grant.subscriptions.filter(
            active=False, error=False,
            is_postive_vote=True).order_by('-created_on')

        activity_count = grant.contribution_count
        contributors = []
        contributions = []
        negative_contributions = []
        voucher_fundings = []
        if tab in ['transactions', 'contributors']:
            _contributions = Contribution.objects.filter(
                subscription__in=grant.subscriptions.all().cache(
                    timeout=60)).cache(timeout=60)
            negative_contributions = _contributions.filter(
                subscription__is_postive_vote=False)
            _contributions = _contributions.filter(
                subscription__is_postive_vote=True)
            phantom_funds = grant.phantom_funding.all().cache(timeout=60)
            contributions = list(_contributions.order_by('-created_on'))
            voucher_fundings = [
                ele.to_mock_contribution()
                for ele in phantom_funds.order_by('-created_on')
            ]
            contributors = list(
                _contributions.distinct('subscription__contributor_profile')
            ) + list(phantom_funds.distinct('profile'))
            activity_count = len(cancelled_subscriptions) + len(contributions)
        user_subscription = grant.subscriptions.filter(
            contributor_profile=profile, active=True).first()
        user_non_errored_subscription = grant.subscriptions.filter(
            contributor_profile=profile, active=True, error=False).first()
        add_cancel_params = user_subscription
    except Grant.DoesNotExist:
        raise Http404

    is_admin = (grant.admin_profile.id
                == profile.id) if profile and grant.admin_profile else False
    if is_admin:
        add_cancel_params = True

    is_team_member = is_grant_team_member(grant, profile)

    if request.method == 'POST' and (is_team_member or request.user.is_staff):
        grant.last_update = timezone.now()
        if request.FILES.get('input_image'):
            logo = request.FILES.get('input_image', None)
            grant.logo = logo
            grant.save()
            record_grant_activity_helper('update_grant', grant, profile)
            return redirect(
                reverse('grants:details', args=(grant.pk, grant.slug)))
        if 'contract_address' in request.POST:
            grant.cancel_tx_id = request.POST.get('grant_cancel_tx_id', '')
            grant.active = False
            grant.save()
            grant_cancellation(grant, user_subscription)
            for sub in subscriptions:
                subscription_terminated(grant, sub)
            record_grant_activity_helper('killed_grant', grant, profile)
        elif 'edit-title' in request.POST:
            grant.title = request.POST.get('edit-title')
            grant.reference_url = request.POST.get('edit-reference_url')
            team_members = request.POST.getlist('edit-grant_members[]')
            team_members.append(str(grant.admin_profile.id))
            grant.team_members.set(team_members)

            if 'edit-description' in request.POST:
                grant.description = request.POST.get('edit-description')
                grant.description_rich = request.POST.get(
                    'edit-description_rich')
            grant.save()

            form_category_ids = request.POST.getlist('edit-categories[]')
            '''Overwrite the existing categories and then add the new ones'''
            grant.categories.clear()
            add_form_categories_to_grant(form_category_ids, grant,
                                         grant.grant_type)

            record_grant_activity_helper('update_grant', grant, profile)
            return redirect(
                reverse('grants:details', args=(grant.pk, grant.slug)))

    # handle grant updates unsubscribe
    key = 'unsubscribed_profiles'
    is_unsubscribed_from_updates_from_this_grant = request.user.is_authenticated and request.user.profile.pk in grant.metadata.get(
        key, [])
    if request.GET.get('unsubscribe') and request.user.is_authenticated:
        ups = grant.metadata.get(key, [])
        ups.append(request.user.profile.pk)
        grant.metadata[key] = ups
        grant.save()
        messages.info(
            request,
            _('You have been unsubscribed from the updates from this grant.'))
        is_unsubscribed_from_updates_from_this_grant = True

    try:
        what = f'grant:{grant.pk}'
        pinned = PinnedPost.objects.get(what=what)
    except PinnedPost.DoesNotExist:
        pinned = None
    params = {
        'active':
        'grant_details',
        'clr_matching_banners_style':
        clr_matching_banners_style,
        'grant':
        grant,
        'tab':
        tab,
        'title':
        matching_live_tiny + grant.title + " | Grants",
        'card_desc':
        grant.description,
        'avatar_url':
        grant.logo.url if grant.logo else None,
        'subscriptions':
        subscriptions,
        'cancelled_subscriptions':
        cancelled_subscriptions,
        'contributions':
        contributions,
        'negative_contributions':
        negative_contributions,
        'user_subscription':
        user_subscription,
        'user_non_errored_subscription':
        user_non_errored_subscription,
        'is_admin':
        is_admin,
        'grant_is_inactive':
        not grant.active,
        'keywords':
        get_keywords(),
        'target':
        f'/activity?what={what}',
        'pinned':
        pinned,
        'what':
        what,
        'activity_count':
        activity_count,
        'contributors':
        contributors,
        'clr_active':
        clr_active,
        'is_team_member':
        is_team_member,
        'voucher_fundings':
        voucher_fundings,
        'is_unsubscribed_from_updates_from_this_grant':
        is_unsubscribed_from_updates_from_this_grant,
        'is_round_5_5':
        False,
        'options':
        [(f'Email Grant Funders ({grant.contributor_count})', 'bullhorn',
          'Select this option to email your status update to all your funders.'
          )] if is_team_member else [],
    }

    if tab == 'stats':
        params['max_graph'] = grant.history_by_month_max
        params['history'] = json.dumps(grant.history_by_month)

    if add_cancel_params:
        add_in_params = {
            'recommend_gas_price':
            recommend_min_gas_price_to_confirm_in_time(4),
            'recommend_gas_price_slow':
            recommend_min_gas_price_to_confirm_in_time(120),
            'recommend_gas_price_avg':
            recommend_min_gas_price_to_confirm_in_time(15),
            'recommend_gas_price_fast':
            recommend_min_gas_price_to_confirm_in_time(1),
            'eth_usd_conv_rate':
            eth_usd_conv_rate(),
            'conf_time_spread':
            conf_time_spread(),
            'gas_advisories':
            gas_advisories(),
        }
        for key, value in add_in_params.items():
            params[key] = value

    return TemplateResponse(request, 'grants/detail/index.html', params)
Пример #7
0
def is_team_member(grant, profile):
    return is_grant_team_member(grant, profile)
Пример #8
0
    def repr(self, user, build_absolute_uri):
        team_members = serializers.serialize('json', self.team_members.all(),
                            fields=['handle', 'url', 'profile__lazy_avatar_url']
                        )
        if self.grant_type:
            grant_type = serializers.serialize('json', [self.grant_type], fields=['name', 'label'])

        grant_tags = serializers.serialize('json', self.tags.all(),fields=['id', 'name'])

        return {
                'id': self.id,
                'active': self.active,
                'logo_url': self.logo.url if self.logo and self.logo.url else build_absolute_uri(static(f'v2/images/grants/logos/{self.id % 3}.png')),
                'details_url': reverse('grants:details', args=(self.id, self.slug)),
                'title': self.title,
                'description': self.description,
                'description_rich': self.description_rich,
                'last_update': self.last_update,
                'last_update_natural': naturaltime(self.last_update),
                'sybil_score': self.sybil_score,
                'weighted_risk_score': self.weighted_risk_score,
                'is_clr_active': self.is_clr_active,
                'clr_round_num': self.clr_round_num,
                'admin_profile': {
                    'url': self.admin_profile.url,
                    'handle': self.admin_profile.handle,
                    'avatar_url': self.admin_profile.lazy_avatar_url
                },
                'favorite': self.favorite(user) if user.is_authenticated else False,
                'is_on_team': is_grant_team_member(self, user.profile) if user.is_authenticated else False,
                'clr_prediction_curve': self.clr_prediction_curve,
                'last_clr_calc_date':  naturaltime(self.last_clr_calc_date) if self.last_clr_calc_date else None,
                'safe_next_clr_calc_date': naturaltime(self.safe_next_clr_calc_date) if self.safe_next_clr_calc_date else None,
                'amount_received_in_round': self.amount_received_in_round,
                'amount_received': self.amount_received,
                'positive_round_contributor_count': self.positive_round_contributor_count,
                'monthly_amount_subscribed': self.monthly_amount_subscribed,
                'is_clr_eligible': self.is_clr_eligible,
                'slug': self.slug,
                'url': self.url,
                'contract_version': self.contract_version,
                'contract_address': self.contract_address,
                'token_symbol': self.token_symbol,
                'admin_address': self.admin_address,
                'zcash_payout_address': self.zcash_payout_address or '',
                'celo_payout_address': self.celo_payout_address,
                'zil_payout_address': self.zil_payout_address,
                'polkadot_payout_address': self.polkadot_payout_address,
                'kusama_payout_address': self.kusama_payout_address,
                'harmony_payout_address': self.harmony_payout_address,
                'binance_payout_address': self.binance_payout_address,
                'rsk_payout_address': self.rsk_payout_address,
                'algorand_payout_address': self.algorand_payout_address,
                'token_address': self.token_address,
                'image_css': self.image_css,
                'verified': self.twitter_verified,
                'tenants': self.tenants,
                'team_members': json.loads(team_members),
                'metadata': self.metadata,
                'grant_type': json.loads(grant_type) if grant_type else None,
                'grant_tags': json.loads(grant_tags),
                'twitter_handle_1': self.twitter_handle_1,
                'twitter_handle_2': self.twitter_handle_2,
                'reference_url': self.reference_url,
                'github_project_url': self.github_project_url or '',
                'funding_info': self.funding_info,
                'admin_message': self.admin_message,
                'link_to_new_grant': self.link_to_new_grant.url if self.link_to_new_grant else self.link_to_new_grant,
                'region': {'name':self.region, 'label':self.get_region_display()} if self.region and self.region != 'null' else None,
                'has_external_funding': self.has_external_funding
            }
Пример #9
0
 def is_on_team(self, profile):
     return is_grant_team_member(self, profile)
Пример #10
0
from dashboard.models import Profile
from grants.models import *
from grants.utils import is_grant_team_member

handles = [
    'adamstallard',
    'alirezapaslar',
]
grant_id = 191
grant = Grant.objects.get(pk=grant_id)

for handle in handles:
    profile = Profile.objects.filter(handle__iexact=handle).first()
    if not profile:
        print(f"{handle} not found")
        continue
    if not is_grant_team_member(grant, profile):
        print(f"adding {handle}")
        grant.team_members.add(profile)
        grant.save()
    else:
        print(f'{handle} is already a team member')
Пример #11
0
def grant_fund(request, grant_id, grant_slug):
    """Handle grant funding."""
    try:
        grant = Grant.objects.get(pk=grant_id, slug=grant_slug)
    except Grant.DoesNotExist:
        raise Http404

    profile = get_profile(request)

    if not grant.active:
        params = {
            'active': 'grant_error',
            'title': _('Fund - Grant Ended'),
            'grant': grant,
            'text': _('This Grant has ended.'),
            'subtext': _('Contributions can no longer be made this grant')
        }
        return TemplateResponse(request, 'grants/shared/error.html', params)

    if is_grant_team_member(grant, profile):
        params = {
            'active': 'grant_error',
            'title': _('Fund - Grant funding blocked'),
            'grant': grant,
            'text': _('This Grant cannot be funded'),
            'subtext': _('Grant team members cannot contribute to their own grant.')
        }
        return TemplateResponse(request, 'grants/shared/error.html', params)

    if grant.link_to_new_grant:
        params = {
            'active': 'grant_error',
            'title': _('Fund - Grant Migrated'),
            'grant': grant.link_to_new_grant,
            'text': f'This Grant has ended',
            'subtext': 'Contributions can no longer be made to this grant. <br> Visit the new grant to contribute.',
            'button_txt': 'View New Grant'
        }
        return TemplateResponse(request, 'grants/shared/error.html', params)

    active_subscription = Subscription.objects.select_related('grant').filter(
        grant=grant_id, active=True, error=False, contributor_profile=request.user.profile, is_postive_vote=True
    )

    if active_subscription:
        params = {
            'active': 'grant_error',
            'title': _('Subscription Exists'),
            'grant': grant,
            'text': _('You already have an active subscription for this grant.')
        }
        return TemplateResponse(request, 'grants/shared/error.html', params)

    if grant.contract_address == '0x0':
        messages.info(
            request,
            _('This grant is not configured to accept funding at this time.  Please contact [email protected] if you believe this message is in error!')
        )
        logger.error(f"Grant {grant.pk} is not properly configured for funding.  Please set grant.contract_address on this grant")
        return redirect(reverse('grants:details', args=(grant.pk, grant.slug)))

    if request.method == 'POST':
        if 'contributor_address' in request.POST:
            subscription = Subscription()

            if grant.negative_voting_enabled:
                #is_postive_vote = True if request.POST.get('is_postive_vote', 1) else False
                is_postive_vote = request.POST.get('match_direction', '+') == '+'
            else:
                is_postive_vote = True
            subscription.is_postive_vote = is_postive_vote

            subscription.active = False
            subscription.contributor_address = request.POST.get('contributor_address', '')
            subscription.amount_per_period = request.POST.get('amount_per_period', 0)
            subscription.real_period_seconds = request.POST.get('real_period_seconds', 2592000)
            subscription.frequency = request.POST.get('frequency', 30)
            subscription.frequency_unit = request.POST.get('frequency_unit', 'days')
            subscription.token_address = request.POST.get('token_address', '')
            subscription.token_symbol = request.POST.get('token_symbol', '')
            subscription.gas_price = request.POST.get('gas_price', 0)
            subscription.new_approve_tx_id = request.POST.get('sub_new_approve_tx_id', '0x0')
            subscription.num_tx_approved = request.POST.get('num_tx_approved', 1)
            subscription.network = request.POST.get('network', '')
            subscription.contributor_profile = profile
            subscription.grant = grant
            subscription.comments = request.POST.get('comment', '')
            subscription.save()

            # one time payments
            activity = None
            if int(subscription.num_tx_approved) == 1:
                subscription.successful_contribution(subscription.new_approve_tx_id);
                subscription.error = True #cancel subs so it doesnt try to bill again
                subscription.subminer_comments = "skipping subminer bc this is a 1 and done subscription, and tokens were alredy sent"
                subscription.save()
                activity = record_subscription_activity_helper('new_grant_contribution', subscription, profile)
            else:
                activity = record_subscription_activity_helper('new_grant_subscription', subscription, profile)

            if 'comment' in request.POST:
                comment = request.POST.get('comment')
                if comment and activity:
                    profile = request.user.profile
                    if subscription and subscription.negative:
                        profile = Profile.objects.filter(handle='gitcoinbot').first()
                        comment = f"Comment from contributor: {comment}"
                    comment = Comment.objects.create(
                        profile=profile,
                        activity=activity,
                        comment=comment)

            message = 'Your contribution has succeeded. Thank you for supporting Public Goods on Gitcoin !'
            if request.session.get('send_notification'):
                msg_html = request.session.get('msg_html')
                cta_text = request.session.get('cta_text')
                cta_url = request.session.get('cta_url')
                to_user = request.user
                send_notification_to_user_from_gitcoinbot(to_user, cta_url, cta_text, msg_html)
            if int(subscription.num_tx_approved) > 1:
                message = 'Your subscription has been created. It will bill within the next 5 minutes or so. Thank you for supporting Public Goods on Gitcoin !'

            messages.info(
                request,
                message
            )

            return JsonResponse({
                'success': True,
            })

        if 'hide_wallet_address' in request.POST:
            profile.hide_wallet_address = bool(request.POST.get('hide_wallet_address', False))
            profile.save()

        if 'signature' in request.POST:
            sub_new_approve_tx_id = request.POST.get('sub_new_approve_tx_id', '')
            subscription = Subscription.objects.filter(new_approve_tx_id=sub_new_approve_tx_id).first()
            subscription.active = True

            subscription.subscription_hash = request.POST.get('subscription_hash', '')
            subscription.contributor_signature = request.POST.get('signature', '')
            if 'split_tx_id' in request.POST:
                subscription.split_tx_id = request.POST.get('split_tx_id', '')
                subscription.save_split_tx_to_contribution()
            if 'split_tx_confirmed' in request.POST:
                subscription.split_tx_confirmed = bool(request.POST.get('split_tx_confirmed', False))
                subscription.save_split_tx_to_contribution()
            subscription.save()

            value_usdt = subscription.get_converted_amount()
            if value_usdt:
                grant.monthly_amount_subscribed += subscription.get_converted_monthly_amount()

            grant.save()
            if not subscription.negative:
                new_supporter(grant, subscription)
                thank_you_for_supporting(grant, subscription)
            return JsonResponse({
                'success': True,
                'url': reverse('grants:details', args=(grant.pk, grant.slug))
            })

    # handle phantom funding
    active_tab = 'normal'
    fund_reward = None
    round_number = clr_round
    can_phantom_fund = request.user.is_authenticated and request.user.groups.filter(name='phantom_funders_round_5').exists() and clr_active
    phantom_funds = PhantomFunding.objects.filter(profile=request.user.profile, round_number=round_number).order_by('created_on').nocache() if request.user.is_authenticated else PhantomFunding.objects.none()
    is_phantom_funding_this_grant = can_phantom_fund and phantom_funds.filter(grant=grant).exists()
    show_tweet_modal = False
    fund_reward = get_fund_reward(request, grant)
    if can_phantom_fund and request.POST.get('toggle_phantom_fund'):
        if is_phantom_funding_this_grant:
            msg = "You are no longer signaling for this grant."
            phantom_funds.filter(grant=grant).delete()
        else:
            msg = "You are now signaling for this grant."
            show_tweet_modal = True
            pt = PhantomFunding.objects.create(grant=grant, profile=request.user.profile, round_number=round_number)
            record_grant_activity_helper('new_grant_contribution', grant, request.user.profile, amount=pt.value, token='DAI')

        messages.info(
            request,
            msg
        )
        is_phantom_funding_this_grant = not is_phantom_funding_this_grant
    images = [
        'new.svg',
        'torchbearer.svg',
        'robots.png',
        'profile/fund.svg',
    ]
    img = random.choice(images)
    params = {
        'profile': profile,
        'active': 'fund_grant',
        'title': matching_live + grant.title + " | Fund Now",
        'card_desc': grant.description,
        'avatar_url': grant.logo.url if grant.logo else None,
        'subscription': {},
        'show_tweet_modal': show_tweet_modal,
        'direction': request.GET.get('direction', '+'),
        'grant_has_no_token': True if grant.token_address == '0x0000000000000000000000000000000000000000' else False,
        'grant': grant,
        'img': img,
        'clr_prediction_curve': [c[1] for c in grant.clr_prediction_curve] if grant.clr_prediction_curve and len(grant.clr_prediction_curve[0]) > 1 else [0, 0, 0, 0, 0, 0],
        'keywords': get_keywords(),
        'recommend_gas_price': recommend_min_gas_price_to_confirm_in_time(4),
        'recommend_gas_price_slow': recommend_min_gas_price_to_confirm_in_time(120),
        'recommend_gas_price_avg': recommend_min_gas_price_to_confirm_in_time(15),
        'recommend_gas_price_fast': recommend_min_gas_price_to_confirm_in_time(1),
        'eth_usd_conv_rate': eth_usd_conv_rate(),
        'conf_time_spread': conf_time_spread(),
        'gas_advisories': gas_advisories(),
        'splitter_contract_address': settings.SPLITTER_CONTRACT_ADDRESS,
        'gitcoin_donation_address': settings.GITCOIN_DONATION_ADDRESS,
        'can_phantom_fund': can_phantom_fund,
        'is_phantom_funding_this_grant': is_phantom_funding_this_grant,
        'active_tab': active_tab,
        'fund_reward': fund_reward,
        'phantom_funds': phantom_funds,
        'clr_round': clr_round,
        'clr_active': clr_active,
        'total_clr_pot': total_clr_pot,
    }
    return TemplateResponse(request, 'grants/fund.html', params)