added products as NFT

This commit is contained in:
Alexander Karpov 2022-10-09 06:27:35 +03:00
parent abbd90551a
commit 5c3b109f47
9 changed files with 76 additions and 13 deletions

View File

@ -5,7 +5,8 @@ from blockchain.api.views import (
TransactFromAdminView,
TransactToUserView,
TransactToAdminView,
GetMoneyApi, TransactionHistoryApi,
GetMoneyApi,
TransactionHistoryApi,
)
from events.api.views import (
ListCreateEventApi,
@ -15,7 +16,7 @@ from events.api.views import (
ListAttendedWorkersApi,
SubmitWorkerAttendedEvent,
)
from marketplace.api.views import ListCreateProductApi, RetrieveUpdateDestroyProductApi
from marketplace.api.views import ListCreateProductApi, RetrieveUpdateDestroyProductApi, BuyProductApi
from users.api.views import (
ListCreateUserApi,
RetrieveUpdateDeleteUserApi,
@ -27,6 +28,7 @@ from users.api.views import (
RetrieveUpdateDeleteCommandApi,
CreateSeasonApi,
ListClansApiView,
GetSelfUserApi,
)
urlpatterns = [
@ -118,6 +120,11 @@ urlpatterns = [
RetrieveUpdateDestroyProductApi.as_view(),
name="get_update_destroy_product",
),
path(
"product/<str:slug>/buy",
BuyProductApi.as_view(),
name="bui_product",
),
]
),
),
@ -126,6 +133,7 @@ urlpatterns = [
include(
[
path("", ListCreateUserApi.as_view(), name="list_create_user"),
path("self/", GetSelfUserApi.as_view(), name="get_self_user_api"),
path(
"<str:username>",
RetrieveUpdateDeleteUserApi.as_view(),

View File

@ -12,13 +12,11 @@ class ProductSerializer(serializers.ModelSerializer):
"description",
"image",
"image_cropped",
"nft",
"price",
"creator",
]
extra_kwargs = {
"image": {"write_only": True},
"nft": {"read_only": True},
"slug": {"read_only": True},
"image_cropped": {"read_only": True},
"creator": {"read_only": True},

View File

@ -2,10 +2,14 @@ from rest_framework import generics
from rest_framework.generics import get_object_or_404
from rest_framework.permissions import IsAuthenticated
from rest_framework.parsers import FormParser, MultiPartParser
from rest_framework.views import APIView
from blockchain.services import transact_to_admin
from conf import settings
from marketplace.api.serializers import ProductSerializer
from marketplace.models import Product
from common.permissions import IsManager
from utils.blockchain import transfer_nft
class ListCreateProductApi(generics.ListCreateAPIView):
@ -27,3 +31,16 @@ class RetrieveUpdateDestroyProductApi(generics.RetrieveUpdateDestroyAPIView):
slug=self.request.parser_context["kwargs"]["slug"],
)
return product
class BuyProductApi(generics.DestroyAPIView):
permission_classes = [IsAuthenticated]
def get_object(self):
product = get_object_or_404(
Product,
slug=self.request.parser_context["kwargs"]["slug"],
)
transact_to_admin(self.request.user, product.price)
transfer_nft(settings.MAIN_WALLET, self.request.user.wallet_public_key, product.token)
return product

View File

@ -11,7 +11,7 @@ class Product(models.Model):
image = models.ImageField(upload_to="uploads/")
image_cropped = models.ImageField(upload_to="cropped/", blank=True)
nft = models.CharField(max_length=500, blank=True)
token = models.IntegerField(default=0)
price = models.IntegerField(validators=[MinValueValidator(0)])
creator = models.ForeignKey(User, related_name="products", on_delete=models.CASCADE)

View File

@ -5,6 +5,7 @@ from django.dispatch import receiver
from utils.file import crop_image
from utils.generators import generate_charset
from .models import Product
from .tasks import await_nft
@receiver(pre_save, sender=Product)
@ -17,9 +18,12 @@ def create_product(sender, instance, **kwargs):
@receiver(post_save, sender=Product)
def process_product(sender, instance, created, **kwargs):
if instance.image and kwargs["update_fields"] != frozenset({"image_cropped"}):
if instance.image and kwargs["update_fields"] is None:
instance.image_cropped = File(
crop_image(instance.image.path, cut_to=(250, 250)),
name=instance.image.path.split(".")[0].split("/")[-1] + ".png",
)
instance.save(update_fields=["image_cropped"])
if created and kwargs["update_fields"] is None:
await_nft.apply_async(kwargs={"pk": instance.pk})

35
app/marketplace/tasks.py Normal file
View File

@ -0,0 +1,35 @@
from time import sleep
from celery import shared_task
from conf import settings
from marketplace.models import Product
from utils.blockchain import check_transaction, get_nfts, create_nft
@shared_task
def await_nft(pk: int):
product = Product.objects.get(pk=pk)
url = product.image.url
t = create_nft(settings.PUB_KEY, url)
status = ""
try:
status = check_transaction(t.transaction_hash)
except KeyError as e:
pass
while status != "Success":
sleep(3)
try:
status = check_transaction(t.transaction_hash)
except KeyError as e:
pass
print(status)
nfts = get_nfts(settings.PUB_KEY)
for nft in nfts:
if nft.uri == product.image.url:
product.token = nft.tokens[0]
product.save(update_fields=["token"])
return pk

View File

@ -75,3 +75,11 @@ class ListClansApiView(generics.ListAPIView):
serializer_class = ClanSerializer
queryset = Clan.objects.all()
permission_classes = [IsAuthenticated, IsAdmin]
class GetSelfUserApi(generics.RetrieveAPIView):
def get_object(self):
return self.request.user
permission_classes = [IsAuthenticated]
serializer_class = UserSerializer

View File

@ -1,6 +0,0 @@
from celery import shared_task
@shared_task
def process_dir(path):
return path

View File

@ -81,7 +81,6 @@ def create_nft(wallet_public_key: str, string_url: str) -> TransHash:
def get_nfts(wallet_public_key: str) -> List[NftInfo]:
res = r.get(URL + f"/v1/wallets/{wallet_public_key}/nft/balance")
print(res.json())
return list(
map(
lambda res: NftInfo(uri=res["uri"], tokens=res["tokens"]),