mirror of
https://github.com/RoboSats/robosats.git
synced 2024-12-13 19:06:26 +00:00
516537a38e
* Minor fixes on dev setup start up * Add pgp cleartext signatures
618 lines
22 KiB
Python
618 lines
22 KiB
Python
from decouple import config
|
|
from rest_framework import serializers
|
|
|
|
from .models import MarketTick, Order
|
|
|
|
RETRY_TIME = int(config("RETRY_TIME"))
|
|
MIN_PUBLIC_ORDER_DURATION_SECS = 60 * 60 * float(config("MIN_PUBLIC_ORDER_DURATION"))
|
|
MAX_PUBLIC_ORDER_DURATION_SECS = 60 * 60 * float(config("MAX_PUBLIC_ORDER_DURATION"))
|
|
|
|
|
|
class InfoSerializer(serializers.Serializer):
|
|
num_public_buy_orders = serializers.IntegerField()
|
|
num_public_sell_orders = serializers.IntegerField()
|
|
book_liquidity = serializers.IntegerField(
|
|
help_text="Total amount of BTC in the order book"
|
|
)
|
|
active_robots_today = serializers.CharField()
|
|
last_day_nonkyc_btc_premium = serializers.FloatField(
|
|
help_text="Average premium (weighted by volume) of the orders in the last 24h"
|
|
)
|
|
last_day_volume = serializers.FloatField(
|
|
help_text="Total volume in BTC in the last 24h"
|
|
)
|
|
lifetime_volume = serializers.FloatField(
|
|
help_text="Total volume in BTC since exchange's inception"
|
|
)
|
|
lnd_version = serializers.CharField()
|
|
robosats_running_commit_hash = serializers.CharField()
|
|
alternative_site = serializers.CharField()
|
|
alternative_name = serializers.CharField()
|
|
node_alias = serializers.CharField()
|
|
node_id = serializers.CharField()
|
|
network = serializers.CharField()
|
|
maker_fee = serializers.FloatField(help_text="Exchange's set maker fee")
|
|
taker_fee = serializers.FloatField(help_text="Exchange's set taker fee ")
|
|
bond_size = serializers.FloatField(help_text="Default bond size (percent)")
|
|
current_swap_fee_rate = serializers.FloatField(
|
|
help_text="Swap fees to perform on-chain transaction (percent)"
|
|
)
|
|
|
|
|
|
class ListOrderSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = Order
|
|
fields = (
|
|
"id",
|
|
"status",
|
|
"created_at",
|
|
"expires_at",
|
|
"type",
|
|
"currency",
|
|
"amount",
|
|
"has_range",
|
|
"min_amount",
|
|
"max_amount",
|
|
"payment_method",
|
|
"is_explicit",
|
|
"premium",
|
|
"satoshis",
|
|
"maker",
|
|
"taker",
|
|
"escrow_duration",
|
|
"bond_size",
|
|
)
|
|
|
|
|
|
# Only used in oas_schemas
|
|
class SummarySerializer(serializers.Serializer):
|
|
sent_fiat = serializers.IntegerField(
|
|
required=False, help_text="same as `amount` (only for buyer)"
|
|
)
|
|
received_sats = serializers.IntegerField(
|
|
required=False, help_text="same as `trade_satoshis` (only for buyer)"
|
|
)
|
|
is_swap = serializers.BooleanField(
|
|
required=False, help_text="True if the payout was on-chain (only for buyer)"
|
|
)
|
|
received_onchain_sats = serializers.IntegerField(
|
|
required=False,
|
|
help_text="The on-chain sats received (only for buyer and if `is_swap` is `true`)",
|
|
)
|
|
mining_fee_sats = serializers.IntegerField(
|
|
required=False,
|
|
help_text="Mining fees paid in satoshis (only for buyer and if `is_swap` is `true`)",
|
|
)
|
|
swap_fee_sats = serializers.IntegerField(
|
|
required=False,
|
|
help_text="Exchange swap fee in sats (i.e excluding miner fees) (only for buyer and if `is_swap` is `true`)",
|
|
)
|
|
swap_fee_percent = serializers.FloatField(
|
|
required=False,
|
|
help_text="same as `swap_fee_rate` (only for buyer and if `is_swap` is `true`",
|
|
)
|
|
sent_sats = serializers.IntegerField(
|
|
required=False, help_text="The total sats you sent (only for seller)"
|
|
)
|
|
received_fiat = serializers.IntegerField(
|
|
required=False, help_text="same as `amount` (only for seller)"
|
|
)
|
|
trade_fee_sats = serializers.IntegerField(
|
|
required=False,
|
|
help_text="Exchange fees in sats (Does not include swap fee and miner fee)",
|
|
)
|
|
|
|
|
|
# Only used in oas_schemas
|
|
class PlatformSummarySerializer(serializers.Serializer):
|
|
contract_timestamp = serializers.DateTimeField(
|
|
required=False,
|
|
help_text="Timestamp of when the contract was finalized (price and sats fixed)",
|
|
)
|
|
contract_total_time = serializers.FloatField(
|
|
required=False,
|
|
help_text="The time taken for the contract to complete (from taker taking the order to completion of order) in seconds",
|
|
)
|
|
routing_fee_sats = serializers.IntegerField(
|
|
required=False,
|
|
help_text="Sats payed by the exchange for routing fees. Mining fee in case of on-chain swap payout",
|
|
)
|
|
trade_revenue_sats = serializers.IntegerField(
|
|
required=False, help_text="The sats the exchange earned from the trade"
|
|
)
|
|
|
|
|
|
# Only used in oas_schemas
|
|
class OrderDetailSerializer(serializers.ModelSerializer):
|
|
total_secs_exp = serializers.IntegerField(
|
|
required=False,
|
|
help_text="Duration of time (in seconds) to expire, according to the current status of order."
|
|
"This is duration of time after `created_at` (in seconds) that the order will automatically expire."
|
|
"This value changes according to which stage the order is in",
|
|
)
|
|
penalty = serializers.DateTimeField(
|
|
required=False,
|
|
help_text="Time when the user penalty will expire. Penalty applies when you create orders repeatedly without commiting a bond",
|
|
)
|
|
is_maker = serializers.BooleanField(
|
|
required=False, help_text="Whether you are the maker or not"
|
|
)
|
|
is_taker = serializers.BooleanField(
|
|
required=False, help_text="Whether you are the taker or not"
|
|
)
|
|
is_participant = serializers.BooleanField(
|
|
required=False,
|
|
help_text="True if you are either a taker or maker, False otherwise",
|
|
)
|
|
maker_status = serializers.CharField(
|
|
required=False,
|
|
help_text="Status of the maker:\n"
|
|
"- **'Active'** (seen within last 2 min)\n"
|
|
"- **'Seen Recently'** (seen within last 10 min)\n"
|
|
"- **'Inactive'** (seen more than 10 min ago)\n\n"
|
|
"Note: When you make a request to this route, your own status get's updated and can be seen by your counterparty",
|
|
)
|
|
taker_status = serializers.BooleanField(
|
|
required=False,
|
|
help_text="True if you are either a taker or maker, False otherwise",
|
|
)
|
|
price_now = serializers.IntegerField(
|
|
required=False,
|
|
help_text="Price of the order in the order's currency at the time of request (upto 5 significant digits)",
|
|
)
|
|
premium = serializers.IntegerField(
|
|
required=False, help_text="Premium over the CEX price at the current time"
|
|
)
|
|
premium_percentile = serializers.IntegerField(
|
|
required=False,
|
|
help_text="(Only if `is_maker`) Premium percentile of your order compared to other public orders in the same currency currently in the order book",
|
|
)
|
|
num_similar_orders = serializers.IntegerField(
|
|
required=False,
|
|
help_text="(Only if `is_maker`) The number of public orders of the same currency currently in the order book",
|
|
)
|
|
tg_enabled = serializers.BooleanField(
|
|
required=False,
|
|
help_text="(Only if `is_maker`) Whether Telegram notification is enabled or not",
|
|
)
|
|
tg_token = serializers.CharField(
|
|
required=False,
|
|
help_text="(Only if `is_maker`) Your telegram bot token required to enable notifications.",
|
|
)
|
|
tg_bot_name = serializers.CharField(
|
|
required=False,
|
|
help_text="(Only if `is_maker`) The Telegram username of the bot",
|
|
)
|
|
is_buyer = serializers.BooleanField(
|
|
required=False,
|
|
help_text="Whether you are a buyer of sats (you will be receiving sats)",
|
|
)
|
|
is_seller = serializers.BooleanField(
|
|
required=False,
|
|
help_text="Whether you are a seller of sats or not (you will be sending sats)",
|
|
)
|
|
maker_nick = serializers.CharField(
|
|
required=False, help_text="Nickname (Robot name) of the maker"
|
|
)
|
|
taker_nick = serializers.CharField(
|
|
required=False, help_text="Nickname (Robot name) of the taker"
|
|
)
|
|
status_message = serializers.CharField(
|
|
required=False,
|
|
help_text="The current status of the order corresponding to the `status`",
|
|
)
|
|
is_fiat_sent = serializers.BooleanField(
|
|
required=False, help_text="Whether or not the fiat amount is sent by the buyer"
|
|
)
|
|
is_disputed = serializers.BooleanField(
|
|
required=False, help_text="Whether or not the counterparty raised a dispute"
|
|
)
|
|
ur_nick = serializers.CharField(required=False, help_text="Your Nickname")
|
|
ur_nick = serializers.CharField(required=False, help_text="Your Nick")
|
|
maker_locked = serializers.BooleanField(
|
|
required=False, help_text="True if maker bond is locked, False otherwise"
|
|
)
|
|
taker_locked = serializers.BooleanField(
|
|
required=False, help_text="True if taker bond is locked, False otherwise"
|
|
)
|
|
escrow_locked = serializers.BooleanField(
|
|
required=False,
|
|
help_text="True if escrow is locked, False otherwise. Escrow is the sats to be sold, held by Robosats until the trade is finised.",
|
|
)
|
|
trade_satoshis = serializers.IntegerField(
|
|
required=False,
|
|
help_text="Seller sees the amount of sats they need to send. Buyer sees the amount of sats they will receive ",
|
|
)
|
|
bond_invoice = serializers.CharField(
|
|
required=False, help_text="When `status` = `0`, `3`. Bond invoice to be paid"
|
|
)
|
|
bond_satoshis = serializers.IntegerField(
|
|
required=False, help_text="The bond amount in satoshis"
|
|
)
|
|
escrow_invoice = serializers.CharField(
|
|
required=False,
|
|
help_text="For the seller, the escrow invoice to be held by RoboSats",
|
|
)
|
|
escrow_satoshis = serializers.IntegerField(
|
|
required=False, help_text="The escrow amount in satoshis"
|
|
)
|
|
invoice_amount = serializers.IntegerField(
|
|
required=False,
|
|
help_text="The amount in sats the buyer needs to submit an invoice of to receive the trade amount",
|
|
)
|
|
swap_allowed = serializers.BooleanField(
|
|
required=False, help_text="Whether on-chain swap is allowed"
|
|
)
|
|
swap_failure_reason = serializers.CharField(
|
|
required=False, help_text="Reason for why on-chain swap is not available"
|
|
)
|
|
suggested_mining_fee_rate = serializers.IntegerField(
|
|
required=False, help_text="fee in sats/vbyte for the on-chain swap"
|
|
)
|
|
swap_fee_rate = serializers.FloatField(
|
|
required=False,
|
|
help_text="in percentage, the swap fee rate the platform charges",
|
|
)
|
|
pending_cancel = serializers.BooleanField(
|
|
required=False,
|
|
help_text="Your counterparty requested for a collaborative cancel when `status` is either `8`, `9` or `10`",
|
|
)
|
|
asked_for_cancel = serializers.BooleanField(
|
|
required=False,
|
|
help_text="You requested for a collaborative cancel `status` is either `8`, `9` or `10`",
|
|
)
|
|
statement_submitted = serializers.BooleanField(
|
|
required=False,
|
|
help_text="True if you have submitted a statement. Available when `status` is `11`",
|
|
)
|
|
retries = serializers.IntegerField(
|
|
required=False,
|
|
help_text="Number of times ln node has tried to make the payment to you (only if you are the buyer)",
|
|
)
|
|
next_retry_time = serializers.DateTimeField(
|
|
required=False,
|
|
help_text=f"The next time payment will be retried. Payment is retried every {RETRY_TIME} sec",
|
|
)
|
|
failure_reason = serializers.CharField(
|
|
required=False, help_text="The reason the payout failed"
|
|
)
|
|
invoice_expired = serializers.BooleanField(
|
|
required=False,
|
|
help_text="True if the payout invoice expired. `invoice_amount` will be re-set and sent which means the user has to submit a new invoice to be payed",
|
|
)
|
|
trade_fee_percent = serializers.IntegerField(
|
|
required=False,
|
|
help_text="The fee for the trade (fees differ for maker and taker)",
|
|
)
|
|
bond_size_sats = serializers.IntegerField(
|
|
required=False, help_text="The size of the bond in sats"
|
|
)
|
|
bond_size_percent = serializers.IntegerField(
|
|
required=False, help_text="same as `bond_size`"
|
|
)
|
|
maker_summary = SummarySerializer(required=False)
|
|
taker_summary = SummarySerializer(required=False)
|
|
platform_summary = PlatformSummarySerializer(required=True)
|
|
expiry_message = serializers.CharField(
|
|
required=False,
|
|
help_text="The reason the order expired (message associated with the `expiry_reason`)",
|
|
)
|
|
num_satoshis = serializers.IntegerField(
|
|
required=False,
|
|
help_text="only if status = `14` (Successful Trade) and is_buyer = `true`",
|
|
)
|
|
sent_satoshis = serializers.IntegerField(
|
|
required=False,
|
|
help_text="only if status = `14` (Successful Trade) and is_buyer = `true`",
|
|
)
|
|
txid = serializers.CharField(
|
|
required=False,
|
|
help_text="Transaction id of the on-chain swap payout. Only if status = `14` (Successful Trade) and is_buyer = `true`",
|
|
)
|
|
network = serializers.CharField(
|
|
required=False,
|
|
help_text="The network eg. 'testnet', 'mainnet'. Only if status = `14` (Successful Trade) and is_buyer = `true`",
|
|
)
|
|
|
|
class Meta:
|
|
model = Order
|
|
fields = (
|
|
"id",
|
|
"status",
|
|
"created_at",
|
|
"expires_at",
|
|
"type",
|
|
"currency",
|
|
"amount",
|
|
"has_range",
|
|
"min_amount",
|
|
"max_amount",
|
|
"payment_method",
|
|
"is_explicit",
|
|
"premium",
|
|
"satoshis",
|
|
"maker",
|
|
"taker",
|
|
"escrow_duration",
|
|
"total_secs_exp",
|
|
"penalty",
|
|
"is_maker",
|
|
"is_taker",
|
|
"is_participant",
|
|
"maker_status",
|
|
"taker_status",
|
|
"price_now",
|
|
"premium",
|
|
"premium_percentile",
|
|
"num_similar_orders",
|
|
"tg_enabled",
|
|
"tg_token",
|
|
"tg_bot_name",
|
|
"is_buyer",
|
|
"is_seller",
|
|
"maker_nick",
|
|
"taker_nick",
|
|
"status_message",
|
|
"is_fiat_sent",
|
|
"is_disputed",
|
|
"ur_nick",
|
|
"ur_nick",
|
|
"maker_locked",
|
|
"taker_locked",
|
|
"escrow_locked",
|
|
"trade_satoshis",
|
|
"bond_invoice",
|
|
"bond_satoshis",
|
|
"escrow_invoice",
|
|
"escrow_satoshis",
|
|
"invoice_amount",
|
|
"swap_allowed",
|
|
"swap_failure_reason",
|
|
"suggested_mining_fee_rate",
|
|
"swap_fee_rate",
|
|
"pending_cancel",
|
|
"asked_for_cancel",
|
|
"statement_submitted",
|
|
"retries",
|
|
"next_retry_time",
|
|
"failure_reason",
|
|
"invoice_expired",
|
|
"public_duration",
|
|
"bond_size",
|
|
"trade_fee_percent",
|
|
"bond_size_sats",
|
|
"bond_size_percent",
|
|
"maker_summary",
|
|
"taker_summary",
|
|
"platform_summary",
|
|
"expiry_reason",
|
|
"expiry_message",
|
|
"num_satoshis",
|
|
"sent_satoshis",
|
|
"txid",
|
|
"network",
|
|
)
|
|
|
|
|
|
class OrderPublicSerializer(serializers.ModelSerializer):
|
|
maker_nick = serializers.CharField(required=False)
|
|
maker_status = serializers.CharField(
|
|
help_text='Status of the nick - "Active" or "Inactive"', required=False
|
|
)
|
|
price = serializers.FloatField(
|
|
help_text="Price in order's fiat currency", required=False
|
|
)
|
|
satoshis_now = serializers.IntegerField(
|
|
help_text="The amount of sats to be traded at the present moment (not including the fees)",
|
|
required=False,
|
|
)
|
|
|
|
class Meta:
|
|
model = Order
|
|
fields = (
|
|
"id",
|
|
"created_at",
|
|
"expires_at",
|
|
"type",
|
|
"currency",
|
|
"amount",
|
|
"has_range",
|
|
"min_amount",
|
|
"max_amount",
|
|
"payment_method",
|
|
"is_explicit",
|
|
"premium",
|
|
"satoshis",
|
|
"maker",
|
|
"maker_nick",
|
|
"maker_status",
|
|
"price",
|
|
"escrow_duration",
|
|
"satoshis_now",
|
|
"bond_size",
|
|
)
|
|
|
|
|
|
class MakeOrderSerializer(serializers.ModelSerializer):
|
|
currency = serializers.IntegerField(
|
|
required=True,
|
|
help_text="Currency id. See [here](https://github.com/RoboSats/robosats/blob/main/frontend/static/assets/currencies.json) for a list of all IDs",
|
|
)
|
|
payment_method = serializers.CharField(
|
|
max_length=70,
|
|
default="not specified",
|
|
required=False,
|
|
help_text="Can be any string. The UI recognizes [these payment methods](https://github.com/RoboSats/robosats/blob/main/frontend/src/components/payment-methods/Methods.js) and displays them with a logo.",
|
|
)
|
|
is_explicit = serializers.BooleanField(
|
|
default=False,
|
|
help_text="Whether the order is explicitly priced or not. If set to `true` then `satoshis` need to be specified",
|
|
)
|
|
has_range = serializers.BooleanField(
|
|
default=False,
|
|
help_text="Whether the order specifies a range of amount or a fixed amount.\n\nIf `true`, then `min_amount` and `max_amount` fields are **required**.\n\n If `false` then `amount` is **required**",
|
|
)
|
|
|
|
class Meta:
|
|
model = Order
|
|
fields = (
|
|
"type",
|
|
"currency",
|
|
"amount",
|
|
"has_range",
|
|
"min_amount",
|
|
"max_amount",
|
|
"payment_method",
|
|
"is_explicit",
|
|
"premium",
|
|
"satoshis",
|
|
"public_duration",
|
|
"escrow_duration",
|
|
"bond_size",
|
|
)
|
|
|
|
|
|
class UpdateOrderSerializer(serializers.Serializer):
|
|
invoice = serializers.CharField(
|
|
max_length=15000,
|
|
allow_null=True,
|
|
allow_blank=True,
|
|
default=None,
|
|
help_text="Invoice used for payouts. Must be PGP signed with the robot's public key. The expected Armored PGP header is -----BEGIN PGP SIGNED MESSAGE-----\nHash: SHA512\n\n",
|
|
)
|
|
routing_budget_ppm = serializers.IntegerField(
|
|
default=0,
|
|
min_value=0,
|
|
max_value=100_001,
|
|
allow_null=True,
|
|
required=False,
|
|
help_text="Max budget to allocate for routing in PPM",
|
|
)
|
|
address = serializers.CharField(
|
|
max_length=15000,
|
|
allow_null=True,
|
|
allow_blank=True,
|
|
default=None,
|
|
help_text="Onchain address used for payouts. Must be PGP signed with the robot's public key. The expected Armored PGP header is -----BEGIN PGP SIGNED MESSAGE-----\nHash: SHA512\n\n",
|
|
)
|
|
statement = serializers.CharField(
|
|
max_length=500_000, allow_null=True, allow_blank=True, default=None
|
|
)
|
|
action = serializers.ChoiceField(
|
|
choices=(
|
|
"pause",
|
|
"take",
|
|
"update_invoice",
|
|
"update_address",
|
|
"submit_statement",
|
|
"dispute",
|
|
"cancel",
|
|
"confirm",
|
|
"undo_confirm",
|
|
"rate_platform",
|
|
),
|
|
allow_null=False,
|
|
)
|
|
rating = serializers.ChoiceField(
|
|
choices=("1", "2", "3", "4", "5"),
|
|
allow_null=True,
|
|
allow_blank=True,
|
|
default=None,
|
|
)
|
|
amount = serializers.DecimalField(
|
|
max_digits=18, decimal_places=8, allow_null=True, required=False, default=None
|
|
)
|
|
mining_fee_rate = serializers.DecimalField(
|
|
max_digits=6, decimal_places=3, allow_null=True, required=False, default=None
|
|
)
|
|
|
|
|
|
class UserGenSerializer(serializers.Serializer):
|
|
# Mandatory fields
|
|
token_sha256 = serializers.CharField(
|
|
min_length=64,
|
|
max_length=64,
|
|
allow_null=False,
|
|
allow_blank=False,
|
|
required=True,
|
|
help_text="SHA256 of user secret",
|
|
)
|
|
# Optional fields
|
|
# (PGP keys are mandatory for new users, but optional for logins)
|
|
public_key = serializers.CharField(
|
|
max_length=2000,
|
|
allow_null=False,
|
|
allow_blank=False,
|
|
required=False,
|
|
help_text="Armored ASCII PGP public key block",
|
|
)
|
|
encrypted_private_key = serializers.CharField(
|
|
max_length=2000,
|
|
allow_null=False,
|
|
allow_blank=False,
|
|
required=False,
|
|
help_text="Armored ASCII PGP encrypted private key block",
|
|
)
|
|
|
|
ref_code = serializers.CharField(
|
|
max_length=30,
|
|
allow_null=True,
|
|
allow_blank=True,
|
|
required=False,
|
|
default=None,
|
|
help_text="Referal code",
|
|
)
|
|
counts = serializers.ListField(
|
|
child=serializers.IntegerField(),
|
|
allow_null=True,
|
|
required=False,
|
|
default=None,
|
|
help_text="Counts of the unique characters in the token",
|
|
)
|
|
length = serializers.IntegerField(
|
|
allow_null=True,
|
|
default=None,
|
|
required=False,
|
|
min_value=1,
|
|
help_text="Length of the token",
|
|
)
|
|
unique_values = serializers.IntegerField(
|
|
allow_null=True,
|
|
default=None,
|
|
required=False,
|
|
min_value=1,
|
|
help_text="Number of unique values in the token",
|
|
)
|
|
|
|
|
|
class ClaimRewardSerializer(serializers.Serializer):
|
|
invoice = serializers.CharField(
|
|
max_length=2000,
|
|
allow_null=True,
|
|
allow_blank=True,
|
|
default=None,
|
|
help_text="A valid LN invoice with the reward amount to withdraw",
|
|
)
|
|
|
|
|
|
class PriceSerializer(serializers.Serializer):
|
|
pass
|
|
|
|
|
|
class TickSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = MarketTick
|
|
fields = (
|
|
"timestamp",
|
|
"currency",
|
|
"volume",
|
|
"price",
|
|
"premium",
|
|
"fee",
|
|
)
|
|
depth = 1
|
|
|
|
|
|
class StealthSerializer(serializers.Serializer):
|
|
wantsStealth = serializers.BooleanField()
|