from django.contrib import admin, messages from django_admin_relation_links import AdminChangeLinksMixin from django.contrib.auth.models import Group, User from django.contrib.auth.admin import UserAdmin from api.models import OnchainPayment, Order, LNPayment, Profile, MarketTick, Currency from api.logics import Logics admin.site.unregister(Group) admin.site.unregister(User) class ProfileInline(admin.StackedInline): model = Profile can_delete = False fields = ("avatar_tag", ) readonly_fields = ["avatar_tag"] show_change_link = True # extended users with avatars @admin.register(User) class EUserAdmin(AdminChangeLinksMixin, UserAdmin): inlines = [ProfileInline] list_display = ( "avatar_tag", "id", "profile_link", "username", "last_login", "date_joined", "is_staff", ) list_display_links = ("id", "username") change_links = ( "profile", ) ordering = ("-id", ) def avatar_tag(self, obj): return obj.profile.avatar_tag() @admin.register(Order) class OrderAdmin(AdminChangeLinksMixin, admin.ModelAdmin): list_display = ( "id", "type", "maker_link", "taker_link", "status", "amt", "currency_link", "t0_satoshis", "is_disputed", "is_fiat_sent", "created_at", "expires_at", "payout_tx_link", "payout_link", "maker_bond_link", "taker_bond_link", "trade_escrow_link", ) list_display_links = ("id", "type") change_links = ( "maker", "taker", "currency", "payout_tx", "payout", "maker_bond", "taker_bond", "trade_escrow", ) raw_id_fields = ( "maker", "taker", "payout_tx", "payout", "maker_bond", "taker_bond", "trade_escrow", ) list_filter = ("is_disputed", "is_fiat_sent", "is_swap","type", "currency", "status") search_fields = ["id","amount","min_amount","max_amount"] actions = ['maker_wins', 'taker_wins', 'return_everything'] @admin.action(description='Solve dispute: maker wins') def maker_wins(self, request, queryset): ''' Solves a dispute on favor of the maker. Adds Sats to compensations (earned_rewards) of the maker profile. ''' for order in queryset: if order.status in [Order.Status.DIS, Order.Status.WFR] and order.is_disputed: own_bond_sats = order.maker_bond.num_satoshis if Logics.is_buyer(order, order.maker): if order.is_swap: trade_sats = order.payout_tx.num_satoshis else: trade_sats = order.payout.num_satoshis else: trade_sats = order.trade_escrow.num_satoshis order.status = Order.Status.TLD order.maker.profile.earned_rewards = own_bond_sats + trade_sats order.maker.profile.save() order.save() self.message_user(request,f"Dispute of order {order.id} solved successfully on favor of the maker", messages.SUCCESS) else: self.message_user(request,f"Order {order.id} is not in a disputed state", messages.ERROR) @admin.action(description='Solve dispute: taker wins') def taker_wins(self, request, queryset): ''' Solves a dispute on favor of the taker. Adds Sats to compensations (earned_rewards) of the taker profile. ''' for order in queryset: if order.status in [Order.Status.DIS, Order.Status.WFR] and order.is_disputed: own_bond_sats = order.maker_bond.num_satoshis if Logics.is_buyer(order, order.taker): if order.is_swap: trade_sats = order.payout_tx.num_satoshis else: trade_sats = order.payout.num_satoshis else: trade_sats = order.trade_escrow.num_satoshis order.status = Order.Status.TLD order.taker.profile.earned_rewards = own_bond_sats + trade_sats order.taker.profile.save() order.save() self.message_user(request,f"Dispute of order {order.id} solved successfully on favor of the taker", messages.SUCCESS) else: self.message_user(request,f"Order {order.id} is not in a disputed state", messages.ERROR) @admin.action(description='Solve dispute: return everything') def return_everything(self, request, queryset): ''' Solves a dispute by pushing back every bond and escrow to their sender. ''' for order in queryset: if order.status in [Order.Status.DIS, Order.Status.WFR] and order.is_disputed: order.maker_bond.sender.profile.earned_rewards += order.maker_bond.num_satoshis order.maker_bond.sender.profile.save() order.taker_bond.sender.profile.earned_rewards += order.taker_bond.num_satoshis order.taker_bond.sender.profile.save() order.trade_escrow.sender.profile.earned_rewards += order.trade_escrow.num_satoshis order.trade_escrow.sender.profile.save() order.status = Order.Status.TLD order.save() self.message_user(request,f"Dispute of order {order.id} solved successfully, everything returned as compensations", messages.SUCCESS) else: self.message_user(request,f"Order {order.id} is not in a disputed state", messages.ERROR) def amt(self, obj): if obj.has_range and obj.amount == None: return str(float(obj.min_amount))+"-"+ str(float(obj.max_amount)) else: return float(obj.amount) @admin.register(LNPayment) class LNPaymentAdmin(AdminChangeLinksMixin, admin.ModelAdmin): list_display = ( "hash", "concept", "status", "num_satoshis", "fee", "type", "expires_at", "expiry_height", "sender_link", "receiver_link", "order_made_link", "order_taken_link", "order_escrow_link", "order_paid_LN_link", ) list_display_links = ("hash", "concept") change_links = ( "sender", "receiver", "order_made", "order_taken", "order_escrow", "order_paid_LN", ) list_filter = ("type", "concept", "status") ordering = ("-expires_at", ) search_fields = ["payment_hash","num_satoshis","sender__username","receiver__username","description"] @admin.register(OnchainPayment) class OnchainPaymentAdmin(AdminChangeLinksMixin, admin.ModelAdmin): list_display = ( "id", "address", "concept", "status", "num_satoshis", "hash", "swap_fee_rate", "mining_fee_sats", "balance_link", "order_paid_TX_link", ) change_links = ( "balance", "order_paid_TX", ) list_display_links = ("id","address", "concept") list_filter = ("concept", "status") search_fields = ["address","num_satoshis","receiver__username","txid"] @admin.register(Profile) class UserProfileAdmin(AdminChangeLinksMixin, admin.ModelAdmin): list_display = ( "avatar_tag", "id", "user_link", "is_referred", "telegram_enabled", "total_contracts", "pending_rewards", "earned_rewards", "claimed_rewards", "platform_rating", "total_ratings", "avg_rating", "num_disputes", "lost_disputes", ) raw_id_fields = ( "user", "referred_by", ) list_editable = ["pending_rewards", "earned_rewards"] list_display_links = ("avatar_tag", "id") change_links = ["user"] readonly_fields = ["avatar_tag"] search_fields = ["user__username","id"] readonly_fields = ("public_key", "encrypted_private_key") @admin.register(Currency) class CurrencieAdmin(admin.ModelAdmin): list_display = ("id", "currency", "exchange_rate", "timestamp") list_display_links = ("id", "currency") readonly_fields = ("currency", "exchange_rate", "timestamp") ordering = ("id", ) @admin.register(MarketTick) class MarketTickAdmin(admin.ModelAdmin): list_display = ("timestamp", "price", "volume", "premium", "currency", "fee") readonly_fields = ("timestamp", "price", "volume", "premium", "currency", "fee") list_filter = ["currency"] ordering = ("-timestamp", )