Show trades
This commit is contained in:
parent
1e7d8f6c8d
commit
fa7ea66c65
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
"""
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -107,5 +107,4 @@ class AntiFraud(object):
|
|||
# )
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
antifraud = AntiFraud()
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
from core.lib.schemas import agora_s # noqa
|
||||
from core.lib.schemas import nordigen_s # noqa
|
||||
|
|
|
@ -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",
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 #}
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue