Source code for payments.views

import logging
from rest_framework import viewsets
from rest_framework.authentication import SessionAuthentication
from rest_framework.decorators import api_view
from rest_framework.pagination import LimitOffsetPagination
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework.views import APIView

from payments.coin_handlers import get_manager
from payments.models import Deposit, Coin, CoinPair, AddressAccountMap, Conversion
from payments.serializers import DepositSerializer, CoinSerializer, CoinPairSerializer, ConversionSerializer

"""
    +===================================================+
    |                 © 2019 Privex Inc.                |
    |               https://www.privex.io               |
    +===================================================+
    |                                                   |
    |        CryptoToken Converter                      |
    |                                                   |
    |        Core Developer(s):                         |
    |                                                   |
    |          (+)  Chris (@someguy123) [Privex]        |
    |                                                   |
    +===================================================+
"""

# Create your views here.
from django.views.generic import TemplateView

log = logging.getLogger(__name__)


[docs]class IndexView(TemplateView): template_name = 'base.html'
[docs]class ConvertView(TemplateView): template_name = 'convert.html'
[docs]@api_view(['GET']) def api_root(request, format=None): return Response({ 'coins': reverse('coin-list', request=request, format=format), 'pairs': reverse('coinpair-list', request=request, format=format), 'deposits': reverse('deposit-list', request=request, format=format), 'conversions': reverse('conversion-list', request=request, format=format), 'start_conversion': reverse('start_convert', request=request, format=format) })
[docs]class CustomPaginator(LimitOffsetPagination): default_limit = 100 max_limit = 1000
[docs]class CoinAPI(viewsets.ReadOnlyModelViewSet): lookup_value_regex = '[^/]+' queryset = Coin.objects.filter(enabled=True) serializer_class = CoinSerializer filterset_fields = ('symbol', 'symbol_id', 'our_account', 'coin_type', 'can_issue')
[docs]class DepositAPI(viewsets.ReadOnlyModelViewSet): queryset = Deposit.objects.all().order_by('-created_at') order_by = 'created' serializer_class = DepositSerializer filterset_fields = ( 'address', 'from_account', 'to_account', 'txid', 'memo', 'conversion__to_address', 'conversion__to_memo', 'conversion__to_txid', 'status', 'coin' ) pagination_class = CustomPaginator
[docs]class CoinPairAPI(viewsets.ReadOnlyModelViewSet): lookup_value_regex = '[^/]+' queryset = CoinPair.objects.filter(from_coin__enabled=True, to_coin__enabled=True) serializer_class = CoinPairSerializer filterset_fields = ('from_coin', 'to_coin')
[docs]class ConversionAPI(viewsets.ReadOnlyModelViewSet): queryset = Conversion.objects.all().order_by('-created_at') serializer_class = ConversionSerializer filterset_fields = ( 'from_coin', 'to_coin', 'from_address', 'to_address', 'deposit__from_account', 'deposit__to_account', 'deposit__memo' ) pagination_class = CustomPaginator
[docs]def r_err(msg, status=500): return Response(dict(error=True, message=msg), status=status)
[docs]class DRFNoCSRF(SessionAuthentication):
[docs] def enforce_csrf(self, request): return # disable csrf check
[docs]class ConvertAPI(APIView): """ Required form / JSON fields: * ``from_coin`` - The API coin symbol to convert from (send this coin) * ``to_coin`` - The API coin symbol to convert into (we send you this coin) * ``destination`` - The account / address to send to Optional: * ``dest_memo`` - For coins that support memos, you can specify a custom memo to use when sending. Example (application/json) .. code-block:: json {"from_coin": "BTC", "to_coin": "BTCP", "destination": "someguy123"} Example (application/x-www-form-urlencoded):: from_coin=BTC&to_coin=BTCP&destination=someguy123 """ authentication_classes = (DRFNoCSRF,)
[docs] def post(self, request: Request): try: return self._post(request) except: log.exception("An unhandled exception occurred while handling ConvertAPI.post") return r_err('An unknown error has occurred... please contact support', 500)
def _post(self, request: Request): d = request.data # If they didn't specify one of these, it will simply raise an exception for us to handle below. try: from_coin = str(d['from_coin']).upper() to_coin = str(d['to_coin']).upper() destination = str(d['destination']) dest_memo = d.get('memo', None) except (AttributeError, KeyError): return r_err("You must specify 'from_coin', 'to_coin', and 'destination'", 400) # Check if the coin pair specified actually exists. If it doesn't, it'll throw a DoesNotExist. try: c = CoinPair.objects.get(from_coin__symbol=from_coin, to_coin__symbol=to_coin) except CoinPair.DoesNotExist: return r_err("There is no such coin pair {} -> {}".format(d['from_coin'], d['to_coin']), 404) # Grab the x(BaseManager) instances for the from/to coin, so we can do some validation + generate deposit info m = get_manager(from_coin) m_to = get_manager(to_coin) # To save users from sending their coins into the abyss, make sure their destination address/account is # actually valid / exists. if not m_to.address_valid(destination): return r_err("The destination {} address/account '{}' is not valid".format(to_coin, destination), 400) # Ask the Coin Handler for their from_coin how to handle deposits for that coin dep_type, dep_addr = m.get_deposit() # Data to return in the 'result' key of our response. res = dict( ex_rate=c.exchange_rate, destination=destination, pair=str(c) ) if dep_type == 'account': # If the coin handler uses an account system, that means we just give them our account to deposit into, # and generate a memo with destination coin/address details. res['memo'] = "{} {}".format(to_coin, destination) if dest_memo is not None: res['memo'] = "{} {} {}".format(to_coin, destination, dest_memo) res['account'] = dep_addr else: # If it's not account based, assume it's address based. dep_data = dict(deposit_coin=c.from_coin, deposit_address=dep_addr, destination_coin=c.to_coin, destination_address=destination, destination_memo=dest_memo) res['address'] = dep_addr # Store the address so we can map it to their destination coin when they deposit to it. AddressAccountMap(**dep_data).save() return Response(res)