def redeem_bulk_kudos(self, kt_id, retry=False): """ :param self: :param kt_id: :return: """ try: with redis.lock("tasks:redeem_bulk_kudos:%s" % kt_id, timeout=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) if gas_price > delay_if_gas_prices_gt_redeem: # do not retry is gas prices are too high # TODO: revisit this when gas prices go down # self.retry(countdown=60*10) return obj = KudosTransfer.objects.get(pk=kt_id) w3 = get_web3(obj.network) 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 (SoftTimeLimitExceeded, TimeLimitExceeded): print('max timeout for bulk kudos redeem exceeded ... giving up!') except Exception as e: print(e) if self.request.retries < self.max_retries: self.retry(countdown=(30 * (self.request.retries + 1))) else: print("max retries for bulk kudos redeem exceeded ... giving up!")
def receive_bulk(request, secret): coupons = BulkTransferCoupon.objects.filter(secret=secret) if not coupons.exists(): raise Http404 coupon = coupons.first() if coupon.num_uses_remaining <= 0: messages.info(request, f'Sorry but the coupon for a free kudos has has expired. Contact the person who sent you the coupon link, or you can still purchase one on this page.') return redirect(coupon.token.url) kudos_transfer = None if request.user.is_authenticated: redemptions = BulkTransferRedemption.objects.filter(redeemed_by=request.user.profile, coupon=coupon) if redemptions.exists(): kudos_transfer = redemptions.first().kudostransfer error = False if request.POST: try: address = Web3.toChecksumAddress(request.POST.get('forwarding_address')) except: error = "You must enter a valid Ethereum address (so we know where to send your Kudos). Please try again." if request.user.is_anonymous: error = "You must login." if not error: user = request.user profile = user.profile save_addr = request.POST.get('save_addr') ip_address = get_ip(request) # handle form submission if save_addr: profile.preferred_payout_address = address profile.save() kudos_contract_address = Web3.toChecksumAddress(settings.KUDOS_CONTRACT_MAINNET) kudos_owner_address = Web3.toChecksumAddress(settings.KUDOS_OWNER_ACCOUNT) w3 = get_web3(coupon.token.contract.network) contract = w3.eth.contract(Web3.toChecksumAddress(kudos_contract_address), abi=kudos_abi()) nonce = w3.eth.getTransactionCount(kudos_owner_address) tx = contract.functions.clone(address, coupon.token.token_id, 1).buildTransaction({ 'nonce': nonce, 'gas': 500000, 'gasPrice': int(recommend_min_gas_price_to_confirm_in_time(2) * 10**9), 'value': int(coupon.token.price_finney / 1000.0 * 10**18), }) if not profile.trust_profile and profile.github_created_on > (timezone.now() - timezone.timedelta(days=7)): messages.error(request, f'Your github profile is too new. Cannot receive kudos.') else: signed = w3.eth.account.signTransaction(tx, settings.KUDOS_PRIVATE_KEY) txid = w3.eth.sendRawTransaction(signed.rawTransaction).hex() with transaction.atomic(): kudos_transfer = KudosTransfer.objects.create( emails=[request.user.email], # For kudos, `token` is a kudos.models.Token instance. kudos_token_cloned_from=coupon.token, amount=0, comments_public=coupon.comments_to_put_in_kudos_transfer, ip=ip_address, github_url='', from_name=coupon.sender_profile.handle, from_email='', from_username=coupon.sender_profile.handle, username=profile.handle, network=coupon.token.contract.network, from_address=settings.KUDOS_OWNER_ACCOUNT, is_for_bounty_fulfiller=False, metadata={'coupon_redemption': True, 'nonce': nonce}, recipient_profile=profile, sender_profile=coupon.sender_profile, txid=txid, receive_txid=txid, tx_status='pending', receive_tx_status='pending', ) # save to DB BulkTransferRedemption.objects.create( coupon=coupon, redeemed_by=profile, ip_address=ip_address, kudostransfer=kudos_transfer, ) coupon.num_uses_remaining -= 1 coupon.current_uses += 1 coupon.save() # send email maybe_market_kudos_to_email(kudos_transfer) title = f"Redeem {coupon.token.humanized_name} Kudos from @{coupon.sender_profile.handle}" desc = f"This Kudos has been AirDropped to you. About this Kudos: {coupon.token.description}" params = { 'title': title, 'card_title': title, 'card_desc': desc, 'error': error, 'avatar_url': coupon.token.img_url, 'coupon': coupon, 'user': request.user, 'is_authed': request.user.is_authenticated, 'kudos_transfer': kudos_transfer, 'tweet_text': urllib.parse.quote_plus(f"I just got a {coupon.token.humanized_name} Kudos on @GetGitcoin. ") } return TemplateResponse(request, 'transaction/receive_bulk.html', params)
def receive_bulk(request, secret): coupons = BulkTransferCoupon.objects.filter(secret=secret) if not coupons.exists(): raise Http404 coupon = coupons.first() if coupon.num_uses_remaining <= 0: raise PermissionDenied kudos_transfer = None if request.user.is_authenticated: redemptions = BulkTransferRedemption.objects.filter( redeemed_by=request.user.profile, coupon=coupon) if redemptions.exists(): kudos_transfer = redemptions.first().kudostransfer if request.POST: address = Web3.toChecksumAddress( request.POST.get('forwarding_address')) user = request.user profile = user.profile save_addr = request.POST.get('save_addr') ip_address = get_ip(request) # handle form submission if save_addr: profile.preferred_payout_address = address profile.save() kudos_contract_address = Web3.toChecksumAddress( settings.KUDOS_CONTRACT_MAINNET) kudos_owner_address = Web3.toChecksumAddress( settings.KUDOS_OWNER_ACCOUNT) w3 = get_web3(coupon.token.contract.network) contract = w3.eth.contract( Web3.toChecksumAddress(kudos_contract_address), abi=kudos_abi()) tx = contract.functions.clone( address, coupon.token.token_id, 1).buildTransaction({ 'nonce': get_nonce(coupon.token.contract.network, kudos_owner_address), 'gas': 500000, 'gasPrice': int(recommend_min_gas_price_to_confirm_in_time(5) * 10**9), 'value': int(coupon.token.price_finney / 1000.0 * 10**18), }) signed = w3.eth.account.signTransaction(tx, settings.KUDOS_PRIVATE_KEY) txid = w3.eth.sendRawTransaction(signed.rawTransaction).hex() with transaction.atomic(): kudos_transfer = KudosTransfer.objects.create( emails=[request.user.email], # For kudos, `token` is a kudos.models.Token instance. kudos_token_cloned_from=coupon.token, amount=0, comments_public=coupon.comments_to_put_in_kudos_transfer, ip=ip_address, github_url='', from_name=coupon.sender_profile.handle, from_email='', from_username=coupon.sender_profile.handle, username=profile.handle, network=coupon.token.contract.network, from_address=settings.KUDOS_OWNER_ACCOUNT, is_for_bounty_fulfiller=False, metadata={'coupon_redemption': True}, recipient_profile=profile, sender_profile=coupon.sender_profile, txid=txid, receive_txid=txid, ) # save to DB BulkTransferRedemption.objects.create( coupon=coupon, redeemed_by=profile, ip_address=ip_address, kudostransfer=kudos_transfer, ) coupon.num_uses_remaining -= 1 coupon.current_uses += 1 title = f"Redeem AirDropped *{coupon.token.humanized_name}* Kudos" desc = f"This Kudos has been AirDropped to you. About this Kudos: {coupon.token.description}" params = { 'title': title, 'card_title': title, 'card_desc': desc, 'avatar_url': coupon.token.img_url, 'coupon': coupon, 'user': request.user, 'is_authed': request.user.is_authenticated, 'kudos_transfer': kudos_transfer, } return TemplateResponse(request, 'transaction/receive_bulk.html', params)
def redeem_bulk_coupon(coupon, profile, address, ip_address, save_addr=False, submit_later=False, exit_after_sending_tx=False, max_gas_price_we_are_willing_to_pay_gwei=15): try: address = Web3.toChecksumAddress(address) except: error = "You must enter a valid Ethereum address (so we know where to send your Kudos). Please try again." return None, error, None # handle form submission kudos_transfer = None if save_addr: profile.preferred_payout_address = address profile.save() private_key = settings.KUDOS_PRIVATE_KEY if not coupon.sender_pk else coupon.sender_pk kudos_owner_address = settings.KUDOS_OWNER_ACCOUNT if not coupon.sender_address else coupon.sender_address gas_price_confirmation_time = 1 if not coupon.sender_address else 60 gas_price_multiplier = 1.3 if not coupon.sender_address else 1 kudos_contract_address = Web3.toChecksumAddress( settings.KUDOS_CONTRACT_MAINNET) kudos_owner_address = Web3.toChecksumAddress(kudos_owner_address) w3 = get_web3(coupon.token.contract.network) contract = w3.eth.contract(Web3.toChecksumAddress(kudos_contract_address), abi=kudos_abi()) nonce = w3.eth.getTransactionCount(kudos_owner_address) gas_price = int( int( recommend_min_gas_price_to_confirm_in_time( gas_price_confirmation_time) * 10**9) * gas_price_multiplier) tx = contract.functions.clone( address, coupon.token.token_id, 1).buildTransaction({ 'nonce': nonce, 'gas': 500000, 'gasPrice': gas_price, 'value': int(coupon.token.price_finney / 1000.0 * 10**18), }) if not profile.is_brightid_verified and not profile.is_twitter_verified and not profile.trust_profile and profile.github_created_on > ( timezone.now() - timezone.timedelta(days=7)): error = f'Your github profile is too new, so you cannot receive kudos. Please verifiy your profile on BrightID and/or Twitter to proceed.' return None, error, None else: if profile.bulk_transfer_redemptions.filter(coupon=coupon).exists(): error = f'You have already redeemed this kudos.' return None, error, None signed = w3.eth.account.signTransaction(tx, private_key) retry_later = False tx_status = 'pending' if submit_later: txid = '' tx_status = 'not_subed' else: try: # TODO - in the future, override this if the user pays for expediated processing if recommend_min_gas_price_to_confirm_in_time( 1) > max_gas_price_we_are_willing_to_pay_gwei: if coupon.token.contract.network == 'mainnet': raise Exception( "gas price is too high. try again when its not pls" ) txid = w3.eth.sendRawTransaction(signed.rawTransaction).hex() except Exception as e: txid = "pending_celery" retry_later = True if exit_after_sending_tx: return txid, None, None with transaction.atomic(): kudos_transfer = KudosTransfer.objects.create( emails=[profile.email], # For kudos, `token` is a kudos.models.Token instance. kudos_token_cloned_from=coupon.token, amount=coupon.token.price_in_eth, comments_public=coupon.comments_to_put_in_kudos_transfer, ip=ip_address, github_url='', from_name=coupon.sender_profile.handle, from_email='', from_username=coupon.sender_profile.handle, username=profile.handle, network=coupon.token.contract.network, from_address=kudos_owner_address, is_for_bounty_fulfiller=False, metadata={ 'coupon_redemption': True, 'nonce': nonce }, recipient_profile=profile, sender_profile=coupon.sender_profile, txid=txid, receive_txid=txid, tx_status=tx_status, receive_tx_status=tx_status, receive_address=address, ) # save to DB BulkTransferRedemption.objects.create( coupon=coupon, redeemed_by=profile, ip_address=ip_address, kudostransfer=kudos_transfer, ) coupon.num_uses_remaining -= 1 coupon.current_uses += 1 coupon.save() # user actions record_user_action(kudos_transfer.username, 'new_kudos', kudos_transfer) record_user_action(kudos_transfer.from_username, 'receive_kudos', kudos_transfer) record_kudos_activity(kudos_transfer, kudos_transfer.username, 'receive_kudos') # send email maybe_market_kudos_to_email(kudos_transfer) if retry_later: redeem_bulk_kudos.delay(kudos_transfer.id) return True, None, kudos_transfer
def redeem_bulk_coupon(coupon, profile, address, ip_address, save_addr=False): try: address = Web3.toChecksumAddress(address) except: error = "You must enter a valid Ethereum address (so we know where to send your Kudos). Please try again." return None, error, None # handle form submission kudos_transfer = None if save_addr: profile.preferred_payout_address = address profile.save() private_key = settings.KUDOS_PRIVATE_KEY if not coupon.sender_pk else coupon.sender_pk kudos_owner_address = settings.KUDOS_OWNER_ACCOUNT if not coupon.sender_address else coupon.sender_address gas_price_confirmation_time = 1 if not coupon.sender_address else 60 kudos_contract_address = Web3.toChecksumAddress(settings.KUDOS_CONTRACT_MAINNET) kudos_owner_address = Web3.toChecksumAddress(kudos_owner_address) w3 = get_web3(coupon.token.contract.network) contract = w3.eth.contract(Web3.toChecksumAddress(kudos_contract_address), abi=kudos_abi()) nonce = w3.eth.getTransactionCount(kudos_owner_address) tx = contract.functions.clone(address, coupon.token.token_id, 1).buildTransaction({ 'nonce': nonce, 'gas': 500000, 'gasPrice': int(recommend_min_gas_price_to_confirm_in_time(gas_price_confirmation_time) * 10**9), 'value': int(coupon.token.price_finney / 1000.0 * 10**18), }) if not profile.trust_profile and profile.github_created_on > (timezone.now() - timezone.timedelta(days=7)): error = f'Your github profile is too new. Cannot receive kudos.' return None, error, None else: signed = w3.eth.account.signTransaction(tx, private_key) retry_later = False try: txid = w3.eth.sendRawTransaction(signed.rawTransaction).hex() except Exception as e: txid = "pending_celery" retry_later = True with transaction.atomic(): kudos_transfer = KudosTransfer.objects.create( emails=[profile.email], # For kudos, `token` is a kudos.models.Token instance. kudos_token_cloned_from=coupon.token, amount=coupon.token.price_in_eth, comments_public=coupon.comments_to_put_in_kudos_transfer, ip=ip_address, github_url='', from_name=coupon.sender_profile.handle, from_email='', from_username=coupon.sender_profile.handle, username=profile.handle, network=coupon.token.contract.network, from_address=kudos_owner_address, is_for_bounty_fulfiller=False, metadata={'coupon_redemption': True, 'nonce': nonce}, recipient_profile=profile, sender_profile=coupon.sender_profile, txid=txid, receive_txid=txid, tx_status='pending', receive_tx_status='pending', ) # save to DB BulkTransferRedemption.objects.create( coupon=coupon, redeemed_by=profile, ip_address=ip_address, kudostransfer=kudos_transfer, ) coupon.num_uses_remaining -= 1 coupon.current_uses += 1 coupon.save() # user actions record_user_action(kudos_transfer.username, 'new_kudos', kudos_transfer) record_user_action(kudos_transfer.from_username, 'receive_kudos', kudos_transfer) # send email 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()) return True, None, kudos_transfer
def redeem_bulk_kudos(self, kt_id, delay_if_gas_prices_gt_redeem=50, override_gas_price=None, send_notif_email=False, override_lock_timeout=LOCK_TIMEOUT, retry=False): """ :param self: :param kt_id: :return: """ try: if True: # override for allowing many xdai minting; we can change this back later there is a race condition # but for now the lock was providing more trouble than good - KO 10/20/2020 #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) if override_gas_price: gas_price = override_gas_price if gas_price > delay_if_gas_prices_gt_redeem: # do not retry is gas prices are too high # TODO: revisit this when gas prices go down # self.retry(countdown=60*10) return if override_gas_price: gas_price = override_gas_price * 10**9 obj = KudosTransfer.objects.get(pk=kt_id) w3 = get_web3(obj.network) 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) contract_addr = settings.KUDOS_CONTRACT_MAINNET if obj.network == 'xdai': contract_addr = settings.KUDOS_CONTRACT_XDAI if obj.network == 'rinkeby': contract_addr = settings.KUDOS_CONTRACT_RINKEBY kudos_contract_address = Web3.toChecksumAddress(contract_addr) 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 if send_notif_email: from_email = '*****@*****.**' from_name = 'Kevin @ Gitcoin' _to_email = obj.recipient_profile.email subject = f"Your '{obj.kudos_token_cloned_from.name}' Kudos has been minted 🌈" block_url = f'https://etherscan.io/tx/{obj.txid}' if obj.network == 'xdai': block_url = f'https://blockscout.com/poa/xdai/tx/{obj.txid}/internal-transactions' body = f''' Hello @{obj.recipient_profile.handle}, Back on {obj.created_on} you minted a '{obj.kudos_token_cloned_from.name}' Kudos, but the Ethereum network's gas fees were too high for us to mint it on-chain. We're writing with good news. The gas prices on Ethereum have come down, and we are have now minted your token. You can now see the Kudos in your gitcoin profile ( https://gitcoin.co/{obj.recipient_profile.handle} ) or any blockchain wallet that connects to the {obj.network} network ( {block_url} ). HOORAY! Party on, Kevin + the Gitcoin team ''' send_mail(from_email, _to_email, subject, body, from_name=from_name) except (SoftTimeLimitExceeded, TimeLimitExceeded): print('max timeout for bulk kudos redeem exceeded ... giving up!') except Exception as e: print(e) if self.request.retries < self.max_retries: self.retry(countdown=(30 * (self.request.retries + 1))) else: print("max retries for bulk kudos redeem exceeded ... giving up!")
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 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(address, token_id, 1).buildTransaction({ 'nonce': nonce, 'gas': 500000, 'gasPrice': gasPrice, 'value': int(price_finney / 1000.0 * 10**18), })
def redeem_bulk_kudos(self, kt_id, retry=False): """ :param self: :param kt_id: :return: """ with redis.lock("tasks:all_kudos_requests", timeout=LOCK_TIMEOUT): with redis.lock("tasks:redeem_bulk_kudos:%s" % kt_id, timeout=LOCK_TIMEOUT): from dashboard.utils import has_tx_mined from gas.utils import recommend_min_gas_price_to_confirm_in_time try: 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(countdown=120) return obj = KudosTransfer.objects.get(pk=kt_id) w3 = get_web3(obj.network) 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: print(e) self.retry(countdown=(30 * (self.request.retries + 1)))
def receive_bulk_ethdenver(request, secret): coupons = BulkTransferCoupon.objects.filter(secret=secret) if not coupons.exists(): raise Http404 coupon = coupons.first() kudos_transfer = "" if coupon.num_uses_remaining <= 0: messages.info( request, f'Sorry but this kudos redeem link has expired! Please contact the person who sent you the coupon link, or contact your nearest Gitcoin representative.' ) return redirect(coupon.token.url) error = False if request.POST: try: address = Web3.toChecksumAddress( request.POST.get('forwarding_address')) except: error = "You must enter a valid Ethereum address (so we know where to send your Kudos). Please try again." if not error: address = Web3.toChecksumAddress( request.POST.get('forwarding_address')) already_claimed = KudosTransfer.objects.filter( receive_address=address, kudos_token_cloned_from=coupon.token) if already_claimed.count() > 0: messages.info( request, f'You already redeemed this kudos! If you think this wrong contact the ETHDenver Team!' ) return redirect(coupon.token.url) ip_address = get_ip(request) kudos_contract_address = Web3.toChecksumAddress( settings.KUDOS_CONTRACT_MAINNET) kudos_owner_address = Web3.toChecksumAddress( settings.KUDOS_OWNER_ACCOUNT) w3 = get_web3(coupon.token.contract.network) nonce = w3.eth.getTransactionCount(kudos_owner_address) contract = w3.eth.contract( Web3.toChecksumAddress(kudos_contract_address), abi=kudos_abi()) tx = contract.functions.clone( address, coupon.token.token_id, 1).buildTransaction({ 'nonce': nonce, 'gas': 500000, 'gasPrice': int(recommend_min_gas_price_to_confirm_in_time(1) * 10**9), 'value': int(coupon.token.price_finney / 1000.0 * 10**18), }) try: signed = w3.eth.account.signTransaction( tx, settings.KUDOS_PRIVATE_KEY) txid = w3.eth.sendRawTransaction(signed.rawTransaction).hex() with transaction.atomic(): kudos_transfer = KudosTransfer.objects.create( emails=["*****@*****.**"], # For kudos, `token` is a kudos.models.Token instance. kudos_token_cloned_from=coupon.token, amount=coupon.token.price_in_eth, comments_public=coupon. comments_to_put_in_kudos_transfer, ip=ip_address, github_url='', from_name=coupon.sender_profile.handle, from_email='', from_username=coupon.sender_profile.handle, network=coupon.token.contract.network, from_address=settings.KUDOS_OWNER_ACCOUNT, receive_address=address, is_for_bounty_fulfiller=False, metadata={'coupon_redemption': True}, sender_profile=coupon.sender_profile, txid=txid, receive_txid=txid, tx_status='pending', receive_tx_status='pending', ) coupon.num_uses_remaining -= 1 coupon.current_uses += 1 coupon.save() except: error = "Could not redeem your kudos. Please try again soon." title = f"Redeem ETHDenver event kudos: *{coupon.token.humanized_name}*" desc = f"Thank you for joining the event! About this Kudos: {coupon.token.description}" params = { 'title': title, 'card_title': title, 'card_desc': desc, 'error': error, 'avatar_url': coupon.token.img_url, 'coupon': coupon, 'user': request.user, 'is_authed': request.user.is_authenticated, 'kudos_transfer': kudos_transfer, } return TemplateResponse(request, 'ethdenver2019/receive_bulk.html', params)
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
kudos_owner_address = Web3.toChecksumAddress(settings.KUDOS_OWNER_ACCOUNT) nonce = w3.eth.getTransactionCount(kudos_owner_address) # pk range to re-send min_pk = 1684 max_pk = 1740 TIME_SLEEP = 1 for kt in KudosTransfer.objects.filter(pk__gte=min_pk, pk__lte=max_pk): token_id = kt.kudos_token_cloned_from.token_id address = kt.receive_address price_finney = kt.kudos_token_cloned_from.price_finney contract = w3.eth.contract(Web3.toChecksumAddress(kudos_contract_address), abi=kudos_abi()) tx = contract.functions.clone(address, token_id, 1).buildTransaction({ 'nonce': nonce, 'gas': 500000, 'gasPrice': int(recommend_min_gas_price_to_confirm_in_time(2) * 10**9), 'value': int(price_finney / 1000.0 * 10**18), }) signed = w3.eth.account.signTransaction(tx, settings.KUDOS_PRIVATE_KEY) time.sleep(TIME_SLEEP) try: