mirror of
https://github.com/more-tech4-magnum-opus/backend.git
synced 2024-11-10 14:36:34 +03:00
fixed blockchain, added base operations
This commit is contained in:
parent
79587c322d
commit
abbd90551a
|
@ -1,4 +1,5 @@
|
|||
DJANGO_DEBUG=yes
|
||||
DATABASE_URL=postgres://postgres:debug@127.0.0.1:5432/moretech
|
||||
CELERY_BROKER_URL=redis://localhost:6379/0
|
||||
MAIN_WALLET=46d3684932f300a7fcdc8cc73cfa3057b5f61695c6e0299a5cb551f645e4cb9c
|
||||
MAIN_WALLET=46d3684932f300a7fcdc8cc73cfa3057b5f61695c6e0299a5cb551f645e4cb9
|
||||
PUB_KEY=0x1a63208e5b82588320a8C24b2c595Ba5d5cbfF3
|
0
app/blockchain/api/__init__.py
Normal file
0
app/blockchain/api/__init__.py
Normal file
17
app/blockchain/api/serializers.py
Normal file
17
app/blockchain/api/serializers.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
from django.core.validators import MinValueValidator
|
||||
from rest_framework import serializers
|
||||
from rest_framework.generics import get_object_or_404
|
||||
|
||||
from users.models import User
|
||||
|
||||
|
||||
class TransactFromAdminSerializer(serializers.Serializer):
|
||||
username = serializers.CharField(max_length=200)
|
||||
amount = serializers.IntegerField(validators=[MinValueValidator(1)])
|
||||
|
||||
def validate_username(self, val):
|
||||
return get_object_or_404(User, username=val)
|
||||
|
||||
|
||||
class TransactToAdminSerializer(serializers.Serializer):
|
||||
amount = serializers.IntegerField(validators=[MinValueValidator(1)])
|
76
app/blockchain/api/views.py
Normal file
76
app/blockchain/api/views.py
Normal file
|
@ -0,0 +1,76 @@
|
|||
from drf_yasg.utils import swagger_auto_schema
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
|
||||
from blockchain.api.serializers import (
|
||||
TransactFromAdminSerializer,
|
||||
TransactToAdminSerializer,
|
||||
)
|
||||
from blockchain.models import Transaction
|
||||
from blockchain.services import (
|
||||
transact_from_admin,
|
||||
transact_to_admin,
|
||||
list_user_transactions,
|
||||
)
|
||||
from common.permissions import IsAdmin
|
||||
from utils.blockchain import get_balance
|
||||
|
||||
|
||||
class TransactFromAdminView(APIView):
|
||||
permission_classes = [IsAuthenticated, IsAdmin]
|
||||
|
||||
@swagger_auto_schema(request_body=TransactFromAdminSerializer)
|
||||
def post(self, request):
|
||||
serializer = TransactFromAdminSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
user = serializer.validated_data["username"]
|
||||
amount = serializer.validated_data["amount"]
|
||||
transact_from_admin(user, amount)
|
||||
return Response({"amount": user.money})
|
||||
|
||||
|
||||
class TransactToAdminView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
@swagger_auto_schema(request_body=TransactToAdminSerializer)
|
||||
def post(self, request):
|
||||
serializer = TransactToAdminSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
amount = serializer.validated_data["amount"]
|
||||
transact_to_admin(request.user, amount)
|
||||
return Response({"amount": request.user.money})
|
||||
|
||||
|
||||
class TransactToUserView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
@swagger_auto_schema(request_body=TransactFromAdminSerializer)
|
||||
def post(self, request):
|
||||
serializer = TransactFromAdminSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
user = serializer.validated_data["username"]
|
||||
amount = serializer.validated_data["amount"]
|
||||
t = Transaction.objects.create(
|
||||
user_from=request.user, user_to=user, amount=amount
|
||||
)
|
||||
return Response({"your_amount": t.user_from.money, "amount": t.user_to.money})
|
||||
|
||||
|
||||
class GetMoneyApi(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get(self, request):
|
||||
user_money = int(get_balance(request.user.wallet_public_key).coins)
|
||||
if request.user.money != user_money:
|
||||
request.user.money = user_money
|
||||
request.user.save(update_fields=["money"])
|
||||
|
||||
return Response({"amount": user_money})
|
||||
|
||||
|
||||
class TransactionHistoryApi(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get(self, request):
|
||||
return Response(list_user_transactions(request.user))
|
|
@ -2,5 +2,8 @@ from django.apps import AppConfig
|
|||
|
||||
|
||||
class BlockchainConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'blockchain'
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "blockchain"
|
||||
|
||||
def ready(self):
|
||||
import blockchain.signals
|
||||
|
|
|
@ -19,6 +19,18 @@ class Transaction(models.Model):
|
|||
|
||||
hash = models.CharField(max_length=256, unique=True)
|
||||
|
||||
@property
|
||||
def t_type(self):
|
||||
return False
|
||||
|
||||
@property
|
||||
def user_from_username(self):
|
||||
return self.user_from.username
|
||||
|
||||
@property
|
||||
def user_to_username(self):
|
||||
return self.user_to.username
|
||||
|
||||
def __str__(self):
|
||||
return f"transaction from {self.user_from} to {self.user_to}"
|
||||
|
||||
|
@ -39,11 +51,15 @@ class AdminTransaction(models.Model):
|
|||
hash = models.CharField(max_length=256, unique=True)
|
||||
|
||||
@property
|
||||
def user_from(self):
|
||||
def user_from_username(self):
|
||||
return "system" if self.type == self.TransactionType.TO else self.user.username
|
||||
|
||||
@property
|
||||
def user_to(self):
|
||||
def t_type(self):
|
||||
return self.type.lower()
|
||||
|
||||
@property
|
||||
def user_to_username(self):
|
||||
return (
|
||||
"system" if self.type == self.TransactionType.FROM else self.user.username
|
||||
)
|
||||
|
|
|
@ -1,25 +1,33 @@
|
|||
from itertools import chain
|
||||
|
||||
from django.conf import settings
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from blockchain.models import Transaction, AdminTransaction
|
||||
from users.models import User
|
||||
from utils.blockchain import transfer_rubbles
|
||||
from utils.blockchain import transfer_rubbles, get_balance
|
||||
|
||||
|
||||
def list_user_transactions(user: User) -> list:
|
||||
transaction = []
|
||||
qs = (
|
||||
user.transactions_to.all()
|
||||
| user.transactions_from.all()
|
||||
| user.admin_transactions.all()
|
||||
l = (
|
||||
[x for x in user.transactions_to.all()]
|
||||
+ [x for x in user.transactions_from.all()]
|
||||
+ [x for x in user.admin_transactions.all()]
|
||||
)
|
||||
l.sort(
|
||||
key=lambda instance: instance.created, reverse=True
|
||||
)
|
||||
qs.order_by("created")
|
||||
username = user.username
|
||||
for el in qs: # type: Transaction
|
||||
for el in l: # type: Transaction
|
||||
if not (t := el.t_type):
|
||||
t = "to" if el.user_from.username == username else "from"
|
||||
|
||||
transaction.append(
|
||||
{
|
||||
"type": "addition" if el.user_from.username == username else "transfer",
|
||||
"user_from": el.user_from.username,
|
||||
"user_to": el.user_to.username,
|
||||
"type": t,
|
||||
"user_from": el.user_from_username,
|
||||
"user_to": el.user_to_username,
|
||||
"amount": el.amount,
|
||||
}
|
||||
)
|
||||
|
@ -36,3 +44,21 @@ def transact_from_admin(user: User, amount: int):
|
|||
user.money += amount
|
||||
user.save(update_fields=["money"])
|
||||
|
||||
|
||||
def transact_to_admin(user: User, amount: int):
|
||||
user_from_money = int(get_balance(user.wallet_public_key).coins)
|
||||
if user.money != user_from_money:
|
||||
user.money = user_from_money
|
||||
user.save(update_fields=["money"])
|
||||
|
||||
if user_from_money - amount < 0:
|
||||
raise ValidationError("Not enough money")
|
||||
|
||||
t = transfer_rubbles(user.wallet_private_key, settings.PUB_KEY, amount)
|
||||
print(t.transaction_hash)
|
||||
user.money -= amount
|
||||
user.save(update_fields=["money"])
|
||||
|
||||
AdminTransaction.objects.create(
|
||||
type="PAYMENT", amount=amount, user=user, hash=t.transaction_hash
|
||||
)
|
||||
|
|
|
@ -21,16 +21,18 @@ def validate_create_transaction(sender, instance: Transaction, **kwargs):
|
|||
instance.user_from.money = user_from_money
|
||||
instance.user_from.save(update_fields=["money"])
|
||||
|
||||
if user_from_money - instance.amount <= 0:
|
||||
if user_from_money - instance.amount < 0:
|
||||
raise ValidationError(
|
||||
f"{instance.user_from.username} doesn't have enough money"
|
||||
)
|
||||
|
||||
transaction = transfer_rubbles(
|
||||
instance.user_from.wallet_private_key,
|
||||
instance.user_to.wallet_public_key,
|
||||
amount=instance.amount,
|
||||
)
|
||||
try:
|
||||
transaction = transfer_rubbles(
|
||||
instance.user_from.wallet_private_key,
|
||||
instance.user_to.wallet_public_key,
|
||||
amount=instance.amount,
|
||||
)
|
||||
except AttributeError:
|
||||
raise ValidationError("Transaction unsuccessful")
|
||||
instance.user_from.money -= instance.amount
|
||||
instance.user_from.save(update_fields=["money"])
|
||||
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
from django.urls import path, include
|
||||
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
|
||||
|
||||
from blockchain.api.views import (
|
||||
TransactFromAdminView,
|
||||
TransactToUserView,
|
||||
TransactToAdminView,
|
||||
GetMoneyApi, TransactionHistoryApi,
|
||||
)
|
||||
from events.api.views import (
|
||||
ListCreateEventApi,
|
||||
RetrieveUpdateDeleteEventApi,
|
||||
|
@ -33,6 +39,38 @@ urlpatterns = [
|
|||
]
|
||||
),
|
||||
),
|
||||
path(
|
||||
"blockchain/",
|
||||
include(
|
||||
[
|
||||
path(
|
||||
"salary/",
|
||||
TransactFromAdminView.as_view(),
|
||||
name="admin_to_user_transaction_api",
|
||||
),
|
||||
path(
|
||||
"payment/",
|
||||
TransactToAdminView.as_view(),
|
||||
name="user_to_admin_transaction_api",
|
||||
),
|
||||
path(
|
||||
"transact/",
|
||||
TransactToUserView.as_view(),
|
||||
name="user_to_user_transaction_api",
|
||||
),
|
||||
path(
|
||||
"amount/",
|
||||
GetMoneyApi.as_view(),
|
||||
name="get_user_money_api",
|
||||
),
|
||||
path(
|
||||
"history/",
|
||||
TransactionHistoryApi.as_view(),
|
||||
name="list_transactions_api",
|
||||
),
|
||||
]
|
||||
),
|
||||
),
|
||||
path(
|
||||
"events/",
|
||||
include(
|
||||
|
|
|
@ -219,4 +219,5 @@ CORS_ALLOW_ALL_ORIGINS = True
|
|||
|
||||
|
||||
MAIN_WALLET = env("MAIN_WALLET")
|
||||
PUB_KEY = env("PUB_KEY")
|
||||
TELEGRAM_API = "https://tender-badgers-eat-178-71-165-37.loca.lt"
|
||||
|
|
|
@ -23,7 +23,11 @@ class User(AbstractUser):
|
|||
max_length=6, choices=WorkerType.choices, default=WorkerType.WORKER
|
||||
)
|
||||
clan = models.ForeignKey(
|
||||
"users.Clan", related_name="users", on_delete=models.SET_NULL, null=True
|
||||
"users.Clan",
|
||||
related_name="users",
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
command = models.ForeignKey(
|
||||
"users.Command", related_name="workers", on_delete=models.CASCADE
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
from django.db.models.signals import pre_save, post_save
|
||||
from django.dispatch import receiver
|
||||
|
||||
from conf import settings
|
||||
from users.models import User
|
||||
from utils.blockchain import create_wallet
|
||||
from utils.blockchain import create_wallet, send_matic
|
||||
|
||||
|
||||
@receiver(post_save, sender=User)
|
||||
|
@ -11,6 +12,7 @@ def process_user(sender, instance, created, **kwargs):
|
|||
instance.set_password(instance.password)
|
||||
|
||||
wallet = create_wallet()
|
||||
send_matic(settings.MAIN_WALLET, wallet.publicKey, 0.1)
|
||||
|
||||
instance.wallet_public_key = wallet.publicKey
|
||||
instance.wallet_private_key = wallet.privateKey
|
||||
|
|
|
@ -132,3 +132,20 @@ def get_balance(my_public_wallet_key: str) -> WalletBalance:
|
|||
return WalletBalance(
|
||||
matic=res.json()["maticAmount"], coins=res.json()["coinsAmount"]
|
||||
)
|
||||
|
||||
|
||||
def send_matic(
|
||||
my_private_wallet_key: str, transfer_publick_key: str, amount: float
|
||||
) -> TransHash:
|
||||
res = r.post(
|
||||
URL + "/v1/transfers/matic",
|
||||
data=json.dumps(
|
||||
{
|
||||
"fromPrivateKey": my_private_wallet_key,
|
||||
"toPublicKey": transfer_publick_key,
|
||||
"amount": amount,
|
||||
}
|
||||
),
|
||||
headers=base_headers,
|
||||
)
|
||||
return TransHash(transaction_hash=res.json()["transaction"])
|
||||
|
|
Loading…
Reference in New Issue
Block a user