From ca538358a7bea159e5cdcf96c933e9b8ca78a17f Mon Sep 17 00:00:00 2001 From: Lev Lybin Date: Wed, 3 Jul 2019 20:33:44 +0700 Subject: [PATCH] #34 start api --- Pipfile | 2 ++ Pipfile.lock | 40 ++++++++++++++++++++++++++++------------ api/__init__.py | 0 api/urls.py | 8 ++++++++ api/v1/__init__.py | 0 api/v1/serializers.py | 40 ++++++++++++++++++++++++++++++++++++++++ api/v1/urls.py | 9 +++++++++ api/v1/views.py | 24 ++++++++++++++++++++++++ explorer/settings.py | 11 ++++++++++- explorer/urls.py | 1 + 10 files changed, 122 insertions(+), 13 deletions(-) create mode 100644 api/__init__.py create mode 100644 api/urls.py create mode 100644 api/v1/__init__.py create mode 100644 api/v1/serializers.py create mode 100644 api/v1/urls.py create mode 100644 api/v1/views.py diff --git a/Pipfile b/Pipfile index ad76272b..3760e774 100644 --- a/Pipfile +++ b/Pipfile @@ -13,7 +13,9 @@ vcrpy = "==2.0.1" celery = {version = "==4.3.0",extras = ["redis"]} django = "==2.2.2" django-cache-memoize = "==0.1.6" +django-cors-headers = "==3.0.2" django-redis = "==4.10.0" +djangorestframework = "==3.9.4" jsonschema = "==3.0.1" mysqlclient = "==1.4.2.post1" python-dotenv = "==0.10.3" diff --git a/Pipfile.lock b/Pipfile.lock index 9f6c9025..c79f19a1 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "a0dcb4065ee84eb042df66ad0ab09fcdf7ae74370de0734c5d3d83cfd862aad1" + "sha256": "b33a1fa1f7edabd6cae1b3ea9f7cf27301178db84062b4017ebccd112eff0d29" }, "pipfile-spec": 6, "requires": { @@ -49,10 +49,10 @@ }, "certifi": { "hashes": [ - "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5", - "sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae" + "sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939", + "sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695" ], - "version": "==2019.3.9" + "version": "==2019.6.16" }, "chardet": { "hashes": [ @@ -77,6 +77,14 @@ "index": "pypi", "version": "==0.1.6" }, + "django-cors-headers": { + "hashes": [ + "sha256:5b80bf0f8d7fc6e2bcb4f40781d5ff3661961bbf1982e52daec77241dea3b890", + "sha256:ebf3e2cf25aa6993b959a8e6a87828ebb3c8fe5bc3ec4a2d6e65f3b8d9b4212c" + ], + "index": "pypi", + "version": "==3.0.2" + }, "django-redis": { "hashes": [ "sha256:af0b393864e91228dd30d8c85b5c44d670b5524cb161b7f9e41acc98b6e5ace7", @@ -85,6 +93,14 @@ "index": "pypi", "version": "==4.10.0" }, + "djangorestframework": { + "hashes": [ + "sha256:376f4b50340a46c15ae15ddd0c853085f4e66058f97e4dbe7d43ed62f5e60651", + "sha256:c12869cfd83c33d579b17b3cb28a2ae7322a53c3ce85580c2a2ebe4e3f56c4fb" + ], + "index": "pypi", + "version": "==3.9.4" + }, "idna": { "hashes": [ "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", @@ -310,10 +326,10 @@ }, "jedi": { "hashes": [ - "sha256:2bb0603e3506f708e792c7f4ad8fc2a7a9d9c2d292a358fbbd58da531695595b", - "sha256:2c6bcd9545c7d6440951b12b44d373479bf18123a401a52025cf98563fbd826c" + "sha256:49ccb782651bb6f7009810d17a3316f8867dde31654c750506970742e18b553d", + "sha256:79d0f6595f3846dffcbe667cc6dc821b96e5baa8add125176c31a3917eb19d58" ], - "version": "==0.13.3" + "version": "==0.14.0" }, "multidict": { "hashes": [ @@ -351,10 +367,10 @@ }, "parso": { "hashes": [ - "sha256:17cc2d7a945eb42c3569d4564cdf49bde221bc2b552af3eca9c1aad517dcdd33", - "sha256:2e9574cb12e7112a87253e14e2c380ce312060269d04bd018478a3c92ea9a376" + "sha256:5052bb33be034cba784193e74b1cde6ebf29ae8b8c1e4ad94df0c4209bfc4826", + "sha256:db5881df1643bf3e66c097bfd8935cf03eae73f4cb61ae4433c9ea4fb6613446" ], - "version": "==0.4.0" + "version": "==0.5.0" }, "pexpect": { "hashes": [ @@ -454,9 +470,9 @@ }, "wrapt": { "hashes": [ - "sha256:4aea003270831cceb8a90ff27c4031da6ead7ec1886023b80ce0dfe0adf61533" + "sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1" ], - "version": "==1.11.1" + "version": "==1.11.2" }, "yarl": { "hashes": [ diff --git a/api/__init__.py b/api/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/api/urls.py b/api/urls.py new file mode 100644 index 00000000..5c89f27b --- /dev/null +++ b/api/urls.py @@ -0,0 +1,8 @@ +from django.conf.urls import include +from django.conf.urls import url + + +urlpatterns = [ + url(r'^v1/', include(('api.v1.urls', 'api'), namespace='v1')), + url(r'', include(('api.v1.urls', 'api'), namespace='last')), +] diff --git a/api/v1/__init__.py b/api/v1/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/api/v1/serializers.py b/api/v1/serializers.py new file mode 100644 index 00000000..0de752b1 --- /dev/null +++ b/api/v1/serializers.py @@ -0,0 +1,40 @@ +from datetime import datetime + +from rest_framework import serializers + +from java_wallet.constants import BLOCK_CHAIN_START_AT, TxSubtypePayment + + +class PendingTxsSerializer(serializers.Serializer): + type = serializers.IntegerField(read_only=True) + subtype = serializers.IntegerField(read_only=True) + timestamp = serializers.SerializerMethodField(read_only=True) + amountNQT = serializers.IntegerField(read_only=True) + feeNQT = serializers.IntegerField(read_only=True) + sender = serializers.IntegerField(read_only=True) + recipient = serializers.IntegerField(read_only=True) + recipients = serializers.SerializerMethodField(read_only=True) + + @staticmethod + def get_timestamp(data): + return datetime.fromtimestamp(data['timestamp'] + BLOCK_CHAIN_START_AT) + + def get_recipients(self, data): + result = [] + + if data['subtype'] == TxSubtypePayment.MULTI_OUT: + for x in data['attachment']['recipients']: + result.append({'address': int(x[0]), 'amount': int(x[1])}) + + elif data['subtype'] == TxSubtypePayment.MULTI_OUT_SAME: + amount = int(data['amountNQT']) / len(data['attachment']['recipients']) + for x in data['attachment']['recipients']: + result.append({'address': int(x), 'amount': amount}) + + return result or None + + def update(self, instance, validated_data): + pass + + def create(self, validated_data): + pass diff --git a/api/v1/urls.py b/api/v1/urls.py new file mode 100644 index 00000000..201f56b3 --- /dev/null +++ b/api/v1/urls.py @@ -0,0 +1,9 @@ +from rest_framework import routers + +from api.v1 import views + +router = routers.DefaultRouter() + +router.register('pending_txs', views.PendingTxsList, basename='pending_txs') + +urlpatterns = router.urls diff --git a/api/v1/views.py b/api/v1/views.py new file mode 100644 index 00000000..7859669b --- /dev/null +++ b/api/v1/views.py @@ -0,0 +1,24 @@ +from django.conf import settings +from rest_framework import viewsets +from rest_framework.response import Response +from sentry_sdk import capture_exception + +from burst.api.brs.api import BrsApi +from burst.api.exceptions import APIException +from api.v1.serializers import PendingTxsSerializer + + +class PendingTxsList(viewsets.ViewSet): + @staticmethod + def list(request): + try: + txs = BrsApi(settings.BRS_NODE).get_unconfirmed_transactions() + txs.sort(key=lambda _x: int(_x['feeNQT']), reverse=True) + + serializer = PendingTxsSerializer(txs, many=True) + result = serializer.data + except (APIException, ValueError) as e: + capture_exception(e) + result = [] + + return Response(result) diff --git a/explorer/settings.py b/explorer/settings.py index 9d8e4466..3a9e64e8 100644 --- a/explorer/settings.py +++ b/explorer/settings.py @@ -36,7 +36,7 @@ INTERNAL_IPS = os.getenv('DEBUG_TOOLBAR_INTERNAL_IPS') ALLOWED_HOSTS = ['*'] - +CORS_ORIGIN_ALLOW_ALL = True # Application definition @@ -48,6 +48,9 @@ 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.humanize', + 'corsheaders', + 'rest_framework', + 'api', 'scan', 'java_wallet', ] @@ -58,6 +61,7 @@ MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', + 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', @@ -163,6 +167,11 @@ } } +REST_FRAMEWORK = { + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', + 'PAGE_SIZE': 25 +} + LOGGING = { 'version': 1, 'disable_existing_loggers': False, diff --git a/explorer/urls.py b/explorer/urls.py index 987c8599..e8df972d 100644 --- a/explorer/urls.py +++ b/explorer/urls.py @@ -49,6 +49,7 @@ path('at/', AtDetailView.as_view(), name='at-detail'), path('search/', search_view, name='search'), path('admin/', admin.site.urls), + path('api/', include(('api.urls', 'api'), namespace='api')), ] if settings.DEBUG: