Ejemplo n.º 1
0
def batch_process_grant_contributions(self,
                                      grants_with_payload,
                                      profile_id,
                                      retry: bool = True) -> None:
    """
    :param self:
    :param grants_with_payload: list of dicts with grant_id, grant_slug and payload
    :param profile_id:
    :return:
    """
    grants_with_subscription = []
    for grant_with_payload in grants_with_payload:
        grant_id = grant_with_payload["grant_id"]
        grant_slug = grant_with_payload["grant_slug"]
        payload = grant_with_payload["payload"]
        grant, subscription = process_grant_contribution(
            grant_id,
            grant_slug,
            profile_id,
            payload,
            send_supporter_mail=False,
            retry=retry)
        grants_with_subscription.append({
            "grant": grant,
            "subscription": subscription
        })
        recalc_clr_if_x_minutes_old.delay(grant_id, 10)
    try:
        thank_you_for_supporting(grants_with_subscription)
    except Exception as e:
        logger.exception(e)
Ejemplo n.º 2
0
def record_contribution_activity(contribution):
    from dashboard.models import Activity
    from marketing.mails import new_supporter, thank_you_for_supporting, successful_contribution
    from grants.tasks import update_grant_metadata

    try:
        event_name = 'new_grant_contribution'

        subscription = contribution.subscription
        grant = subscription.grant

        metadata = {
            'id': subscription.id,
            'value_in_token': str(subscription.amount_per_period),
            'value_in_usdt_now':
            str(round(subscription.amount_per_period_usdt, 2)),
            'token_name': subscription.token_symbol,
            'title': subscription.grant.title,
            'grant_url': subscription.grant.url,
            'num_tx_approved': round(subscription.num_tx_approved),
            'category': 'grant',
        }

        kwargs = {
            'activity_type': event_name,
            'grant': grant,
            'subscription': subscription,
            'profile': subscription.contributor_profile,
            'metadata': metadata
        }

        activity = Activity.objects.create(**kwargs)
        if subscription.comments and activity:
            Comment.objects.create(profile=subscription.contributor_profile,
                                   activity=activity,
                                   comment=subscription.comments)

        # note: commenting out for optimistic UI
        # successful_contribution(grant, subscription, contribution)
        # update_grant_metadata.delay(grant.pk)
        new_supporter(grant, subscription)
        grants_with_subscription = [{
            'grant': grant,
            'subscription': subscription
        }]
        thank_you_for_supporting(grants_with_subscription)

    except Exception as e:
        logger.error(
            f"error in record_contribution_activity: {e} - {contribution}")
Ejemplo n.º 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)
Ejemplo n.º 4
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': _('Grant Ended'),
            'grant': grant,
            'text': _('This Grant is not longer active.')
        }
        return TemplateResponse(request, 'grants/shared/error.html', params)

    if grant.admin_profile == profile:
        params = {
            'active': 'grant_error',
            'title': _('Invalid Grant Subscription'),
            'grant': grant,
            'text': _('You cannot fund your own Grant.')
        }
        return TemplateResponse(request, 'grants/shared/error.html', params)

    active_subscription = Subscription.objects.select_related('grant').filter(
        grant=grant_id, active=True, 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 request.method == 'POST':
        subscription = Subscription()

        subscription.subscription_hash = request.POST.get(
            'subscription_hash', '')
        subscription.contributor_signature = request.POST.get('signature', '')
        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('denomination', '')
        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', '')
        subscription.network = request.POST.get('network', '')
        subscription.contributor_profile = profile
        subscription.grant = grant
        subscription.save()
        new_supporter(grant, subscription)
        thank_you_for_supporting(grant, subscription)
        return redirect(reverse('grants:details', args=(grant.pk, grant.slug)))

    params = {
        'active':
        'fund_grant',
        'title':
        _('Fund Grant'),
        'card_desc':
        _('Provide sustainable funding for Open Source with Gitcoin Grants'),
        'subscription': {},
        'grant_has_no_token':
        True if grant.token_address
        == '0x0000000000000000000000000000000000000000' else False,
        'grant':
        grant,
        '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(),
    }
    return TemplateResponse(request, 'grants/fund.html', params)
Ejemplo n.º 5
0
def process_grant_contribution(self,
                               grant_id,
                               grant_slug,
                               profile_id,
                               package,
                               retry: bool = True) -> None:
    """
    :param self:
    :param grant_id:
    :param grant_slug:
    :param profile_id:
    :param package:
    :return:
    """
    grant = Grant.objects.get(pk=grant_id)
    profile = Profile.objects.get(pk=profile_id)

    if 'contributor_address' in package:
        subscription = Subscription()

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

        fee_pct = float(package.get('gitcoin-grant-input-amount', 0))

        subscription.active = False
        subscription.contributor_address = package.get('contributor_address',
                                                       '')
        subscription.amount_per_period = package.get('amount_per_period', 0)
        subscription.real_period_seconds = package.get('real_period_seconds',
                                                       2592000)
        subscription.frequency = package.get('frequency', 30)
        subscription.frequency_unit = package.get('frequency_unit', 'days')
        subscription.token_address = package.get('token_address', '')
        subscription.token_symbol = package.get('token_symbol', '')
        subscription.gas_price = (float(subscription.amount_per_period) *
                                  (fee_pct / 100))
        subscription.new_approve_tx_id = package.get('sub_new_approve_tx_id',
                                                     '0x0')
        subscription.split_tx_id = package.get('split_tx_id', '0x0')
        subscription.num_tx_approved = package.get('num_tx_approved', 1)
        subscription.network = package.get('network', '')
        subscription.contributor_profile = profile
        subscription.grant = grant
        subscription.comments = package.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 package:
            _profile = profile
            comment = package.get('comment')
            if comment and activity:
                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)

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

        new_supporter(grant, subscription)
        thank_you_for_supporting(grant, subscription)

        update_grant_metadata.delay(grant_id)
