Show trades

This commit is contained in:
Mark Veidemanis 2023-03-10 00:23:05 +00:00
parent 1e7d8f6c8d
commit fa7ea66c65
Signed by: m
GPG Key ID: 5ACFCEED46C0904F
12 changed files with 236 additions and 16 deletions

View File

@ -143,4 +143,10 @@ urlpatterns = [
platforms.PlatformDelete.as_view(),
name="platform_delete",
),
# Trades
path(
"trades/<str:type>/",
platforms.PlatformTrades.as_view(),
name="trades",
),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

View File

@ -28,6 +28,15 @@ class LocalPlatformClient(ABC):
async def connect(self):
self.api = AgoraDesk(self.instance.token)
async def call_method(self, method, *args, **kwargs):
"""
Call a method using the self.api object.
"""
if hasattr(self.api, method):
return await getattr(self.api, method)(*args, **kwargs)
else:
raise Exception(f"Method {method} not found in {self.name} API.")
# TODO: do in schedules
# def setup_loop(self):
# """
@ -62,19 +71,18 @@ class LocalPlatformClient(ABC):
async def wrap_dashboard(self, dash=None): # backwards compatibility with TX
if not dash:
dash = await self.api.dashboard()
# dash = await self.api.dashboard()
dash = await self.call("dashboard")
print("DASH22", dash)
# if dash["response"] is None:
# return False
dash_tmp = {}
if not dash:
return False
if not dash["response"]:
return False
if "data" not in dash["response"]:
# log.error(f"Data not in dashboard response: {dash}")
return dash_tmp
if dash["response"]["data"]["contact_count"] > 0:
for contact in dash["response"]["data"]["contact_list"]:
if dash["contact_count"] > 0:
for contact in dash["contact_list"]:
contact_id = contact["data"]["contact_id"]
dash_tmp[contact_id] = contact
return dash_tmp

View File

@ -6,7 +6,7 @@ from core.clients.platform import LocalPlatformClient
from core.lib.money import Money
class AgoraClient(BaseClient, LocalPlatformClient):
class AgoraClient(LocalPlatformClient, BaseClient):
"""
AgoraDesk API handler.
"""

View File

@ -87,6 +87,7 @@ class AgoraDesk:
async with aiohttp.ClientSession() as session:
async with session.post(api_call_url, **cast) as response_raw:
response = await response_raw.json()
status_code = response_raw.status
else:
# response = httpx.get(url=api_call_url, headers=headers, params=query_values)
@ -95,12 +96,15 @@ class AgoraDesk:
async with aiohttp.ClientSession() as session:
async with session.get(api_call_url, **cast) as response_raw:
response = await response_raw.json()
status_code = response_raw.status
if response:
print("YES RESPONSE", response)
logger.debug(response)
result["status"] = response.code
if response.code == 200:
result["status"] = status_code
if status_code == 200:
result["success"] = True
result["message"] = "OK"
result["response"] = response
else:
result["message"] = "API ERROR"

View File

@ -107,5 +107,4 @@ class AntiFraud(object):
# )
if __name__ == "__main__":
antifraud = AntiFraud()
antifraud = AntiFraud()

View File

@ -1 +1,2 @@
from core.lib.schemas import agora_s # noqa
from core.lib.schemas import nordigen_s # noqa

View File

@ -0,0 +1,86 @@
from pydantic import BaseModel
class ContactDataBuyerSeller(BaseModel):
username: str
name: str
feedback_score: int
trade_count: str
last_online: str
class ContactDataAd(BaseModel):
payment_method: str
trade_type: str
advertiser: ContactDataBuyerSeller
asset: str
id: str
class ContactData(BaseModel):
buyer: ContactDataBuyerSeller
seller: ContactDataBuyerSeller
amount: str
amount_xmr: str
fee_xmr: str
advertisement: ContactDataAd
contact_id: str
currency: str
country: str
account_info: str
price_equation: str
is_buying: bool
is_selling: bool
created_at: str
escrowed_at: str
funded_at: str
canceled_at: str | None
closed_at: str | None
msg: str
released_at: str | None
payment_completed_at: str | None
disputed_at: str | None
arbitrated: bool
transfer_to_seller_non_custodial_wallet_transaction_confirmations: str | None
transfer_to_buyer_settlement_wallet_transaction_id: str | None
transfer_to_buyer_settlement_wallet_transaction_key: str | None
buyer_settlement_address: str | None
buyer_settlement_fee_level: str | None
seller_non_custodial_wallet_mnemonic: str | None
transfer_to_seller_non_custodial_wallet_transaction_id: str | None
class ContactActions(BaseModel):
advertisement_public_view: str
advertisement_url: str
message_post_url: str
messages_url: str
release_url: str
class Contact(BaseModel):
data: ContactData
actions: ContactActions
class ResponseData(BaseModel):
contact_count: int
contact_list: list[Contact]
class Response(BaseModel):
data: ResponseData
class Dashboard(BaseModel):
success: bool
message: str
response: Response
DashboardSchema = {
"success": "success",
"message": "message",
"contact_count": "response.data.contact_count",
"contact_list": "response.data.contact_list",
}

