From 69dc0b1b8532111428ada80ffa9ae9158f5649da Mon Sep 17 00:00:00 2001 From: ilia Date: Sat, 8 Oct 2022 14:39:52 +0300 Subject: [PATCH] end up blockchain and add clans --- ..._product_slug_alter_product_description.py | 23 ++++ app/marketplace/models.py | 2 +- app/requirements/base.txt | 2 +- ...02_clan_user_salary_user_type_user_clan.py | 36 +++++ app/users/models.py | 13 +- app/utils/blockchain.py | 124 +++++++++++++++++- 6 files changed, 192 insertions(+), 8 deletions(-) create mode 100644 app/marketplace/migrations/0002_product_slug_alter_product_description.py create mode 100644 app/users/migrations/0002_clan_user_salary_user_type_user_clan.py diff --git a/app/marketplace/migrations/0002_product_slug_alter_product_description.py b/app/marketplace/migrations/0002_product_slug_alter_product_description.py new file mode 100644 index 0000000..bb32d21 --- /dev/null +++ b/app/marketplace/migrations/0002_product_slug_alter_product_description.py @@ -0,0 +1,23 @@ +# Generated by Django 4.0.8 on 2022-10-08 09:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('marketplace', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='product', + name='slug', + field=models.SlugField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='product', + name='description', + field=models.TextField(blank=True), + ), + ] diff --git a/app/marketplace/models.py b/app/marketplace/models.py index 3601e73..9bcfb63 100644 --- a/app/marketplace/models.py +++ b/app/marketplace/models.py @@ -5,7 +5,7 @@ from users.models import User class Product(models.Model): name = models.CharField(max_length=200) - slug = models.SlugField(max_length=20) + slug = models.SlugField(max_length=20, null=True) description = models.TextField(blank=True) image = models.ImageField(upload_to="uploads/") diff --git a/app/requirements/base.txt b/app/requirements/base.txt index f702abc..991a350 100644 --- a/app/requirements/base.txt +++ b/app/requirements/base.txt @@ -3,7 +3,7 @@ djangorestframework-simplejwt==5.2.1 Django==4.0.8 django-cors-headers==3.13.0 django-environ==0.9.0 -"drf-yasg[validation]" +drf-yasg[validation] Pillow==9.2.0 redis==4.3.4 diff --git a/app/users/migrations/0002_clan_user_salary_user_type_user_clan.py b/app/users/migrations/0002_clan_user_salary_user_type_user_clan.py new file mode 100644 index 0000000..c45d8e7 --- /dev/null +++ b/app/users/migrations/0002_clan_user_salary_user_type_user_clan.py @@ -0,0 +1,36 @@ +# Generated by Django 4.0.8 on 2022-10-08 09:27 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Clan', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, null=True)), + ], + ), + migrations.AddField( + model_name='user', + name='salary', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='user', + name='type', + field=models.CharField(choices=[('WORKER', 'worker'), ('HR', 'human resources'), ('ADMIN', 'administrator')], default='WORKER', max_length=6), + ), + migrations.AddField( + model_name='user', + name='clan', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='users.clan'), + ), + ] diff --git a/app/users/models.py b/app/users/models.py index 404b25f..5c9e1e8 100644 --- a/app/users/models.py +++ b/app/users/models.py @@ -1,5 +1,15 @@ from django.contrib.auth.models import AbstractUser from django.db import models +from faker import Faker + + +class Clan(models.Model): + name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + name = Faker().name() + self.name = name + "'s clan" + super(Clan, self).save(*args, **kwargs) class User(AbstractUser): @@ -19,6 +29,7 @@ class User(AbstractUser): max_length=6, choices=WorkerType.choices, default=WorkerType.WORKER ) salary = models.IntegerField(default=0) + clan = models.ForeignKey(Clan, on_delete=models.CASCADE, null=True) def __str__(self): return self.username @@ -36,4 +47,4 @@ class User(AbstractUser): return self.type == self.WorkerType.ADMIN class Meta: - ordering = ["-id"] + ordering = ["-id"] \ No newline at end of file diff --git a/app/utils/blockchain.py b/app/utils/blockchain.py index 14179ae..944a64e 100644 --- a/app/utils/blockchain.py +++ b/app/utils/blockchain.py @@ -1,18 +1,132 @@ -from xml.dom import pulldom from pydantic import BaseModel import requests as r +import json +from time import sleep +from typing import List URL = 'https://hackathon.lsp.team/hk' -"""TODO: Сделать обвязку апишки блокчейна""" +base_headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json' +} -class WalletCreation(BaseModel): +class Wallet(BaseModel): publicKey: str privateKey: str -def create_wallet() -> WalletCreation: +class WalletBalance(BaseModel): + matic: float + coins: float + + +class TransHash(BaseModel): + transaction_hash: str + + +class NftInfo(BaseModel): + uri: str + tokens: List[int] + + +class TransactionHistory(BaseModel): + hash: str + timestamp: int + token_name: str + from_wallet: str + to_wallet: str + + +def create_wallet() -> Wallet: response = r.post(URL+'/v1/wallets/new') data = response.json() - return WalletCreation(publicKey=data['publicKey'], privateKey=data['privateKey']) + return Wallet(publicKey=data['publicKey'], privateKey=data['privateKey']) + + +def check_transaction(trans_hash: str) -> str: + res = r.get(URL + '/v1/transfers/status/'+trans_hash, data=json.dumps({ + 'transactionHash': trans_hash + }), + headers=base_headers + ) + return res.json()['status'] + + +def transfer_rubbles(my_wallet_private_key, transfer_publick_key: str, amount: float) -> TransHash: + response = r.post(URL+'/v1/transfers/ruble', data=json.dumps({ + "fromPrivateKey": my_wallet_private_key, + "toPublicKey": transfer_publick_key, + "amount": amount + }), + headers={ + 'Content-Type': 'application/json', + 'Accept': 'application/json' + } + ) + return TransHash(transaction_hash=response.json()['transaction']) + + +def create_nft(wallet_public_key: str, string_url: str) -> TransHash: + response = r.post(URL + '/v1/nft/generate', data=json.dumps( + { + "toPublicKey": wallet_public_key, + "uri": string_url, + "nftCount": 1 + } + ), + headers=base_headers + ) + return TransHash(transaction_hash=response.json()['transaction_hash']) + + +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'] + ), + res.json()['balance'] + ), + ) + +def get_history(wallet_public_key: str) -> List[TransactionHistory]: + res = r.post(URL+f'/v1/wallets/{wallet_public_key}/history', data=json.dumps({ + "page": 0, + "offset": 100, + "sort": "asc" + + }), headers=base_headers) + return list( + map( + lambda res: TransactionHistory( + hash=res['hash'], + timestamp=res['timeStamp'], + token_name=res['tokenName'], + from_wallet=res['from'], + to_wallet=res['to'] + ), + res.json()['history'] + ), + ) + + +def transfer_nft(my_private_wallet_key: str, transfer_publick_key: str, token_id: int) -> TransHash: + res = r.post(URL+'/v1/transfers/nft', data=json.dumps( + { + "fromPrivateKey": my_private_wallet_key, + "toPublicKey": transfer_publick_key, + "tokenId": token_id + } + ), headers=base_headers) + return TransHash(transaction_hash=res.json()['transaction_hash']) + +def get_balance(my_public_wallet_key: str) -> WalletBalance: + res = r.get(URL+f'/v1/wallets/{my_public_wallet_key}/balance') + return WalletBalance(matic=res.json()['maticAmount'], coins=res.json()['coinsAmount']) + +print(get_balance('0x1a63208e5b82588320a8C24b2c595Ba5d5cbfF3f'))