Ejemplo n.º 6
0
Archivo: views.py Proyecto: rmshea/web
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': _('Grant Ended'),
            'grant': grant,
            'text': _('This Grant is not longer active.')
        }
        return TemplateResponse(request, 'grants/shared/error.html', params)

    if grant.admin_profile == profile:
        params = {
            'active': 'grant_error',
            'title': _('Invalid Grant Subscription'),
            'grant': grant,
            'text': _('You cannot fund your own 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.save()

            # one time payments
            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()
                record_subscription_activity_helper('new_grant_contribution',
                                                    subscription, profile)
            else:
                record_subscription_activity_helper('new_grant_subscription',
                                                    subscription, profile)

            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 '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', '')
            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

    params = {
        'active':
        'fund_grant',
        'title':
        _('Fund Grant'),
        'card_desc':
        _('Provide sustainable funding for Open Source with Gitcoin Grants'),
        'subscription': {},
        'grant_has_no_token':
        True if grant.token_address
        == '0x0000000000000000000000000000000000000000' else False,
        'grant':
        grant,
        '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
    }
    return TemplateResponse(request, 'grants/fund.html', params)
Ejemplo n.º 7
0
def process_grant_contribution(self,
                               grant_id,
                               grant_slug,
                               profile_id,
                               package,
                               send_supporter_mail: bool = True,
                               retry: bool = True):
    """
    :param self:
    :param grant_id:
    :param grant_slug:
    :param profile_id:
    :param package:
    :param send_supporter_mail:
    :return:
    """
    from grants.views import record_subscription_activity_helper

    grant = Grant.objects.get(pk=grant_id)
    profile = Profile.objects.get(pk=profile_id)

    if 'contributor_address' in package:
        subscription = Subscription()

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

        fee_pct = float(package.get('gitcoin-grant-input-amount', 0))

        subscription.active = False
        subscription.contributor_address = package.get('contributor_address',
                                                       '')
        subscription.amount_per_period = package.get('amount_per_period', 0)
        subscription.real_period_seconds = package.get('real_period_seconds',
                                                       2592000)
        subscription.frequency = package.get('frequency', 30)
        subscription.frequency_unit = package.get('frequency_unit', 'days')
        subscription.token_address = package.get('token_address', '')
        subscription.token_symbol = package.get('token_symbol', '')
        subscription.gas_price = (float(subscription.amount_per_period) *
                                  (fee_pct / 100))
        subscription.new_approve_tx_id = package.get('sub_new_approve_tx_id',
                                                     '0x0')
        subscription.split_tx_id = package.get('split_tx_id', '0x0')
        subscription.num_tx_approved = package.get('num_tx_approved', 1)
        subscription.network = package.get('network', '')
        subscription.visitorId = package.get('visitorId', '')
        if subscription.network == 'undefined':
            # we unfortunately cannot trust the frontend to give us a valid network name
            # so this handles that case.  more details are available at
            # https://gitcoincore.slack.com/archives/C01FQV4FX4J/p1607980714026400
            if not settings.DEBUG:
                subscription.network = 'mainnet'
        subscription.contributor_profile = profile
        subscription.grant = grant
        subscription.comments = package.get('comment', '')
        subscription.save()

        value_usdt = subscription.get_converted_amount(True)
        include_for_clr = package.get('include_for_clr')
        if value_usdt < 1 or subscription.contributor_profile.shadowbanned:
            include_for_clr = False

        subscription.successful_contribution(subscription.new_approve_tx_id,
                                             include_for_clr,
                                             checkout_type=package.get(
                                                 'checkout_type', None))

        # one time payments
        activity = None
        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()

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

        if 'anonymize_gitcoin_grants_contributions' in package:
            profile.anonymize_gitcoin_grants_contributions = package.get(
                'anonymize_gitcoin_grants_contributions')
            profile.save()

        activity_profile = profile if not profile.anonymize_gitcoin_grants_contributions else Profile.objects.get(
            handle='gitcoinbot')

        activity = record_subscription_activity_helper(
            'new_grant_contribution', subscription, activity_profile)

        if 'comment' in package:
            _profile = profile
            comment = package.get('comment')
            if value_usdt >= 1 and comment and activity:
                if profile.anonymize_gitcoin_grants_contributions:
                    _profile = Profile.objects.filter(
                        handle='gitcoinbot').first()
                    comment = f"Comment from contributor: {comment}"
                comment = Comment.objects.create(profile=_profile,
                                                 activity=activity,
                                                 comment=comment)

        # emails to contributor
        if value_usdt >= 1 and send_supporter_mail:
            grants_with_subscription = [{
                'grant': grant,
                'subscription': subscription
            }]
            try:
                thank_you_for_supporting(grants_with_subscription)
            except Exception as e:
                logger.exception(e)

        update_grant_metadata.delay(grant_id)
        return grant, subscription
Ejemplo n.º 8
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)