View File

@ -122,6 +122,10 @@ class Platform(models.Model):
enabled = models.BooleanField(default=True)
@classmethod
def get_for_user(cls, user):
return cls.objects.filter(user=user, enabled=True)
@property
def currencies(self):
return Aggregator.get_currencies_for_platform(self)

View File

@ -242,6 +242,12 @@
</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="{% url 'trades' type='page' %}">
Trades
</a>
<a class="navbar-item" href="#">
Wallets
</a>
<a class="navbar-item" href="#">
Advert Configuration
</a>

View File

@ -0,0 +1,82 @@
{% load cache %}
{% load cachalot cache %}
{% get_last_invalidation 'core.Platform' as last %}
{% include 'mixins/partials/notify.html' %}
{# cache 600 objects_platform_trades request.user.id object_list type last #}
{% for platform_name, trade_map in object_list.items %}
<h2 class="title is-4">{{ platform_name }}</h2>
<table
class="table is-fullwidth is-hoverable"
hx-target="#{{ context_object_name }}-table"
id="{{ context_object_name }}-table"
hx-swap="outerHTML"
hx-trigger="{{ context_object_name_singular }}Event from:body"
hx-get="{{ list_url }}">
<thead>
<th>id</th>
<th>buyer</th>
<th>seller</th>
<th>amount</th>
<th>crypto</th>
<th>provider</th>
<th>type</th>
<th>actions</th>
</thead>
{% for item in trade_map.values %}
<tr>
<td>
<a
class="has-text-grey"
onclick="window.prompt('Copy to clipboard: Ctrl+C, Enter', '{{ item.data.contact_id }}/');">
<span class="icon" data-tooltip="Copy to clipboard">
<i class="fa-solid fa-copy" aria-hidden="true"></i>
</span>
</a>
</td>
<td data-tooltip="{{ item.data.buyer.name }}
Trades: {{ item.data.buyer.trade_count }}
Last online: {{ item.data.buyer.last_online }}">{{ item.data.buyer.username }}</td>
<td data-tooltip="{{ item.data.seller.name }}
Trades: {{ item.data.seller.trade_count }}
Last online: {{ item.data.seller.last_online }}">{{ item.data.seller.username }}</td>
<td>{{ item.data.amount }} {{ item.data.currency }}</td>
<td>{{ item.data.amount_xmr }} XMR</td>
<td>{{ item.data.advertisement.payment_method }}</td>
<td>{{ item.data.advertisement.trade_type }}</td>
<td>
<div class="buttons">
<button
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-get="{# url 'platform_update' type=type pk=item.id #}"
hx-trigger="click"
hx-target="#{{ type }}s-here"
hx-swap="innerHTML"
class="button">
<span class="icon-text">
<span class="icon">
<i class="fa-solid fa-pencil"></i>
</span>
</span>
</button>
<button
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-delete="{# url 'platform_delete' type=type pk=item.id #}"
hx-trigger="click"
hx-target="#modals-here"
hx-swap="innerHTML"
hx-confirm="Are you sure you wish to delete {{ item.name }}?"
class="button">
<span class="icon-text">
<span class="icon">
<i class="fa-solid fa-xmark"></i>
</span>
</span>
</button>
</div>
</td>
</tr>
{% endfor %}
</table>
{% endfor %}
{# endcache #}

View File

@ -11,16 +11,37 @@ from mixins.views import ( # ObjectRead,
)
from two_factor.views.mixins import OTPRequiredMixin
# from core.clients.platforms.agora import AgoraClient
from core.clients.platforms.agora import AgoraClient
from core.forms import PlatformForm
from core.models import Platform
from core.util import logs
# from core.views.helpers import synchronize_async_helper
from core.views.helpers import synchronize_async_helper
log = logs.get_logger(__name__)
class PlatformTrades(LoginRequiredMixin, OTPRequiredMixin, ObjectList):
list_template = "partials/platform-trades.html"
page_title = "List of trades"
list_url_name = "trades"
list_url_args = ["type"]
context_object_name_singular = "trade"
context_object_name = "trades"
def get_queryset(self, **kwargs):
platforms = Platform.get_for_user(self.request.user)
total_trades = {}
for platform in platforms:
run = synchronize_async_helper(AgoraClient(platform))
dash = synchronize_async_helper(run.wrap_dashboard())
print("DASH", dash)
total_trades[platform.name] = dash
return total_trades
class PlatformList(LoginRequiredMixin, OTPRequiredMixin, ObjectList):
list_template = "partials/platform-list.html"
model = Platform

View File

@ -108,3 +108,6 @@ class AntiFraud(util.Base):
trade_id,
f"Hi! To continue the trade, please complete the verification form: {auth_url}",
)
antifraud = AntiFraud()