mirror of
https://github.com/RoboSats/robosats.git
synced 2025-01-18 20:21:35 +00:00
Implement public API non-KYC BTC prices
This commit is contained in:
parent
408516241d
commit
f383d20c37
@ -318,16 +318,11 @@ class Order(models.Model):
|
|||||||
3: int(config("EXP_TAKER_BOND_INVOICE")), # 'Waiting for taker bond'
|
3: int(config("EXP_TAKER_BOND_INVOICE")), # 'Waiting for taker bond'
|
||||||
4: 0, # 'Cancelled'
|
4: 0, # 'Cancelled'
|
||||||
5: 0, # 'Expired'
|
5: 0, # 'Expired'
|
||||||
6: 60 * int(config("INVOICE_AND_ESCROW_DURATION")
|
6: 60 * int(config("INVOICE_AND_ESCROW_DURATION")), # 'Waiting for trade collateral and buyer invoice'
|
||||||
), # 'Waiting for trade collateral and buyer invoice'
|
7: 60 * int(config("INVOICE_AND_ESCROW_DURATION")), # 'Waiting only for seller trade collateral'
|
||||||
7: 60 * int(config("INVOICE_AND_ESCROW_DURATION")
|
8: 60 * int(config("INVOICE_AND_ESCROW_DURATION")), # 'Waiting only for buyer invoice'
|
||||||
), # 'Waiting only for seller trade collateral'
|
9: 60 * 60 * int(config("FIAT_EXCHANGE_DURATION")), # 'Sending fiat - In chatroom'
|
||||||
8: 60 * int(config("INVOICE_AND_ESCROW_DURATION")
|
10: 60 * 60 * int(config("FIAT_EXCHANGE_DURATION")),# 'Fiat sent - In chatroom'
|
||||||
), # 'Waiting only for buyer invoice'
|
|
||||||
9: 60 * 60 *
|
|
||||||
int(config("FIAT_EXCHANGE_DURATION")), # 'Sending fiat - In chatroom'
|
|
||||||
10: 60 * 60 *
|
|
||||||
int(config("FIAT_EXCHANGE_DURATION")), # 'Fiat sent - In chatroom'
|
|
||||||
11: 1 * 24 * 60 * 60, # 'In dispute'
|
11: 1 * 24 * 60 * 60, # 'In dispute'
|
||||||
12: 0, # 'Collaboratively cancelled'
|
12: 0, # 'Collaboratively cancelled'
|
||||||
13: 24 * 60 * 60, # 'Sending satoshis to buyer'
|
13: 24 * 60 * 60, # 'Sending satoshis to buyer'
|
||||||
|
@ -72,3 +72,6 @@ class ClaimRewardSerializer(serializers.Serializer):
|
|||||||
allow_null=True,
|
allow_null=True,
|
||||||
allow_blank=True,
|
allow_blank=True,
|
||||||
default=None)
|
default=None)
|
||||||
|
|
||||||
|
class PriceSerializer(serializers.Serializer):
|
||||||
|
pass
|
@ -1,5 +1,5 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
from .views import MakerView, OrderView, UserView, BookView, InfoView, RewardView
|
from .views import MakerView, OrderView, UserView, BookView, InfoView, RewardView, PriceView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("make/", MakerView.as_view()),
|
path("make/", MakerView.as_view()),
|
||||||
@ -12,5 +12,6 @@ urlpatterns = [
|
|||||||
path("book/", BookView.as_view()),
|
path("book/", BookView.as_view()),
|
||||||
# path('robot/') # Profile Info
|
# path('robot/') # Profile Info
|
||||||
path("info/", InfoView.as_view()),
|
path("info/", InfoView.as_view()),
|
||||||
|
path("price/", PriceView.as_view()),
|
||||||
path("reward/", RewardView.as_view()),
|
path("reward/", RewardView.as_view()),
|
||||||
]
|
]
|
||||||
|
13
api/utils.py
13
api/utils.py
@ -109,3 +109,16 @@ def compute_premium_percentile(order):
|
|||||||
|
|
||||||
rates = np.array(rates)
|
rates = np.array(rates)
|
||||||
return round(np.sum(rates < order_rate) / len(rates), 2)
|
return round(np.sum(rates < order_rate) / len(rates), 2)
|
||||||
|
|
||||||
|
|
||||||
|
def compute_avg_premium(queryset):
|
||||||
|
weighted_premiums = []
|
||||||
|
volumes = []
|
||||||
|
for tick in queryset:
|
||||||
|
weighted_premiums.append(tick.premium * tick.volume)
|
||||||
|
volumes.append(tick.volume)
|
||||||
|
|
||||||
|
total_volume = sum(volumes)
|
||||||
|
# Avg_premium is the weighted average of the premiums by volume
|
||||||
|
avg_premium = sum(weighted_premiums) / total_volume
|
||||||
|
return avg_premium, total_volume
|
50
api/views.py
50
api/views.py
@ -9,12 +9,12 @@ from rest_framework.response import Response
|
|||||||
from django.contrib.auth import authenticate, login, logout
|
from django.contrib.auth import authenticate, login, logout
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
from api.serializers import ListOrderSerializer, MakeOrderSerializer, UpdateOrderSerializer, ClaimRewardSerializer
|
from api.serializers import ListOrderSerializer, MakeOrderSerializer, UpdateOrderSerializer, ClaimRewardSerializer, PriceSerializer
|
||||||
from api.models import LNPayment, MarketTick, Order, Currency, Profile
|
from api.models import LNPayment, MarketTick, Order, Currency, Profile
|
||||||
from api.logics import Logics
|
from api.logics import Logics
|
||||||
from api.messages import Telegram
|
from api.messages import Telegram
|
||||||
from secrets import token_urlsafe
|
from secrets import token_urlsafe
|
||||||
from api.utils import get_lnd_version, get_commit_robosats, compute_premium_percentile
|
from api.utils import get_lnd_version, get_commit_robosats, compute_premium_percentile, compute_avg_premium
|
||||||
|
|
||||||
from .nick_generator.nick_generator import NickGenerator
|
from .nick_generator.nick_generator import NickGenerator
|
||||||
from robohash import Robohash
|
from robohash import Robohash
|
||||||
@ -655,18 +655,11 @@ class InfoView(ListAPIView):
|
|||||||
# Compute average premium and volume of today
|
# Compute average premium and volume of today
|
||||||
queryset = MarketTick.objects.filter(timestamp__day=today.day)
|
queryset = MarketTick.objects.filter(timestamp__day=today.day)
|
||||||
if not len(queryset) == 0:
|
if not len(queryset) == 0:
|
||||||
weighted_premiums = []
|
avg_premium, total_volume = compute_avg_premium(queryset)
|
||||||
volumes = []
|
# If no contracts, fallback to lifetime avg premium
|
||||||
for tick in queryset:
|
|
||||||
weighted_premiums.append(tick.premium * tick.volume)
|
|
||||||
volumes.append(tick.volume)
|
|
||||||
|
|
||||||
total_volume = sum(volumes)
|
|
||||||
# Avg_premium is the weighted average of the premiums by volume
|
|
||||||
avg_premium = sum(weighted_premiums) / total_volume
|
|
||||||
else:
|
else:
|
||||||
avg_premium = 0
|
queryset = MarketTick.objects.all()
|
||||||
total_volume = 0
|
avg_premium, total_volume = compute_avg_premium(queryset)
|
||||||
|
|
||||||
queryset = MarketTick.objects.all()
|
queryset = MarketTick.objects.all()
|
||||||
if not len(queryset) == 0:
|
if not len(queryset) == 0:
|
||||||
@ -729,6 +722,33 @@ class RewardView(CreateAPIView):
|
|||||||
context['successful_withdrawal'] = False
|
context['successful_withdrawal'] = False
|
||||||
return Response(context, status.HTTP_400_BAD_REQUEST)
|
return Response(context, status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return Response({"successful_withdrawal": True}, status.HTTP_200_OK)
|
return Response({"successful_withdrawal": True}, status.HTTP_200_OK)
|
||||||
|
|
||||||
|
class PriceView(CreateAPIView):
|
||||||
|
|
||||||
|
serializer_class = PriceSerializer
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
|
||||||
|
# Compute average premium and volume of last 24 h
|
||||||
|
start_datetime = timezone.now() - timedelta(days=1)
|
||||||
|
queryset = MarketTick.objects.filter(timestamp__gt=start_datetime)
|
||||||
|
if not len(queryset) == 0:
|
||||||
|
avg_premium, _ = compute_avg_premium(queryset)
|
||||||
|
|
||||||
|
# If no contracts exists in the last 24 h, fallback to lifetime average premium.
|
||||||
|
else:
|
||||||
|
queryset = MarketTick.objects.all()
|
||||||
|
avg_premium, _ = compute_avg_premium(queryset)
|
||||||
|
|
||||||
|
payload = {}
|
||||||
|
queryset = Currency.objects.all().order_by('currency')
|
||||||
|
for currency in queryset:
|
||||||
|
code = Currency.currency_dict[str(currency.currency)]
|
||||||
|
payload[code] = {'price': currency.exchange_rate * (1 + avg_premium / 100),
|
||||||
|
'premium': avg_premium}
|
||||||
|
|
||||||
|
# A hack here. BTC swaps have usually no premium (at least, they are totally different)
|
||||||
|
payload['BTC'] = {'price': 1, 'premium': 0}
|
||||||
|
|
||||||
|
return Response(payload, status.HTTP_200_OK)
|
@ -315,11 +315,11 @@ export default class BottomBar extends Component {
|
|||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<PasswordIcon/>
|
<PasswordIcon/>
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText secondary="It will not remain here">
|
<ListItemText secondary="Your token (will not remain here)">
|
||||||
{this.props.token ?
|
{this.props.token ?
|
||||||
<TextField
|
<TextField
|
||||||
disabled
|
disabled
|
||||||
label='Your Token, back it up!'
|
label='Back it up!'
|
||||||
value={this.props.token }
|
value={this.props.token }
|
||||||
variant='filled'
|
variant='filled'
|
||||||
size='small'
|
size='small'
|
||||||
|
@ -367,6 +367,17 @@ export default class OrderPage extends Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BackButton = () => {
|
||||||
|
// If order has expired, show back button.
|
||||||
|
if (this.state.status == 5){
|
||||||
|
return(
|
||||||
|
<Grid item xs={12} align="center">
|
||||||
|
<Button variant='contained' color='secondary' onClick={this.props.history.goBack}>Back</Button>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
return(null)
|
||||||
|
}
|
||||||
|
|
||||||
CancelButton = () => {
|
CancelButton = () => {
|
||||||
|
|
||||||
// If maker and Waiting for Bond. Or if taker and Waiting for bond.
|
// If maker and Waiting for Bond. Or if taker and Waiting for bond.
|
||||||
@ -561,7 +572,10 @@ export default class OrderPage extends Component {
|
|||||||
<Grid item xs={12} align="center">
|
<Grid item xs={12} align="center">
|
||||||
{/* Participants can see the "Cancel" Button, but cannot see the "Back" or "Take Order" buttons */}
|
{/* Participants can see the "Cancel" Button, but cannot see the "Back" or "Take Order" buttons */}
|
||||||
{this.state.is_participant ?
|
{this.state.is_participant ?
|
||||||
|
<>
|
||||||
<this.CancelButton/>
|
<this.CancelButton/>
|
||||||
|
<this.BackButton/>
|
||||||
|
</>
|
||||||
:
|
:
|
||||||
<Grid container spacing={1}>
|
<Grid container spacing={1}>
|
||||||
<Grid item xs={12} align="center">
|
<Grid item xs={12} align="center">
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user