Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/stable'
Browse files Browse the repository at this point in the history
  • Loading branch information
thelostone-mc committed Dec 1, 2020
2 parents e0d31d8 + e5a00c0 commit 12595e3
Show file tree
Hide file tree
Showing 19 changed files with 236 additions and 86 deletions.
1 change: 1 addition & 0 deletions app/app/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
# kudos
re_path(r'^kudos/?$', kudos.views.about, name='kudos_main'),
re_path(r'^kudos/about/?$', kudos.views.about, name='kudos_about'),
re_path(r'^kudos/sync/?$', kudos.views.sync, name='kudos_sync'),
re_path(r'^kudos/marketplace/?$', kudos.views.marketplace, name='kudos_marketplace'),
re_path(r'^kudos/mint/?$', kudos.views.mint, name='kudos_mint'),
re_path(r'^kudos/send/?$', kudos.views.send_2, name='kudos_send'),
Expand Down
2 changes: 1 addition & 1 deletion app/assets/onepager/js/receive.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ $(document).ready(function() {
gasLimit = new web3.utils.BN(gasLimit);
var send_amount = holderBalance.sub(gasLimit.mul(gas_price_wei)).sub(buffer);

if (document.override_send_amount) {
if (document.override_send_amount && (document.override_send_amount * 10 ** 18) < send_amount) {
send_amount = document.override_send_amount * 10 ** 18; // TODO: decimals
}

Expand Down
28 changes: 28 additions & 0 deletions app/assets/v2/js/pages/profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,34 @@ $(document).ready(function() {
}
});
}
$('#kudos-section').on('click', '.fa-sync', function(e) {
e.preventDefault();
e.stopPropagation();
if ($(this).data('owned') == 'False') {
_alert('To re-issue this kudos, please contact the sender and have them re-send it.', 'error');
return;
}
let url = '/kudos/sync/?pk=' + $(this).data('id');
let $target = $(this).parents('.flip-card__extra-data').find('.block_explorer_link');

$.get(url, function(response) {
let block_ex_url = response['url'];
let txid = response['txid'];

$target.attr('href', block_ex_url);
let txid_trunc = txid.substring(0, 5) + '...' + txid.substring(txid.length - 10, txid.length);

$target.text(txid_trunc);
$target.css('color', 'grey');
setTimeout(function() {
$target.css('color', 'white');
}, 1000);
_alert('Sync re-submitted to chain.', 'info', 1000);
});
$(this).remove();

});


$('#kudos-section').on('click keypress', '.flip-card', e => {
if ($(e.target).is('a')) {
Expand Down
13 changes: 11 additions & 2 deletions app/dashboard/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3160,6 +3160,13 @@ def kudos_authored(self):
from kudos.models import Token
return Token.objects.filter(artist=self.handle, num_clones_allowed__gt=1, hidden=False)

@property
def get_failed_kudos(self):
from kudos.models import KudosTransfer
pks = list(self.get_my_kudos.values_list('pk', flat=True)) + list(self.get_sent_kudos.values_list('pk', flat=True))
qs = KudosTransfer.objects.filter(pk__in=pks)
return qs.filter(Q(txid='pending_celery') | Q(tx_status__in=['dropped', 'unknown']))

@property
def get_my_kudos(self):
from kudos.models import KudosTransfer
Expand All @@ -3175,7 +3182,8 @@ def get_my_kudos(self):
kudos_transfers = kudos_transfers.filter(
kudos_token_cloned_from__contract__network__in=[settings.KUDOS_NETWORK, 'xdai']
)
kudos_transfers = kudos_transfers.send_success() | kudos_transfers.send_pending() | kudos_transfers.not_submitted()
# Multiple support requests for kudos not showing on profile were caused by this
# kudos_transfers = kudos_transfers.send_success() | kudos_transfers.send_pending() | kudos_transfers.not_submitted()

# remove this line IFF we ever move to showing multiple kudos transfers on a profile
kudos_transfers = kudos_transfers.distinct('id')
Expand All @@ -3191,7 +3199,8 @@ def get_sent_kudos(self):
kt_sender_profile = KudosTransfer.objects.filter(sender_profile=self)

kudos_transfers = kt_address | kt_sender_profile
kudos_transfers = kudos_transfers.send_success() | kudos_transfers.send_pending() | kudos_transfers.not_submitted()
# Multiple support requests for kudos not showing on profile were caused by this
# kudos_transfers = kudos_transfers.send_success() | kudos_transfers.send_pending() | kudos_transfers.not_submitted()
kudos_transfers = kudos_transfers.filter(
kudos_token_cloned_from__contract__network__in=[settings.KUDOS_NETWORK, 'xdai']
)
Expand Down
2 changes: 2 additions & 0 deletions app/dashboard/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2883,6 +2883,8 @@ def get_profile_tab(request, profile, tab, prev_context):
kudos_limit = 8
context['kudos'] = owned_kudos[0:kudos_limit]
context['sent_kudos'] = sent_kudos[0:kudos_limit]
if request.GET.get('failed', 0):
context['kudos'] = profile.get_failed_kudos
context['kudos_count'] = owned_kudos.count()
context['sent_kudos_count'] = sent_kudos.count()
elif tab == 'ptokens':
Expand Down
70 changes: 70 additions & 0 deletions app/kudos/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,73 @@ def reconcile_kudos_preferred_wallet(profile):
profile.save()

return profile.preferred_kudos_wallet


def re_send_kudos_transfer(kt, override_with_xdai_okay):
from dashboard.utils import get_web3, has_tx_mined
from gas.utils import recommend_min_gas_price_to_confirm_in_time
from kudos.utils import kudos_abi
from web3 import Web3
from kudos.models import KudosTransfer
from django.utils import timezone

gas_clear_within_mins = 1
gas_multiplier = 1.2

if not kt.kudos_token_cloned_from.is_owned_by_gitcoin:
print(f'{kt.id} => not owned by gitcoin')
return

network = kt.network
if network == 'mainnet':
if kt.kudos_token_cloned_from.on_xdai and override_with_xdai_okay:
network = 'xdai'
kt.network = 'xdai'
kt.kudos_token_cloned_from = kt.kudos_token_cloned_from.on_xdai
kt.save()
w3 = get_web3(network)
kudos_contract_address = Web3.toChecksumAddress(settings.KUDOS_CONTRACT_MAINNET)
if network == 'xdai':
kudos_contract_address = Web3.toChecksumAddress(settings.KUDOS_CONTRACT_XDAI)
kudos_owner_address = Web3.toChecksumAddress(settings.KUDOS_OWNER_ACCOUNT)
nonce = w3.eth.getTransactionCount(kudos_owner_address)

token_id = kt.kudos_token_cloned_from.token_id
address = kt.receive_address
if not address:
address = kt.recipient_profile.preferred_payout_address
if not address:
address = kt.recipient_profile.last_observed_payout_address
price_finney = kt.kudos_token_cloned_from.price_finney

try:

contract = w3.eth.contract(Web3.toChecksumAddress(kudos_contract_address), abi=kudos_abi())
gasPrice = int(gas_multiplier * float(recommend_min_gas_price_to_confirm_in_time(gas_clear_within_mins)) * 10**9)
if network == 'xdai':
gasPrice = 1 * 10**9
tx = contract.functions.clone(Web3.toChecksumAddress(address), token_id, 1).buildTransaction({
'nonce': nonce,
'gas': 500000,
'gasPrice': gasPrice,
'value': int(price_finney / 1000.0 * 10**18),
})

signed = w3.eth.account.signTransaction(tx, settings.KUDOS_PRIVATE_KEY)
txid = w3.eth.sendRawTransaction(signed.rawTransaction).hex()
nonce += 1
print(f'sent tx nonce:{nonce} for kt:{kt.id} on {network}')
kt.txid = txid
kt.receive_txid = txid
kt.tx_status = 'pending'
kt.receive_tx_status = 'pending'
kt.network = network
kt.tx_time = timezone.now()
kt.receive_tx_time = timezone.now()
kt.save()
return txid

except Exception as e:
print(e)
error = "Could not redeem your kudos. Please try again soon."
return None
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def handle(self, *args, **options):
_async = options['async']
override_gas_price = options['override_gas_price']
order_by = options['order_by'].replace('_', '-')
delay_if_gas_prices_gt_redeem = 300
delay_if_gas_prices_gt_redeem = 200
send_notif_email = True
send_on_xdai = True
gitcoin_owner_addr = '0x6239FF1040E412491557a7a02b2CBcC5aE85dc8F'
Expand Down
6 changes: 4 additions & 2 deletions app/kudos/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ def redeem_bulk_kudos(self, kt_id, delay_if_gas_prices_gt_redeem= 50, override_g
with redis.lock("tasks:all_kudos_requests", timeout=LOCK_TIMEOUT):
with redis.lock("tasks:redeem_bulk_kudos:%s" % kt_id, timeout=override_lock_timeout):
multiplier = 1
# high gas prices, 5 hour gas limit - DL
gas_price = int(float(recommend_min_gas_price_to_confirm_in_time(300)) * multiplier)
gas_price = int(float(recommend_min_gas_price_to_confirm_in_time(1)) * multiplier * 10**9)
if network == 'xdai':
gas_price = 1 * 10**9

if override_gas_price:
gas_price = override_gas_price
if gas_price > delay_if_gas_prices_gt_redeem:
Expand Down
10 changes: 8 additions & 2 deletions app/kudos/templates/shared/kudos_card_hover_content.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,15 @@
<a href="{{kt.github_url}}" target="_blank">{% trans 'Issue url' %}</a>
{% endif %}
{% if kt.receive_txid == 'pending_celery' %}
Pending Issuance on Chain
Pending Issuance on Chain
{% else %}
<a title="{% trans 'tx on block explroer' %}" href="{{kt.receive_tx_blockexplorer_link}}" target="_blank" class="mb-1">{{ kt.receive_txid|humanize_address }}</a>
<a title="{% trans 'tx on block explorer' %}" href="{{kt.receive_tx_blockexplorer_link}}" target="_blank" class="mb-1 block_explorer_link">{{ kt.receive_txid|humanize_address }}</a>
{% endif %}
{% if kt.receive_txid == 'pending_celery' or kt.receive_tx_status == 'dropped' or kt.receive_tx_status == 'unknown' %}
{% if github_handle == kt.username or github_handle == kt.from_username or 1 %}
<div><i class="fas fa-sync" data-id="{{kt.id}}" data-owned='{{kt.kudos_token_cloned_from.is_owned_by_gitcoin}}'></i></div>
{% endif %}
{% endif %}

</div>
{% endfor %}
23 changes: 23 additions & 0 deletions app/kudos/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,29 @@ def get_profile(handle):
return to_profile


def sync(request):
response = {}
try:
kt_id = request.GET.get('pk')
kt = KudosTransfer.objects.get(pk=kt_id)
response['txid'] = kt.txid
if kt.kudos_token_cloned_from.is_owned_by_gitcoin:
if request.user.is_authenticated:
if request.user.profile.handle in [kt.username.replace('@',''), kt.from_username.replace('@','')] or settings.DEBUG:
authd = not kt.tx_time or kt.tx_time < (timezone.now() - timezone.timedelta(minutes=30))
authd = authd and (kt.receive_txid == 'pending_celery' or kt.receive_tx_status == 'dropped' or kt.receive_tx_status == 'unknown')
if authd:
from kudos.helpers import re_send_kudos_transfer
response['txid'] = re_send_kudos_transfer(kt, True)
from dashboard.utils import tx_id_to_block_explorer_url
response['url'] = tx_id_to_block_explorer_url(kt.txid, kt.network)
response['success'] = 1
except Exception as e:
response['error'] = str(e)

return JsonResponse(response)


def about(request):
"""Render the Kudos 'about' page."""
activity_limit = 5
Expand Down
29 changes: 29 additions & 0 deletions app/marketing/management/commands/prune_bad_activities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'''
Copyright (C) 2020 Gitcoin Core
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
'''
import time

from django.core.management.base import BaseCommand
from django.utils import timezone

from dashboard.models import Activity


class Command(BaseCommand):
help = 'deletes the None None activity feed items in the newsfeed. No idea where they come from, but this at least keeps them from showing up too long'

def handle(self, *args, **options):
then = timezone.now() - timezone.timedelta(minutes=60)
activities = Activity.objects.filter(activity_type='status_update', metadata__title=None, created_on__gt=then).order_by('-pk')
print(activities.count())
activities.delete()
43 changes: 26 additions & 17 deletions app/perftools/management/commands/create_page_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
'''

import json
import logging

from django.conf import settings
from django.core.management.base import BaseCommand
Expand Down Expand Up @@ -46,6 +47,7 @@
from retail.views import get_contributor_landing_page_context, get_specific_activities
from townsquare.views import tags

logger = logging.getLogger(__name__)

def create_email_inventory_cache():
print('create_email_inventory_cache')
Expand Down Expand Up @@ -384,24 +386,31 @@ class Command(BaseCommand):
help = 'generates some /results data'

def handle(self, *args, **options):
create_grant_type_cache()
create_grant_clr_cache()
create_grant_category_size_cache()
create_grant_active_clr_mapping()
operations = []
operations.append(create_grant_type_cache)
operations.append(create_grant_clr_cache)
operations.append(create_grant_category_size_cache)
operations.append(create_grant_active_clr_mapping)
if not settings.DEBUG:
create_results_cache()
create_hidden_profiles_cache()
create_tribes_cache()
create_activity_cache()
create_post_cache()
create_top_grant_spenders_cache()
create_avatar_cache()
create_quests_cache()
create_grants_cache()
create_contributor_landing_page_context()
create_hackathon_cache()
create_hackathon_list_page_cache()
operations.append(create_results_cache)
operations.append(create_hidden_profiles_cache)
operations.append(create_tribes_cache)
operations.append(create_activity_cache)
operations.append(create_post_cache)
operations.append(create_top_grant_spenders_cache)
operations.append(create_avatar_cache)
operations.append(create_quests_cache)
operations.append(create_grants_cache)
operations.append(create_contributor_landing_page_context)
operations.append(create_hackathon_cache)
operations.append(create_hackathon_list_page_cache)
hour = int(timezone.now().strftime('%H'))
if hour < 4:
# do dailyi updates
create_email_inventory_cache()
operations.append(create_email_inventory_cache)
for func in operations:
try:
print(f'running {func}')
func()
except Exception as e:
logger.exception(e)
3 changes: 3 additions & 0 deletions app/perftools/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ def sitemap(request, section=None, template_name='sitemap.xml', mimetype='applic
@csrf_exempt
def blocknative(request):
from economy.models import TXUpdate
if not request.body:
from dashboard.views import profile
return profile(request, 'blocknative')
body = json.loads(request.body)
if body['apiKey'] == settings.BLOCKNATIVE_API:
txu = TXUpdate.objects.create(body=body)
Expand Down
7 changes: 6 additions & 1 deletion app/quests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ def get_base_quest_view_params(user, quest):
profile = user.profile if user.is_authenticated else None
attempts = quest.attempts.filter(profile=profile) if profile else QuestAttempt.objects.none()
is_owner = quest.creator.pk == user.profile.pk if user.is_authenticated else False
title = "Play the *" + quest.title + "* Gitcoin Quest"
if quest.kudos_reward:
title += f" and win a *{quest.kudos_reward.humanized_name}* Kudos"
if quest.reward_tip:
title = f"[WIN {quest.reward_tip.value_true} {quest.reward_tip.tokenName}] " + title
params = {
'quest': quest,
'hide_col': True,
Expand All @@ -105,7 +110,7 @@ def get_base_quest_view_params(user, quest):
'is_owner': is_owner,
'is_owner_or_staff': is_owner or user.is_staff,
'body_class': 'quest_battle',
'title': "Play the *" + quest.title + (f"* Gitcoin Quest and win a *{quest.kudos_reward.humanized_name}* Kudos" if quest.kudos_reward else ""),
'title': title,
'avatar_url': quest.avatar_url_png,
'card_desc': quest.description,
'seconds_per_question': quest.game_schema.get('seconds_per_question', 30),
Expand Down
2 changes: 2 additions & 0 deletions app/quests/templates/quests/new.html
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ <h4>
<div class=hidden>
{% include 'shared/add_kudos.html' with name='reward2' filter_by_address="0x6239FF1040E412491557a7a02b2CBcC5aE85dc8F" %}
</div>
{% elif package.reward_tip %}
Tip Reward, N/A
{% else %}
{% include 'shared/add_kudos.html' with name='reward' filter_by_address="0x6239FF1040E412491557a7a02b2CBcC5aE85dc8F" %}
{% endif %}
Expand Down
6 changes: 4 additions & 2 deletions app/quests/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,11 @@ def editquest(request, pk=None):
counter += 1

validation_pass = True
reward = None
try:
enemy = Token.objects.get(pk=package.get('enemy'))
reward = Token.objects.get(pk=package.get('reward'))
if package.get('reward'):
reward = Token.objects.get(pk=package.get('reward'))
except Exception as e:
messages.error(request, 'Unable to find Kudos')
validation_pass = False
Expand Down Expand Up @@ -195,7 +197,7 @@ def editquest(request, pk=None):
package['reading_material_url'] = quest.game_schema.get('prep_materials', [{}])[0].get('url')
package['reading_material_name'] = quest.game_schema.get('prep_materials', [{}])[0].get('title')
package['video_enabled'] = quest.video
package['reward'] = quest.kudos_reward.pk
package['reward'] = quest.kudos_reward.pk if quest.kudos_reward else None
package['enemy'] = quest.game_metadata.get('enemy', {}).get('id')
package['points'] = quest.value
package['minutes'] = quest.cooldown_minutes
Expand Down
Loading

0 comments on commit 12595e3

Please sign in to comment.