diff --git a/app/assets/v2/images/avatar3d/chappie2.svg b/app/assets/v2/images/avatar3d/chappie2.svg
new file mode 100644
index 00000000000..4bbd3def941
--- /dev/null
+++ b/app/assets/v2/images/avatar3d/chappie2.svg
@@ -0,0 +1,11546 @@
+
+
+
diff --git a/app/assets/v2/images/avatar3d/walle3.svg b/app/assets/v2/images/avatar3d/walle3.svg
new file mode 100644
index 00000000000..0cbd8aa32b0
--- /dev/null
+++ b/app/assets/v2/images/avatar3d/walle3.svg
@@ -0,0 +1,2768 @@
+
+
\ No newline at end of file
diff --git a/app/avatar/views_3d.py b/app/avatar/views_3d.py
index 06e9cd91890..56f242482d2 100644
--- a/app/avatar/views_3d.py
+++ b/app/avatar/views_3d.py
@@ -423,6 +423,15 @@ def get_avatar_attrs(theme, key):
'tone_maps': [],
'path': 'assets/v2/images/avatar3d/walle2.svg',
},
+ 'walle3': {
+ 'preview_viewbox': {
+ 'background': '0 0 350 350',
+ },
+ 'hair_tones': [],
+ 'skin_tones': [],
+ 'tone_maps': [],
+ 'path': 'assets/v2/images/avatar3d/walle3.svg',
+ },
'chappie': {
'preview_viewbox': {
'background': '0 0 350 350',
@@ -432,6 +441,15 @@ def get_avatar_attrs(theme, key):
'tone_maps': [],
'path': 'assets/v2/images/avatar3d/chappie.svg',
},
+ 'chappie2': {
+ 'preview_viewbox': {
+ 'background': '0 0 350 350',
+ },
+ 'hair_tones': [],
+ 'skin_tones': [],
+ 'tone_maps': [],
+ 'path': 'assets/v2/images/avatar3d/chappie2.svg',
+ },
'megaman2': {
'preview_viewbox': {
'Background': '0 0 350 350',
diff --git a/app/chat/management/commands/sync_users_to_chat.py b/app/chat/management/commands/sync_users_to_chat.py
index 94a589b5910..201a3bf4923 100644
--- a/app/chat/management/commands/sync_users_to_chat.py
+++ b/app/chat/management/commands/sync_users_to_chat.py
@@ -59,6 +59,6 @@ def handle(self, *args, **options):
except ConnectionError as exec:
logger.error(str(exec))
- self.retry(30)
+ self.retry(countdown=30)
except Exception as e:
logger.error(str(e))
diff --git a/app/chat/tasks.py b/app/chat/tasks.py
index 9b44b8e8b1d..0c060d07d3f 100644
--- a/app/chat/tasks.py
+++ b/app/chat/tasks.py
@@ -208,7 +208,7 @@ def create_channel(self, options, bounty_id=None, retry: bool = True) -> None:
except ConnectionError as exc:
logger.info(str(exc))
logger.info("Retrying connection")
- self.retry(30)
+ self.retry(countdown=30)
except Exception as e:
print("we got an exception when creating a channel")
logger.error(str(e))
@@ -308,7 +308,7 @@ def add_to_channel(self, channel_details, chat_user_ids: list, retry: bool = Tru
except ConnectionError as exc:
logger.info(str(exc))
logger.info("Retrying connection")
- self.retry(30)
+ self.retry(countdown=30)
except Exception as e:
logger.error(str(e))
@@ -342,7 +342,7 @@ def create_user(self, options, params, profile_handle='', retry: bool = True):
except ConnectionError as exc:
logger.info(str(exc))
logger.info("Retrying connection")
- self.retry(30)
+ self.retry(countdown=30)
except Exception as e:
logger.error(str(e))
return None
@@ -382,6 +382,6 @@ def patch_chat_user(self, query_opts, update_opts, retry: bool = True) -> None:
logger.info(str(exc))
logger.info("Retrying connection")
- self.retry(30)
+ self.retry(countdown=30)
except Exception as e:
logger.error(str(e))
diff --git a/app/dashboard/tasks.py b/app/dashboard/tasks.py
index 0227a5aeef4..2fcd7e28131 100644
--- a/app/dashboard/tasks.py
+++ b/app/dashboard/tasks.py
@@ -77,7 +77,7 @@ def bounty_emails(self, emails, msg, profile_handle, invite_url=None, kudos_invi
except ConnectionError as exc:
logger.info(str(exc))
logger.info("Retrying connection")
- self.retry(30)
+ self.retry(countdown=30)
except Exception as e:
logger.error(str(e))
diff --git a/app/grants/views.py b/app/grants/views.py
index 600e4c9cd4e..787ea42952a 100644
--- a/app/grants/views.py
+++ b/app/grants/views.py
@@ -79,7 +79,7 @@
round_end = timezone.datetime(2020, 4, 7, 17, 0)
round_types = ['media', 'tech', 'health']
-kudos_reward_pks = [12580, 12584, 12572, 125868, 12552, 12556, 12557, 125677, 12550, 12427, 12392, 12307, 12343, 12156, 12164]
+kudos_reward_pks = [12580, 12584, 12572, 125868, 12552, 12556, 12557, 125677, 12550, 12392, 12307, 12343, 12156, 12164]
if not clr_active:
clr_matching_banners_style = 'results'
diff --git a/app/kudos/migrations/0012_tokenrequest_bounty_url.py b/app/kudos/migrations/0012_tokenrequest_bounty_url.py
new file mode 100644
index 00000000000..56d86bf7e8f
--- /dev/null
+++ b/app/kudos/migrations/0012_tokenrequest_bounty_url.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.2.4 on 2020-04-01 20:46
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('kudos', '0011_auto_20191106_0237'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='tokenrequest',
+ name='bounty_url',
+ field=models.CharField(blank=True, default='', max_length=255),
+ ),
+ ]
diff --git a/app/kudos/models.py b/app/kudos/models.py
index a560dfe8cbf..e49a5215994 100644
--- a/app/kudos/models.py
+++ b/app/kudos/models.py
@@ -639,6 +639,7 @@ class TokenRequest(SuperModel):
artist = models.CharField(max_length=255)
platform = models.CharField(max_length=255)
to_address = models.CharField(max_length=255)
+ bounty_url = models.CharField(max_length=255, blank=True, default='')
artwork_url = models.CharField(max_length=255)
numClonesAllowed = models.IntegerField(default=18)
metadata = JSONField(null=True, default=dict, blank=True)
@@ -665,7 +666,6 @@ def mint(self, gas_price_gwei=None):
'description': self.description,
'priceFinney': self.priceFinney,
'artist': self.artist,
- 'platform': self.name,
'platform': self.platform,
'numClonesAllowed': self.numClonesAllowed,
'tags': self.tags,
@@ -673,7 +673,7 @@ def mint(self, gas_price_gwei=None):
}
kudos_contract = KudosContract(network=self.network)
gas_price_gwei = recommend_min_gas_price_to_confirm_in_time(1) * 2 if not gas_price_gwei else None
- tx_id = mint_kudos(kudos_contract, kudos, account, private_key, gas_price_gwei, mint_to=None, live=True, dont_wait_for_kudos_id_return_tx_hash_instead=True)
+ tx_id = mint_kudos(kudos_contract, kudos, account, private_key, gas_price_gwei, mint_to=self.to_address, live=True, dont_wait_for_kudos_id_return_tx_hash_instead=True)
self.processed = True
self.approved = True
self.save()
diff --git a/app/kudos/tasks.py b/app/kudos/tasks.py
index 52b93a73a70..19e36fedd0d 100644
--- a/app/kudos/tasks.py
+++ b/app/kudos/tasks.py
@@ -1,11 +1,16 @@
import time
+from django.conf import settings
+
from app.redis_service import RedisService
from celery import app
from celery.utils.log import get_task_logger
from dashboard.utils import get_web3
from hexbytes import HexBytes
from kudos.models import KudosTransfer, TokenRequest
+from kudos.utils import kudos_abi
+from marketing.mails import notify_kudos_minted
+from web3 import Web3
logger = get_task_logger(__name__)
@@ -28,10 +33,10 @@ def mint_token_request(self, token_req_id, retry=False):
from gas.utils import recommend_min_gas_price_to_confirm_in_time
from dashboard.utils import has_tx_mined
obj = TokenRequest.objects.get(pk=token_req_id)
- multiplier = 1 if not retry else min((mint_token_request.request.retries + 1), 10)
+ multiplier = 1
gas_price = int(float(recommend_min_gas_price_to_confirm_in_time(1)) * multiplier)
if gas_price > delay_if_gas_prices_gt:
- self.retry(120)
+ self.retry(countdown=120)
return
tx_id = obj.mint(gas_price)
if tx_id:
@@ -41,16 +46,16 @@ def mint_token_request(self, token_req_id, retry=False):
sync_latest(1)
sync_latest(2)
sync_latest(3)
+ notify_kudos_minted(obj)
else:
- self.retry(30)
+ self.retry(countdown=(30 * (self.request.retries + 1)))
-@app.shared_task(bind=True, max_retries=3)
-def redeem_bulk_kudos(self, kt_id, signed_rawTransaction, retry=False):
+@app.shared_task(bind=True, max_retries=10)
+def redeem_bulk_kudos(self, kt_id, retry=False):
"""
:param self:
:param kt_id:
- :param signed_rawTransaction:
:return:
"""
with redis.lock("tasks:all_kudos_requests", timeout=LOCK_TIMEOUT):
@@ -58,20 +63,36 @@ def redeem_bulk_kudos(self, kt_id, signed_rawTransaction, retry=False):
from dashboard.utils import has_tx_mined
from gas.utils import recommend_min_gas_price_to_confirm_in_time
try:
- obj = TokenRequest.objects.get(pk=token_req_id)
- multiplier = 1 if not retry else min((mint_token_request.request.retries + 1), 10)
+ multiplier = 1
gas_price = int(float(recommend_min_gas_price_to_confirm_in_time(1)) * multiplier)
if gas_price > delay_if_gas_prices_gt:
- self.retry(120)
+ self.retry(countdown=120)
return
obj = KudosTransfer.objects.get(pk=kt_id)
w3 = get_web3(obj.network)
- obj.txid = w3.eth.sendRawTransaction(HexBytes(signed_rawTransaction)).hex()
+ token = obj.kudos_token_cloned_from
+ if token.owner_address.lower() != '0x6239FF1040E412491557a7a02b2CBcC5aE85dc8F'.lower():
+ raise Exception("kudos isnt owned by Gitcoin; cowardly refusing to spend Gitcoin's ETH minting it")
+ kudos_owner_address = settings.KUDOS_OWNER_ACCOUNT
+ kudos_owner_address = Web3.toChecksumAddress(kudos_owner_address)
+ kudos_contract_address = Web3.toChecksumAddress(settings.KUDOS_CONTRACT_MAINNET)
+ contract = w3.eth.contract(Web3.toChecksumAddress(kudos_contract_address), abi=kudos_abi())
+ nonce = w3.eth.getTransactionCount(kudos_owner_address)
+ tx = contract.functions.clone(Web3.toChecksumAddress(obj.receive_address), token.token_id, 1).buildTransaction({
+ 'nonce': nonce,
+ 'gas': 500000,
+ 'gasPrice': gas_price,
+ 'value': int(token.price_finney / 1000.0 * 10**18),
+ })
+ private_key = settings.KUDOS_PRIVATE_KEY
+ signed = w3.eth.account.signTransaction(tx, private_key)
+ obj.txid = w3.eth.sendRawTransaction(signed.rawTransaction).hex()
obj.receive_txid = obj.txid
obj.save()
while not has_tx_mined(obj.txid, obj.network):
time.sleep(1)
pass
except Exception as e:
- self.retry(30)
+ print(e)
+ self.retry(countdown=(30 * (self.request.retries + 1)))
diff --git a/app/kudos/templates/kudos_details.html b/app/kudos/templates/kudos_details.html
index 43317293fd2..8107299b13a 100644
--- a/app/kudos/templates/kudos_details.html
+++ b/app/kudos/templates/kudos_details.html
@@ -37,7 +37,7 @@
{% include 'shared/kudos_levitate.html' %}
-
+
diff --git a/app/kudos/views.py b/app/kudos/views.py
index 9a25c7d1645..47d83eb8bdf 100644
--- a/app/kudos/views.py
+++ b/app/kudos/views.py
@@ -46,6 +46,7 @@
from dashboard.views import record_user_action
from gas.utils import recommend_min_gas_price_to_confirm_in_time
from git.utils import get_emails_by_category, get_emails_master, get_github_primary_email
+from kudos.tasks import redeem_bulk_kudos
from kudos.utils import kudos_abi
from marketing.mails import new_kudos_request
from ratelimit.decorators import ratelimit
@@ -738,6 +739,7 @@ def redeem_bulk_coupon(coupon, profile, address, ip_address, save_addr=False):
receive_txid=txid,
tx_status='pending',
receive_tx_status='pending',
+ receive_address=address,
)
# save to DB
@@ -765,8 +767,7 @@ def redeem_bulk_coupon(coupon, profile, address, ip_address, save_addr=False):
maybe_market_kudos_to_email(kudos_transfer)
if retry_later:
- from kudos.tasks import redeem_bulk_kudos
- redeem_bulk_kudos.delay(kudos_transfer.id, signed.rawTransaction.hex())
+ redeem_bulk_kudos.delay(kudos_transfer.id)
return True, None, kudos_transfer
@@ -857,6 +858,7 @@ def newkudos(request):
description=request.POST['description'],
priceFinney=request.POST['priceFinney'],
artist=request.POST['artist'],
+ bounty_url=request.POST['bounty_url'],
platform=request.POST['platform'],
numClonesAllowed=request.POST['numClonesAllowed'],
tags=request.POST['tags'].split(","),
diff --git a/app/marketing/mails.py b/app/marketing/mails.py
index dbb98e536cf..c0111e1c508 100644
--- a/app/marketing/mails.py
+++ b/app/marketing/mails.py
@@ -720,6 +720,27 @@ def notify_deadbeat_quest(quest):
translation.activate(cur_language)
+def notify_kudos_minted(token_request):
+ to_email = token_request.profile.email
+ from_email = 'kevin@gitcoin.co'
+ cur_language = translation.get_language()
+ try:
+ setup_lang(to_email)
+ subject = _("Kudos has been minted")
+ body = f"Your kudos '{token_request.name}' has been minted and should be available on https://gitcoin.co/kudos/marketplace soon."
+ if not should_suppress_notification_email(to_email, 'faucet'):
+ send_mail(
+ from_email,
+ to_email,
+ subject,
+ body,
+ from_name=_("No Reply from Gitcoin.co"),
+ categories=['admin', func_name()],
+ )
+ finally:
+ translation.activate(cur_language)
+
+
def notify_deadbeat_grants(grants):
to_email = 'kevin@gitcoin.co'
from_email = to_email
diff --git a/app/retail/templates/newkudos.html b/app/retail/templates/newkudos.html
index 7018c77ecb9..cde8f08bf2a 100644
--- a/app/retail/templates/newkudos.html
+++ b/app/retail/templates/newkudos.html
@@ -111,6 +111,10 @@
+
+
+
+
{% if is_staff %}
diff --git a/docs/CREATING_CELERY_TASKS.md b/docs/CREATING_CELERY_TASKS.md
index 480b7235d5e..096376c6917 100644
--- a/docs/CREATING_CELERY_TASKS.md
+++ b/docs/CREATING_CELERY_TASKS.md
@@ -49,7 +49,7 @@ def bounty_emails(self, emails, msg, profile_handle, invite_url=None, kudos_invi
except ConnectionError as exc:
print(exc)
- self.retry(30)
+ self.retry(countdown=30)
```
diff --git a/scripts/debug/grants_contributioin_ips.py b/scripts/debug/grants_contributioin_ips.py
index 922f474059d..12b8942d7fa 100644
--- a/scripts/debug/grants_contributioin_ips.py
+++ b/scripts/debug/grants_contributioin_ips.py
@@ -1,6 +1,7 @@
from django.utils import timezone
from grants.models import *
+
pk= 600
grant = Grant.objects.get(pk=pk)
@@ -15,4 +16,3 @@
for key, val in last_ips.items():
if val > 1:
print(key, "created", val, "accounts")
-