def on_transfer_confirmation(transaction_id): transfer = Transfer.objects.get(id=transaction_id, swap=False) transfer_data = TransferSerializer(transfer, read_only=True).data # send transfer confirmed notification to both wallets # to cover use cases where multiple clients might be listening for the same wallet's state send_notification(stream_prefix="wallet", stream_id="{}/{}".format( transfer.recipient.token.address, transfer.recipient.address), event_name=TRANSFER_CONFIRMATION, data=transfer_data) send_notification(stream_prefix="wallet", stream_id="{}/{}".format(transfer.wallet.token.address, transfer.wallet.address), event_name=TRANSFER_CONFIRMATION, data=transfer_data) operator_celery.send_task( 'synchronizer.tasks.trigger_hook', args=[ ConciseTransactionSerializer(transfer).data, ], )
def interpret(self, decoded_event, txid, block_number, eon_number, verbose=False): wallet_address = hex_address(decoded_event.get(u'recipient')) try: wallet = Wallet.objects.get(token__address__iexact=hex_address( decoded_event.get(u'token')), address__iexact=wallet_address) except Wallet.DoesNotExist: logger.warning( "UNKNOWN WALLET PERFORMING DEPOSIT {}".format(wallet_address)) BlacklistEntry.objects.get_or_create(address=wallet_address) return with wallet.lock(auto_renewal=True): deposit = Deposit.objects.create( wallet=wallet, amount=decoded_event.get(u'amount'), eon_number=eon_number, block=block_number, txid=remove_0x_prefix(txid)) # send deposit added notification to sender send_notification(stream_prefix="wallet", stream_id="{}/{}".format(wallet.token.address, wallet.address), event_name=CONFIRMED_DEPOSIT, data=DepositSerializer(deposit, read_only=True).data)
def interpret(self, decoded_event, txid, block_number, eon_number, verbose=False): token_address = decoded_event.get(u'token') wallet_address = decoded_event.get(u'requestor') amount = decoded_event.get(u'amount') try: wallet = Wallet.objects.get( token__address__iexact=hex_address(token_address), address__iexact=hex_address(wallet_address)) except Wallet.DoesNotExist: return # get all unconfirmed unslashed withdrawal requests for this wallet # sorted in ascending order by the date they were added unslashed_unconfirmed_requests = WithdrawalRequest.objects \ .filter(wallet=wallet, slashed=False, withdrawal__isnull=True) \ .order_by('id') withdrawal_requests = [] accumulator = 0 # add withdrawal requests until confirmation amount is reached # from older to newer requests for withdrawal_request in unslashed_unconfirmed_requests: if accumulator < amount: withdrawal_requests.append(withdrawal_request) accumulator += withdrawal_request.amount else: break # if accumulator is not equal to confirmed amount there is something very wrong going on if accumulator != amount: logger.error( 'CONFIRMED WITHDRAWALS BY {} FOR TOKEN {} DID NOT SUM UP TO EXPECTED AMOUNT {}' .format(hex_address(wallet_address), hex_address(token_address), amount)) # create a withdrawal object for every confirmed withdrawal request for withdrawal_request in withdrawal_requests: confirmation = Withdrawal( wallet=wallet, amount=withdrawal_request.amount, eon_number=eon_number, request=withdrawal_request, block=block_number, txid=remove_0x_prefix(txid)) # send withdrawal confirmed notification to wallet send_notification( stream_prefix="wallet", stream_id="{}/{}".format(wallet.token.address, wallet.address), event_name=CONFIRMED_WITHDRAWAL, data=WithdrawalSerializer( confirmation, read_only=True).data ) if verbose: print(withdrawal_request) print(confirmation) confirmation.save()
def interpret(self, decoded_event, txid, block_number, eon_number, verbose=False): try: wallet = Wallet.objects.get( token__address__iexact=hex_address( decoded_event.get(u'token')), address__iexact=hex_address(decoded_event.get(u'requestor'))) except Wallet.DoesNotExist: # TODO this is a problem logger.error("UNKNOWN WALLET REQUESTING WITHDRAWAL {}".format( hex_address(decoded_event.get(u'requestor')))) return with wallet.lock(auto_renewal=True): withdrawal_request = WithdrawalRequest.objects.create( wallet=wallet, amount=decoded_event.get(u'amount'), eon_number=eon_number, block=block_number, txid=remove_0x_prefix(txid)) # send withdrawal requested notification to wallet send_notification( stream_prefix="wallet", stream_id="{}/{}".format(wallet.token.address, wallet.address), event_name=REQUESTED_WITHDRAWAL, data=WithdrawalRequestSerializer( withdrawal_request, read_only=True).data ) logger.warning(withdrawal_request) if verbose: print(withdrawal_request)
def broadcast_wallet_data(): eon_number = LocalViewInterface.latest().eon_number() for wallet in Wallet.objects.all(): request_model = MockModel(eon_number=eon_number, wallet=wallet, transfer_id=0) data = WalletStateSerializer(request_model).data send_notification(stream_prefix='wallet', stream_id="{}/{}".format(wallet.token.address, wallet.address), event_name=CHECKPOINT_CREATED, data=data)
def on_swap_finalization(transaction_id): swap = Transfer.objects.get(id=transaction_id, swap=True) swap_data = SwapFinalizationSerializer(swap, read_only=True).data # send swap cancellation notification to both wallets # to cover use cases where multiple clients might be listening for the same wallet's state send_notification(stream_prefix="wallet", stream_id="{}/{}".format(swap.recipient.token.address, swap.recipient.address), event_name=SWAP_FINALIZATION, data=swap_data) send_notification(stream_prefix="wallet", stream_id="{}/{}".format(swap.wallet.token.address, swap.wallet.address), event_name=SWAP_FINALIZATION, data=swap_data)
def on_swap_confirmation(transaction_id): swap = Transfer.objects.get(id=transaction_id, swap=True) swap_data = SwapSerializer(swap, read_only=True).data # send swap confirmed notification to both wallets # to cover use cases where multiple clients might be listening for the same wallet's state send_notification(stream_prefix="wallet", stream_id="{}/{}".format(swap.recipient.token.address, swap.recipient.address), event_name=SWAP_CONFIRMATION, data=swap_data) send_notification(stream_prefix="wallet", stream_id="{}/{}".format(swap.wallet.token.address, swap.wallet.address), event_name=SWAP_CONFIRMATION, data=swap_data) # send swap incoming notification to clients interested in pairs send_notification(stream_prefix="tokenpair", stream_id="{}/{}".format(swap.wallet.token.address, swap.recipient.token.address), event_name=INCOMING_SWAP, data=swap_data)
def on_swap_matching(swap_id, opposite_id): swap = Transfer.objects.get(id=swap_id, swap=True) opposite = Transfer.objects.get(id=opposite_id, swap=True) swap_data = SwapSerializer(swap, read_only=True).data opposite_data = SwapSerializer(opposite, read_only=True).data # send swap matched notification to recipient send_notification(stream_prefix="wallet", stream_id="{}/{}".format( opposite.recipient.token.address, opposite.recipient.address), event_name=MATCHED_SWAP, data=opposite_data) send_notification(stream_prefix="wallet", stream_id="{}/{}".format(swap.recipient.token.address, swap.recipient.address), event_name=MATCHED_SWAP, data=swap_data) # send swap matched notification to sender send_notification(stream_prefix="wallet", stream_id="{}/{}".format(opposite.wallet.token.address, opposite.wallet.address), event_name=MATCHED_SWAP, data=opposite_data) send_notification(stream_prefix="wallet", stream_id="{}/{}".format(swap.wallet.token.address, swap.wallet.address), event_name=MATCHED_SWAP, data=swap_data) # send swap matched notification to tokenpair listeners send_notification(stream_prefix="tokenpair", stream_id="{}/{}".format(opposite.wallet.token.address, swap.wallet.token.address), event_name=MATCHED_SWAP, data=opposite_data) # send swap matched notification to tokenpair listeners send_notification(stream_prefix="tokenpair", stream_id="{}/{}".format(swap.wallet.token.address, opposite.wallet.token.address), event_name=MATCHED_SWAP, data=swap_data)
def process_admissions_for_latest_eon(): latest_eon_number = LocalViewInterface.latest().eon_number() checkpoint_created = RootCommitment.objects.filter( eon_number=latest_eon_number).exists() to_update_records = [] to_delete_ids = [] wallet_offsets = {} operator_wallets = {} with transaction.atomic(): pending_approval = Wallet.objects.select_for_update().filter( registration_operator_authorization__isnull=True) for token in Token.objects.all(): wallet_offsets[token.id] = Wallet.objects.filter( registration_operator_authorization__isnull=False, token=token).count() try: operator_wallets[token.id] = Wallet.objects.get( address=remove_0x_prefix( settings.HUB_OWNER_ACCOUNT_ADDRESS), token=token) except Wallet.DoesNotExist: logger.error( 'Could not admit client wallets for token {}. Owner wallet {} not yet registered.' .format(token.address, settings.HUB_OWNER_ACCOUNT_ADDRESS)) return for wallet in pending_approval: try: if wallet.registration_operator_authorization is not None: logger.error('Wallet {} already admitted.'.format( wallet.address)) continue if should_void_admission(wallet, latest_eon_number, checkpoint_created): to_delete_ids.append(wallet.id) continue wallet.trail_identifier = wallet_offsets[wallet.token.id] wallet.registration_operator_authorization = wallet.sign_admission( eon_number=latest_eon_number, operator_wallet=operator_wallets[wallet.token.id], private_key=settings.HUB_OWNER_ACCOUNT_KEY) wallet_offsets[wallet.token.id] += 1 to_update_records.append(wallet) except IntegrityError as error: logger.error('Admission Verification Integrity Error') logger.error(error) break pending_approval.filter(pk__in=to_delete_ids).delete() Wallet.objects.bulk_update( to_update_records, ['registration_operator_authorization', 'trail_identifier']) for wallet in to_update_records: send_notification(stream_prefix="wallet", stream_id="{}/{}".format(wallet.token.address, wallet.address), event_name=REGISTERED_WALLET, data=AdmissionSerializer(wallet, read_only=True).data) logger.info('Wallet {} admitted.'.format(wallet.address))