From 9ab52853d5288ef061d838af6aba38def7c85836 Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Fri, 7 Jan 2022 10:22:52 -0800 Subject: [PATCH 01/29] Work on more logics. Rough draft finished --- api/admin.py | 2 +- api/logics.py | 76 +++++++++++++++++++++++----- api/models.py | 36 ++++++++----- api/urls.py | 5 +- api/views.py | 64 ++++++++++++++++++----- frontend/src/components/MakerPage.js | 3 +- 6 files changed, 142 insertions(+), 44 deletions(-) diff --git a/api/admin.py b/api/admin.py index b45ca85b..9b57b651 100644 --- a/api/admin.py +++ b/api/admin.py @@ -24,7 +24,7 @@ class EUserAdmin(UserAdmin): @admin.register(Order) class OrderAdmin(AdminChangeLinksMixin, admin.ModelAdmin): - list_display = ('id','type','maker_link','taker_link','status','amount','currency','t0_satoshis','created_at','expires_at', 'buyer_invoice_link','maker_bond_link','taker_bond_link','trade_escrow_link') + list_display = ('id','type','maker_link','taker_link','status','amount','currency','t0_satoshis','is_disputed','is_fiat_sent','created_at','expires_at', 'buyer_invoice_link','maker_bond_link','taker_bond_link','trade_escrow_link') list_display_links = ('id','type') change_links = ('maker','taker','buyer_invoice','maker_bond','taker_invoice','taker_bond','trade_escrow') diff --git a/api/logics.py b/api/logics.py index a0f6c62a..5a8afe12 100644 --- a/api/logics.py +++ b/api/logics.py @@ -23,8 +23,6 @@ ESCROW_EXPIRY = int(config('ESCROW_EXPIRY')) class Logics(): - # escrow_user = User.objects.get(username=ESCROW_USERNAME) - def validate_already_maker_or_taker(user): '''Checks if the user is already partipant of an order''' queryset = Order.objects.filter(maker=user) @@ -130,16 +128,23 @@ class Logics(): @classmethod def rate_counterparty(cls, order, user, rating): - # if maker, rates taker - if order.maker == user: - order.taker.profile.total_ratings = order.taker.profile.total_ratings + 1 - last_ratings = list(order.taker.profile.last_ratings).append(rating) - order.taker.profile.total_ratings = sum(last_ratings) / len(last_ratings) - # if taker, rates maker - if order.taker == user: - order.maker.profile.total_ratings = order.maker.profile.total_ratings + 1 - last_ratings = list(order.maker.profile.last_ratings).append(rating) - order.maker.profile.total_ratings = sum(last_ratings) / len(last_ratings) + + # If the trade is finished + if order.status > Order.Status.PAY: + + # if maker, rates taker + if order.maker == user: + order.taker.profile.total_ratings = order.taker.profile.total_ratings + 1 + last_ratings = list(order.taker.profile.last_ratings).append(rating) + order.taker.profile.total_ratings = sum(last_ratings) / len(last_ratings) + + # if taker, rates maker + if order.taker == user: + order.maker.profile.total_ratings = order.maker.profile.total_ratings + 1 + last_ratings = list(order.maker.profile.last_ratings).append(rating) + order.maker.profile.total_ratings = sum(last_ratings) / len(last_ratings) + else: + return False, {'bad_request':'You cannot rate your counterparty yet.'} order.save() return True, None @@ -291,4 +296,49 @@ class Logics(): expires_at = expires_at) order.save() - return True, {'escrow_invoice':invoice,'escrow_satoshis': escrow_satoshis} \ No newline at end of file + return True, {'escrow_invoice':invoice,'escrow_satoshis': escrow_satoshis} + + def settle_escrow(order): + ''' Settles the trade escrow HTLC''' + # TODO ERROR HANDLING + + valid = LNNode.settle_hodl_htlcs(order.trade_escrow.payment_hash) + return valid + + def pay_buyer_invoice(order): + ''' Settles the trade escrow HTLC''' + # TODO ERROR HANDLING + + valid = LNNode.pay_invoice(order.buyer_invoice.payment_hash) + return valid + + @classmethod + def confirm_fiat(cls, order, user): + ''' If Order is in the CHAT states: + If user is buyer: mark the FIAT SENT andettle escrow! + If User is the seller and FIAT was already sent: Pay buyer invoice!''' + + if order.status == Order.Status.CHA or order.status == Order.Status.FSE: # TODO Alternatively, if all collateral is locked? test out + + # If buyer, settle escrow and mark fiat sent + if cls.is_buyer(order, user): + if cls.settle_escrow(order): # KEY LINE - SETTLES THE TRADE ESCROW !! + order.trade_escrow.status = LNPayment.Status.SETLED + order.status = Order.Status.FSE + order.is_fiat_sent = True + + # If seller and fiat sent, pay buyer invoice + elif cls.is_seller(order, user): + if not order.is_fiat_sent: + return False, {'bad_request':'You cannot confirm to have received the fiat before it is confirmed to be sent by the buyer.'} + + # Double check the escrow is settled. + if LNNode.double_check_htlc_is_settled(order.trade_escrow.payment_hash): + if cls.pay_buyer_invoice(order): # KEY LINE - PAYS THE BUYER !! + order.status = Order.Status.PAY + order.buyer_invoice.status = LNPayment.Status.PAYING + else: + return False, {'bad_request':'You cannot confirm the fiat payment at this stage'} + + order.save() + return True, None \ No newline at end of file diff --git a/api/models.py b/api/models.py index accc8e18..4f818b62 100644 --- a/api/models.py +++ b/api/models.py @@ -38,7 +38,8 @@ class LNPayment(models.Model): RETNED = 3, 'Returned' MISSNG = 4, 'Missing' VALIDI = 5, 'Valid' - INFAIL = 6, 'Failed routing' + PAYING = 6, 'Paying ongoing' + FAILRO = 7, 'Failed routing' # payment use details type = models.PositiveSmallIntegerField(choices=Types.choices, null=False, default=Types.HODL) @@ -78,20 +79,20 @@ class Order(models.Model): DEL = 2, 'Deleted' TAK = 3, 'Waiting for taker bond' UCA = 4, 'Cancelled' - WF2 = 5, 'Waiting for trade collateral and buyer invoice' - WFE = 6, 'Waiting only for seller trade collateral' - WFI = 7, 'Waiting only for buyer invoice' - CHA = 8, 'Sending fiat - In chatroom' - CCA = 9, 'Collaboratively cancelled' + EXP = 5, 'Expired' + WF2 = 6, 'Waiting for trade collateral and buyer invoice' + WFE = 7, 'Waiting only for seller trade collateral' + WFI = 8, 'Waiting only for buyer invoice' + CHA = 9, 'Sending fiat - In chatroom' FSE = 10, 'Fiat sent - In chatroom' - FCO = 11, 'Fiat confirmed' - SUC = 12, 'Sucessfully settled' - FAI = 13, 'Failed lightning network routing' - UPI = 14, 'Updated invoice' - DIS = 15, 'In dispute' + DIS = 11, 'In dispute' + CCA = 12, 'Collaboratively cancelled' + PAY = 13, 'Sending satoshis to buyer' + SUC = 14, 'Sucessfully settled' + FAI = 15, 'Failed lightning network routing' MLD = 16, 'Maker lost dispute' TLD = 17, 'Taker lost dispute' - EXP = 18, 'Expired' + # order info status = models.PositiveSmallIntegerField(choices=Status.choices, null=False, default=Status.WFB) @@ -102,7 +103,7 @@ class Order(models.Model): type = models.PositiveSmallIntegerField(choices=Types.choices, null=False) currency = models.PositiveSmallIntegerField(choices=Currencies.choices, null=False) amount = models.DecimalField(max_digits=9, decimal_places=4, validators=[MinValueValidator(0.00001)]) - payment_method = models.CharField(max_length=30, null=False, default="not specified", blank=True) + payment_method = models.CharField(max_length=50, null=False, default="not specified", blank=True) # order pricing method. A explicit amount of sats, or a relative premium above/below market. is_explicit = models.BooleanField(default=False, null=False) @@ -118,8 +119,11 @@ class Order(models.Model): maker = models.ForeignKey(User, related_name='maker', on_delete=models.CASCADE, null=True, default=None) # unique = True, a maker can only make one order taker = models.ForeignKey(User, related_name='taker', on_delete=models.SET_NULL, null=True, default=None, blank=True) # unique = True, a taker can only take one order is_pending_cancel = models.BooleanField(default=False, null=False) # When collaborative cancel is needed and one partner has cancelled. + is_disputed = models.BooleanField(default=False, null=False) + is_fiat_sent = models.BooleanField(default=False, null=False) - # order collateral + # HTLCs + # Order collateral maker_bond = models.ForeignKey(LNPayment, related_name='maker_bond', on_delete=models.SET_NULL, null=True, default=None, blank=True) taker_bond = models.ForeignKey(LNPayment, related_name='taker_bond', on_delete=models.SET_NULL, null=True, default=None, blank=True) trade_escrow = models.ForeignKey(LNPayment, related_name='trade_escrow', on_delete=models.SET_NULL, null=True, default=None, blank=True) @@ -127,6 +131,10 @@ class Order(models.Model): # buyer payment LN invoice buyer_invoice = models.ForeignKey(LNPayment, related_name='buyer_invoice', on_delete=models.SET_NULL, null=True, default=None, blank=True) + # cancel LN invoice // these are only needed to charge lower-than-bond amounts. E.g., a taken order has a small cost if cancelled, to avoid DDOSing. + maker_cancel = models.ForeignKey(LNPayment, related_name='maker_cancel', on_delete=models.SET_NULL, null=True, default=None, blank=True) + taker_cancel = models.ForeignKey(LNPayment, related_name='taker_cancel', on_delete=models.SET_NULL, null=True, default=None, blank=True) + def __str__(self): # Make relational back to ORDER return (f'Order {self.id}: {self.Types(self.type).label} BTC for {self.amount} {self.Currencies(self.currency).label}') diff --git a/api/urls.py b/api/urls.py index b10893c8..7ba757ba 100644 --- a/api/urls.py +++ b/api/urls.py @@ -1,9 +1,10 @@ from django.urls import path -from .views import OrderMakerView, OrderView, UserView, BookView +from .views import MakerView, OrderView, UserView, BookView, InfoView urlpatterns = [ - path('make/', OrderMakerView.as_view()), + path('make/', MakerView.as_view()), path('order/', OrderView.as_view({'get':'get','post':'take_update_confirm_dispute_cancel'})), path('usergen/', UserView.as_view()), path('book/', BookView.as_view()), + path('info/', InfoView.as_view()), ] \ No newline at end of file diff --git a/api/views.py b/api/views.py index c1cf3897..71d5b2e8 100644 --- a/api/views.py +++ b/api/views.py @@ -22,13 +22,14 @@ from django.utils import timezone from decouple import config EXP_MAKER_BOND_INVOICE = int(config('EXP_MAKER_BOND_INVOICE')) +FEE = float(config('FEE')) avatar_path = Path('frontend/static/assets/avatars') avatar_path.mkdir(parents=True, exist_ok=True) # Create your views here. -class OrderMakerView(CreateAPIView): +class MakerView(CreateAPIView): serializer_class = MakeOrderSerializer def post(self,request): @@ -121,7 +122,19 @@ class OrderView(viewsets.ViewSet): data['is_seller'] = Logics.is_seller(order,request.user) data['maker_nick'] = str(order.maker) data['taker_nick'] = str(order.taker) - data['status_message'] = Order.Status(order.status).label + data['status_message'] = Order.Status(order.status).label + data['is_fiat_sent'] = order.is_fiat_sent + data['is_disputed'] = order.is_disputed + + # If both bonds are locked, participants can see the trade in sats is also final. + if order.taker_bond: + if order.maker_bond.status == order.taker_bond.status == order.trade_escrow.status == LNPayment.Status.LOCKED: + # Seller sees the amount he pays + if data['is_seller']: + data['trade_satoshis'] = order.last_satoshis + # Buyer sees the amount he receives + elif data['is_buyer']: + data['trade_satoshis'] = order.last_satoshis * (1-FEE) # 5) If status is 'waiting for maker bond' and user is MAKER, reply with a MAKER HODL invoice. if order.status == Order.Status.WFB and data['is_maker']: @@ -166,7 +179,11 @@ class OrderView(viewsets.ViewSet): if order.maker_bond.status == order.taker_bond.status == order.trade_escrow.status == LNPayment.Status.LOCKED: # add whether a collaborative cancel is pending data['pending_cancel'] = order.is_pending_cancel - + + # 9) if buyer confirmed FIAT SENT + elif order.status == Order.Status.FSE: + data['buyer_confirmed'] + return Response(data, status.HTTP_200_OK) def take_update_confirm_dispute_cancel(self, request, format=None): @@ -195,32 +212,42 @@ class OrderView(viewsets.ViewSet): Logics.take(order, request.user) else: Response({'bad_request':'This order is not public anymore.'}, status.HTTP_400_BAD_REQUEST) - # 2) If action is update (invoice) - elif action == 'update_invoice' and invoice: + # Any other action is only allowed if the user is a participant + if not (order.maker == request.user or order.taker == request.user): + return Response({'bad_request':'You are not a participant in this order'}, status.HTTP_403_FORBIDDEN) + + # 2) If action is 'update invoice' + if action == 'update_invoice' and invoice: valid, context = Logics.update_invoice(order,request.user,invoice) - if not valid: return Response(context,status.HTTP_400_BAD_REQUEST) + if not valid: return Response(context, status.HTTP_400_BAD_REQUEST) # 3) If action is cancel elif action == 'cancel': valid, context = Logics.cancel_order(order,request.user) - if not valid: return Response(context,status.HTTP_400_BAD_REQUEST) + if not valid: return Response(context, status.HTTP_400_BAD_REQUEST) # 4) If action is confirm elif action == 'confirm': - pass + valid, context = Logics.confirm_fiat(order,request.user) + if not valid: return Response(context, status.HTTP_400_BAD_REQUEST) # 5) If action is dispute elif action == 'dispute': - pass + valid, context = Logics.open_dispute(order,request.user, rating) + if not valid: return Response(context, status.HTTP_400_BAD_REQUEST) - # 6) If action is dispute + # 6) If action is rate elif action == 'rate' and rating: valid, context = Logics.rate_counterparty(order,request.user, rating) - if not valid: return Response(context,status.HTTP_400_BAD_REQUEST) + if not valid: return Response(context, status.HTTP_400_BAD_REQUEST) - # If nothing... something else is going on. Probably not allowed! + # If nothing of the above... something else is going on. Probably not allowed! else: - return Response({'bad_request':'The Robotic Satoshis working in the warehouse did not understand you'}) + return Response( + {'bad_request': + 'The Robotic Satoshis working in the warehouse did not understand you. ' + + 'Please, fill a Bug Issue in Github https://github.com/Reckless-Satoshi/robosats/issues'}, + status.HTTP_501_NOT_IMPLEMENTED) return self.get(request) @@ -337,6 +364,17 @@ class BookView(ListAPIView): book_data.append(data) return Response(book_data, status=status.HTTP_200_OK) + +class InfoView(ListAPIView): + + def get(self, request, format = None): + context = {} + context['num_public_buy_orders'] = len(Order.objects.filter(type=Order.Types.BUY, status=Order.Status.PUB)) + context['num_public_sell_orders'] = len(Order.objects.filter(type=Order.Types.BUY, status=Order.Status.PUB)) + context['num_active_robots'] = None # Todo + context['total_volume'] = None + + return Response(context, status.HTTP_200_ok) diff --git a/frontend/src/components/MakerPage.js b/frontend/src/components/MakerPage.js index a98e5049..6b1ee1b1 100644 --- a/frontend/src/components/MakerPage.js +++ b/frontend/src/components/MakerPage.js @@ -177,7 +177,8 @@ export default class MakerPage extends Component { type="text" require={true} inputProps={{ - style: {textAlign:"center"} + style: {textAlign:"center"}, + maxLength: 50 }} onChange={this.handlePaymentMethodChange} /> From b472b4928c26c52063bc053b650fabbe68c53f7b Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Fri, 7 Jan 2022 11:22:07 -0800 Subject: [PATCH 02/29] More logics, bug hunt --- api/lightning.py | 22 +++++++++++++--------- api/logics.py | 31 +++++++++++++++++++++++-------- api/models.py | 2 +- api/views.py | 4 ++-- 4 files changed, 39 insertions(+), 20 deletions(-) diff --git a/api/lightning.py b/api/lightning.py index cf66a12f..a10f258b 100644 --- a/api/lightning.py +++ b/api/lightning.py @@ -22,32 +22,36 @@ class LNNode(): return invoice, payment_hash, expires_at - def validate_hodl_invoice_locked(): + def validate_hodl_invoice_locked(payment_hash): '''Generates hodl invoice to publish an order''' return True - def validate_ln_invoice(invoice): # num_satoshis + def validate_ln_invoice(invoice, num_satoshis): # num_satoshis '''Checks if the submited LN invoice is as expected''' valid = True - num_satoshis = 50000 # TODO decrypt and confirm sats are as expected + context = None description = 'Placeholder desc' # TODO decrypt from LN invoice - payment_hash = '567126' # TODO decrypt + payment_hash = '567&*GIHU126' # TODO decrypt expires_at = timezone.now() # TODO decrypt - return valid, num_satoshis, description, payment_hash, expires_at + return valid, context, description, payment_hash, expires_at - def pay_buyer_invoice(invoice): - '''Sends sats to buyer''' + def pay_invoice(invoice): + '''Sends sats to buyer, or cancelinvoices''' return True - def charge_hodl_htlcs(invoice): + def settle_hodl_htlcs(payment_hash): '''Charges a LN hodl invoice''' return True - def free_hodl_htlcs(invoice): + def return_hodl_htlcs(payment_hash): '''Returns sats''' return True + def double_check_htlc_is_settled(payment_hash): + ''' Just as it sounds. Better safe than sorry!''' + return True + diff --git a/api/logics.py b/api/logics.py index 5a8afe12..19dd971b 100644 --- a/api/logics.py +++ b/api/logics.py @@ -87,10 +87,19 @@ class Logics(): @classmethod def update_invoice(cls, order, user, invoice): - is_valid_invoice, num_satoshis, description, payment_hash, expires_at = LNNode.validate_ln_invoice(invoice) - # only user is the buyer and a valid LN invoice - if not (cls.is_buyer(order, user) or is_valid_invoice): - return False, {'bad_request':'Invalid Lightning Network Invoice. It starts by LNTB...'} + + # only the buyer can post a buyer invoice + if not cls.is_buyer(order, user): + return False, {'bad_request':'Only the buyer of this order can provide a buyer invoice.'} + if not order.taker_bond: + return False, {'bad_request':'Wait for your order to be taken.'} + if not (order.taker_bond.status == order.maker_bond.status == LNPayment.Status.LOCKED): + return False, {'bad_request':'You cannot a invoice while bonds are not posted.'} + + num_satoshis = cls.buyer_invoice_amount(order, user)[1]['invoice_amount'] + valid, context, description, payment_hash, expires_at = LNNode.validate_ln_invoice(invoice, num_satoshis) + if not valid: + return False, context order.buyer_invoice, _ = LNPayment.objects.update_or_create( concept = LNPayment.Concepts.PAYBUYER, @@ -150,7 +159,7 @@ class Logics(): return True, None @classmethod - def cancel_order(cls, order, user, state): + def cancel_order(cls, order, user, state=None): # 1) When maker cancels before bond '''The order never shows up on the book and order @@ -315,8 +324,8 @@ class Logics(): @classmethod def confirm_fiat(cls, order, user): ''' If Order is in the CHAT states: - If user is buyer: mark the FIAT SENT andettle escrow! - If User is the seller and FIAT was already sent: Pay buyer invoice!''' + If user is buyer: mark FIAT SENT and settle escrow! + If User is the seller and FIAT is SENT: Pay buyer invoice!''' if order.status == Order.Status.CHA or order.status == Order.Status.FSE: # TODO Alternatively, if all collateral is locked? test out @@ -334,7 +343,13 @@ class Logics(): # Double check the escrow is settled. if LNNode.double_check_htlc_is_settled(order.trade_escrow.payment_hash): - if cls.pay_buyer_invoice(order): # KEY LINE - PAYS THE BUYER !! + + # Make sure the trade escrow is at least as big as the buyer invoice + if order.trade_escrow.num_satoshis <= order.buyer_invoice.num_satoshis: + return False, {'bad_request':'Woah, something broke badly. Report in the public channels, or open a Github Issue.'} + + # Double check the trade escrow is settled + elif cls.pay_buyer_invoice(order): # KEY LINE - PAYS THE BUYER !! order.status = Order.Status.PAY order.buyer_invoice.status = LNPayment.Status.PAYING else: diff --git a/api/models.py b/api/models.py index 4f818b62..054381c9 100644 --- a/api/models.py +++ b/api/models.py @@ -137,7 +137,7 @@ class Order(models.Model): def __str__(self): # Make relational back to ORDER - return (f'Order {self.id}: {self.Types(self.type).label} BTC for {self.amount} {self.Currencies(self.currency).label}') + return (f'Order {self.id}: {self.Types(self.type).label} BTC for {float(self.amount)} {self.Currencies(self.currency).label}') @receiver(pre_delete, sender=Order) def delelete_HTLCs_at_order_deletion(sender, instance, **kwargs): diff --git a/api/views.py b/api/views.py index 71d5b2e8..8ac2fd3e 100644 --- a/api/views.py +++ b/api/views.py @@ -128,13 +128,13 @@ class OrderView(viewsets.ViewSet): # If both bonds are locked, participants can see the trade in sats is also final. if order.taker_bond: - if order.maker_bond.status == order.taker_bond.status == order.trade_escrow.status == LNPayment.Status.LOCKED: + if order.maker_bond.status == order.taker_bond.status == LNPayment.Status.LOCKED: # Seller sees the amount he pays if data['is_seller']: data['trade_satoshis'] = order.last_satoshis # Buyer sees the amount he receives elif data['is_buyer']: - data['trade_satoshis'] = order.last_satoshis * (1-FEE) + data['trade_satoshis'] = Logics.buyer_invoice_amount(order, request.user)[1]['invoice_amount'] # 5) If status is 'waiting for maker bond' and user is MAKER, reply with a MAKER HODL invoice. if order.status == Order.Status.WFB and data['is_maker']: From eb9042eaa4f32e34d7e10fb58433bcd43cc33f7f Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Fri, 7 Jan 2022 14:46:30 -0800 Subject: [PATCH 03/29] Add Non-KYC Bitcoin price historical records --- api/admin.py | 16 ++++++++++++---- api/logics.py | 14 ++++++-------- api/models.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- api/utils.py | 12 ++++++++++++ api/views.py | 34 ++++++++++++++++++++-------------- 5 files changed, 96 insertions(+), 31 deletions(-) create mode 100644 api/utils.py diff --git a/api/admin.py b/api/admin.py index 9b57b651..a5b32506 100644 --- a/api/admin.py +++ b/api/admin.py @@ -2,7 +2,7 @@ from django.contrib import admin from django_admin_relation_links import AdminChangeLinksMixin from django.contrib.auth.models import Group, User from django.contrib.auth.admin import UserAdmin -from .models import Order, LNPayment, Profile +from .models import Order, LNPayment, Profile, MarketTick admin.site.unregister(Group) admin.site.unregister(User) @@ -17,8 +17,8 @@ class ProfileInline(admin.StackedInline): @admin.register(User) class EUserAdmin(UserAdmin): inlines = [ProfileInline] - list_display = ('avatar_tag',) + UserAdmin.list_display - list_display_links = ['username'] + list_display = ('avatar_tag','id','username','last_login','date_joined','is_staff') + list_display_links = ('id','username') def avatar_tag(self, obj): return obj.profile.avatar_tag() @@ -27,16 +27,24 @@ class OrderAdmin(AdminChangeLinksMixin, admin.ModelAdmin): list_display = ('id','type','maker_link','taker_link','status','amount','currency','t0_satoshis','is_disputed','is_fiat_sent','created_at','expires_at', 'buyer_invoice_link','maker_bond_link','taker_bond_link','trade_escrow_link') list_display_links = ('id','type') change_links = ('maker','taker','buyer_invoice','maker_bond','taker_invoice','taker_bond','trade_escrow') + list_filter = ('is_disputed','is_fiat_sent','type','currency','status') @admin.register(LNPayment) class LNPaymentAdmin(AdminChangeLinksMixin, admin.ModelAdmin): list_display = ('id','concept','status','num_satoshis','type','invoice','expires_at','sender_link','receiver_link') list_display_links = ('id','concept') change_links = ('sender','receiver') + list_filter = ('type','concept','status') @admin.register(Profile) class UserProfileAdmin(AdminChangeLinksMixin, admin.ModelAdmin): list_display = ('avatar_tag','id','user_link','total_ratings','avg_rating','num_disputes','lost_disputes') list_display_links = ('avatar_tag','id') change_links =['user'] - readonly_fields = ['avatar_tag'] \ No newline at end of file + readonly_fields = ['avatar_tag'] + +@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'] \ No newline at end of file diff --git a/api/logics.py b/api/logics.py index 19dd971b..140f8ae1 100644 --- a/api/logics.py +++ b/api/logics.py @@ -1,10 +1,10 @@ from datetime import timedelta from django.utils import timezone -import requests from .lightning import LNNode -from .models import Order, LNPayment, User +from .models import Order, LNPayment, MarketTick, User from decouple import config +from .utils import get_exchange_rate FEE = float(config('FEE')) BOND_SIZE = float(config('BOND_SIZE')) @@ -61,11 +61,9 @@ class Logics(): if order.is_explicit: satoshis_now = order.satoshis else: - # TODO Add fallback Public APIs and error handling - # Think about polling price data in a different way (e.g. store locally every t seconds) - market_prices = requests.get(MARKET_PRICE_API).json() - exchange_rate = float(market_prices[Order.Currencies(order.currency).label]['last']) - satoshis_now = ((float(order.amount) * 1+float(order.premium)) / exchange_rate) * 100*1000*1000 + exchange_rate = get_exchange_rate(Order.Currencies(order.currency).label) + premium_rate = exchange_rate * (1+float(order.premium)/100) + satoshis_now = (float(order.amount) / premium_rate) * 100*1000*1000 return int(satoshis_now) @@ -306,7 +304,7 @@ class Logics(): order.save() return True, {'escrow_invoice':invoice,'escrow_satoshis': escrow_satoshis} - + def settle_escrow(order): ''' Settles the trade escrow HTLC''' # TODO ERROR HANDLING diff --git a/api/models.py b/api/models.py index 054381c9..d69cd767 100644 --- a/api/models.py +++ b/api/models.py @@ -7,18 +7,14 @@ from django.utils.html import mark_safe from decouple import config from pathlib import Path +from .utils import get_exchange_rate -############################# -# TODO -# Load hparams from .env file MIN_TRADE = int(config('MIN_TRADE')) MAX_TRADE = int(config('MAX_TRADE')) FEE = float(config('FEE')) BOND_SIZE = float(config('BOND_SIZE')) - - class LNPayment(models.Model): class Types(models.IntegerChoices): @@ -192,3 +188,48 @@ class Profile(models.Model): def avatar_tag(self): return mark_safe('' % self.get_avatar()) +class MarketTick(models.Model): + ''' + Records tick by tick Non-KYC Bitcoin price. + Data to be aggregated and offered via public API. + + It is checked against current cex prices for nice + insight on the historical premium of Non-KYC BTC + + Price is set when both taker bond is locked. Both + maker and taker are commited with bonds (contract + is finished and cancellation has a cost) + ''' + + price = models.DecimalField(max_digits=10, decimal_places=2, default=None, null=True, validators=[MinValueValidator(0)]) + volume = models.DecimalField(max_digits=8, decimal_places=8, default=None, null=True, validators=[MinValueValidator(0)]) + premium = models.DecimalField(max_digits=5, decimal_places=2, default=None, null=True, validators=[MinValueValidator(-100), MaxValueValidator(999)], blank=True) + currency = models.PositiveSmallIntegerField(choices=Order.Currencies.choices, null=True) + timestamp = models.DateTimeField(auto_now_add=True) + + # Relevant to keep record of the historical fee, so the insight on the premium can be better analyzed + fee = models.DecimalField(max_digits=4, decimal_places=4, default=FEE, validators=[MinValueValidator(0), MaxValueValidator(1)]) + + def log_a_tick(order): + ''' + Adds a new tick + ''' + if not order.taker_bond: + return None + + elif order.taker_bond.status == LNPayment.Status.LOCKED: + volume = order.last_satoshis / 100000000 + price = float(order.amount) / volume # Amount Fiat / Amount BTC + premium = 100 * (price / get_exchange_rate(Order.Currencies(order.currency).label) - 1) + + tick = MarketTick.objects.create( + price=price, + volume=volume, + premium=premium, + currency=order.currency) + tick.save() + + def __str__(self): + return f'Tick: {self.id}' + + diff --git a/api/utils.py b/api/utils.py new file mode 100644 index 00000000..0b1b934b --- /dev/null +++ b/api/utils.py @@ -0,0 +1,12 @@ + +from decouple import config +import requests + +def get_exchange_rate(currency): + # TODO Add fallback Public APIs and error handling + # Think about polling price data in a different way (e.g. store locally every t seconds) + + market_prices = requests.get(config('MARKET_PRICE_API')).json() + exchange_rate = float(market_prices[currency]['last']) + + return exchange_rate \ No newline at end of file diff --git a/api/views.py b/api/views.py index 8ac2fd3e..d8ccf874 100644 --- a/api/views.py +++ b/api/views.py @@ -322,23 +322,27 @@ class UserView(APIView): # It is unlikely, but maybe the nickname is taken (1 in 20 Billion change) context['found'] = 'Bad luck, this nickname is taken' context['bad_request'] = 'Enter a different token' - return Response(context, status=status.HTTP_403_FORBIDDEN) + return Response(context, status.HTTP_403_FORBIDDEN) def delete(self,request): - user = User.objects.get(id = request.user.id) + ''' Pressing "give me another" deletes the logged in user ''' + user = request.user + if not user: + return Response(status.HTTP_403_FORBIDDEN) - # TO DO. Pressing "give me another" deletes the logged in user - # However it might be a long time recovered user - # Only delete if user live is < 5 minutes + # Only delete if user life is shorter than 30 minutes. Helps deleting users by mistake + if user.date_joined < (timezone.now() - timedelta(minutes=30)): + return Response(status.HTTP_400_BAD_REQUEST) - # TODO check if user exists AND it is not a maker or taker! - if user is not None: - logout(request) - user.delete() + # Check if it is not a maker or taker! + if not Logics.validate_already_maker_or_taker(user): + return Response({'bad_request':'User cannot be deleted while he is part of an order'}, status.HTTP_400_BAD_REQUEST) - return Response({'user_deleted':'User deleted permanently'},status=status.HTTP_302_FOUND) + logout(request) + user.delete() + return Response({'user_deleted':'User deleted permanently'}, status.HTTP_301_MOVED_PERMANENTLY) - return Response(status=status.HTTP_403_FORBIDDEN) + class BookView(ListAPIView): serializer_class = ListOrderSerializer @@ -367,14 +371,16 @@ class BookView(ListAPIView): class InfoView(ListAPIView): - def get(self, request, format = None): + def get(self): context = {} + context['num_public_buy_orders'] = len(Order.objects.filter(type=Order.Types.BUY, status=Order.Status.PUB)) context['num_public_sell_orders'] = len(Order.objects.filter(type=Order.Types.BUY, status=Order.Status.PUB)) - context['num_active_robots'] = None # Todo + context['last_day_avg_btc_premium'] = None # Todo + context['num_active_robots'] = None context['total_volume'] = None - return Response(context, status.HTTP_200_ok) + return Response(context, status.HTTP_200_OK) From 4516f1974a865a1b3ea85572f2076a25a08b3b2f Mon Sep 17 00:00:00 2001 From: fieryfrank Date: Fri, 7 Jan 2022 18:48:23 -0500 Subject: [PATCH 04/29] backend and BookPage.js use currencies.json --- api/currencies.json | 6 ++++++ api/models.py | 11 +++++------ api/urls.py | 3 ++- api/views.py | 9 ++++++++- frontend/src/components/BookPage.js | 20 ++++++++++++++++---- frontend/urls.py | 3 ++- 6 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 api/currencies.json diff --git a/api/currencies.json b/api/currencies.json new file mode 100644 index 00000000..bf3a4382 --- /dev/null +++ b/api/currencies.json @@ -0,0 +1,6 @@ +{ + "1":"USD", + "2":"EUR", + "3":"ETH", + "4":"ABC" +} diff --git a/api/models.py b/api/models.py index 452e57e3..6fa81646 100644 --- a/api/models.py +++ b/api/models.py @@ -7,6 +7,7 @@ from django.dispatch import receiver from django.utils.html import mark_safe from pathlib import Path +import json ############################# # TODO @@ -65,11 +66,6 @@ class Order(models.Model): BUY = 0, 'BUY' SELL = 1, 'SELL' - class Currencies(models.IntegerChoices): - USD = 1, 'USD' - EUR = 2, 'EUR' - ETH = 3, 'ETH' - class Status(models.IntegerChoices): WFB = 0, 'Waiting for bond' PUB = 1, 'Published in order book' @@ -92,6 +88,9 @@ class Order(models.Model): TLD = 18, 'Taker lost dispute' EXP = 19, 'Expired' + currency_dict = json.load(open('./api/currencies.json')) + currency_choices = [(int(val), label) for val, label in list(currency_dict.items())] + print(currency_choices) # order info status = models.PositiveSmallIntegerField(choices=Status.choices, null=False, default=Status.WFB) created_at = models.DateTimeField(auto_now_add=True) @@ -99,7 +98,7 @@ class Order(models.Model): # order details type = models.PositiveSmallIntegerField(choices=Types.choices, null=False) - currency = models.PositiveSmallIntegerField(choices=Currencies.choices, null=False) + currency = models.PositiveSmallIntegerField(choices=currency_choices, null=False) amount = models.DecimalField(max_digits=9, decimal_places=4, validators=[MinValueValidator(0.00001)]) payment_method = models.CharField(max_length=30, null=False, default="not specified", blank=True) diff --git a/api/urls.py b/api/urls.py index eae708dd..a3b73309 100644 --- a/api/urls.py +++ b/api/urls.py @@ -1,9 +1,10 @@ from django.urls import path -from .views import OrderMakerView, OrderView, UserView, BookView +from .views import OrderMakerView, OrderView, UserView, BookView, get_currencies_json urlpatterns = [ path('make/', OrderMakerView.as_view()), path('order/', OrderView.as_view({'get':'get','post':'take_or_update'})), path('usergen/', UserView.as_view()), path('book/', BookView.as_view()), + path('currencies/', get_currencies_json), ] \ No newline at end of file diff --git a/api/views.py b/api/views.py index 04fc6d42..470d02e7 100644 --- a/api/views.py +++ b/api/views.py @@ -21,6 +21,9 @@ from pathlib import Path from datetime import timedelta from django.utils import timezone +import json +from django.http import HttpResponse + # .env expiration_time = 8 @@ -263,6 +266,7 @@ class BookView(ListAPIView): def get(self,request, format=None): currency = request.GET.get('currency') + print("currency:", currency) type = request.GET.get('type') queryset = Order.objects.filter(currency=currency, type=type, status=int(Order.Status.PUB)) if len(queryset)== 0: @@ -281,7 +285,10 @@ class BookView(ListAPIView): book_data.append(data) return Response(book_data, status=status.HTTP_200_OK) - + +def get_currencies_json(request): + currency_dict = json.load(open('./api/currencies.json')) + return HttpResponse(json.dumps(currency_dict),content_type="application/json") diff --git a/frontend/src/components/BookPage.js b/frontend/src/components/BookPage.js index 93cb63d8..1f43c68a 100644 --- a/frontend/src/components/BookPage.js +++ b/frontend/src/components/BookPage.js @@ -8,8 +8,10 @@ export default class BookPage extends Component { orders: new Array(), currency: 1, type: 1, + currencies_dict: {"1":"USD"} }; this.getOrderDetails() + this.getCurrencyDict() this.state.currencyCode = this.getCurrencyCode(this.state.currency) } @@ -24,6 +26,15 @@ export default class BookPage extends Component { not_found: data.not_found, })); } + getCurrencyDict() { + fetch('/api/currencies') + .then((response) => response.json()) + .then((data) => + this.setState({ + currencies_dict: data + })); + + } handleCardClick=(e)=>{ console.log(e) @@ -48,7 +59,7 @@ export default class BookPage extends Component { // Gets currency code (3 letters) from numeric (e.g., 1 -> USD) // Improve this function so currencies are read from json getCurrencyCode(val){ - return (val == 1 ) ? "USD": ((val == 2 ) ? "EUR":"ETH") + return this.state.currencies_dict[val.toString()] } // pretty numbers @@ -156,9 +167,10 @@ export default class BookPage extends Component { }} onChange={this.handleCurrencyChange} > - USD - EUR - ETH + { + Object.entries(this.state.currencies_dict) + .map( ([key, value]) => {value} ) + } diff --git a/frontend/urls.py b/frontend/urls.py index 74fb0594..d7b68630 100644 --- a/frontend/urls.py +++ b/frontend/urls.py @@ -8,5 +8,6 @@ urlpatterns = [ path('make/', index), path('book/', index), path('order/', index), - path('wait/', index), + path('wait/', index), + path('currencies/',index) ] \ No newline at end of file From 7b6b4865529bea44c2772e3b999a81c6dee98242 Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Fri, 7 Jan 2022 16:29:04 -0800 Subject: [PATCH 05/29] updated env-sample --- .env-sample | 10 ++++++++-- api/logics.py | 4 ---- api/models.py | 6 ++++-- frontend/src/components/MakerPage.js | 2 +- frontend/src/components/OrderPage.js | 2 ++ .../components/{TradePipelineBox.js => TradeBox.js} | 0 6 files changed, 15 insertions(+), 9 deletions(-) rename frontend/src/components/{TradePipelineBox.js => TradeBox.js} (100%) diff --git a/.env-sample b/.env-sample index 2e88f3ec..a80d8ef6 100644 --- a/.env-sample +++ b/.env-sample @@ -10,8 +10,14 @@ BOND_SIZE = 0.01 MIN_TRADE = 10000 MAX_TRADE = 500000 -# Expiration time in minutes -EXPIRATION_MAKE = 5 +# Expiration time for HODL invoices and returning collateral in HOURS +BOND_EXPIRY = 8 +ESCROW_EXPIRY = 8 + +# Expiration time for locking collateral in MINUTES +EXP_MAKER_BOND_INVOICE = 300 +EXP_TAKER_BOND_INVOICE = 200 +EXP_TRADE_ESCR_INVOICE = 200 # Username for HTLCs escrows ESCROW_USERNAME = 'admin' \ No newline at end of file diff --git a/api/logics.py b/api/logics.py index 140f8ae1..7fad23ec 100644 --- a/api/logics.py +++ b/api/logics.py @@ -126,10 +126,6 @@ class Logics(): else: order.status = Order.Status.WFE - # If the order status was Payment Failed. Move forward to invoice Updated. - if order.status == Order.Status.FAI: - order.status = Order.Status.UPI - order.save() return True, None diff --git a/api/models.py b/api/models.py index d69cd767..464540de 100644 --- a/api/models.py +++ b/api/models.py @@ -99,7 +99,7 @@ class Order(models.Model): type = models.PositiveSmallIntegerField(choices=Types.choices, null=False) currency = models.PositiveSmallIntegerField(choices=Currencies.choices, null=False) amount = models.DecimalField(max_digits=9, decimal_places=4, validators=[MinValueValidator(0.00001)]) - payment_method = models.CharField(max_length=50, null=False, default="not specified", blank=True) + payment_method = models.CharField(max_length=35, null=False, default="not specified", blank=True) # order pricing method. A explicit amount of sats, or a relative premium above/below market. is_explicit = models.BooleanField(default=False, null=False) @@ -212,8 +212,9 @@ class MarketTick(models.Model): def log_a_tick(order): ''' - Adds a new tick + Creates a new tick ''' + if not order.taker_bond: return None @@ -227,6 +228,7 @@ class MarketTick(models.Model): volume=volume, premium=premium, currency=order.currency) + tick.save() def __str__(self): diff --git a/frontend/src/components/MakerPage.js b/frontend/src/components/MakerPage.js index 6b1ee1b1..8057e86a 100644 --- a/frontend/src/components/MakerPage.js +++ b/frontend/src/components/MakerPage.js @@ -178,7 +178,7 @@ export default class MakerPage extends Component { require={true} inputProps={{ style: {textAlign:"center"}, - maxLength: 50 + maxLength: 35 }} onChange={this.handlePaymentMethodChange} /> diff --git a/frontend/src/components/OrderPage.js b/frontend/src/components/OrderPage.js index 86ed50ec..8c806e93 100644 --- a/frontend/src/components/OrderPage.js +++ b/frontend/src/components/OrderPage.js @@ -98,6 +98,8 @@ export default class OrderPage extends Component { .then((data) => (console.log(data) & this.getOrderDetails(data.id))); } + + render (){ return ( diff --git a/frontend/src/components/TradePipelineBox.js b/frontend/src/components/TradeBox.js similarity index 100% rename from frontend/src/components/TradePipelineBox.js rename to frontend/src/components/TradeBox.js From 215af668a2b037407344e119b7be6537528c6406 Mon Sep 17 00:00:00 2001 From: LowEntropyFace Date: Sat, 8 Jan 2022 06:51:55 -0500 Subject: [PATCH 06/29] merge htlc-model --- api/admin.py | 4 +- api/lightning.py | 24 +- api/logics.py | 294 +++++++++++++++++++++++++ api/models.py | 106 +++++---- api/serializers.py | 8 +- api/urls.py | 2 +- api/views.py | 274 ++++++++++++++--------- frontend/src/components/BookPage.js | 35 ++- frontend/src/components/MakerPage.js | 31 ++- frontend/src/components/OrderPage.js | 7 +- frontend/src/components/UserGenPage.js | 2 +- setup.md | 5 +- 12 files changed, 601 insertions(+), 191 deletions(-) create mode 100644 api/logics.py diff --git a/api/admin.py b/api/admin.py index 1d0bd415..b45ca85b 100644 --- a/api/admin.py +++ b/api/admin.py @@ -24,13 +24,13 @@ class EUserAdmin(UserAdmin): @admin.register(Order) class OrderAdmin(AdminChangeLinksMixin, admin.ModelAdmin): - list_display = ('id','type','maker_link','taker_link','status','amount','currency','created_at','expires_at', 'buyer_invoice_link','maker_bond_link','taker_bond_link','trade_escrow_link') + list_display = ('id','type','maker_link','taker_link','status','amount','currency','t0_satoshis','created_at','expires_at', 'buyer_invoice_link','maker_bond_link','taker_bond_link','trade_escrow_link') list_display_links = ('id','type') change_links = ('maker','taker','buyer_invoice','maker_bond','taker_invoice','taker_bond','trade_escrow') @admin.register(LNPayment) class LNPaymentAdmin(AdminChangeLinksMixin, admin.ModelAdmin): - list_display = ('id','concept','status','amount','type','invoice','secret','expires_at','sender_link','receiver_link') + list_display = ('id','concept','status','num_satoshis','type','invoice','expires_at','sender_link','receiver_link') list_display_links = ('id','concept') change_links = ('sender','receiver') diff --git a/api/lightning.py b/api/lightning.py index 50d60529..cf66a12f 100644 --- a/api/lightning.py +++ b/api/lightning.py @@ -1,3 +1,6 @@ +from datetime import timedelta +from django.utils import timezone + import random import string @@ -10,17 +13,28 @@ class LNNode(): Place holder functions to interact with Lightning Node ''' - def gen_hodl_invoice(): + def gen_hodl_invoice(num_satoshis, description, expiry): '''Generates hodl invoice to publish an order''' - return ''.join(random.choices(string.ascii_uppercase + string.digits, k=80)) + # TODO + invoice = ''.join(random.choices(string.ascii_uppercase + string.digits, k=80)) #FIX + payment_hash = ''.join(random.choices(string.ascii_uppercase + string.digits, k=40)) #FIX + expires_at = timezone.now() + timedelta(hours=8) ##FIX + + return invoice, payment_hash, expires_at def validate_hodl_invoice_locked(): '''Generates hodl invoice to publish an order''' return True - def validate_ln_invoice(invoice): - '''Checks if a LN invoice is valid''' - return True + def validate_ln_invoice(invoice): # num_satoshis + '''Checks if the submited LN invoice is as expected''' + valid = True + num_satoshis = 50000 # TODO decrypt and confirm sats are as expected + description = 'Placeholder desc' # TODO decrypt from LN invoice + payment_hash = '567126' # TODO decrypt + expires_at = timezone.now() # TODO decrypt + + return valid, num_satoshis, description, payment_hash, expires_at def pay_buyer_invoice(invoice): '''Sends sats to buyer''' diff --git a/api/logics.py b/api/logics.py new file mode 100644 index 00000000..4324b2b8 --- /dev/null +++ b/api/logics.py @@ -0,0 +1,294 @@ +from datetime import timedelta +from django.utils import timezone +import requests +from .lightning import LNNode + +from .models import Order, LNPayment, User +from decouple import config + +FEE = float(config('FEE')) +BOND_SIZE = float(config('BOND_SIZE')) +MARKET_PRICE_API = config('MARKET_PRICE_API') +ESCROW_USERNAME = config('ESCROW_USERNAME') + +MIN_TRADE = int(config('MIN_TRADE')) +MAX_TRADE = int(config('MAX_TRADE')) + +EXP_MAKER_BOND_INVOICE = int(config('EXP_MAKER_BOND_INVOICE')) +EXP_TAKER_BOND_INVOICE = int(config('EXP_TAKER_BOND_INVOICE')) +EXP_TRADE_ESCR_INVOICE = int(config('EXP_TRADE_ESCR_INVOICE')) + +BOND_EXPIRY = int(config('BOND_EXPIRY')) +ESCROW_EXPIRY = int(config('ESCROW_EXPIRY')) + +class Logics(): + + # escrow_user = User.objects.get(username=ESCROW_USERNAME) + + def validate_already_maker_or_taker(user): + '''Checks if the user is already partipant of an order''' + queryset = Order.objects.filter(maker=user) + if queryset.exists(): + return False, {'bad_request':'You are already maker of an order'} + queryset = Order.objects.filter(taker=user) + if queryset.exists(): + return False, {'bad_request':'You are already taker of an order'} + return True, None + + def validate_order_size(order): + '''Checks if order is withing limits at t0''' + if order.t0_satoshis > MAX_TRADE: + return False, {'bad_request': f'Your order is too big. It is worth {order.t0_satoshis} now. But maximum is {MAX_TRADE}'} + if order.t0_satoshis < MIN_TRADE: + return False, {'bad_request': f'Your order is too small. It is worth {order.t0_satoshis} now. But minimum is {MIN_TRADE}'} + return True, None + + def take(order, user): + order.taker = user + order.status = Order.Status.TAK + order.save() + + def is_buyer(order, user): + is_maker = order.maker == user + is_taker = order.taker == user + return (is_maker and order.type == Order.Types.BUY) or (is_taker and order.type == Order.Types.SELL) + + def is_seller(order, user): + is_maker = order.maker == user + is_taker = order.taker == user + return (is_maker and order.type == Order.Types.SELL) or (is_taker and order.type == Order.Types.BUY) + + def satoshis_now(order): + ''' checks trade amount in sats ''' + if order.is_explicit: + satoshis_now = order.satoshis + else: + # TODO Add fallback Public APIs and error handling + # Think about polling price data in a different way (e.g. store locally every t seconds) + market_prices = requests.get(MARKET_PRICE_API).json() + exchange_rate = float(market_prices[Order.currency_dict[str(order.currency)]]['last']) + satoshis_now = ((float(order.amount) * 1+float(order.premium)) / exchange_rate) * 100*1000*1000 + + return int(satoshis_now) + + def order_expires(order): + order.status = Order.Status.EXP + order.maker = None + order.taker = None + order.save() + + @classmethod + def buyer_invoice_amount(cls, order, user): + ''' Computes buyer invoice amount. Uses order.last_satoshis, + that is the final trade amount set at Taker Bond time''' + + if cls.is_buyer(order, user): + invoice_amount = int(order.last_satoshis * (1-FEE)) # Trading FEE is charged here. + + return True, {'invoice_amount': invoice_amount} + + @classmethod + def update_invoice(cls, order, user, invoice): + is_valid_invoice, num_satoshis, description, payment_hash, expires_at = LNNode.validate_ln_invoice(invoice) + # only user is the buyer and a valid LN invoice + if not (cls.is_buyer(order, user) or is_valid_invoice): + return False, {'bad_request':'Invalid Lightning Network Invoice. It starts by LNTB...'} + + order.buyer_invoice, _ = LNPayment.objects.update_or_create( + concept = LNPayment.Concepts.PAYBUYER, + type = LNPayment.Types.NORM, + sender = User.objects.get(username=ESCROW_USERNAME), + receiver= user, + # if there is a LNPayment matching these above, it updates that one with defaults below. + defaults={ + 'invoice' : invoice, + 'status' : LNPayment.Status.VALIDI, + 'num_satoshis' : num_satoshis, + 'description' : description, + 'payment_hash' : payment_hash, + 'expires_at' : expires_at} + ) + + # If the order status is 'Waiting for invoice'. Move forward to 'waiting for invoice' + if order.status == Order.Status.WFE: order.status = Order.Status.CHA + + # If the order status is 'Waiting for both'. Move forward to 'waiting for escrow' or to 'chat' + if order.status == Order.Status.WF2: + print(order.trade_escrow) + if order.trade_escrow: + if order.trade_escrow.status == LNPayment.Status.LOCKED: + order.status = Order.Status.CHA + else: + order.status = Order.Status.WFE + + # If the order status was Payment Failed. Move forward to invoice Updated. + if order.status == Order.Status.FAI: + order.status = Order.Status.UPI + + order.save() + return True, None + + @classmethod + def rate_counterparty(cls, order, user, rating): + # if maker, rates taker + if order.maker == user: + order.taker.profile.total_ratings = order.taker.profile.total_ratings + 1 + last_ratings = list(order.taker.profile.last_ratings).append(rating) + order.taker.profile.total_ratings = sum(last_ratings) / len(last_ratings) + # if taker, rates maker + if order.taker == user: + order.maker.profile.total_ratings = order.maker.profile.total_ratings + 1 + last_ratings = list(order.maker.profile.last_ratings).append(rating) + order.maker.profile.total_ratings = sum(last_ratings) / len(last_ratings) + + order.save() + return True, None + + @classmethod + def cancel_order(cls, order, user, state): + + # 1) When maker cancels before bond + '''The order never shows up on the book and order + status becomes "cancelled". That's it.''' + if order.status == Order.Status.WFB and order.maker == user: + order.maker = None + order.status = Order.Status.UCA + order.save() + return True, None + + # 2) When maker cancels after bond + '''The order dissapears from book and goes to cancelled. + Maker is charged a small amount of sats, to prevent DDOS + on the LN node and order book''' + + # 3) When taker cancels before bond + ''' The order goes back to the book as public. + LNPayment "order.taker_bond" is deleted() ''' + + # 4) When taker or maker cancel after bond (before escrow) + '''The order goes into cancelled status if maker cancels. + The order goes into the public book if taker cancels. + In both cases there is a small fee.''' + + # 5) When trade collateral has been posted (after escrow) + '''Always goes to cancelled status. Collaboration is needed. + When a user asks for cancel, 'order.is_pending_cancel' goes True. + When the second user asks for cancel. Order is totally cancelled. + Has a small cost for both parties to prevent node DDOS.''' + + else: + return False, {'bad_request':'You cannot cancel this order'} + + @classmethod + def gen_maker_hodl_invoice(cls, order, user): + + # Do not gen and cancel if order is more than 5 minutes old + if order.expires_at < timezone.now(): + cls.order_expires(order) + return False, {'bad_request':'Invoice expired. You did not confirm publishing the order in time. Make a new order.'} + + # Return the previous invoice if there was one and is still unpaid + if order.maker_bond: + if order.maker_bond.status == LNPayment.Status.INVGEN: + return True, {'bond_invoice':order.maker_bond.invoice,'bond_satoshis':order.maker_bond.num_satoshis} + else: + return False, None + + order.last_satoshis = cls.satoshis_now(order) + bond_satoshis = int(order.last_satoshis * BOND_SIZE) + description = f'RoboSats - Publishing {str(order)} - This bond will return to you if you do not cheat.' + + # Gen HODL Invoice + invoice, payment_hash, expires_at = LNNode.gen_hodl_invoice(bond_satoshis, description, BOND_EXPIRY*3600) + + order.maker_bond = LNPayment.objects.create( + concept = LNPayment.Concepts.MAKEBOND, + type = LNPayment.Types.HODL, + sender = user, + receiver = User.objects.get(username=ESCROW_USERNAME), + invoice = invoice, + status = LNPayment.Status.INVGEN, + num_satoshis = bond_satoshis, + description = description, + payment_hash = payment_hash, + expires_at = expires_at) + + order.save() + return True, {'bond_invoice':invoice,'bond_satoshis':bond_satoshis} + + @classmethod + def gen_taker_hodl_invoice(cls, order, user): + + # Do not gen and cancel if a taker invoice is there and older than X minutes and unpaid still + if order.taker_bond: + # Check if status is INVGEN and still not expired + if order.taker_bond.status == LNPayment.Status.INVGEN: + if order.taker_bond.created_at > (timezone.now()+timedelta(minutes=EXP_TAKER_BOND_INVOICE)): + cls.cancel_order(order, user, 3) # State 3, cancel order before taker bond + return False, {'bad_request':'Invoice expired. You did not confirm taking the order in time.'} + # Return the previous invoice there was with INVGEN status + else: + return True, {'bond_invoice':order.taker_bond.invoice,'bond_satoshis':order.taker_bond.num_satoshis} + # Invoice exists, but was already locked or settled + else: + return False, None + + order.last_satoshis = cls.satoshis_now(order) # LOCKS THE AMOUNT OF SATOSHIS FOR THE TRADE + bond_satoshis = int(order.last_satoshis * BOND_SIZE) + description = f'RoboSats - Taking {str(order)} - This bond will return to you if you do not cheat.' + + # Gen HODL Invoice + invoice, payment_hash, expires_at = LNNode.gen_hodl_invoice(bond_satoshis, description, BOND_EXPIRY*3600) + + order.taker_bond = LNPayment.objects.create( + concept = LNPayment.Concepts.TAKEBOND, + type = LNPayment.Types.HODL, + sender = user, + receiver = User.objects.get(username=ESCROW_USERNAME), + invoice = invoice, + status = LNPayment.Status.INVGEN, + num_satoshis = bond_satoshis, + description = description, + payment_hash = payment_hash, + expires_at = expires_at) + + order.save() + return True, {'bond_invoice':invoice,'bond_satoshis': bond_satoshis} + + @classmethod + def gen_escrow_hodl_invoice(cls, order, user): + + # Do not generate and cancel if an invoice is there and older than X minutes and unpaid still + if order.trade_escrow: + # Check if status is INVGEN and still not expired + if order.taker_bond.status == LNPayment.Status.INVGEN: + if order.taker_bond.created_at > (timezone.now()+timedelta(minutes=EXP_TRADE_ESCR_INVOICE)): # Expired + cls.cancel_order(order, user, 4) # State 4, cancel order before trade escrow locked + return False, {'bad_request':'Invoice expired. You did not lock the trade escrow in time.'} + # Return the previous invoice there was with INVGEN status + else: + return True, {'escrow_invoice':order.trade_escrow.invoice,'escrow_satoshis':order.trade_escrow.num_satoshis} + # Invoice exists, but was already locked or settled + else: + return False, None # Does not return any context of a healthy locked escrow + + escrow_satoshis = order.last_satoshis # Trade sats amount was fixed at the time of taker bond generation (order.last_satoshis) + description = f'RoboSats - Escrow amount for {str(order)} - This escrow will be released to the buyer once you confirm you received the fiat.' + + # Gen HODL Invoice + invoice, payment_hash, expires_at = LNNode.gen_hodl_invoice(escrow_satoshis, description, ESCROW_EXPIRY*3600) + + order.taker_bond = LNPayment.objects.create( + concept = LNPayment.Concepts.TRESCROW, + type = LNPayment.Types.HODL, + sender = user, + receiver = User.objects.get(username=ESCROW_USERNAME), + invoice = invoice, + status = LNPayment.Status.INVGEN, + num_satoshis = escrow_satoshis, + description = description, + payment_hash = payment_hash, + expires_at = expires_at) + + order.save() + return True, {'escrow_invoice':invoice,'escrow_satoshis': escrow_satoshis} \ No newline at end of file diff --git a/api/models.py b/api/models.py index 6fa81646..8dbfe09a 100644 --- a/api/models.py +++ b/api/models.py @@ -3,9 +3,9 @@ from django.contrib.auth.models import User from django.core.validators import MaxValueValidator, MinValueValidator, validate_comma_separated_integer_list from django.db.models.signals import post_save, pre_delete from django.dispatch import receiver - from django.utils.html import mark_safe +from decouple import config from pathlib import Path import json @@ -13,10 +13,11 @@ import json # TODO # Load hparams from .env file -MIN_TRADE = 10*1000 #In sats -MAX_TRADE = 500*1000 -FEE = 0.002 # Trade fee in % -BOND_SIZE = 0.01 # Bond in % +MIN_TRADE = int(config('MIN_TRADE')) +MAX_TRADE = int(config('MAX_TRADE')) +FEE = float(config('FEE')) +BOND_SIZE = float(config('BOND_SIZE')) + class LNPayment(models.Model): @@ -27,38 +28,39 @@ class LNPayment(models.Model): class Concepts(models.IntegerChoices): MAKEBOND = 0, 'Maker bond' - TAKEBOND = 1, 'Taker-buyer bond' + TAKEBOND = 1, 'Taker bond' TRESCROW = 2, 'Trade escrow' PAYBUYER = 3, 'Payment to buyer' class Status(models.IntegerChoices): - INVGEN = 0, 'Hodl invoice was generated' - LOCKED = 1, 'Hodl invoice has HTLCs locked' - CHRGED = 2, 'Hodl invoice was charged' - RETNED = 3, 'Hodl invoice was returned' - MISSNG = 4, 'Buyer invoice is missing' - IVALID = 5, 'Buyer invoice is valid' - INPAID = 6, 'Buyer invoice was paid' - INFAIL = 7, 'Buyer invoice routing failed' + INVGEN = 0, 'Generated' + LOCKED = 1, 'Locked' + SETLED = 2, 'Settled' + RETNED = 3, 'Returned' + MISSNG = 4, 'Missing' + VALIDI = 5, 'Valid' + INFAIL = 6, 'Failed routing' - # payment use case + # payment use details type = models.PositiveSmallIntegerField(choices=Types.choices, null=False, default=Types.HODL) concept = models.PositiveSmallIntegerField(choices=Concepts.choices, null=False, default=Concepts.MAKEBOND) status = models.PositiveSmallIntegerField(choices=Status.choices, null=False, default=Status.INVGEN) + routing_retries = models.PositiveSmallIntegerField(null=False, default=0) - # payment details + # payment info invoice = models.CharField(max_length=300, unique=False, null=True, default=None, blank=True) - secret = models.CharField(max_length=300, unique=False, null=True, default=None, blank=True) + payment_hash = models.CharField(max_length=300, unique=False, null=True, default=None, blank=True) + description = models.CharField(max_length=300, unique=False, null=True, default=None, blank=True) + created_at = models.DateTimeField(auto_now_add=True) expires_at = models.DateTimeField() - amount = models.PositiveBigIntegerField(validators=[MinValueValidator(MIN_TRADE*BOND_SIZE), MaxValueValidator(MAX_TRADE*(1+BOND_SIZE+FEE))]) + num_satoshis = models.PositiveBigIntegerField(validators=[MinValueValidator(MIN_TRADE*BOND_SIZE), MaxValueValidator(MAX_TRADE*(1+BOND_SIZE+FEE))]) - # payment relationals + # involved parties sender = models.ForeignKey(User, related_name='sender', on_delete=models.CASCADE, null=True, default=None) receiver = models.ForeignKey(User, related_name='receiver', on_delete=models.CASCADE, null=True, default=None) def __str__(self): - # Make relational back to ORDER - return (f'HTLC {self.id}: {self.Concepts(self.concept).label}') + return (f'HTLC {self.id}: {self.Concepts(self.concept).label} - {self.Status(self.status).label}') class Order(models.Model): @@ -67,26 +69,25 @@ class Order(models.Model): SELL = 1, 'SELL' class Status(models.IntegerChoices): - WFB = 0, 'Waiting for bond' - PUB = 1, 'Published in order book' - DEL = 2, 'Deleted from order book' - TAK = 3, 'Taken' - UCA = 4, 'Unilaterally cancelled' - RET = 5, 'Returned to order book' # Probably same as 1 in most cases. - WF2 = 6, 'Waiting for trade collateral and buyer invoice' - WTC = 7, 'Waiting only for trade collateral' - WBI = 8, 'Waiting only for buyer invoice' - EXF = 9, 'Exchanging fiat / In chat' - CCA = 10, 'Collaboratively cancelled' - FSE = 11, 'Fiat sent' - FCO = 12, 'Fiat confirmed' - SUC = 13, 'Sucessfully settled' - FAI = 14, 'Failed lightning network routing' - UPI = 15, 'Updated invoice' - DIS = 16, 'In dispute' - MLD = 17, 'Maker lost dispute' - TLD = 18, 'Taker lost dispute' - EXP = 19, 'Expired' + WFB = 0, 'Waiting for maker bond' + PUB = 1, 'Public' + DEL = 2, 'Deleted' + TAK = 3, 'Waiting for taker bond' + UCA = 4, 'Cancelled' + WF2 = 5, 'Waiting for trade collateral and buyer invoice' + WFE = 6, 'Waiting only for seller trade collateral' + WFI = 7, 'Waiting only for buyer invoice' + CHA = 8, 'Sending fiat - In chatroom' + CCA = 9, 'Collaboratively cancelled' + FSE = 10, 'Fiat sent - In chatroom' + FCO = 11, 'Fiat confirmed' + SUC = 12, 'Sucessfully settled' + FAI = 13, 'Failed lightning network routing' + UPI = 14, 'Updated invoice' + DIS = 15, 'In dispute' + MLD = 16, 'Maker lost dispute' + TLD = 17, 'Taker lost dispute' + EXP = 18, 'Expired' currency_dict = json.load(open('./api/currencies.json')) currency_choices = [(int(val), label) for val, label in list(currency_dict.items())] @@ -104,16 +105,19 @@ class Order(models.Model): # order pricing method. A explicit amount of sats, or a relative premium above/below market. is_explicit = models.BooleanField(default=False, null=False) - # marked to marked + # marked to market premium = models.DecimalField(max_digits=5, decimal_places=2, default=0, null=True, validators=[MinValueValidator(-100), MaxValueValidator(999)], blank=True) - t0_market_satoshis = models.PositiveBigIntegerField(null=True, validators=[MinValueValidator(MIN_TRADE), MaxValueValidator(MAX_TRADE)], blank=True) # explicit satoshis = models.PositiveBigIntegerField(null=True, validators=[MinValueValidator(MIN_TRADE), MaxValueValidator(MAX_TRADE)], blank=True) + # how many sats at creation and at last check (relevant for marked to market) + t0_satoshis = models.PositiveBigIntegerField(null=True, validators=[MinValueValidator(MIN_TRADE), MaxValueValidator(MAX_TRADE)], blank=True) # sats at creation + last_satoshis = models.PositiveBigIntegerField(null=True, validators=[MinValueValidator(0), MaxValueValidator(MAX_TRADE*2)], blank=True) # sats last time checked. Weird if 2* trade max... # order participants maker = models.ForeignKey(User, related_name='maker', on_delete=models.CASCADE, null=True, default=None) # unique = True, a maker can only make one order taker = models.ForeignKey(User, related_name='taker', on_delete=models.SET_NULL, null=True, default=None, blank=True) # unique = True, a taker can only take one order - + is_pending_cancel = models.BooleanField(default=False, null=False) # When collaborative cancel is needed and one partner has cancelled. + # order collateral maker_bond = models.ForeignKey(LNPayment, related_name='maker_bond', on_delete=models.SET_NULL, null=True, default=None, blank=True) taker_bond = models.ForeignKey(LNPayment, related_name='taker_bond', on_delete=models.SET_NULL, null=True, default=None, blank=True) @@ -122,6 +126,19 @@ class Order(models.Model): # buyer payment LN invoice buyer_invoice = models.ForeignKey(LNPayment, related_name='buyer_invoice', on_delete=models.SET_NULL, null=True, default=None, blank=True) + def __str__(self): + # Make relational back to ORDER + return (f'Order {self.id}: {self.Types(self.type).label} BTC for {self.amount} {self.Currencies(self.currency).label}') + +@receiver(pre_delete, sender=Order) +def delelete_HTLCs_at_order_deletion(sender, instance, **kwargs): + to_delete = (instance.maker_bond, instance.buyer_invoice, instance.taker_bond, instance.trade_escrow) + + for htlc in to_delete: + try: + htlc.delete() + except: + pass class Profile(models.Model): @@ -165,3 +182,4 @@ class Profile(models.Model): # method to create a fake table field in read only mode def avatar_tag(self): return mark_safe('' % self.get_avatar()) + diff --git a/api/serializers.py b/api/serializers.py index c88b14b8..a819db91 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -11,7 +11,7 @@ class MakeOrderSerializer(serializers.ModelSerializer): model = Order fields = ('type','currency','amount','payment_method','is_explicit','premium','satoshis') -class UpdateOrderSerializer(serializers.ModelSerializer): - class Meta: - model = Order - fields = ('id','buyer_invoice') \ No newline at end of file +class UpdateOrderSerializer(serializers.Serializer): + invoice = serializers.CharField(max_length=300, allow_null=True, allow_blank=True, default=None) + action = serializers.ChoiceField(choices=('take','update_invoice','dispute','cancel','confirm','rate'), allow_null=False) + rating = serializers.ChoiceField(choices=('1','2','3','4','5'), allow_null=True, allow_blank=True, default=None) \ No newline at end of file diff --git a/api/urls.py b/api/urls.py index a3b73309..1b2897d5 100644 --- a/api/urls.py +++ b/api/urls.py @@ -3,7 +3,7 @@ from .views import OrderMakerView, OrderView, UserView, BookView, get_currencies urlpatterns = [ path('make/', OrderMakerView.as_view()), - path('order/', OrderView.as_view({'get':'get','post':'take_or_update'})), + path('order/', OrderView.as_view({'get':'get','post':'take_update_confirm_dispute_cancel'})), path('usergen/', UserView.as_view()), path('book/', BookView.as_view()), path('currencies/', get_currencies_json), diff --git a/api/views.py b/api/views.py index 470d02e7..4674cd29 100644 --- a/api/views.py +++ b/api/views.py @@ -1,15 +1,14 @@ -from rest_framework import status, serializers +from rest_framework import status, viewsets from rest_framework.generics import CreateAPIView, ListAPIView from rest_framework.views import APIView -from rest_framework import viewsets from rest_framework.response import Response from django.contrib.auth import authenticate, login, logout from django.contrib.auth.models import User from .serializers import ListOrderSerializer, MakeOrderSerializer, UpdateOrderSerializer -from .models import Order, LNPayment -from .lightning import LNNode +from .models import LNPayment, Order +from .logics import Logics from .nick_generator.nick_generator import NickGenerator from robohash import Robohash @@ -20,29 +19,16 @@ import hashlib from pathlib import Path from datetime import timedelta from django.utils import timezone +from decouple import config import json from django.http import HttpResponse -# .env -expiration_time = 8 +EXP_MAKER_BOND_INVOICE = int(config('EXP_MAKER_BOND_INVOICE')) avatar_path = Path('frontend/static/assets/avatars') avatar_path.mkdir(parents=True, exist_ok=True) -def validate_already_maker_or_taker(request): - '''Checks if the user is already partipant of an order''' - - queryset = Order.objects.filter(maker=request.user.id) - if queryset.exists(): - return False, Response({'Bad Request':'You are already maker of an order'}, status=status.HTTP_400_BAD_REQUEST) - - queryset = Order.objects.filter(taker=request.user.id) - if queryset.exists(): - return False, Response({'Bad Request':'You are already taker of an order'}, status=status.HTTP_400_BAD_REQUEST) - - return True, None - # Create your views here. class OrderMakerView(CreateAPIView): @@ -51,36 +37,38 @@ class OrderMakerView(CreateAPIView): def post(self,request): serializer = self.serializer_class(data=request.data) - if serializer.is_valid(): - otype = serializer.data.get('type') - currency = serializer.data.get('currency') - amount = serializer.data.get('amount') - payment_method = serializer.data.get('payment_method') - premium = serializer.data.get('premium') - satoshis = serializer.data.get('satoshis') - is_explicit = serializer.data.get('is_explicit') + if not serializer.is_valid(): return Response(status=status.HTTP_400_BAD_REQUEST) - valid, response = validate_already_maker_or_taker(request) - if not valid: - return response + type = serializer.data.get('type') + currency = serializer.data.get('currency') + amount = serializer.data.get('amount') + payment_method = serializer.data.get('payment_method') + premium = serializer.data.get('premium') + satoshis = serializer.data.get('satoshis') + is_explicit = serializer.data.get('is_explicit') - # Creates a new order in db - order = Order( - type=otype, - status=Order.Status.PUB, # TODO orders are public by default for the moment. Future it will be WFB (waiting for bond) - currency=currency, - amount=amount, - payment_method=payment_method, - premium=premium, - satoshis=satoshis, - is_explicit=is_explicit, - expires_at= timezone.now()+timedelta(hours=expiration_time), - maker=request.user) - order.save() + valid, context = Logics.validate_already_maker_or_taker(request.user) + if not valid: return Response(context, status.HTTP_409_CONFLICT) - if not serializer.is_valid(): - return Response(status=status.HTTP_400_BAD_REQUEST) - + # Creates a new order + order = Order( + type=type, + currency=currency, + amount=amount, + payment_method=payment_method, + premium=premium, + satoshis=satoshis, + is_explicit=is_explicit, + expires_at=timezone.now()+timedelta(minutes=EXP_MAKER_BOND_INVOICE), # TODO Move to class method + maker=request.user) + + # TODO move to Order class method when new instance is created! + order.last_satoshis = order.t0_satoshis = Logics.satoshis_now(order) + + valid, context = Logics.validate_order_size(order) + if not valid: return Response(context, status.HTTP_400_BAD_REQUEST) + + order.save() return Response(ListOrderSerializer(order).data, status=status.HTTP_201_CREATED) @@ -89,87 +77,154 @@ class OrderView(viewsets.ViewSet): lookup_url_kwarg = 'order_id' def get(self, request, format=None): + ''' + Full trade pipeline takes place while looking/refreshing the order page. + ''' order_id = request.GET.get(self.lookup_url_kwarg) - if order_id != None: - order = Order.objects.filter(id=order_id) + if order_id == None: + return Response({'bad_request':'Order ID parameter not found in request'}, status=status.HTTP_400_BAD_REQUEST) + + order = Order.objects.filter(id=order_id) - # check if exactly one order is found in the db - if len(order) == 1 : - order = order[0] - data = ListOrderSerializer(order).data - nickname = request.user.username + # check if exactly one order is found in the db + if len(order) != 1 : + return Response({'bad_request':'Invalid Order Id'}, status.HTTP_404_NOT_FOUND) + + # This is our order. + order = order[0] - # Add booleans if user is maker, taker, partipant, buyer or seller - data['is_maker'] = str(order.maker) == nickname - data['is_taker'] = str(order.taker) == nickname - data['is_participant'] = data['is_maker'] or data['is_taker'] - data['is_buyer'] = (data['is_maker'] and order.type == Order.Types.BUY) or (data['is_taker'] and order.type == Order.Types.SELL) - data['is_seller'] = (data['is_maker'] and order.type == Order.Types.SELL) or (data['is_taker'] and order.type == Order.Types.BUY) - - # If not a participant and order is not public, forbid. - if not data['is_participant'] and order.status != Order.Status.PUB: - return Response({'bad_request':'Not allowed to see this order'},status.HTTP_403_FORBIDDEN) + # 1) If order expired + if order.status == Order.Status.EXP: + return Response({'bad_request':'This order has expired'},status.HTTP_400_BAD_REQUEST) - # return nicks too - data['maker_nick'] = str(order.maker) - data['taker_nick'] = str(order.taker) - - data['status_message'] = Order.Status(order.status).label + # 2) If order cancelled + if order.status == Order.Status.UCA: + return Response({'bad_request':'This order has been cancelled by the maker'},status.HTTP_400_BAD_REQUEST) + if order.status == Order.Status.CCA: + return Response({'bad_request':'This order has been cancelled collaborativelly'},status.HTTP_400_BAD_REQUEST) - if data['is_participant']: - return Response(data, status=status.HTTP_200_OK) - else: - # Non participants should not see the status, who is the taker, etc - for key in ('status','status_message','taker','taker_nick','is_maker','is_taker','is_buyer','is_seller'): - del data[key] - return Response(data, status=status.HTTP_200_OK) + data = ListOrderSerializer(order).data - return Response({'Order Not Found':'Invalid Order Id'},status=status.HTTP_404_NOT_FOUND) - return Response({'Bad Request':'Order ID parameter not found in request'}, status=status.HTTP_400_BAD_REQUEST) + # Add booleans if user is maker, taker, partipant, buyer or seller + data['is_maker'] = order.maker == request.user + data['is_taker'] = order.taker == request.user + data['is_participant'] = data['is_maker'] or data['is_taker'] + + # 3) If not a participant and order is not public, forbid. + if not data['is_participant'] and order.status != Order.Status.PUB: + return Response({'bad_request':'You are not allowed to see this order'},status.HTTP_403_FORBIDDEN) + + # 4) Non participants can view details (but only if PUB) + elif not data['is_participant'] and order.status != Order.Status.PUB: + return Response(data, status=status.HTTP_200_OK) + # For participants add position side, nicks and status as message + data['is_buyer'] = Logics.is_buyer(order,request.user) + data['is_seller'] = Logics.is_seller(order,request.user) + data['maker_nick'] = str(order.maker) + data['taker_nick'] = str(order.taker) + data['status_message'] = Order.Status(order.status).label - def take_or_update(self, request, format=None): + # 5) If status is 'waiting for maker bond' and user is MAKER, reply with a MAKER HODL invoice. + if order.status == Order.Status.WFB and data['is_maker']: + valid, context = Logics.gen_maker_hodl_invoice(order, request.user) + if valid: + data = {**data, **context} + else: + return Response(context, status.HTTP_400_BAD_REQUEST) + + # 6) If status is 'waiting for taker bond' and user is TAKER, reply with a TAKER HODL invoice. + elif order.status == Order.Status.TAK and data['is_taker']: + valid, context = Logics.gen_taker_hodl_invoice(order, request.user) + if valid: + data = {**data, **context} + else: + return Response(context, status.HTTP_400_BAD_REQUEST) + + # 7) If status is 'WF2'or'WTC' + elif (order.status == Order.Status.WF2 or order.status == Order.Status.WFE): + + # If the two bonds are locked + if order.maker_bond.status == order.taker_bond.status == LNPayment.Status.LOCKED: + + # 7.a) And if user is Seller, reply with an ESCROW HODL invoice. + if data['is_seller']: + valid, context = Logics.gen_escrow_hodl_invoice(order, request.user) + if valid: + data = {**data, **context} + else: + return Response(context, status.HTTP_400_BAD_REQUEST) + + # 7.b) If user is Buyer, reply with an AMOUNT so he can send the buyer invoice. + elif data['is_buyer']: + valid, context = Logics.buyer_invoice_amount(order, request.user) + if valid: + data = {**data, **context} + else: + return Response(context, status.HTTP_400_BAD_REQUEST) + + # 8) If status is 'CHA'or '' or '' and all HTLCS are in LOCKED + elif order.status == Order.Status.CHA: # TODO Add the other status + if order.maker_bond.status == order.taker_bond.status == order.trade_escrow.status == LNPayment.Status.LOCKED: + # add whether a collaborative cancel is pending + data['pending_cancel'] = order.is_pending_cancel + + return Response(data, status.HTTP_200_OK) + + def take_update_confirm_dispute_cancel(self, request, format=None): + ''' + Here take place all of the user updates to the order object. + That is: take, confim, cancel, dispute, update_invoice or rate. + ''' order_id = request.GET.get(self.lookup_url_kwarg) serializer = UpdateOrderSerializer(data=request.data) + if not serializer.is_valid(): return Response(status=status.HTTP_400_BAD_REQUEST) + order = Order.objects.get(id=order_id) - if serializer.is_valid(): - invoice = serializer.data.get('buyer_invoice') + # action is either 1)'take', 2)'confirm', 3)'cancel', 4)'dispute' , 5)'update_invoice' 6)'rate' (counterparty) + action = serializer.data.get('action') + invoice = serializer.data.get('invoice') + rating = serializer.data.get('rating') - # If this is an empty POST request (no invoice), it must be taker request! - if not invoice and order.status == Order.Status.PUB: - - valid, response = validate_already_maker_or_taker(request) - if not valid: - return response + # 1) If action is take, it is be taker request! + if action == 'take': + if order.status == Order.Status.PUB: + valid, context = Logics.validate_already_maker_or_taker(request.user) + if not valid: return Response(context, status=status.HTTP_409_CONFLICT) - order.taker = self.request.user - order.status = Order.Status.TAK + Logics.take(order, request.user) + else: Response({'bad_request':'This order is not public anymore.'}, status.HTTP_400_BAD_REQUEST) - #TODO REPLY WITH HODL INVOICE - data = ListOrderSerializer(order).data - - # An invoice came in! update it - elif invoice: - if LNNode.validate_ln_invoice(invoice): - order.invoice = invoice - - #TODO Validate if request comes from PARTICIPANT AND BUYER - - #If the order status was Payment Failed. Move foward to invoice Updated. - if order.status == Order.Status.FAI: - order.status = Order.Status.UPI - - else: - return Response({'bad_request':'Invalid Lightning Network Invoice. It starts by LNTB...'}) + # 2) If action is update (invoice) + elif action == 'update_invoice' and invoice: + valid, context = Logics.update_invoice(order,request.user,invoice) + if not valid: return Response(context,status.HTTP_400_BAD_REQUEST) - # Something else is going on. Probably not allowed. - else: - return Response({'bad_request':'Not allowed'}) + # 3) If action is cancel + elif action == 'cancel': + valid, context = Logics.cancel_order(order,request.user) + if not valid: return Response(context,status.HTTP_400_BAD_REQUEST) + + # 4) If action is confirm + elif action == 'confirm': + pass + + # 5) If action is dispute + elif action == 'dispute': + pass + + # 6) If action is dispute + elif action == 'rate' and rating: + valid, context = Logics.rate_counterparty(order,request.user, rating) + if not valid: return Response(context,status.HTTP_400_BAD_REQUEST) + + # If nothing... something else is going on. Probably not allowed! + else: + return Response({'bad_request':'The Robotic Satoshis working in the warehouse did not understand you'}) - order.save() return self.get(request) class UserView(APIView): @@ -223,7 +278,7 @@ class UserView(APIView): with open(image_path, "wb") as f: rh.img.save(f, format="png") - # Create new credentials and logsin if nickname is new + # Create new credentials and log in if nickname is new if len(User.objects.filter(username=nickname)) == 0: User.objects.create_user(username=nickname, password=token, is_staff=False) user = authenticate(request, username=nickname, password=token) @@ -279,6 +334,7 @@ class BookView(ListAPIView): user = User.objects.filter(id=data['maker']) if len(user) == 1: data['maker_nick'] = user[0].username + # Non participants should not see the status or who is the taker for key in ('status','taker'): del data[key] diff --git a/frontend/src/components/BookPage.js b/frontend/src/components/BookPage.js index 1f43c68a..961c72b9 100644 --- a/frontend/src/components/BookPage.js +++ b/frontend/src/components/BookPage.js @@ -1,5 +1,6 @@ import React, { Component } from "react"; -import { Button , Divider, Card, CardActionArea, CardContent, Typography, Grid, Select, MenuItem, FormControl, FormHelperText, List, ListItem, ListItemText, Avatar, Link, RouterLink, ListItemAvatar} from "@material-ui/core" +import { Button , Divider, Card, CardActionArea, CardContent, Typography, Grid, Select, MenuItem, FormControl, FormHelperText, List, ListItem, ListItemText, Avatar, RouterLink, ListItemAvatar} from "@material-ui/core" +import { Link } from 'react-router-dom' export default class BookPage extends Component { constructor(props) { @@ -15,7 +16,6 @@ export default class BookPage extends Component { this.state.currencyCode = this.getCurrencyCode(this.state.currency) } - // Fix needed to handle HTTP 404 error when no order is found // Show message to be the first one to make an order getOrderDetails() { fetch('/api/book' + '?currency=' + this.state.currency + "&type=" + this.state.type) @@ -26,15 +26,6 @@ export default class BookPage extends Component { not_found: data.not_found, })); } - getCurrencyDict() { - fetch('/api/currencies') - .then((response) => response.json()) - .then((data) => - this.setState({ - currencies_dict: data - })); - - } handleCardClick=(e)=>{ console.log(e) @@ -55,7 +46,15 @@ export default class BookPage extends Component { }) this.getOrderDetails(); } - + + getCurrencyDict() { + fetch('/api/currencies') + .then((response) => response.json()) + .then((data) => + this.setState({ + currencies_dict: data + })); + } // Gets currency code (3 letters) from numeric (e.g., 1 -> USD) // Improve this function so currencies are read from json getCurrencyCode(val){ @@ -101,14 +100,14 @@ export default class BookPage extends Component { ◑ Payment via {order.payment_method} - +{/* ◑ Priced {order.is_explicit ? " explicitly at " + this.pn(order.satoshis) + " Sats" : ( " at " + parseFloat(parseFloat(order.premium).toFixed(4)) + "% over the market" )} - + */} {" 42,354 "}{this.getCurrencyCode(order.currency)}/BTC (Binance API) @@ -188,13 +187,13 @@ export default class BookPage extends Component { No orders found to {this.state.type == 0 ? ' sell ' :' buy ' } BTC for {this.state.currencyCode} + + + + Be the first one to create an order - - - - ) : this.bookCards() } diff --git a/frontend/src/components/MakerPage.js b/frontend/src/components/MakerPage.js index fa344cbf..e3912385 100644 --- a/frontend/src/components/MakerPage.js +++ b/frontend/src/components/MakerPage.js @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import { Paper, Button , Grid, Typography, TextField, Select, FormHelperText, MenuItem, FormControl, Radio, FormControlLabel, RadioGroup, Menu} from "@material-ui/core" +import { Paper, Alert, AlertTitle, Button , Grid, Typography, TextField, Select, FormHelperText, MenuItem, FormControl, Radio, FormControlLabel, RadioGroup, Menu} from "@material-ui/core" import { Link } from 'react-router-dom' function getCookie(name) { @@ -37,7 +37,9 @@ export default class MakerPage extends Component { payment_method: this.defaultPaymentMethod, premium: 0, satoshis: null, + currencies_dict: {"1":"USD"} } + this.getCurrencyDict() } handleTypeChange=(e)=>{ @@ -46,10 +48,9 @@ export default class MakerPage extends Component { }); } handleCurrencyChange=(e)=>{ - var code = (e.target.value == 1 ) ? "USD": ((e.target.value == 2 ) ? "EUR":"ETH") this.setState({ currency: e.target.value, - currencyCode: code, + currencyCode: this.getCurrencyCode(e.target.value), }); } handleAmountChange=(e)=>{ @@ -104,7 +105,22 @@ export default class MakerPage extends Component { }; fetch("/api/make/",requestOptions) .then((response) => response.json()) - .then((data) => (console.log(data) & this.props.history.push('/order/' + data.id))); + .then((data) => (this.setState({badRequest:data.bad_request}) + & (data.id ? this.props.history.push('/order/' + data.id) :""))); + } + + getCurrencyDict() { + fetch('/api/currencies') + .then((response) => response.json()) + .then((data) => + this.setState({ + currencies_dict: data + })); + + } + + getCurrencyCode(val){ + return this.state.currencies_dict[val.toString()] } render() { @@ -242,6 +258,13 @@ export default class MakerPage extends Component { + + + {this.state.badRequest ? + + {this.state.badRequest}
+
+ : ""}
Create a BTC {this.state.type==0 ? "buy":"sell"} order for {this.state.amount} {this.state.currencyCode} diff --git a/frontend/src/components/OrderPage.js b/frontend/src/components/OrderPage.js index 6deef6bf..86ed50ec 100644 --- a/frontend/src/components/OrderPage.js +++ b/frontend/src/components/OrderPage.js @@ -68,6 +68,7 @@ export default class OrderPage extends Component { isBuyer:data.buyer, isSeller:data.seller, expiresAt:data.expires_at, + badRequest:data.bad_request, }); }); } @@ -87,8 +88,10 @@ export default class OrderPage extends Component { console.log(this.state) const requestOptions = { method: 'POST', - headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken')}, - body: JSON.stringify({}), + headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),}, + body: JSON.stringify({ + 'action':'take', + }), }; fetch('/api/order/' + '?order_id=' + this.orderId, requestOptions) .then((response) => response.json()) diff --git a/frontend/src/components/UserGenPage.js b/frontend/src/components/UserGenPage.js index 0332043b..ef7d9c98 100644 --- a/frontend/src/components/UserGenPage.js +++ b/frontend/src/components/UserGenPage.js @@ -58,7 +58,7 @@ export default class UserGenPage extends Component { delGeneratedUser() { const requestOptions = { method: 'DELETE', - headers: {'Content-Type':'application/json', 'X-CSRFToken': csrftoken}, + headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken')}, }; fetch("/api/usergen", requestOptions) .then((response) => response.json()) diff --git a/setup.md b/setup.md index c9c82cbf..c1cbf307 100644 --- a/setup.md +++ b/setup.md @@ -4,7 +4,10 @@ `sudo apt install python3 python3 pip` ### Install virtual environments -`pip install virtualenvwrapper` +``` +pip install virtualenvwrapper +pip install python-decouple +``` ### Add to .bashrc From 400fb2b21e28430c697dfa562742981398fb3a62 Mon Sep 17 00:00:00 2001 From: LowEntropyFace Date: Sat, 8 Jan 2022 07:48:03 -0500 Subject: [PATCH 07/29] OrderPage.js, MakerPage.js use currencies.json --- api/currencies.json | 4 +++- api/models.py | 2 +- frontend/src/components/BookPage.js | 2 +- frontend/src/components/MakerPage.js | 7 ++++--- frontend/src/components/OrderPage.js | 24 ++++++++++++++++++------ 5 files changed, 27 insertions(+), 12 deletions(-) diff --git a/api/currencies.json b/api/currencies.json index bf3a4382..f246908d 100644 --- a/api/currencies.json +++ b/api/currencies.json @@ -2,5 +2,7 @@ "1":"USD", "2":"EUR", "3":"ETH", - "4":"ABC" + "4":"AUD", + "5":"BRL", + "6":"CAD" } diff --git a/api/models.py b/api/models.py index 8dbfe09a..bda4d442 100644 --- a/api/models.py +++ b/api/models.py @@ -128,7 +128,7 @@ class Order(models.Model): def __str__(self): # Make relational back to ORDER - return (f'Order {self.id}: {self.Types(self.type).label} BTC for {self.amount} {self.Currencies(self.currency).label}') + return (f'Order {self.id}: {self.Types(self.type).label} BTC for {self.amount} {self.currency_dict[str(self.currency)]}') @receiver(pre_delete, sender=Order) def delelete_HTLCs_at_order_deletion(sender, instance, **kwargs): diff --git a/frontend/src/components/BookPage.js b/frontend/src/components/BookPage.js index 961c72b9..10a591ae 100644 --- a/frontend/src/components/BookPage.js +++ b/frontend/src/components/BookPage.js @@ -11,8 +11,8 @@ export default class BookPage extends Component { type: 1, currencies_dict: {"1":"USD"} }; - this.getOrderDetails() this.getCurrencyDict() + this.getOrderDetails() this.state.currencyCode = this.getCurrencyCode(this.state.currency) } diff --git a/frontend/src/components/MakerPage.js b/frontend/src/components/MakerPage.js index e3912385..f0635c59 100644 --- a/frontend/src/components/MakerPage.js +++ b/frontend/src/components/MakerPage.js @@ -178,9 +178,10 @@ export default class MakerPage extends Component { }} onChange={this.handleCurrencyChange} > - USD - EUR - ETH + { + Object.entries(this.state.currencies_dict) + .map( ([key, value]) => {value} ) + } diff --git a/frontend/src/components/OrderPage.js b/frontend/src/components/OrderPage.js index 86ed50ec..adc11cc3 100644 --- a/frontend/src/components/OrderPage.js +++ b/frontend/src/components/OrderPage.js @@ -40,8 +40,10 @@ export default class OrderPage extends Component { super(props); this.state = { isExplicit: false, + currencies_dict: {"1":"USD"} }; this.orderId = this.props.match.params.orderId; + this.getCurrencyDict(); this.getOrderDetails(); } @@ -49,6 +51,7 @@ export default class OrderPage extends Component { fetch('/api/order' + '?order_id=' + this.orderId) .then((response) => response.json()) .then((data) => { + console.log(data) this.setState({ statusCode: data.status, statusText: data.status_message, @@ -73,12 +76,6 @@ export default class OrderPage extends Component { }); } - // Gets currency code (3 letters) from numeric (e.g., 1 -> USD) - // Improve this function so currencies are read from json - getCurrencyCode(val){ - return (val == 1 ) ? "USD": ((val == 2 ) ? "EUR":"ETH") - } - // Fix to use proper react props handleClickBackButton=()=>{ window.history.back(); @@ -97,6 +94,21 @@ export default class OrderPage extends Component { .then((response) => response.json()) .then((data) => (console.log(data) & this.getOrderDetails(data.id))); } + getCurrencyDict() { + fetch('/api/currencies') + .then((response) => response.json()) + .then((data) => + this.setState({ + currencies_dict: data + })); + } + // Gets currency code (3 letters) from numeric (e.g., 1 -> USD) + // Improve this function so currencies are read from json + getCurrencyCode(val){ + console.log("---------------------------------") + console.log(val) + return this.state.currencies_dict[val.toString()] + } render (){ return ( From 5fb776aca76330675171c03bf224444aee81fc41 Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Sat, 8 Jan 2022 05:08:03 -0800 Subject: [PATCH 08/29] Add TradeBox and QR client side generation --- api/models.py | 2 +- api/urls.py | 3 +- frontend/package-lock.json | 4870 +++++++++++++++++++++++- frontend/package.json | 3 + frontend/src/components/OrderPage.js | 69 +- frontend/src/components/TradeBox.js | 64 + frontend/src/components/UserGenPage.js | 2 +- frontend/webpack.config.js | 3 + setup.md | 1 + 9 files changed, 4847 insertions(+), 170 deletions(-) diff --git a/api/models.py b/api/models.py index 464540de..3a268841 100644 --- a/api/models.py +++ b/api/models.py @@ -193,7 +193,7 @@ class MarketTick(models.Model): Records tick by tick Non-KYC Bitcoin price. Data to be aggregated and offered via public API. - It is checked against current cex prices for nice + It is checked against current CEX price for useful insight on the historical premium of Non-KYC BTC Price is set when both taker bond is locked. Both diff --git a/api/urls.py b/api/urls.py index 7ba757ba..563fb14c 100644 --- a/api/urls.py +++ b/api/urls.py @@ -4,7 +4,8 @@ from .views import MakerView, OrderView, UserView, BookView, InfoView urlpatterns = [ path('make/', MakerView.as_view()), path('order/', OrderView.as_view({'get':'get','post':'take_update_confirm_dispute_cancel'})), - path('usergen/', UserView.as_view()), + path('user/', UserView.as_view()), path('book/', BookView.as_view()), + # path('robot/') # Profile Info path('info/', InfoView.as_view()), ] \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b5eb7116..51cf6798 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -15,14 +15,12 @@ "@babel/compat-data": { "version": "7.16.4", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.4.tgz", - "integrity": "sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==", - "dev": true + "integrity": "sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==" }, "@babel/core": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.7.tgz", "integrity": "sha512-aeLaqcqThRNZYmbMqtulsetOQZ/5gbR/dWruUCJcpas4Qoyy+QeagfDsPdMrqwsPRDNxJvBlRiZxxX7THO7qtA==", - "dev": true, "requires": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.16.7", @@ -44,8 +42,7 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, @@ -78,7 +75,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", - "dev": true, "requires": { "@babel/helper-explode-assignable-expression": "^7.16.7", "@babel/types": "^7.16.7" @@ -88,7 +84,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", - "dev": true, "requires": { "@babel/compat-data": "^7.16.4", "@babel/helper-validator-option": "^7.16.7", @@ -114,7 +109,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.7.tgz", "integrity": "sha512-fk5A6ymfp+O5+p2yCkXAu5Kyj6v0xh0RBeNcAkYUMDvvAAoxvSKXn+Jb37t/yWFiQVDFK1ELpUTD8/aLhCPu+g==", - "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.16.7", "regexpu-core": "^4.7.1" @@ -124,7 +118,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.0.tgz", "integrity": "sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg==", - "dev": true, "requires": { "@babel/helper-compilation-targets": "^7.13.0", "@babel/helper-module-imports": "^7.12.13", @@ -148,7 +141,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", - "dev": true, "requires": { "@babel/types": "^7.16.7" } @@ -199,7 +191,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz", "integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==", - "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", @@ -228,7 +219,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.7.tgz", "integrity": "sha512-C3o117GnP/j/N2OWo+oepeWbFEKRfNaay+F1Eo5Mj3A1SRjyx+qaFhm23nlipub7Cjv2azdUUiDH+VlpdwUFRg==", - "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-wrap-function": "^7.16.7", @@ -251,7 +241,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", - "dev": true, "requires": { "@babel/types": "^7.16.7" } @@ -260,7 +249,6 @@ "version": "7.16.0", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", - "dev": true, "requires": { "@babel/types": "^7.16.0" } @@ -281,14 +269,12 @@ "@babel/helper-validator-option": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==" }, "@babel/helper-wrap-function": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.7.tgz", "integrity": "sha512-7a9sABeVwcunnztZZ7WTgSw6jVYLzM1wua0Z4HIXm9S3/HC96WKQTkFgGEaj5W06SHHihPJ6Le6HzS5cGOQMNw==", - "dev": true, "requires": { "@babel/helper-function-name": "^7.16.7", "@babel/template": "^7.16.7", @@ -300,7 +286,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.7.tgz", "integrity": "sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==", - "dev": true, "requires": { "@babel/template": "^7.16.7", "@babel/traverse": "^7.16.7", @@ -383,6 +368,15 @@ "@babel/plugin-syntax-dynamic-import": "^7.8.3" } }, + "@babel/plugin-proposal-export-default-from": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.16.7.tgz", + "integrity": "sha512-+cENpW1rgIjExn+o5c8Jw/4BuH4eGKKYvkMB8/0ZxFQ9mC0t4z09VsPIwNg6waF69QYC81zxGeAsREGuqQoKeg==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-export-default-from": "^7.16.7" + } + }, "@babel/plugin-proposal-export-namespace-from": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz", @@ -417,7 +411,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" @@ -437,7 +430,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.7.tgz", "integrity": "sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA==", - "dev": true, "requires": { "@babel/compat-data": "^7.16.4", "@babel/helper-compilation-targets": "^7.16.7", @@ -450,7 +442,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" @@ -460,7 +451,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", @@ -512,7 +502,6 @@ "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.12.13" } @@ -530,11 +519,18 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-export-default-from": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.16.7.tgz", + "integrity": "sha512-4C3E4NsrLOgftKaTYTULhHsuQrGv3FHrBzOMDiS7UYKIpgGBkAdawg4h+EI8zPeK9M0fiIIh72hIwsI24K7MbA==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, "@babel/plugin-syntax-export-namespace-from": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", @@ -544,6 +540,14 @@ "@babel/helper-plugin-utils": "^7.8.3" } }, + "@babel/plugin-syntax-flow": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.16.7.tgz", + "integrity": "sha512-UDo3YGQO0jH6ytzVwgSLv9i/CzMcUjbKenL67dTrAZPPv6GFAtDhe6jqnvmoKzC/7htNTohhos+onPtDMqJwaQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, "@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", @@ -574,7 +578,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -592,7 +595,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -601,7 +603,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -610,7 +611,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.0" } @@ -633,11 +633,18 @@ "@babel/helper-plugin-utils": "^7.14.5" } }, + "@babel/plugin-syntax-typescript": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", + "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, "@babel/plugin-transform-arrow-functions": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz", "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7" } @@ -646,7 +653,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.7.tgz", "integrity": "sha512-pFEfjnK4DfXCfAlA5I98BYdDJD8NltMzx19gt6DAmfE+2lXRfPUoa0/5SUjT4+TDE1W/rcxU/1lgN55vpAjjdg==", - "dev": true, "requires": { "@babel/helper-module-imports": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", @@ -657,7 +663,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7" } @@ -666,7 +671,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz", "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7" } @@ -675,7 +679,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz", "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==", - "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-environment-visitor": "^7.16.7", @@ -691,7 +694,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz", "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7" } @@ -700,7 +702,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.7.tgz", "integrity": "sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7" } @@ -728,17 +729,24 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", - "dev": true, "requires": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" } }, + "@babel/plugin-transform-flow-strip-types": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.16.7.tgz", + "integrity": "sha512-mzmCq3cNsDpZZu9FADYYyfZJIOrSONmHcop2XEKPdBNMa4PDC4eEvcOvzZaCNcjKu72v0XQlA5y1g58aLRXdYg==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-flow": "^7.16.7" + } + }, "@babel/plugin-transform-for-of": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz", "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7" } @@ -747,7 +755,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", - "dev": true, "requires": { "@babel/helper-compilation-targets": "^7.16.7", "@babel/helper-function-name": "^7.16.7", @@ -758,7 +765,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz", "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7" } @@ -767,7 +773,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7" } @@ -787,7 +792,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.7.tgz", "integrity": "sha512-h2RP2kE7He1ZWKyAlanMZrAbdv+Acw1pA8dQZhE025WJZE2z0xzFADAinXA9fxd5bn7JnM+SdOGcndGx1ARs9w==", - "dev": true, "requires": { "@babel/helper-module-transforms": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", @@ -836,11 +840,18 @@ "@babel/helper-plugin-utils": "^7.16.7" } }, + "@babel/plugin-transform-object-assign": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.16.7.tgz", + "integrity": "sha512-R8mawvm3x0COTJtveuoqZIjNypn2FjfvXZr4pSQ8VhEFBuQGBz4XhHasZtHXjgXU4XptZ4HtGof3NoYc93ZH9Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, "@babel/plugin-transform-object-super": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-replace-supers": "^7.16.7" @@ -850,7 +861,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz", "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7" } @@ -859,7 +869,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7" } @@ -868,7 +877,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz", "integrity": "sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7" } @@ -877,7 +885,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.7.tgz", "integrity": "sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag==", - "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", @@ -895,6 +902,22 @@ "@babel/plugin-transform-react-jsx": "^7.16.7" } }, + "@babel/plugin-transform-react-jsx-self": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.16.7.tgz", + "integrity": "sha512-oe5VuWs7J9ilH3BCCApGoYjHoSO48vkjX2CbA5bFVhIuO2HKxA3vyF7rleA4o6/4rTDbk6r8hBW7Ul8E+UZrpA==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-react-jsx-source": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.16.7.tgz", + "integrity": "sha512-rONFiQz9vgbsnaMtQlZCjIRwhJvlrPET8TabIUK2hzlXw9B9s2Ieaxte1SCOOXMbWRHodbKixNf3BLcWVOQ8Bw==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, "@babel/plugin-transform-react-pure-annotations": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz", @@ -909,7 +932,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz", "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==", - "dev": true, "requires": { "regenerator-transform": "^0.14.2" } @@ -923,11 +945,23 @@ "@babel/helper-plugin-utils": "^7.16.7" } }, + "@babel/plugin-transform-runtime": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.7.tgz", + "integrity": "sha512-2FoHiSAWkdq4L06uaDN3rS43i6x28desUVxq+zAFuE6kbWYQeiLPJI5IC7Sg9xKYVcrBKSQkVUfH6aeQYbl9QA==", + "requires": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.4.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "semver": "^6.3.0" + } + }, "@babel/plugin-transform-shorthand-properties": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7" } @@ -936,7 +970,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz", "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" @@ -946,7 +979,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7" } @@ -955,7 +987,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz", "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7" } @@ -969,6 +1000,16 @@ "@babel/helper-plugin-utils": "^7.16.7" } }, + "@babel/plugin-transform-typescript": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.7.tgz", + "integrity": "sha512-Hzx1lvBtOCWuCEwMmYOfpQpO7joFeXLgoPuzZZBtTxXqSqUGUubvFGZv2ygo1tB5Bp9q6PXV3H0E/kf7KM0RLA==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-typescript": "^7.16.7" + } + }, "@babel/plugin-transform-unicode-escapes": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", @@ -982,7 +1023,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", - "dev": true, "requires": { "@babel/helper-create-regexp-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" @@ -1070,6 +1110,16 @@ "semver": "^6.3.0" } }, + "@babel/preset-flow": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.16.7.tgz", + "integrity": "sha512-6ceP7IyZdUYQ3wUVqyRSQXztd1YmFHWI4Xv11MIqAlE4WqxBSd/FZ61V9k+TS5Gd4mkHOtQtPp9ymRpxH4y1Ug==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-transform-flow-strip-types": "^7.16.7" + } + }, "@babel/preset-modules": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", @@ -1097,6 +1147,92 @@ "@babel/plugin-transform-react-pure-annotations": "^7.16.7" } }, + "@babel/preset-typescript": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz", + "integrity": "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-transform-typescript": "^7.16.7" + } + }, + "@babel/register": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.16.7.tgz", + "integrity": "sha512-Ft+cuxorVxFj4RrPDs9TbJNE7ZbuJTyazUC6jLWRvBQT/qIDZPMe7MHgjlrA+11+XDLh+I0Pnx7sxPp4LRhzcA==", + "requires": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.0", + "source-map-support": "^0.5.16" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "requires": { + "find-up": "^3.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, "@babel/runtime": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz", @@ -1141,6 +1277,15 @@ "to-fast-properties": "^2.0.0" } }, + "@cnakazawa/watch": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", + "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==", + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + } + }, "@discoveryjs/json-ext": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz", @@ -1273,6 +1418,79 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz", "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==" }, + "@hapi/hoek": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", + "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==" + }, + "@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@jest/create-cache-key-function": { + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-27.4.2.tgz", + "integrity": "sha512-aSSCAJwUNX4R1hJQoyimsND5l+2EsFgzlepS8NuOJJHjXij/UdxYFngac44tmv9IYdI+kglAyORg0plt4/aFMQ==", + "requires": { + "@jest/types": "^27.4.2" + } + }, + "@jest/types": { + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.4.2.tgz", + "integrity": "sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "@material-ui/core": { "version": "4.12.3", "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.3.tgz", @@ -1408,6 +1626,441 @@ "react-is": "^17.0.2" } }, + "@react-native-community/cli-debugger-ui": { + "version": "6.0.0-rc.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-6.0.0-rc.0.tgz", + "integrity": "sha512-achYcPPoWa9D02C5tn6TBzjeY443wQTyx37urptc75JpZ7gR5YHsDyIEEWa3DDYp1va9zx/iGg+uZ/hWw07GAw==", + "requires": { + "serve-static": "^1.13.1" + } + }, + "@react-native-community/cli-hermes": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-6.3.0.tgz", + "integrity": "sha512-Uhbm9bubyZLZ12vFCIfWbE/Qi3SBTbYIN/TC08EudTLhv/KbPomCQnmFsnJ7AXQFuOZJs73mBxoEAYSbRbwyVA==", + "requires": { + "@react-native-community/cli-platform-android": "^6.3.0", + "@react-native-community/cli-tools": "^6.2.0", + "chalk": "^4.1.2", + "hermes-profile-transformer": "^0.0.6", + "ip": "^1.1.5" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@react-native-community/cli-platform-android": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-6.3.0.tgz", + "integrity": "sha512-d5ufyYcvrZoHznYm5bjBXaiHIJv552t5gYtQpnUsxBhHSQ8QlaNmlLUyeSPRDfOw4ND9b0tPHqs4ufwx6vp/fQ==", + "requires": { + "@react-native-community/cli-tools": "^6.2.0", + "chalk": "^4.1.2", + "execa": "^1.0.0", + "fs-extra": "^8.1.0", + "glob": "^7.1.3", + "jetifier": "^1.6.2", + "lodash": "^4.17.15", + "logkitty": "^0.7.1", + "slash": "^3.0.0", + "xmldoc": "^1.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "@react-native-community/cli-platform-ios": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-6.2.0.tgz", + "integrity": "sha512-k15MhExxLiLDDZOeuPgvTxbp0CsoLQQpk2Du0HjZDePqqWcKJylQqMZru1o8HuQHPcEr+b71HIs5V+lKyFYpfg==", + "requires": { + "@react-native-community/cli-tools": "^6.2.0", + "chalk": "^4.1.2", + "glob": "^7.1.3", + "js-yaml": "^3.13.1", + "lodash": "^4.17.15", + "ora": "^3.4.0", + "plist": "^3.0.2", + "xcode": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@react-native-community/cli-plugin-metro": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-6.2.0.tgz", + "integrity": "sha512-JfmzuFNzOr+dFTUQJo1rV0t87XAqgHRTMYXNleQVt8otOVCk1FSCgKlgqMdvQc/FCx2ZjoMWEEV/g0LrPI8Etw==", + "requires": { + "@react-native-community/cli-server-api": "^6.2.0", + "@react-native-community/cli-tools": "^6.2.0", + "chalk": "^4.1.2", + "metro": "^0.66.1", + "metro-config": "^0.66.1", + "metro-core": "^0.66.1", + "metro-react-native-babel-transformer": "^0.66.1", + "metro-resolver": "^0.66.1", + "metro-runtime": "^0.66.1", + "readline": "^1.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@react-native-community/cli-server-api": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-6.2.0.tgz", + "integrity": "sha512-OnbnYclhoDpjge33QO5Slhfn0DsmLzzAgyrSCnb24HhSqwq7ObjMHaLpoEhpajzLG71wq5oKh0APEQjiL4Mknw==", + "requires": { + "@react-native-community/cli-debugger-ui": "^6.0.0-rc.0", + "@react-native-community/cli-tools": "^6.2.0", + "compression": "^1.7.1", + "connect": "^3.6.5", + "errorhandler": "^1.5.0", + "nocache": "^2.1.0", + "pretty-format": "^26.6.2", + "serve-static": "^1.13.1", + "ws": "^1.1.0" + }, + "dependencies": { + "ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", + "requires": { + "options": ">=0.0.5", + "ultron": "1.0.x" + } + } + } + }, + "@react-native-community/cli-tools": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-6.2.0.tgz", + "integrity": "sha512-08ssz4GMEnRxC/1FgTTN/Ud7mExQi5xMphItPjfHiTxpZPhrFn+IMx6mya0ncFEhhxQ207wYlJMRLPRRdBZ8oA==", + "requires": { + "appdirsjs": "^1.2.4", + "chalk": "^4.1.2", + "lodash": "^4.17.15", + "mime": "^2.4.1", + "node-fetch": "^2.6.0", + "open": "^6.2.0", + "semver": "^6.3.0", + "shell-quote": "1.6.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@react-native-community/cli-types": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-6.0.0.tgz", + "integrity": "sha512-K493Fk2DMJC0ZM8s8gnfseKxGasIhuDaCUDeLZcoCSFlrjKEuEs1BKKEJiev0CARhKEXKOyyp/uqYM9nWhisNw==", + "requires": { + "ora": "^3.4.0" + } + }, + "@react-native/assets": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@react-native/assets/-/assets-1.0.0.tgz", + "integrity": "sha512-KrwSpS1tKI70wuKl68DwJZYEvXktDHdZMG0k2AXD/rJVSlB23/X2CB2cutVR0HwNMJIal9HOUOBB2rVfa6UGtQ==" + }, + "@react-native/normalize-color": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@react-native/normalize-color/-/normalize-color-1.0.0.tgz", + "integrity": "sha512-xUNRvNmCl3UGCPbbHvfyFMnpvLPoOjDCcp5bT9m2k+TF/ZBklEQwhPZlkrxRx2NhgFh1X3a5uL7mJ7ZR+8G7Qg==" + }, + "@react-native/polyfills": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@react-native/polyfills/-/polyfills-2.0.0.tgz", + "integrity": "sha512-K0aGNn1TjalKj+65D7ycc1//H9roAQ51GJVk5ZJQFb2teECGmzd86bYDC0aYdbRf7gtovescq4Zt6FR0tgXiHQ==" + }, + "@sideway/address": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.3.tgz", + "integrity": "sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, "@types/eslint": { "version": "8.2.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.2.1.tgz", @@ -1434,6 +2087,35 @@ "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", "dev": true }, + "@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, "@types/json-schema": { "version": "7.0.9", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", @@ -1443,8 +2125,7 @@ "@types/node": { "version": "17.0.6", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.6.tgz", - "integrity": "sha512-+XBAjfZmmivILUzO0HwBJoYkAyyySSLg5KCGBDFLomJo0sV6szvVLAf4ANZZ0pfWzgEds5KmGLG9D5hfEqOhaA==", - "dev": true + "integrity": "sha512-+XBAjfZmmivILUzO0HwBJoYkAyyySSLg5KCGBDFLomJo0sV6szvVLAf4ANZZ0pfWzgEds5KmGLG9D5hfEqOhaA==" }, "@types/parse-json": { "version": "4.0.0", @@ -1494,6 +2175,19 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==" + }, "@webassemblyjs/ast": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", @@ -1673,6 +2367,28 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "absolute-path": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/absolute-path/-/absolute-path-0.0.0.tgz", + "integrity": "sha1-p4di+9rftSl76ZsV01p4Wy8JW/c=" + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, "acorn": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", @@ -1703,6 +2419,33 @@ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true }, + "anser": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", + "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==" + }, + "ansi-fragments": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz", + "integrity": "sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w==", + "requires": { + "colorette": "^1.0.7", + "slice-ansi": "^2.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" + } + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -1711,6 +2454,109 @@ "color-convert": "^1.9.0" } }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "appdirsjs": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.6.tgz", + "integrity": "sha512-D8wJNkqMCeQs3kLasatELsddox/Xqkhp+J07iXGyL54fVN7oc+nmNfYzGuCs1IEP6uBw+TfpuO3JKwc+lECy4w==" + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=" + }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=" + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "ast-types": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", + "integrity": "sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==", + "requires": { + "tslib": "^2.0.1" + } + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==" + }, "babel-loader": { "version": "8.2.3", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz", @@ -1740,7 +2586,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, "requires": { "object.assign": "^4.1.0" } @@ -1759,7 +2604,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.0.tgz", "integrity": "sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA==", - "dev": true, "requires": { "@babel/compat-data": "^7.13.11", "@babel/helper-define-polyfill-provider": "^0.3.0", @@ -1770,7 +2614,6 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.4.0.tgz", "integrity": "sha512-YxFreYwUfglYKdLUGvIF2nJEsGwj+RhWSX/ije3D2vQPOXuyMLMtg/cCGMDpOA7Nd+MwlNdnGODbd2EwUZPlsw==", - "dev": true, "requires": { "@babel/helper-define-polyfill-provider": "^0.3.0", "core-js-compat": "^3.18.0" @@ -1780,22 +2623,162 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.0.tgz", "integrity": "sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg==", - "dev": true, "requires": { "@babel/helper-define-polyfill-provider": "^0.3.0" } }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "7.0.0-beta.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz", + "integrity": "sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ==" + }, + "babel-preset-fbjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz", + "integrity": "sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow==", + "requires": { + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-syntax-class-properties": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-block-scoped-functions": "^7.0.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-member-expression-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-object-super": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-property-literals": "^7.0.0", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-template-literals": "^7.0.0", + "babel-plugin-syntax-trailing-function-commas": "^7.0.0-beta.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==" + }, "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "bplist-creator": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz", + "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==", + "requires": { + "stream-buffers": "2.2.x" + } + }, + "bplist-parser": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.0.tgz", + "integrity": "sha512-zgmaRvT6AN1JpPPV+S0a1/FAtoxSreYDccZGIqEMSvZl9DMe70mJ7MFzpxa1X+gHVdkToE2haRUHHMiW1OdejA==", + "requires": { + "big-integer": "1.6.x" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, "browserslist": { "version": "4.19.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", - "dev": true, "requires": { "caniuse-lite": "^1.0.30001286", "electron-to-chromium": "^1.4.17", @@ -1804,32 +2787,94 @@ "picocolors": "^1.0.0" } }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "requires": { + "node-int64": "^0.4.0" + } + }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" } }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "requires": { + "callsites": "^2.0.0" + }, + "dependencies": { + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=" + } + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "requires": { + "caller-callsite": "^2.0.0" + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, "caniuse-lite": { "version": "1.0.30001294", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001294.tgz", - "integrity": "sha512-LiMlrs1nSKZ8qkNhpUf5KD0Al1KCBE3zaT7OLOwEkagXMEDij98SiOovn9wxVGQpklk9vVC/pUSqgYmkmKOS8g==", - "dev": true + "integrity": "sha512-LiMlrs1nSKZ8qkNhpUf5KD0Al1KCBE3zaT7OLOwEkagXMEDij98SiOovn9wxVGQpklk9vVC/pUSqgYmkmKOS8g==" + }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "requires": { + "rsvp": "^4.8.4" + } }, "chalk": { "version": "2.4.2", @@ -1862,11 +2907,79 @@ "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", "dev": true }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==" + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, "clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, "requires": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", @@ -1878,6 +2991,15 @@ "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -1897,17 +3019,103 @@ "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", "dev": true }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } }, "convert-source-map": { "version": "1.8.0", @@ -1924,11 +3132,15 @@ } } }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, "core-js-compat": { "version": "3.20.2", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.20.2.tgz", "integrity": "sha512-qZEzVQ+5Qh6cROaTPFLNS4lkvQ6mBzE3R6A6EEpssj7Zr2egMHgsy4XapdifqJDGC9CBiNv7s+ejI96rLNQFdg==", - "dev": true, "requires": { "browserslist": "^4.19.1", "semver": "7.0.0" @@ -1937,11 +3149,15 @@ "semver": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" } } }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "cosmiconfig": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", @@ -1965,6 +3181,26 @@ "which": "^2.0.1" } }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, "css-vendor": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", @@ -1974,11 +3210,21 @@ "is-in-browser": "^1.0.2" } }, + "css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==" + }, "csstype": { "version": "2.6.19", "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.19.tgz", "integrity": "sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==" }, + "dayjs": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz", + "integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==" + }, "debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", @@ -1987,15 +3233,89 @@ "ms": "2.1.2" } }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "deepmerge": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.3.0.tgz", + "integrity": "sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA==" + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "requires": { + "clone": "^1.0.2" + } + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, "requires": { "object-keys": "^1.0.12" } }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "denodeify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", + "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, "dom-helpers": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", @@ -2012,11 +3332,50 @@ } } }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + } + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, "electron-to-chromium": { "version": "1.4.31", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.31.tgz", - "integrity": "sha512-t3XVQtk+Frkv6aTD4RRk0OqosU+VLe1dQFW83MDer78ZD6a52frgXuYOIsLYTQiH2Lm+JB2OKYcn7zrX+YGAiQ==", - "dev": true + "integrity": "sha512-t3XVQtk+Frkv6aTD4RRk0OqosU+VLe1dQFW83MDer78ZD6a52frgXuYOIsLYTQiH2Lm+JB2OKYcn7zrX+YGAiQ==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "emojis-list": { "version": "3.0.0", @@ -2024,6 +3383,19 @@ "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "dev": true }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, "enhanced-resolve": { "version": "5.8.3", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", @@ -2034,11 +3406,15 @@ "tapable": "^2.2.0" } }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + }, "envinfo": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", - "dev": true + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==" }, "error-ex": { "version": "1.3.2", @@ -2048,6 +3424,23 @@ "is-arrayish": "^0.2.1" } }, + "error-stack-parser": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz", + "integrity": "sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==", + "requires": { + "stackframe": "^1.1.1" + } + }, + "errorhandler": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz", + "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==", + "requires": { + "accepts": "~1.3.7", + "escape-html": "~1.0.3" + } + }, "es-module-lexer": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", @@ -2057,8 +3450,12 @@ "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "escape-string-regexp": { "version": "1.0.5", @@ -2075,6 +3472,11 @@ "estraverse": "^4.1.1" } }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, "esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -2104,12 +3506,27 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, "events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true }, + "exec-sh": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz", + "integrity": "sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==" + }, "execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -2127,6 +3544,129 @@ "strip-final-newline": "^2.0.0" } }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2145,6 +3685,51 @@ "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", "dev": true }, + "fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "requires": { + "bser": "2.1.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "find-cache-dir": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", @@ -2165,12 +3750,55 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "requires": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, + "flow-parser": { + "version": "0.121.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.121.0.tgz", + "integrity": "sha512-1gIBiWJNR0tKUNv8gZuk7l9rVX06OuLzY9AoGio7y/JT4V1IZErEMEq2TJS+PFcw/y0RshZ1J/27VfK1UQzYVg==" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -2179,14 +3807,17 @@ "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -2199,6 +3830,24 @@ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", @@ -2213,8 +3862,7 @@ "graceful-fs": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" }, "has": { "version": "1.0.3", @@ -2227,14 +3875,84 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "has-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hermes-engine": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/hermes-engine/-/hermes-engine-0.9.0.tgz", + "integrity": "sha512-r7U+Y4P2Qg/igFVZN+DpT7JFfXUn1MM4dFne8aW+cCrF6RRymof+VqrUHs1kl07j8h8V2CNesU19RKgWbr3qPw==" + }, + "hermes-parser": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.4.7.tgz", + "integrity": "sha512-jc+zCtXbtwTiXoMAoXOHepxAaGVFIp89wwE9qcdwnMd/uGVEtPoY8FaFSsx0ThPvyKirdR2EsIIDVrpbSXz1Ag==" + }, + "hermes-profile-transformer": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz", + "integrity": "sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ==", + "requires": { + "source-map": "^0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" + } + } }, "history": { "version": "4.10.1", @@ -2264,6 +3982,18 @@ } } }, + "http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + } + }, "human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -2275,6 +4005,11 @@ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" }, + "image-size": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.6.3.tgz", + "integrity": "sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA==" + }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -2301,17 +4036,80 @@ "resolve-cwd": "^3.0.0" } }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, "interpret": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", "dev": true }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "requires": { + "ci-info": "^2.0.0" + } + }, "is-core-module": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", @@ -2320,16 +4118,70 @@ "has": "^1.0.3" } }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=" + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, "is-in-browser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=" }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "requires": { "isobject": "^3.0.1" } @@ -2340,6 +4192,16 @@ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -2348,14 +4210,273 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "jest-get-type": { + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", + "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==" + }, + "jest-haste-map": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz", + "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==", + "requires": { + "@jest/types": "^26.6.2", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.4", + "jest-regex-util": "^26.0.0", + "jest-serializer": "^26.6.2", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "micromatch": "^4.0.2", + "sane": "^4.0.3", + "walker": "^1.0.7" + }, + "dependencies": { + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-regex-util": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz", + "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==" + }, + "jest-serializer": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz", + "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==", + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.4" + } + }, + "jest-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz", + "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==", + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^2.0.0", + "micromatch": "^4.0.2" + }, + "dependencies": { + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-validate": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz", + "integrity": "sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==", + "requires": { + "@jest/types": "^26.6.2", + "camelcase": "^6.0.0", + "chalk": "^4.0.0", + "jest-get-type": "^26.3.0", + "leven": "^3.1.0", + "pretty-format": "^26.6.2" + }, + "dependencies": { + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } }, "jest-worker": { "version": "27.4.5", @@ -2368,11 +4489,165 @@ "supports-color": "^8.0.0" } }, + "jetifier": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/jetifier/-/jetifier-1.6.8.tgz", + "integrity": "sha512-3Zi16h6L5tXDRQJTb221cnRoVG9/9OvreLdLU2/ZjRv/GILL+2Cemt0IKvkowwkDpvouAU1DQPOJ7qaiHeIdrw==" + }, + "joi": { + "version": "17.5.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.5.0.tgz", + "integrity": "sha512-R7hR50COp7StzLnDi4ywOXHrBrgNXuUUfJWIR5lPY5Bm/pOD3jZaTwpluUXVLRWcoWZxkrHBBJ5hLxgnlehbdw==", + "requires": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.3", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsc-android": { + "version": "250230.2.1", + "resolved": "https://registry.npmjs.org/jsc-android/-/jsc-android-250230.2.1.tgz", + "integrity": "sha512-KmxeBlRjwoqCnBBKGsihFtvsBHyUFlBxJPK4FzeYcIuBfdjv6jFys44JITAgSTbQD+vIdwMEfyZklsuQX0yI1Q==" + }, + "jscodeshift": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.11.0.tgz", + "integrity": "sha512-SdRK2C7jjs4k/kT2mwtO07KJN9RnjxtKn03d9JVj6c3j9WwaLcFYsICYDnLAzY0hp+wG2nxl+Cm2jWLiNVYb8g==", + "requires": { + "@babel/core": "^7.1.6", + "@babel/parser": "^7.1.6", + "@babel/plugin-proposal-class-properties": "^7.1.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.1.0", + "@babel/plugin-proposal-optional-chaining": "^7.1.0", + "@babel/plugin-transform-modules-commonjs": "^7.1.0", + "@babel/preset-flow": "^7.0.0", + "@babel/preset-typescript": "^7.1.0", + "@babel/register": "^7.0.0", + "babel-core": "^7.0.0-bridge.0", + "colors": "^1.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^3.1.10", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.20.3", + "temp": "^0.8.1", + "write-file-atomic": "^2.3.0" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -2381,8 +4656,7 @@ "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, "json-parse-even-better-errors": { "version": "2.3.1", @@ -2399,11 +4673,23 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, "requires": { "minimist": "^1.2.5" } }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, "jss": { "version": "10.9.0", "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz", @@ -2492,8 +4778,25 @@ "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" }, "lines-and-columns": { "version": "1.2.4", @@ -2532,16 +4835,42 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "requires": { "p-locate": "^4.1.0" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "requires": { + "chalk": "^2.0.1" + } + }, + "logkitty": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/logkitty/-/logkitty-0.7.1.tgz", + "integrity": "sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==", + "requires": { + "ansi-fragments": "^0.2.1", + "dayjs": "^1.8.15", + "yargs": "^15.1.0" + } }, "loose-envify": { "version": "1.4.0", @@ -2560,6 +4889,27 @@ "semver": "^6.0.0" } }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "requires": { + "tmpl": "1.0.5" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, "material-ui-image": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/material-ui-image/-/material-ui-image-3.3.2.tgz", @@ -2568,23 +4918,502 @@ "prop-types": "^15.5.8" } }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "metro": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.66.2.tgz", + "integrity": "sha512-uNsISfcQ3iKKSHoN5Q+LAh0l3jeeg7ZcNZ/4BAHGsk02erA0OP+l2m+b5qYVoPptHz9Oc3KyG5oGJoTu41pWjg==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/core": "^7.14.0", + "@babel/generator": "^7.14.0", + "@babel/parser": "^7.14.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.14.0", + "@babel/types": "^7.0.0", + "absolute-path": "^0.0.0", + "accepts": "^1.3.7", + "async": "^2.4.0", + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "denodeify": "^1.2.1", + "error-stack-parser": "^2.0.6", + "fs-extra": "^1.0.0", + "graceful-fs": "^4.1.3", + "hermes-parser": "0.4.7", + "image-size": "^0.6.0", + "invariant": "^2.2.4", + "jest-haste-map": "^26.5.2", + "jest-worker": "^26.0.0", + "lodash.throttle": "^4.1.1", + "metro-babel-register": "0.66.2", + "metro-babel-transformer": "0.66.2", + "metro-cache": "0.66.2", + "metro-cache-key": "0.66.2", + "metro-config": "0.66.2", + "metro-core": "0.66.2", + "metro-hermes-compiler": "0.66.2", + "metro-inspector-proxy": "0.66.2", + "metro-minify-uglify": "0.66.2", + "metro-react-native-babel-preset": "0.66.2", + "metro-resolver": "0.66.2", + "metro-runtime": "0.66.2", + "metro-source-map": "0.66.2", + "metro-symbolicate": "0.66.2", + "metro-transform-plugins": "0.66.2", + "metro-transform-worker": "0.66.2", + "mime-types": "^2.1.27", + "mkdirp": "^0.5.1", + "node-fetch": "^2.2.0", + "nullthrows": "^1.1.1", + "rimraf": "^2.5.4", + "serialize-error": "^2.1.0", + "source-map": "^0.5.6", + "strip-ansi": "^6.0.0", + "temp": "0.8.3", + "throat": "^5.0.0", + "ws": "^1.1.5", + "yargs": "^15.3.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0" + } + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", + "requires": { + "options": ">=0.0.5", + "ultron": "1.0.x" + } + } + } + }, + "metro-babel-register": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-babel-register/-/metro-babel-register-0.66.2.tgz", + "integrity": "sha512-3F+vsVubUPJYKfVMeol8/7pd8CC287Rw92QYzJD8LEmI980xcgwMUEVBZ0UIAUwlLgiJG/f4Mwhuji2EeBXrPg==", + "requires": { + "@babel/core": "^7.14.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.0.0", + "@babel/plugin-syntax-class-properties": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/register": "^7.0.0", + "escape-string-regexp": "^1.0.5" + } + }, + "metro-babel-transformer": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.66.2.tgz", + "integrity": "sha512-aJ/7fc/Xkofw8Fqa51OTDhBzBz26mmpIWrXAZcPdQ8MSTt883EWncxeCEjasc79NJ89BRi7sOkkaWZo2sXlKvw==", + "requires": { + "@babel/core": "^7.14.0", + "hermes-parser": "0.4.7", + "metro-source-map": "0.66.2", + "nullthrows": "^1.1.1" + } + }, + "metro-cache": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.66.2.tgz", + "integrity": "sha512-5QCYJtJOHoBSbL3H4/Fpl36oA697C3oYHqsce+Hk/dh2qtODUGpS3gOBhvP1B8iB+H8jJMyR75lZq129LJEsIQ==", + "requires": { + "metro-core": "0.66.2", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4" + } + }, + "metro-cache-key": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.66.2.tgz", + "integrity": "sha512-WtkNmRt41qOpHh1MkNA4nLiQ/m7iGL90ysSKD+fcLqlUnOBKJptPQm0ZUv8Kfqk18ddWX2KmsSbq+Sf3I6XohQ==" + }, + "metro-config": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.66.2.tgz", + "integrity": "sha512-0C+PrKKIBNNzLZUKN/8ZDJS2U5FLMOTXDWbvBHIdqb6YXz8WplXR2+xlSlaSCCi5b+GR7cWFWUNeKA4GQS1/AQ==", + "requires": { + "cosmiconfig": "^5.0.5", + "jest-validate": "^26.5.2", + "metro": "0.66.2", + "metro-cache": "0.66.2", + "metro-core": "0.66.2", + "metro-runtime": "0.66.2" + }, + "dependencies": { + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + } + } + }, + "metro-core": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.66.2.tgz", + "integrity": "sha512-JieLZkef/516yxXYvQxWnf3OWw5rcgWRy76K8JV/wr/i8LGVGulPAXlIi445/QZzXVydzRVASKAEVqyxM5F4mA==", + "requires": { + "jest-haste-map": "^26.5.2", + "lodash.throttle": "^4.1.1", + "metro-resolver": "0.66.2" + } + }, + "metro-hermes-compiler": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-hermes-compiler/-/metro-hermes-compiler-0.66.2.tgz", + "integrity": "sha512-nCVL1g9uR6vrw5+X1wjwZruRyMkndnzGRMqjqoljf+nGEqBTD607CR7elXw4fMWn/EM+1y0Vdq5altUu9LdgCA==" + }, + "metro-inspector-proxy": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-inspector-proxy/-/metro-inspector-proxy-0.66.2.tgz", + "integrity": "sha512-gnLc9121eznwP0iiA9tCBW8qZjwIsCgwHWMF1g1Qaki9le9tzeJv3dK4/lFNGxyfSaLO7vahQEhsEYsiRnTROg==", + "requires": { + "connect": "^3.6.5", + "debug": "^2.2.0", + "ws": "^1.1.5", + "yargs": "^15.3.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", + "requires": { + "options": ">=0.0.5", + "ultron": "1.0.x" + } + } + } + }, + "metro-minify-uglify": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-minify-uglify/-/metro-minify-uglify-0.66.2.tgz", + "integrity": "sha512-7TUK+L5CmB5x1PVnFbgmjzHW4CUadq9H5jgp0HfFoWT1skXAyEsx0DHkKDXwnot0khnNhBOEfl62ctQOnE110Q==", + "requires": { + "uglify-es": "^3.1.9" + } + }, + "metro-react-native-babel-preset": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.66.2.tgz", + "integrity": "sha512-H/nLBAz0MgfDloSe1FjyH4EnbokHFdncyERvLPXDACY3ROVRCeUyFNo70ywRGXW2NMbrV4H7KUyU4zkfWhC2HQ==", + "requires": { + "@babel/core": "^7.14.0", + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.0.0", + "@babel/plugin-syntax-export-default-from": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.2.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-syntax-optional-chaining": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-async-to-generator": "^7.0.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.0.0", + "@babel/plugin-transform-exponentiation-operator": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-object-assign": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-react-jsx-self": "^7.0.0", + "@babel/plugin-transform-react-jsx-source": "^7.0.0", + "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-template-literals": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.5.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "@babel/template": "^7.0.0", + "react-refresh": "^0.4.0" + } + }, + "metro-react-native-babel-transformer": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.66.2.tgz", + "integrity": "sha512-z1ab7ihIT0pJrwgi9q2IH+LcW/xUWMQ0hH+Mrk7wbKQB0RnJdXFoxphrfoVHBHMUu+TBPetUcEkKawkK1e7Cng==", + "requires": { + "@babel/core": "^7.14.0", + "babel-preset-fbjs": "^3.4.0", + "hermes-parser": "0.4.7", + "metro-babel-transformer": "0.66.2", + "metro-react-native-babel-preset": "0.66.2", + "metro-source-map": "0.66.2", + "nullthrows": "^1.1.1" + } + }, + "metro-resolver": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.66.2.tgz", + "integrity": "sha512-pXQAJR/xauRf4kWFj2/hN5a77B4jLl0Fom5I3PHp6Arw/KxSBp0cnguXpGLwNQ6zQC0nxKCoYGL9gQpzMnN7Hw==", + "requires": { + "absolute-path": "^0.0.0" + } + }, + "metro-runtime": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.66.2.tgz", + "integrity": "sha512-vFhKBk2ot9FS4b+2v0OTa/guCF/QDAOJubY0CNg7PzCS5+w4y3IvZIcPX4SSS1t8pYEZBLvtdtTDarlDl81xmg==" + }, + "metro-source-map": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.66.2.tgz", + "integrity": "sha512-038tFmB7vSh73VQcDWIbr5O1m+WXWyYafDaOy+1A/2K308YP0oj33gbEgDnZsLZDwcJ+xt1x6KUEBIzlX4YGeQ==", + "requires": { + "@babel/traverse": "^7.14.0", + "@babel/types": "^7.0.0", + "invariant": "^2.2.4", + "metro-symbolicate": "0.66.2", + "nullthrows": "^1.1.1", + "ob1": "0.66.2", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "metro-symbolicate": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.66.2.tgz", + "integrity": "sha512-u+DeQHyAFXVD7mVP+GST/894WHJ3i/U8oEJFnT7U3P52ZuLgX8n4tMNxhqZU12RcLR6etF8143aP0Ktx1gFLEQ==", + "requires": { + "invariant": "^2.2.4", + "metro-source-map": "0.66.2", + "nullthrows": "^1.1.1", + "source-map": "^0.5.6", + "through2": "^2.0.1", + "vlq": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "metro-transform-plugins": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.66.2.tgz", + "integrity": "sha512-KTvqplh0ut7oDKovvDG6yzXM02R6X+9b2oVG+qYq8Zd3aCGTi51ASx4ThCNkAHyEvCuJdYg9fxXTL+j+wvhB5w==", + "requires": { + "@babel/core": "^7.14.0", + "@babel/generator": "^7.14.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.14.0", + "nullthrows": "^1.1.1" + } + }, + "metro-transform-worker": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.66.2.tgz", + "integrity": "sha512-dO4PtYOMGB7Vzte8aIzX39xytODhmbJrBYPu+zYzlDjyefJZT7BkZ0LkPIThtyJi96xWcGqi9JBSo0CeRupAHw==", + "requires": { + "@babel/core": "^7.14.0", + "@babel/generator": "^7.14.0", + "@babel/parser": "^7.14.0", + "@babel/types": "^7.0.0", + "babel-preset-fbjs": "^3.4.0", + "metro": "0.66.2", + "metro-babel-transformer": "0.66.2", + "metro-cache": "0.66.2", + "metro-cache-key": "0.66.2", + "metro-hermes-compiler": "0.66.2", + "metro-source-map": "0.66.2", + "metro-transform-plugins": "0.66.2", + "nullthrows": "^1.1.1" + } + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { "version": "1.51.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "dev": true + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" }, "mime-types": { "version": "2.1.34", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dev": true, "requires": { "mime-db": "1.51.0" } @@ -2604,28 +5433,124 @@ "tiny-warning": "^1.0.3" } }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "nocache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz", + "integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q==" + }, + "node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha1-X1Zl2TNRM1yqvvjxxVRRbPXx5OU=", + "requires": { + "minimatch": "^3.0.2" + } + }, + "node-fetch": { + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz", + "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" }, "node-releases": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", - "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", - "dev": true + "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==" + }, + "node-stream-zip": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz", + "integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "npm-run-path": { "version": "4.0.1", @@ -2636,22 +5561,74 @@ "path-key": "^3.0.0" } }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "requires": { + "boolbase": "~1.0.0" + } + }, + "nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==" + }, + "ob1": { + "version": "0.66.2", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.66.2.tgz", + "integrity": "sha512-RFewnL/RjE0qQBOuM+2bbY96zmJPIge/aDtsiDbLSb+MOiK8CReAhBHDgL+zrA3F1hQk00lMWpUwYcep750plA==" + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + } }, "object.assign": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3", @@ -2659,6 +5636,35 @@ "object-keys": "^1.1.1" } }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, "onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", @@ -2668,11 +5674,46 @@ "mimic-fn": "^2.1.0" } }, + "open": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", + "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", + "requires": { + "is-wsl": "^1.1.0" + } + }, + "options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" + }, + "ora": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", + "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==", + "requires": { + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-spinners": "^2.0.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -2681,7 +5722,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, "requires": { "p-limit": "^2.2.0" } @@ -2689,8 +5729,7 @@ "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, "parent-module": { "version": "1.0.1", @@ -2711,11 +5750,25 @@ "lines-and-columns": "^1.1.6" } }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { "version": "3.1.1", @@ -2744,8 +5797,22 @@ "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "pirates": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.4.tgz", + "integrity": "sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw==" }, "pkg-dir": { "version": "4.2.0", @@ -2756,11 +5823,123 @@ "find-up": "^4.0.0" } }, + "plist": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.4.tgz", + "integrity": "sha512-ksrr8y9+nXOxQB2osVNqrgvX/XQPOXaU4BQMKjYq8PvaY1U18mo+fKgBSwzK+luSyinOuPae956lSVcBwxlAMg==", + "requires": { + "base64-js": "^1.5.1", + "xmlbuilder": "^9.0.7" + } + }, "popper.js": { "version": "1.16.1-lts", "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz", "integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==" }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "requires": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "promise": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", + "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==", + "requires": { + "asap": "~2.0.6" + } + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, "prop-types": { "version": "15.8.0", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.0.tgz", @@ -2778,12 +5957,26 @@ } } }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, + "qr.js": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", + "integrity": "sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8=" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -2793,6 +5986,11 @@ "safe-buffer": "^5.1.0" } }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, "react": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", @@ -2803,6 +6001,22 @@ "object-assign": "^4.1.1" } }, + "react-devtools-core": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.22.1.tgz", + "integrity": "sha512-pvpNDHE7p0FtcCmIWGazoY8LLVfBI9sw0Kf10kdHhPI9Tzt3OG/qEt16GrAbE0keuna5WzX3r1qPKVjqOqsuUg==", + "requires": { + "shell-quote": "^1.6.1", + "ws": "^7" + }, + "dependencies": { + "ws": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", + "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==" + } + } + }, "react-dom": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", @@ -2819,6 +6033,269 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "react-native": { + "version": "0.66.4", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.66.4.tgz", + "integrity": "sha512-9vx5dlSfQlKbbDtr8+xMon6qsmSu7jvjdXWZpEKh3XVKpUidbbODv7048gwVKX8YAel1egeR7hN8vzSeI6ssTw==", + "requires": { + "@jest/create-cache-key-function": "^27.0.1", + "@react-native-community/cli": "^6.0.0", + "@react-native-community/cli-platform-android": "^6.0.0", + "@react-native-community/cli-platform-ios": "^6.0.0", + "@react-native/assets": "1.0.0", + "@react-native/normalize-color": "1.0.0", + "@react-native/polyfills": "2.0.0", + "abort-controller": "^3.0.0", + "anser": "^1.4.9", + "base64-js": "^1.1.2", + "event-target-shim": "^5.0.1", + "hermes-engine": "~0.9.0", + "invariant": "^2.2.4", + "jsc-android": "^250230.2.1", + "metro-babel-register": "0.66.2", + "metro-react-native-babel-transformer": "0.66.2", + "metro-runtime": "0.66.2", + "metro-source-map": "0.66.2", + "nullthrows": "^1.1.1", + "pretty-format": "^26.5.2", + "promise": "^8.0.3", + "prop-types": "^15.7.2", + "react-devtools-core": "^4.13.0", + "react-native-codegen": "^0.0.7", + "react-refresh": "^0.4.0", + "regenerator-runtime": "^0.13.2", + "scheduler": "^0.20.2", + "stacktrace-parser": "^0.1.3", + "use-subscription": "^1.0.0", + "whatwg-fetch": "^3.0.0", + "ws": "^6.1.4" + }, + "dependencies": { + "@react-native-community/cli": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-6.3.1.tgz", + "integrity": "sha512-UQ77AkGvPzdwJt6qhYXUyDMP1v2rdCcIlrhU48FOcAhGX+N/LCL9Cp/Ic6CkiiSHJdktbgiEEJ2srprXH8nzVg==", + "requires": { + "@react-native-community/cli-debugger-ui": "^6.0.0-rc.0", + "@react-native-community/cli-hermes": "^6.3.0", + "@react-native-community/cli-plugin-metro": "^6.2.0", + "@react-native-community/cli-server-api": "^6.2.0", + "@react-native-community/cli-tools": "^6.2.0", + "@react-native-community/cli-types": "^6.0.0", + "appdirsjs": "^1.2.4", + "chalk": "^4.1.2", + "command-exists": "^1.2.8", + "commander": "^2.19.0", + "cosmiconfig": "^5.1.0", + "deepmerge": "^3.2.0", + "envinfo": "^7.7.2", + "execa": "^1.0.0", + "find-up": "^4.1.0", + "fs-extra": "^8.1.0", + "glob": "^7.1.3", + "graceful-fs": "^4.1.3", + "joi": "^17.2.1", + "leven": "^3.1.0", + "lodash": "^4.17.15", + "minimist": "^1.2.0", + "node-stream-zip": "^1.9.1", + "ora": "^3.4.0", + "pretty-format": "^26.6.2", + "prompts": "^2.4.0", + "semver": "^6.3.0", + "serve-static": "^1.13.1", + "strip-ansi": "^5.2.0", + "sudo-prompt": "^9.0.0", + "wcwidth": "^1.0.1" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "react-native-codegen": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/react-native-codegen/-/react-native-codegen-0.0.7.tgz", + "integrity": "sha512-dwNgR8zJ3ALr480QnAmpTiqvFo+rDtq6V5oCggKhYFlRjzOmVSFn3YD41u8ltvKS5G2nQ8gCs2vReFFnRGLYng==", + "requires": { + "flow-parser": "^0.121.0", + "jscodeshift": "^0.11.0", + "nullthrows": "^1.1.1" + } + }, + "react-native-svg": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-12.1.1.tgz", + "integrity": "sha512-NIAJ8jCnXGCqGWXkkJ1GTzO4a3Md5at5sagYV8Vh4MXYnL4z5Rh428Wahjhh+LIjx40EE5xM5YtwyJBqOIba2Q==", + "requires": { + "css-select": "^2.1.0", + "css-tree": "^1.0.0-alpha.39" + } + }, + "react-qr-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.0.3.tgz", + "integrity": "sha512-6GDH0l53lksf2JgZwwcoS0D60a1OAal/GQRyNFkMBW19HjSqvtD5S20scmSQsKl+BgWM85Wd5DCcUYoHd+PZnQ==", + "requires": { + "prop-types": "^15.7.2", + "qr.js": "0.0.0" + } + }, + "react-refresh": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz", + "integrity": "sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA==" + }, "react-router": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", @@ -2868,6 +6345,48 @@ "prop-types": "^15.6.2" } }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "readline": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", + "integrity": "sha1-xYDXfvLPyHUrEySYBg3JeTp6wBw=" + }, + "recast": { + "version": "0.20.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.20.5.tgz", + "integrity": "sha512-E5qICoPoNL4yU0H0NoBDntNB0Q5oMSNh9usFctYniLBluTthi3RsQVBXIJNbApOlvSwW/RGxIuokPcAc59J5fQ==", + "requires": { + "ast-types": "0.14.2", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tslib": "^2.0.1" + } + }, "rechoir": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", @@ -2880,14 +6399,12 @@ "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" }, "regenerate-unicode-properties": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz", "integrity": "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==", - "dev": true, "requires": { "regenerate": "^1.4.2" } @@ -2901,16 +6418,23 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", - "dev": true, "requires": { "@babel/runtime": "^7.8.4" } }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, "regexpu-core": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz", "integrity": "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==", - "dev": true, "requires": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^9.0.0", @@ -2923,14 +6447,12 @@ "regjsgen": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", - "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", - "dev": true + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" }, "regjsparser": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz", "integrity": "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==", - "dev": true, "requires": { "jsesc": "~0.5.0" }, @@ -2938,11 +6460,35 @@ "jsesc": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" } } }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, "resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -2972,17 +6518,284 @@ "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "dependencies": { + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "^1.0.0" + } + } + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + }, + "rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==" + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "~0.1.10" + } + }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, "scheduler": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", - "dev": true, "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -3002,8 +6815,54 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "send": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "1.8.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "serialize-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", + "integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=" }, "serialize-javascript": { "version": "6.0.0", @@ -3014,11 +6873,52 @@ "randombytes": "^2.1.0" } }, + "serve-static": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, "shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, "requires": { "kind-of": "^6.0.2" } @@ -3038,28 +6938,311 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "requires": { + "array-filter": "~0.0.0", + "array-map": "~0.0.0", + "array-reduce": "~0.0.0", + "jsonify": "~0.0.0" + } + }, "signal-exit": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", - "dev": true + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" + }, + "simple-plist": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.0.tgz", + "integrity": "sha512-uYWpeGFtZtVt2NhG4AHgpwx323zxD85x42heMJBan1qAiqqozIlaGrwrEt6kRjXWRWIXsuV1VLCvVmZan2B5dg==", + "requires": { + "bplist-creator": "0.1.0", + "bplist-parser": "0.3.0", + "plist": "^3.0.4" + } + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } }, "source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, + "source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "stackframe": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", + "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==" + }, + "stacktrace-parser": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", + "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", + "requires": { + "type-fest": "^0.7.1" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -3071,6 +7254,11 @@ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz", "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==" }, + "sudo-prompt": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz", + "integrity": "sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==" + }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -3086,6 +7274,22 @@ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true }, + "temp": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", + "requires": { + "os-tmpdir": "^1.0.0", + "rimraf": "~2.2.6" + }, + "dependencies": { + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + } + } + }, "terser": { "version": "5.10.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz", @@ -3118,6 +7322,20 @@ "terser": "^5.7.2" } }, + "throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, "tiny-invariant": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", @@ -3128,22 +7346,103 @@ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==" + }, + "uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "requires": { + "commander": "~2.13.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==" + } + } + }, + "ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" + }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" }, "unicode-match-property-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, "requires": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -3152,14 +7451,74 @@ "unicode-match-property-value-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", - "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", - "dev": true + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==" }, "unicode-property-aliases-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", - "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", - "dev": true + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==" + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + } + } }, "uri-js": { "version": "4.4.1", @@ -3170,11 +7529,62 @@ "punycode": "^2.1.0" } }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "use-subscription": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/use-subscription/-/use-subscription-1.5.1.tgz", + "integrity": "sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA==", + "requires": { + "object-assign": "^4.1.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, "value-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "vlq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", + "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==" + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "requires": { + "makeerror": "1.0.12" + } + }, "watchpack": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", @@ -3185,6 +7595,19 @@ "graceful-fs": "^4.1.2" } }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "requires": { + "defaults": "^1.0.3" + } + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, "webpack": { "version": "5.65.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.65.0.tgz", @@ -3261,6 +7684,20 @@ "integrity": "sha512-cp5qdmHnu5T8wRg2G3vZZHoJPN14aqQ89SyQ11NpGH5zEMDCclt49rzo+MaRazk7/UeILhAI+/sEtcM+7Fr0nw==", "dev": true }, + "whatwg-fetch": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3270,16 +7707,149 @@ "isexe": "^2.0.0" } }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, "wildcard": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", "dev": true }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xcode": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-2.1.0.tgz", + "integrity": "sha512-uCrmPITrqTEzhn0TtT57fJaNaw8YJs1aCzs+P/QqxsDbvPZSv7XMPPwXrKvHtD6pLjBM/NaVwraWJm8q83Y4iQ==", + "requires": { + "simple-plist": "^1.0.0", + "uuid": "^3.3.2" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "xmldoc": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/xmldoc/-/xmldoc-1.1.2.tgz", + "integrity": "sha512-ruPC/fyPNck2BD1dpz0AZZyrEwMOrWTO5lDdIXS91rs3wtm4j+T8Rp2o+zoOYkkAxJTZRPOSnOGei1egoRmKMQ==", + "requires": { + "sax": "^1.2.1" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, "yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } } diff --git a/frontend/package.json b/frontend/package.json index f687e275..a8f164ec 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -28,6 +28,9 @@ "@material-ui/icons": "^4.11.2", "@mui/system": "^5.2.6", "material-ui-image": "^3.3.2", + "react-native": "^0.66.4", + "react-native-svg": "^12.1.1", + "react-qr-code": "^2.0.3", "react-router-dom": "^5.2.0" } } diff --git a/frontend/src/components/OrderPage.js b/frontend/src/components/OrderPage.js index 8c806e93..9ad9415b 100644 --- a/frontend/src/components/OrderPage.js +++ b/frontend/src/components/OrderPage.js @@ -1,6 +1,7 @@ import React, { Component } from "react"; import { Paper, Button , Grid, Typography, List, ListItem, ListItemText, ListItemAvatar, Avatar, Divider} from "@material-ui/core" import { Link } from 'react-router-dom' +import TradeBox from "./TradeBox"; function msToTime(duration) { var seconds = Math.floor((duration / 1000) % 60), @@ -65,10 +66,15 @@ export default class OrderPage extends Component { makerNick: data.maker_nick, takerId: data.taker, takerNick: data.taker_nick, - isBuyer:data.buyer, - isSeller:data.seller, - expiresAt:data.expires_at, - badRequest:data.bad_request, + isMaker: data.is_maker, + isTaker: data.is_taker, + isBuyer: data.is_buyer, + isSeller: data.is_seller, + expiresAt: data.expires_at, + badRequest: data.bad_request, + bondInvoice: data.bond_invoice, + bondSatoshis: data.bond_satoshis, + badRequest: data.bad_request, }); }); } @@ -98,10 +104,8 @@ export default class OrderPage extends Component { .then((data) => (console.log(data) & this.getOrderDetails(data.id))); } - - - render (){ - return ( + orderBox=()=>{ + return( @@ -173,16 +177,47 @@ export default class OrderPage extends Component { - - - {this.state.isParticipant ? "" : } - - - - - - + + {/* Participants cannot see the Back or Take Order buttons */} + {this.state.isParticipant ? "" : + <> + + + + + + + + } + + ) + } + + + render (){ + return ( + this.state.badRequest ? +
+ + {this.state.badRequest}
+
+ +
+ : + (this.state.isParticipant ? + + + {this.orderBox()} + + + + + + : + + {this.orderBox()} + ) ); } } \ No newline at end of file diff --git a/frontend/src/components/TradeBox.js b/frontend/src/components/TradeBox.js index e69de29b..f7343d85 100644 --- a/frontend/src/components/TradeBox.js +++ b/frontend/src/components/TradeBox.js @@ -0,0 +1,64 @@ +import React, { Component } from "react"; +import { Paper, FormControl , Grid, Typography, FormHelperText, TextField} from "@material-ui/core" +import QRCode from "react-qr-code" + +export default class TradeBox extends Component { + constructor(props) { + super(props); + // props.state = null + this.data = this.props.data + } + + showInvoice=()=>{ + return ( + + + + Robots around here usually show commitment + + + + {this.data.isMaker ? + + Lock {this.data.bondSatoshis} Sats to PUBLISH order + + : + + Lock {this.data.bondSatoshis} Sats to TAKE the order + + } + + + + + + + + + ); + } + + render() { + return ( + + + + TradeBox + + + {this.data.bondInvoice ? this.showInvoice() : ""} + + + + ); + } +} \ No newline at end of file diff --git a/frontend/src/components/UserGenPage.js b/frontend/src/components/UserGenPage.js index ef7d9c98..060ca5a5 100644 --- a/frontend/src/components/UserGenPage.js +++ b/frontend/src/components/UserGenPage.js @@ -41,7 +41,7 @@ export default class UserGenPage extends Component { } getGeneratedUser() { - fetch('/api/usergen' + '?token=' + this.state.token) + fetch('/api/user' + '?token=' + this.state.token) .then((response) => response.json()) .then((data) => { this.setState({ diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js index acf69254..397e3bfc 100644 --- a/frontend/webpack.config.js +++ b/frontend/webpack.config.js @@ -29,4 +29,7 @@ module.exports = { }, }), ], + resolve: { + extensions: ['.ts', '.js'], + }, }; \ No newline at end of file diff --git a/setup.md b/setup.md index c1cbf307..ad945772 100644 --- a/setup.md +++ b/setup.md @@ -66,6 +66,7 @@ npm install react-router-dom@5.2.0 npm install @material-ui/icons npm install material-ui-image npm install @mui/system @emotion/react @emotion/styled +npm install qrcodejs ``` ### Launch the React render From 3a8e172a73f6a20db762d084c1edb3b4b59f80e4 Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Sat, 8 Jan 2022 07:34:09 -0800 Subject: [PATCH 09/29] Add maker waiting room --- frontend/src/components/OrderPage.js | 63 ++++++++++++++++++++++++++-- frontend/src/components/TradeBox.js | 54 +++++++++++++++++++++--- 2 files changed, 107 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/OrderPage.js b/frontend/src/components/OrderPage.js index 9ad9415b..a302ab8f 100644 --- a/frontend/src/components/OrderPage.js +++ b/frontend/src/components/OrderPage.js @@ -1,6 +1,5 @@ import React, { Component } from "react"; -import { Paper, Button , Grid, Typography, List, ListItem, ListItemText, ListItemAvatar, Avatar, Divider} from "@material-ui/core" -import { Link } from 'react-router-dom' +import { Paper, Button , Grid, Typography, List, ListItem, ListItemText, ListItemAvatar, Avatar, Divider, Box, LinearProgress} from "@material-ui/core" import TradeBox from "./TradeBox"; function msToTime(duration) { @@ -14,6 +13,33 @@ function msToTime(duration) { return hours + "h " + minutes + "m " + seconds + "s"; } +// TO DO fix Progress bar to go from 100 to 0, from total_expiration time, showing time_left +function LinearDeterminate() { + const [progress, setProgress] = React.useState(0); + + React.useEffect(() => { + const timer = setInterval(() => { + setProgress((oldProgress) => { + if (oldProgress === 0) { + return 100; + } + const diff = 1; + return Math.max(oldProgress - diff, 0); + }); + }, 500); + + return () => { + clearInterval(timer); + }; + }, []); + + return ( + + + + ); +} + function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { @@ -104,6 +130,20 @@ export default class OrderPage extends Component { .then((data) => (console.log(data) & this.getOrderDetails(data.id))); } + handleClickCancelOrderButton=()=>{ + console.log(this.state) + const requestOptions = { + method: 'POST', + headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),}, + body: JSON.stringify({ + 'action':'cancel', + }), + }; + fetch('/api/order/' + '?order_id=' + this.orderId, requestOptions) + .then((response) => response.json()) + .then((data) => (console.log(data) & this.getOrderDetails(data.id))); + } + orderBox=()=>{ return( @@ -150,7 +190,7 @@ export default class OrderPage extends Component { } - + @@ -170,10 +210,10 @@ export default class OrderPage extends Component { - + @@ -190,6 +230,21 @@ export default class OrderPage extends Component { } + + {/* Makers can cancel before commiting the bond (status 0)*/} + {this.state.isMaker & this.state.statusCode == 0 ? + + + + :""} + + {/* Takers can cancel before commiting the bond (status 3)*/} + {this.state.isTaker & this.state.statusCode == 3 ? + + + + :""} + ) } diff --git a/frontend/src/components/TradeBox.js b/frontend/src/components/TradeBox.js index f7343d85..1efceaab 100644 --- a/frontend/src/components/TradeBox.js +++ b/frontend/src/components/TradeBox.js @@ -1,11 +1,10 @@ import React, { Component } from "react"; -import { Paper, FormControl , Grid, Typography, FormHelperText, TextField} from "@material-ui/core" +import { Paper, FormControl , Grid, Typography, FormHelperText, TextField, List, ListItem, ListItemText, Divider} from "@material-ui/core" import QRCode from "react-qr-code" export default class TradeBox extends Component { constructor(props) { super(props); - // props.state = null this.data = this.props.data } @@ -29,7 +28,7 @@ export default class TradeBox extends Component { } - + ); } + showMakerWait=()=>{ + return ( + + + + Your order is public, wait for a taker. + + + + + + + + +

Be patient while robots check the book. + It might take some time. This box will ring 🔊 once a robot takes your order.

+

Please note that if your premium is too high, or if your currency or payment + methods are not popular, your order might expire untaken. Your bond will + return to you (no action needed).

+
+
+ + {/* TODO API sends data for a more confortable wait */} + + + + + + + + + + + + + + +
+
+
+ ) + } render() { return ( - + TradeBox {this.data.bondInvoice ? this.showInvoice() : ""} + {this.data.isMaker & this.data.statusCode == 1 ? this.showMakerWait() : ""} From 476fcf1d6f3e23e2e2146582eae8050af1a73d97 Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Sat, 8 Jan 2022 09:19:30 -0800 Subject: [PATCH 10/29] Add trade escrow box --- api/logics.py | 28 +++++++++++----------- api/views.py | 35 ++++++++++++++-------------- frontend/src/components/OrderPage.js | 4 +++- frontend/src/components/TradeBox.js | 27 +++++++++++++++++++++ 4 files changed, 63 insertions(+), 31 deletions(-) diff --git a/api/logics.py b/api/logics.py index 7fad23ec..83b06a90 100644 --- a/api/logics.py +++ b/api/logics.py @@ -260,22 +260,26 @@ class Logics(): payment_hash = payment_hash, expires_at = expires_at) + # Extend expiry time to allow for escrow deposit + ## Not here, on func for confirming taker collar. order.expires_at = timezone.now() + timedelta(minutes=EXP_TRADE_ESCR_INVOICE) + order.save() return True, {'bond_invoice':invoice,'bond_satoshis': bond_satoshis} @classmethod def gen_escrow_hodl_invoice(cls, order, user): - # Do not generate and cancel if an invoice is there and older than X minutes and unpaid still + print('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA') if order.trade_escrow: # Check if status is INVGEN and still not expired - if order.taker_bond.status == LNPayment.Status.INVGEN: - if order.taker_bond.created_at > (timezone.now()+timedelta(minutes=EXP_TRADE_ESCR_INVOICE)): # Expired + if order.trade_escrow.status == LNPayment.Status.INVGEN: + print('CCCCCCCCCCCCCCCCCCC') + if order.trade_escrow.created_at > (timezone.now()+timedelta(minutes=EXP_TRADE_ESCR_INVOICE)): # Expired cls.cancel_order(order, user, 4) # State 4, cancel order before trade escrow locked return False, {'bad_request':'Invoice expired. You did not lock the trade escrow in time.'} # Return the previous invoice there was with INVGEN status else: - return True, {'escrow_invoice':order.trade_escrow.invoice,'escrow_satoshis':order.trade_escrow.num_satoshis} + return True, {'escrow_invoice': order.trade_escrow.invoice, 'escrow_satoshis':order.trade_escrow.num_satoshis} # Invoice exists, but was already locked or settled else: return False, None # Does not return any context of a healthy locked escrow @@ -286,7 +290,7 @@ class Logics(): # Gen HODL Invoice invoice, payment_hash, expires_at = LNNode.gen_hodl_invoice(escrow_satoshis, description, ESCROW_EXPIRY*3600) - order.taker_bond = LNPayment.objects.create( + order.trade_escrow = LNPayment.objects.create( concept = LNPayment.Concepts.TRESCROW, type = LNPayment.Types.HODL, sender = user, @@ -325,7 +329,7 @@ class Logics(): # If buyer, settle escrow and mark fiat sent if cls.is_buyer(order, user): - if cls.settle_escrow(order): # KEY LINE - SETTLES THE TRADE ESCROW !! + if cls.settle_escrow(order): ##### !!! KEY LINE - SETTLES THE TRADE ESCROW !!! order.trade_escrow.status = LNPayment.Status.SETLED order.status = Order.Status.FSE order.is_fiat_sent = True @@ -335,15 +339,13 @@ class Logics(): if not order.is_fiat_sent: return False, {'bad_request':'You cannot confirm to have received the fiat before it is confirmed to be sent by the buyer.'} + # Make sure the trade escrow is at least as big as the buyer invoice + if order.trade_escrow.num_satoshis <= order.buyer_invoice.num_satoshis: + return False, {'bad_request':'Woah, something broke badly. Report in the public channels, or open a Github Issue.'} + # Double check the escrow is settled. if LNNode.double_check_htlc_is_settled(order.trade_escrow.payment_hash): - - # Make sure the trade escrow is at least as big as the buyer invoice - if order.trade_escrow.num_satoshis <= order.buyer_invoice.num_satoshis: - return False, {'bad_request':'Woah, something broke badly. Report in the public channels, or open a Github Issue.'} - - # Double check the trade escrow is settled - elif cls.pay_buyer_invoice(order): # KEY LINE - PAYS THE BUYER !! + if cls.pay_buyer_invoice(order): ##### !!! KEY LINE - PAYS THE BUYER INVOICE !!! order.status = Order.Status.PAY order.buyer_invoice.status = LNPayment.Status.PAYING else: diff --git a/api/views.py b/api/views.py index d8ccf874..addb763e 100644 --- a/api/views.py +++ b/api/views.py @@ -152,27 +152,27 @@ class OrderView(viewsets.ViewSet): else: return Response(context, status.HTTP_400_BAD_REQUEST) - # 7) If status is 'WF2'or'WTC' - elif (order.status == Order.Status.WF2 or order.status == Order.Status.WFE): + # 7 a. ) If seller and status is 'WF2' or 'WFE' + elif data['is_seller'] and (order.status == Order.Status.WF2 or order.status == Order.Status.WFE): - # If the two bonds are locked + # If the two bonds are locked, reply with an ESCROW HODL invoice. if order.maker_bond.status == order.taker_bond.status == LNPayment.Status.LOCKED: + valid, context = Logics.gen_escrow_hodl_invoice(order, request.user) + if valid: + data = {**data, **context} + else: + return Response(context, status.HTTP_400_BAD_REQUEST) - # 7.a) And if user is Seller, reply with an ESCROW HODL invoice. - if data['is_seller']: - valid, context = Logics.gen_escrow_hodl_invoice(order, request.user) - if valid: - data = {**data, **context} - else: - return Response(context, status.HTTP_400_BAD_REQUEST) + # 7.b) If user is Buyer and status is 'WF2' or 'WFI' + elif data['is_buyer'] and (order.status == Order.Status.WF2 or order.status == Order.Status.WFI): - # 7.b) If user is Buyer, reply with an AMOUNT so he can send the buyer invoice. - elif data['is_buyer']: - valid, context = Logics.buyer_invoice_amount(order, request.user) - if valid: - data = {**data, **context} - else: - return Response(context, status.HTTP_400_BAD_REQUEST) + # If the two bonds are locked, reply with an AMOUNT so he can send the buyer invoice. + if order.maker_bond.status == order.taker_bond.status == LNPayment.Status.LOCKED: + valid, context = Logics.buyer_invoice_amount(order, request.user) + if valid: + data = {**data, **context} + else: + return Response(context, status.HTTP_400_BAD_REQUEST) # 8) If status is 'CHA'or '' or '' and all HTLCS are in LOCKED elif order.status == Order.Status.CHA: # TODO Add the other status @@ -365,6 +365,7 @@ class BookView(ListAPIView): # Non participants should not see the status or who is the taker for key in ('status','taker'): del data[key] + book_data.append(data) return Response(book_data, status=status.HTTP_200_OK) diff --git a/frontend/src/components/OrderPage.js b/frontend/src/components/OrderPage.js index a302ab8f..f0dcb309 100644 --- a/frontend/src/components/OrderPage.js +++ b/frontend/src/components/OrderPage.js @@ -100,6 +100,8 @@ export default class OrderPage extends Component { badRequest: data.bad_request, bondInvoice: data.bond_invoice, bondSatoshis: data.bond_satoshis, + escrowInvoice: data.escrow_invoice, + escrowSatoshis: data.escrow_satoshis, badRequest: data.bad_request, }); }); @@ -211,7 +213,7 @@ export default class OrderPage extends Component { - + diff --git a/frontend/src/components/TradeBox.js b/frontend/src/components/TradeBox.js index 1efceaab..90e0e407 100644 --- a/frontend/src/components/TradeBox.js +++ b/frontend/src/components/TradeBox.js @@ -45,6 +45,32 @@ export default class TradeBox extends Component { ); } + showEscrowInvoice=()=>{ + return ( + + + + Deposit {this.data.escrowSatoshis} Sats as trade collateral + + + + + + + + + + ); + } + showMakerWait=()=>{ return ( @@ -98,6 +124,7 @@ export default class TradeBox extends Component { {this.data.bondInvoice ? this.showInvoice() : ""} {this.data.isMaker & this.data.statusCode == 1 ? this.showMakerWait() : ""} + {this.data.isSeller & this.data.escrowInvoice != null ? this.showEscrowInvoice() : ""} From cf2422f924cfaa05ddf048b72175889849b4757b Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Sat, 8 Jan 2022 12:14:19 -0800 Subject: [PATCH 11/29] Small fixes --- api/logics.py | 2 -- frontend/src/components/OrderPage.js | 2 +- frontend/src/components/UserGenPage.js | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/api/logics.py b/api/logics.py index 83b06a90..ec56372f 100644 --- a/api/logics.py +++ b/api/logics.py @@ -269,11 +269,9 @@ class Logics(): @classmethod def gen_escrow_hodl_invoice(cls, order, user): # Do not generate and cancel if an invoice is there and older than X minutes and unpaid still - print('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA') if order.trade_escrow: # Check if status is INVGEN and still not expired if order.trade_escrow.status == LNPayment.Status.INVGEN: - print('CCCCCCCCCCCCCCCCCCC') if order.trade_escrow.created_at > (timezone.now()+timedelta(minutes=EXP_TRADE_ESCR_INVOICE)): # Expired cls.cancel_order(order, user, 4) # State 4, cancel order before trade escrow locked return False, {'bad_request':'Invoice expired. You did not lock the trade escrow in time.'} diff --git a/frontend/src/components/OrderPage.js b/frontend/src/components/OrderPage.js index f0dcb309..e7196d1a 100644 --- a/frontend/src/components/OrderPage.js +++ b/frontend/src/components/OrderPage.js @@ -151,7 +151,7 @@ export default class OrderPage extends Component { - BTC {this.state.type ? " Sell " : " Buy "} Order + {this.state.type ? "Sell " : "Buy "} Order Details diff --git a/frontend/src/components/UserGenPage.js b/frontend/src/components/UserGenPage.js index 060ca5a5..fd80749c 100644 --- a/frontend/src/components/UserGenPage.js +++ b/frontend/src/components/UserGenPage.js @@ -143,7 +143,7 @@ export default class UserGenPage extends Component { - Easy and Private Lightning peer-to-peer Exchange + Simple and Private Lightning peer-to-peer Exchange From 71107a7432f6b38ecbbb9d4789647bee64b5acff Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Sat, 8 Jan 2022 17:23:13 -0800 Subject: [PATCH 12/29] Refresh orders --- api/views.py | 2 +- frontend/src/components/OrderPage.js | 30 +++++++++++++++-- frontend/src/components/TradeBox.js | 49 +++++++++++++++++++++++++++- 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/api/views.py b/api/views.py index addb763e..511891c9 100644 --- a/api/views.py +++ b/api/views.py @@ -372,7 +372,7 @@ class BookView(ListAPIView): class InfoView(ListAPIView): - def get(self): + def get(self, request): context = {} context['num_public_buy_orders'] = len(Order.objects.filter(type=Order.Types.BUY, status=Order.Status.PUB)) diff --git a/frontend/src/components/OrderPage.js b/frontend/src/components/OrderPage.js index e7196d1a..8521918f 100644 --- a/frontend/src/components/OrderPage.js +++ b/frontend/src/components/OrderPage.js @@ -67,15 +67,18 @@ export default class OrderPage extends Component { super(props); this.state = { isExplicit: false, + delay: 5000, // Refresh every 5 seconds }; this.orderId = this.props.match.params.orderId; this.getOrderDetails(); } getOrderDetails() { + this.setState(null) fetch('/api/order' + '?order_id=' + this.orderId) .then((response) => response.json()) .then((data) => { + console.log(data) & this.setState({ statusCode: data.status, statusText: data.status_message, @@ -107,6 +110,29 @@ export default class OrderPage extends Component { }); } + + // These are used to refresh the data + componentDidMount() { + this.interval = setInterval(this.tick, this.state.delay); + } + componentDidUpdate(prevProps, prevState) { + if (prevState.delay !== this.state.delay) { + clearInterval(this.interval); + this.interval = setInterval(this.tick, this.state.delay); + } + } + componentWillUnmount() { + clearInterval(this.interval); + } + tick = () => { + this.getOrderDetails(); + } + handleDelayChange = (e) => { + this.setState({ delay: Number(e.target.value) }); + } + + + // Gets currency code (3 letters) from numeric (e.g., 1 -> USD) // Improve this function so currencies are read from json getCurrencyCode(val){ @@ -162,7 +188,7 @@ export default class OrderPage extends Component { src={window.location.origin +'/static/assets/avatars/' + this.state.makerNick + '.png'} /> - + @@ -171,7 +197,7 @@ export default class OrderPage extends Component { {this.state.takerNick!='None' ? <> - + { + this.setState({ delay: Number(e.target.value) }); + } + tick = () => { + this.data = this.props.data; + } + showInvoice=()=>{ return ( @@ -71,6 +96,27 @@ export default class TradeBox extends Component { ); } + showTakerFound=()=>{ + + // Make some sound here! The maker might have been waiting for long + + return ( + + + + A taker has been found! + + + + + + Please wait for the taker to confirm his commitment by locking a bond. + + + + ); + } + showMakerWait=()=>{ return ( @@ -124,6 +170,7 @@ export default class TradeBox extends Component { {this.data.bondInvoice ? this.showInvoice() : ""} {this.data.isMaker & this.data.statusCode == 1 ? this.showMakerWait() : ""} + {this.data.isMaker & this.data.statusCode == 3 ? this.showTakerFound() : ""} {this.data.isSeller & this.data.escrowInvoice != null ? this.showEscrowInvoice() : ""} From 198f551ad618887bd83aa43f36fb7a385cbacc64 Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Sun, 9 Jan 2022 04:14:11 -0800 Subject: [PATCH 13/29] Work tradebox logics --- frontend/src/components/HomePage.js | 4 -- frontend/src/components/LoginPage.js | 11 ---- frontend/src/components/OrderPage.js | 1 + frontend/src/components/TradeBox.js | 61 +++++++++++++++++++--- frontend/src/components/WaitingRoomPage.js | 11 ---- 5 files changed, 56 insertions(+), 32 deletions(-) delete mode 100644 frontend/src/components/LoginPage.js delete mode 100644 frontend/src/components/WaitingRoomPage.js diff --git a/frontend/src/components/HomePage.js b/frontend/src/components/HomePage.js index 921c73ba..ed544801 100644 --- a/frontend/src/components/HomePage.js +++ b/frontend/src/components/HomePage.js @@ -2,11 +2,9 @@ import React, { Component } from "react"; import { BrowserRouter as Router, Switch, Route, Link, Redirect } from "react-router-dom"; import UserGenPage from "./UserGenPage"; -import LoginPage from "./LoginPage.js"; import MakerPage from "./MakerPage"; import BookPage from "./BookPage"; import OrderPage from "./OrderPage"; -import WaitingRoomPage from "./WaitingRoomPage"; export default class HomePage extends Component { constructor(props) { @@ -19,11 +17,9 @@ export default class HomePage extends Component {

You are at the start page

- -
); diff --git a/frontend/src/components/LoginPage.js b/frontend/src/components/LoginPage.js deleted file mode 100644 index 562bcabf..00000000 --- a/frontend/src/components/LoginPage.js +++ /dev/null @@ -1,11 +0,0 @@ -import React, { Component } from "react"; - -export default class LoginPage extends Component { - constructor(props) { - super(props); - } - - render() { - return

This is the login page

; - } -} \ No newline at end of file diff --git a/frontend/src/components/OrderPage.js b/frontend/src/components/OrderPage.js index 8521918f..4030915b 100644 --- a/frontend/src/components/OrderPage.js +++ b/frontend/src/components/OrderPage.js @@ -105,6 +105,7 @@ export default class OrderPage extends Component { bondSatoshis: data.bond_satoshis, escrowInvoice: data.escrow_invoice, escrowSatoshis: data.escrow_satoshis, + invoiceAmount: data.invoice_amount, badRequest: data.bad_request, }); }); diff --git a/frontend/src/components/TradeBox.js b/frontend/src/components/TradeBox.js index 0626a151..eb819bf3 100644 --- a/frontend/src/components/TradeBox.js +++ b/frontend/src/components/TradeBox.js @@ -6,7 +6,7 @@ export default class TradeBox extends Component { constructor(props) { super(props); this.state = { - delay: 5000, // Refresh every 5 seconds + delay: 100, // checks for new state in OrderPage ever 100 ms }; this.data = this.props.data } @@ -33,7 +33,7 @@ export default class TradeBox extends Component { this.data = this.props.data; } - showInvoice=()=>{ + showQRInvoice=()=>{ return ( @@ -70,7 +70,7 @@ export default class TradeBox extends Component { ); } - showEscrowInvoice=()=>{ + showEscrowQRInvoice=()=>{ return ( @@ -88,7 +88,7 @@ export default class TradeBox extends Component { size="small" defaultValue={this.data.escrowInvoice} disabled="true" - helperText="This is a HODL LN invoice. It will be charged once you confirm you have received the fiat." + helperText="This is a HODL LN invoice. It will be charged once the buyer confirms he sent the fiat." color = "secondary" /> @@ -160,6 +160,33 @@ export default class TradeBox extends Component { ) } + showInputInvoice(){ + + } + + showWaitingForEscrow(){ + + } + showWaitingForBuyerInvoice({ + + }) + + showFiatSentButton(){ + + } + showFiatReceivedButton(){ + + } + + showOpenDisputeButton(){ + + } + + showRateSelect(){ + + } + + render() { return ( @@ -168,10 +195,32 @@ export default class TradeBox extends Component { TradeBox - {this.data.bondInvoice ? this.showInvoice() : ""} + {/* Maker and taker Bond request */} + {this.data.bondInvoice ? this.showQRInvoice() : ""} + + {/* Waiting for taker and taker bond request */} {this.data.isMaker & this.data.statusCode == 1 ? this.showMakerWait() : ""} {this.data.isMaker & this.data.statusCode == 3 ? this.showTakerFound() : ""} - {this.data.isSeller & this.data.escrowInvoice != null ? this.showEscrowInvoice() : ""} + + {/* Send Invoice (buyer) and deposit collateral (seller) */} + {this.data.isSeller & this.data.escrowInvoice != null ? this.showEscrowQRInvoice() : ""} + {this.data.isBuyer & this.data.invoiceAmount != null ? this.showInputInvoice() : ""} + {this.data.isBuyer & this.data.statusCode == 7 ? this.showWaitingForEscrow() : ""} + {this.data.isSeller & this.data.statusCode == 8 ? this.showWaitingForBuyerInvoice() : ""} + + {/* In Chatroom */} + {this.data.isBuyer & this.data.statusCode == 9 ? this.showChat() & this.showFiatSentButton() : ""} + {this.data.isSeller & this.data.statusCode ==9 ? this.showChat() : ""} + {this.data.isBuyer & this.data.statusCode == 10 ? this.showChat() & this.showOpenDisputeButton() : ""} + {this.data.isSeller & this.data.statusCode == 10 ? this.showChat() & this.showFiatReceivedButton() & this.showOpenDisputeButton(): ""} + + {/* Trade Finished */} + {this.data.isSeller & this.data.statusCode > 12 & this.data.statusCode < 15 ? this.showRateSelect() : ""} + {/* TODO */} + {/* */} + {/* */} + + diff --git a/frontend/src/components/WaitingRoomPage.js b/frontend/src/components/WaitingRoomPage.js deleted file mode 100644 index a6563693..00000000 --- a/frontend/src/components/WaitingRoomPage.js +++ /dev/null @@ -1,11 +0,0 @@ -import React, { Component } from "react"; - -export default class WaitingRoomPage extends Component { - constructor(props) { - super(props); - } - - render() { - return

This is the waiting room

; - } -} \ No newline at end of file From 5dcb249bb38606de4b657ff63af334c9efbf106a Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Sun, 9 Jan 2022 06:07:05 -0800 Subject: [PATCH 14/29] Invoice input --- api/models.py | 1 - frontend/src/components/OrderPage.js | 9 +- frontend/src/components/TradeBox.js | 155 ++++++++++++++++++--------- setup.md | 4 +- 4 files changed, 110 insertions(+), 59 deletions(-) diff --git a/api/models.py b/api/models.py index 359ba096..5ec761cb 100644 --- a/api/models.py +++ b/api/models.py @@ -86,7 +86,6 @@ class Order(models.Model): currency_dict = json.load(open('./api/currencies.json')) currency_choices = [(int(val), label) for val, label in list(currency_dict.items())] - print(currency_choices) # order info status = models.PositiveSmallIntegerField(choices=Status.choices, null=False, default=Status.WFB) diff --git a/frontend/src/components/OrderPage.js b/frontend/src/components/OrderPage.js index 9eff532f..6bed6553 100644 --- a/frontend/src/components/OrderPage.js +++ b/frontend/src/components/OrderPage.js @@ -67,7 +67,7 @@ export default class OrderPage extends Component { super(props); this.state = { isExplicit: false, - delay: 5000, // Refresh every 5 seconds + delay: 10000, // Refresh every 10 seconds currencies_dict: {"1":"USD"} }; this.orderId = this.props.match.params.orderId; @@ -79,8 +79,9 @@ export default class OrderPage extends Component { this.setState(null) fetch('/api/order' + '?order_id=' + this.orderId) .then((response) => response.json()) - .then((data) => { + .then((data) => {console.log(data) & this.setState({ + id: data.id, statusCode: data.status, statusText: data.status_message, type: data.type, @@ -203,7 +204,7 @@ export default class OrderPage extends Component { src={window.location.origin +'/static/assets/avatars/' + this.state.makerNick + '.png'} />
- +
@@ -212,7 +213,7 @@ export default class OrderPage extends Component { {this.state.takerNick!='None' ? <> - + { - this.setState({ delay: Number(e.target.value) }); - } - tick = () => { - this.data = this.props.data; } showQRInvoice=()=>{ @@ -42,25 +38,25 @@ export default class TradeBox extends Component { - {this.data.isMaker ? + {this.props.data.isMaker ? - Lock {this.data.bondSatoshis} Sats to PUBLISH order + Lock {pn(this.props.data.bondSatoshis)} Sats to PUBLISH order : - Lock {this.data.bondSatoshis} Sats to TAKE the order + Lock {pn(this.props.data.bondSatoshis)} Sats to TAKE the order } - + - Deposit {this.data.escrowSatoshis} Sats as trade collateral + Deposit {pn(this.props.data.escrowSatoshis)} Sats as trade collateral - + { - // Make some sound here! The maker might have been waiting for long + // TODO Make some sound here! The maker might have been waiting for long return ( @@ -147,7 +143,7 @@ export default class TradeBox extends Component { - + @@ -160,13 +156,66 @@ export default class TradeBox extends Component { ) } - // showInputInvoice(){ + handleInputInvoiceChanged=(e)=>{ + this.setState({ + invoice: e.target.value, + }); + } - // } + handleClickSubmitInvoiceButton=()=>{ + console.log(this.state) + const requestOptions = { + method: 'POST', + headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),}, + body: JSON.stringify({ + 'action':'update_invoice', + 'invoice': this.state.invoice, + }), + }; + fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions) + .then((response) => response.json()) + .then((data) => (this.props.data = data)); + } - // showWaitingForEscrow(){ + showInputInvoice(){ + return ( - // } + // TODO Camera option to read QR + + + + + Submit a LN invoice for {pn(this.props.data.invoiceAmount)} Sats + + + + + The taker is committed! Before letting you send {" "+ parseFloat(parseFloat(this.props.data.amount).toFixed(4))+ + " "+ this.props.data.currencyCode}, we want to make sure you are able to receive the BTC. Please provide a + valid invoice for {pn(this.props.data.invoiceAmount)} Satoshis. + + + + + + + + + + ) + } + + showWaitingForEscrow(){ + + } // showWaitingForBuyerInvoice({ // }) @@ -196,26 +245,26 @@ export default class TradeBox extends Component { {/* Maker and taker Bond request */} - {this.data.bondInvoice ? this.showQRInvoice() : ""} + {this.props.data.bondInvoice ? this.showQRInvoice() : ""} {/* Waiting for taker and taker bond request */} - {this.data.isMaker & this.data.statusCode == 1 ? this.showMakerWait() : ""} - {this.data.isMaker & this.data.statusCode == 3 ? this.showTakerFound() : ""} + {this.props.data.isMaker & this.props.data.statusCode == 1 ? this.showMakerWait() : ""} + {this.props.data.isMaker & this.props.data.statusCode == 3 ? this.showTakerFound() : ""} {/* Send Invoice (buyer) and deposit collateral (seller) */} - {this.data.isSeller & this.data.escrowInvoice != null ? this.showEscrowQRInvoice() : ""} - {this.data.isBuyer & this.data.invoiceAmount != null ? this.showInputInvoice() : ""} - {this.data.isBuyer & this.data.statusCode == 7 ? this.showWaitingForEscrow() : ""} - {this.data.isSeller & this.data.statusCode == 8 ? this.showWaitingForBuyerInvoice() : ""} + {this.props.data.isSeller & this.props.data.escrowInvoice != null ? this.showEscrowQRInvoice() : ""} + {this.props.data.isBuyer & this.props.data.invoiceAmount != null ? this.showInputInvoice() : ""} + {this.props.data.isBuyer & this.props.data.statusCode == 7 ? this.showWaitingForEscrow() : ""} + {this.props.data.isSeller & this.props.data.statusCode == 8 ? this.showWaitingForBuyerInvoice() : ""} {/* In Chatroom */} - {this.data.isBuyer & this.data.statusCode == 9 ? this.showChat() & this.showFiatSentButton() : ""} - {this.data.isSeller & this.data.statusCode ==9 ? this.showChat() : ""} - {this.data.isBuyer & this.data.statusCode == 10 ? this.showChat() & this.showOpenDisputeButton() : ""} - {this.data.isSeller & this.data.statusCode == 10 ? this.showChat() & this.showFiatReceivedButton() & this.showOpenDisputeButton(): ""} + {this.props.data.isBuyer & this.props.data.statusCode == 9 ? this.showChat() & this.showFiatSentButton() : ""} + {this.props.data.isSeller & this.props.data.statusCode ==9 ? this.showChat() : ""} + {this.props.data.isBuyer & this.props.data.statusCode == 10 ? this.showChat() & this.showOpenDisputeButton() : ""} + {this.props.data.isSeller & this.props.data.statusCode == 10 ? this.showChat() & this.showFiatReceivedButton() & this.showOpenDisputeButton(): ""} {/* Trade Finished */} - {this.data.isSeller & this.data.statusCode > 12 & this.data.statusCode < 15 ? this.showRateSelect() : ""} + {this.props.data.isSeller & this.props.data.statusCode > 12 & this.props.data.statusCode < 15 ? this.showRateSelect() : ""} {/* TODO */} {/* */} {/* */} diff --git a/setup.md b/setup.md index ad945772..0a5d2b40 100644 --- a/setup.md +++ b/setup.md @@ -66,7 +66,9 @@ npm install react-router-dom@5.2.0 npm install @material-ui/icons npm install material-ui-image npm install @mui/system @emotion/react @emotion/styled -npm install qrcodejs +npm install react-native +npm install react-native-svg +npm install react-qr-code ``` ### Launch the React render From 229294b878f0761ec4ba74bca5d04bd413c4e77a Mon Sep 17 00:00:00 2001 From: LowEntropyFace Date: Sun, 9 Jan 2022 09:29:10 -0500 Subject: [PATCH 15/29] change currencies.json access, fix async book filtering --- api/models.py | 2 +- api/urls.py | 3 +-- api/views.py | 8 -------- frontend/src/components/BookPage.js | 18 ++++++++---------- frontend/src/components/MakerPage.js | 2 +- frontend/src/components/OrderPage.js | 14 ++------------ .../static/assets}/currencies.json | 0 frontend/urls.py | 1 - 8 files changed, 13 insertions(+), 35 deletions(-) rename {api => frontend/static/assets}/currencies.json (100%) diff --git a/api/models.py b/api/models.py index 359ba096..dfc86a9b 100644 --- a/api/models.py +++ b/api/models.py @@ -84,7 +84,7 @@ class Order(models.Model): MLD = 16, 'Maker lost dispute' TLD = 17, 'Taker lost dispute' - currency_dict = json.load(open('./api/currencies.json')) + currency_dict = json.load(open('./frontend/static/assets/currencies.json')) currency_choices = [(int(val), label) for val, label in list(currency_dict.items())] print(currency_choices) diff --git a/api/urls.py b/api/urls.py index 172994dd..563fb14c 100644 --- a/api/urls.py +++ b/api/urls.py @@ -1,5 +1,5 @@ from django.urls import path -from .views import MakerView, OrderView, UserView, BookView, InfoView, get_currencies_json +from .views import MakerView, OrderView, UserView, BookView, InfoView urlpatterns = [ path('make/', MakerView.as_view()), @@ -8,5 +8,4 @@ urlpatterns = [ path('book/', BookView.as_view()), # path('robot/') # Profile Info path('info/', InfoView.as_view()), - path('currencies/', get_currencies_json), ] \ No newline at end of file diff --git a/api/views.py b/api/views.py index 4215f793..ed6dab9e 100644 --- a/api/views.py +++ b/api/views.py @@ -21,9 +21,6 @@ from datetime import timedelta from django.utils import timezone from decouple import config -import json -from django.http import HttpResponse - EXP_MAKER_BOND_INVOICE = int(config('EXP_MAKER_BOND_INVOICE')) FEE = float(config('FEE')) @@ -386,10 +383,5 @@ class InfoView(ListAPIView): context['total_volume'] = None return Response(context, status.HTTP_200_OK) - -def get_currencies_json(request): - currency_dict = json.load(open('./api/currencies.json')) - return HttpResponse(json.dumps(currency_dict),content_type="application/json") - diff --git a/frontend/src/components/BookPage.js b/frontend/src/components/BookPage.js index 10a591ae..c119b37b 100644 --- a/frontend/src/components/BookPage.js +++ b/frontend/src/components/BookPage.js @@ -12,15 +12,15 @@ export default class BookPage extends Component { currencies_dict: {"1":"USD"} }; this.getCurrencyDict() - this.getOrderDetails() + this.getOrderDetails(this.state.type,this.state.currency) this.state.currencyCode = this.getCurrencyCode(this.state.currency) } // Show message to be the first one to make an order - getOrderDetails() { - fetch('/api/book' + '?currency=' + this.state.currency + "&type=" + this.state.type) + getOrderDetails(type,currency) { + fetch('/api/book' + '?currency=' + currency + "&type=" + type) .then((response) => response.json()) - .then((data) => //console.log(data)); + .then((data) => this.setState({ orders: data, not_found: data.not_found, @@ -32,31 +32,29 @@ export default class BookPage extends Component { this.props.history.push('/order/' + e); } - // Make these two functions sequential. getOrderDetails needs setState to be finish beforehand. handleTypeChange=(e)=>{ this.setState({ type: e.target.value, }); - this.getOrderDetails(); + this.getOrderDetails(e.target.value,this.state.currency); } handleCurrencyChange=(e)=>{ this.setState({ currency: e.target.value, currencyCode: this.getCurrencyCode(e.target.value), }) - this.getOrderDetails(); + this.getOrderDetails(this.state.type, e.target.value); } getCurrencyDict() { - fetch('/api/currencies') + fetch('/static/assets/currencies.json') .then((response) => response.json()) .then((data) => this.setState({ currencies_dict: data })); } - // Gets currency code (3 letters) from numeric (e.g., 1 -> USD) - // Improve this function so currencies are read from json + getCurrencyCode(val){ return this.state.currencies_dict[val.toString()] } diff --git a/frontend/src/components/MakerPage.js b/frontend/src/components/MakerPage.js index 5bd46427..68191be7 100644 --- a/frontend/src/components/MakerPage.js +++ b/frontend/src/components/MakerPage.js @@ -110,7 +110,7 @@ export default class MakerPage extends Component { } getCurrencyDict() { - fetch('/api/currencies') + fetch('/static/assets/currencies.json') .then((response) => response.json()) .then((data) => this.setState({ diff --git a/frontend/src/components/OrderPage.js b/frontend/src/components/OrderPage.js index 9eff532f..03045456 100644 --- a/frontend/src/components/OrderPage.js +++ b/frontend/src/components/OrderPage.js @@ -132,12 +132,6 @@ export default class OrderPage extends Component { this.setState({ delay: Number(e.target.value) }); } - // Gets currency code (3 letters) from numeric (e.g., 1 -> USD) - // Improve this function so currencies are read from json - getCurrencyCode(val){ - return (val == 1 ) ? "USD": ((val == 2 ) ? "EUR":"ETH") - } - // Fix to use proper react props handleClickBackButton=()=>{ window.history.back(); @@ -157,7 +151,7 @@ export default class OrderPage extends Component { .then((data) => (console.log(data) & this.getOrderDetails(data.id))); } getCurrencyDict() { - fetch('/api/currencies') + fetch('/static/assets/currencies.json') .then((response) => response.json()) .then((data) => this.setState({ @@ -165,11 +159,7 @@ export default class OrderPage extends Component { })); } - // Gets currency code (3 letters) from numeric (e.g., 1 -> USD) - // Improve this function so currencies are read from json getCurrencyCode(val){ - console.log("---------------------------------") - console.log(val) return this.state.currencies_dict[val.toString()] } @@ -318,4 +308,4 @@ export default class OrderPage extends Component { ) ); } -} \ No newline at end of file +} diff --git a/api/currencies.json b/frontend/static/assets/currencies.json similarity index 100% rename from api/currencies.json rename to frontend/static/assets/currencies.json diff --git a/frontend/urls.py b/frontend/urls.py index d7b68630..e938dc97 100644 --- a/frontend/urls.py +++ b/frontend/urls.py @@ -9,5 +9,4 @@ urlpatterns = [ path('book/', index), path('order/', index), path('wait/', index), - path('currencies/',index) ] \ No newline at end of file From aa8e1f50a2b93dd178987fb7aeb4041108183f91 Mon Sep 17 00:00:00 2001 From: LowEntropyFace Date: Sun, 9 Jan 2022 09:43:47 -0500 Subject: [PATCH 16/29] fix async user generation --- frontend/src/components/UserGenPage.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/UserGenPage.js b/frontend/src/components/UserGenPage.js index fd80749c..b0e165a8 100644 --- a/frontend/src/components/UserGenPage.js +++ b/frontend/src/components/UserGenPage.js @@ -26,7 +26,7 @@ export default class UserGenPage extends Component { this.state = { token: this.genBase62Token(32), }; - this.getGeneratedUser(); + this.getGeneratedUser(this.state.token); } // sort of cryptographically strong function to generate Base62 token client-side @@ -40,8 +40,8 @@ export default class UserGenPage extends Component { .substring(0, length); } - getGeneratedUser() { - fetch('/api/user' + '?token=' + this.state.token) + getGeneratedUser(token) { + fetch('/api/user' + '?token=' + token) .then((response) => response.json()) .then((data) => { this.setState({ @@ -82,7 +82,7 @@ export default class UserGenPage extends Component { this.setState({ token: e.target.value, }) - this.getGeneratedUser(); + this.getGeneratedUser(e.target.value); } // TO FIX CSRF TOKEN IS NOT UPDATED UNTIL WINDOW IS RELOADED From 09bd46bb9d231844348d136854d0929b3c79264d Mon Sep 17 00:00:00 2001 From: LowEntropyFace Date: Sun, 9 Jan 2022 10:24:41 -0500 Subject: [PATCH 17/29] fix bug --- frontend/src/components/UserGenPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/UserGenPage.js b/frontend/src/components/UserGenPage.js index b0e165a8..d638f57d 100644 --- a/frontend/src/components/UserGenPage.js +++ b/frontend/src/components/UserGenPage.js @@ -60,7 +60,7 @@ export default class UserGenPage extends Component { method: 'DELETE', headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken')}, }; - fetch("/api/usergen", requestOptions) + fetch("/api/user", requestOptions) .then((response) => response.json()) .then((data) => console.log(data)); } From 48862a76778835660ce41ea23ba98480d7546640 Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Sun, 9 Jan 2022 07:28:12 -0800 Subject: [PATCH 18/29] Fix bugs --- frontend/src/components/OrderPage.js | 12 +---- frontend/src/components/TradeBox.js | 71 +++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 16 deletions(-) diff --git a/frontend/src/components/OrderPage.js b/frontend/src/components/OrderPage.js index 6bed6553..37f5e04b 100644 --- a/frontend/src/components/OrderPage.js +++ b/frontend/src/components/OrderPage.js @@ -108,7 +108,6 @@ export default class OrderPage extends Component { escrowInvoice: data.escrow_invoice, escrowSatoshis: data.escrow_satoshis, invoiceAmount: data.invoice_amount, - badRequest: data.bad_request, }); }); } @@ -133,12 +132,6 @@ export default class OrderPage extends Component { this.setState({ delay: Number(e.target.value) }); } - // Gets currency code (3 letters) from numeric (e.g., 1 -> USD) - // Improve this function so currencies are read from json - getCurrencyCode(val){ - return (val == 1 ) ? "USD": ((val == 2 ) ? "EUR":"ETH") - } - // Fix to use proper react props handleClickBackButton=()=>{ window.history.back(); @@ -169,9 +162,8 @@ export default class OrderPage extends Component { // Gets currency code (3 letters) from numeric (e.g., 1 -> USD) // Improve this function so currencies are read from json getCurrencyCode(val){ - console.log("---------------------------------") - console.log(val) - return this.state.currencies_dict[val.toString()] + let code = val ? this.state.currencies_dict[val.toString()] : "" + return code } handleClickCancelOrderButton=()=>{ diff --git a/frontend/src/components/TradeBox.js b/frontend/src/components/TradeBox.js index 7691d8ee..397c5aa4 100644 --- a/frontend/src/components/TradeBox.js +++ b/frontend/src/components/TradeBox.js @@ -105,7 +105,7 @@ export default class TradeBox extends Component { - + Please wait for the taker to confirm his commitment by locking a bond. @@ -162,8 +162,9 @@ export default class TradeBox extends Component { }); } + // Fix this, clunky because it takes time. this.props.data does not refresh until next refresh of OrderPage. + handleClickSubmitInvoiceButton=()=>{ - console.log(this.state) const requestOptions = { method: 'POST', headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),}, @@ -215,14 +216,72 @@ export default class TradeBox extends Component { showWaitingForEscrow(){ + return( + + + + Your invoice looks good! + + + + +

We are waiting for the seller to deposit the full trade BTC amount + into the escrow.

+

Just hang on for a moment. If the seller does not deposit, + you will get your bond back automatically.

+
+
+
+ ) } - // showWaitingForBuyerInvoice({ - // }) + showWaitingForBuyerInvoice(){ - // showFiatSentButton(){ + return( + + + + The trade collateral is locked! :D + + + + +

We are waiting for the buyer to post a lightning invoice. Once + he does, you will be able to directly communicate the fiat payment + details.

+

Just hang on for a moment. If the buyer does not cooperate, + you will get back the trade collateral and your bond automatically.

+
+
+
+ ) + } + + handleClickFiatConfirmButton=()=>{ + const requestOptions = { + method: 'POST', + headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),}, + body: JSON.stringify({ + 'action':'confirm', + 'invoice': this.state.invoice, + }), + }; + fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions) + .then((response) => response.json()) + .then((data) => (this.props.data = data)); +} + + + showFiatSentButton(){ + return( + + + + + + ) + } - // } // showFiatReceivedButton(){ // } From 8e5233267f3c9fbef7b7c33a2687a93c5192f043 Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Sun, 9 Jan 2022 12:05:19 -0800 Subject: [PATCH 19/29] Work frontend trade pipeline --- api/lightning.py | 60 +++++++++++++++--- api/logics.py | 30 ++++----- api/models.py | 10 +-- api/views.py | 17 +++-- frontend/src/components/BookPage.js | 1 - frontend/src/components/OrderPage.js | 12 +++- frontend/src/components/TradeBox.js | 93 +++++++++++++++++++++++----- 7 files changed, 166 insertions(+), 57 deletions(-) diff --git a/api/lightning.py b/api/lightning.py index a10f258b..38230a28 100644 --- a/api/lightning.py +++ b/api/lightning.py @@ -1,3 +1,6 @@ +# import codecs, grpc, os +# import lightning_pb2 as lnrpc, lightning_pb2_grpc as lightningstub + from datetime import timedelta from django.utils import timezone @@ -12,9 +15,16 @@ class LNNode(): ''' Place holder functions to interact with Lightning Node ''' + + # macaroon = codecs.encode(open('LND_DIR/data/chain/bitcoin/simnet/admin.macaroon', 'rb').read(), 'hex') + # os.environ['GRPC_SSL_CIPHER_SUITES'] = 'HIGH+ECDSA' + # cert = open('LND_DIR/tls.cert', 'rb').read() + # ssl_creds = grpc.ssl_channel_credentials(cert) + # channel = grpc.secure_channel('localhost:10009', ssl_creds) + # stub = lightningstub.LightningStub(channel) - def gen_hodl_invoice(num_satoshis, description, expiry): - '''Generates hodl invoice to publish an order''' + def gen_hold_invoice(num_satoshis, description, expiry): + '''Generates hold invoice to publish an order''' # TODO invoice = ''.join(random.choices(string.ascii_uppercase + string.digits, k=80)) #FIX payment_hash = ''.join(random.choices(string.ascii_uppercase + string.digits, k=40)) #FIX @@ -22,12 +32,46 @@ class LNNode(): return invoice, payment_hash, expires_at - def validate_hodl_invoice_locked(payment_hash): - '''Generates hodl invoice to publish an order''' + def validate_hold_invoice_locked(payment_hash): + '''Checks if hodl invoice is locked''' + + # request = ln.InvoiceSubscription() + # When invoice is settled, return true. If time expires, return False. + # for invoice in stub.SubscribeInvoices(request): + # print(invoice) + return True - def validate_ln_invoice(invoice, num_satoshis): # num_satoshis + def validate_ln_invoice(invoice, num_satoshis): '''Checks if the submited LN invoice is as expected''' + + # request = lnrpc.PayReqString(pay_req=invoice) + # response = stub.DecodePayReq(request, metadata=[('macaroon', macaroon)]) + + # # { + # # "destination": , + # # "payment_hash": , + # # "num_satoshis": , + # # "timestamp": , + # # "expiry": , + # # "description": , + # # "description_hash": , + # # "fallback_addr": , + # # "cltv_expiry": , + # # "route_hints": , + # # "payment_addr": , + # # "num_msat": , + # # "features": , + # # } + + # if not response['num_satoshis'] == num_satoshis: + # return False, {'bad_invoice':f'The invoice provided is not for {num_satoshis}. '}, None, None, None + # description = response['description'] + # payment_hash = response['payment_hash'] + # expires_at = timezone(response['expiry']) + # if payment_hash and expires_at > timezone.now(): + # return True, None, description, payment_hash, expires_at + valid = True context = None description = 'Placeholder desc' # TODO decrypt from LN invoice @@ -40,11 +84,11 @@ class LNNode(): '''Sends sats to buyer, or cancelinvoices''' return True - def settle_hodl_htlcs(payment_hash): - '''Charges a LN hodl invoice''' + def settle_hold_htlcs(payment_hash): + '''Charges a LN hold invoice''' return True - def return_hodl_htlcs(payment_hash): + def return_hold_htlcs(payment_hash): '''Returns sats''' return True diff --git a/api/logics.py b/api/logics.py index ecfb2f38..0dd2f499 100644 --- a/api/logics.py +++ b/api/logics.py @@ -188,7 +188,7 @@ class Logics(): return False, {'bad_request':'You cannot cancel this order'} @classmethod - def gen_maker_hodl_invoice(cls, order, user): + def gen_maker_hold_invoice(cls, order, user): # Do not gen and cancel if order is more than 5 minutes old if order.expires_at < timezone.now(): @@ -206,12 +206,12 @@ class Logics(): bond_satoshis = int(order.last_satoshis * BOND_SIZE) description = f'RoboSats - Publishing {str(order)} - This bond will return to you if you do not cheat.' - # Gen HODL Invoice - invoice, payment_hash, expires_at = LNNode.gen_hodl_invoice(bond_satoshis, description, BOND_EXPIRY*3600) + # Gen hold Invoice + invoice, payment_hash, expires_at = LNNode.gen_hold_invoice(bond_satoshis, description, BOND_EXPIRY*3600) order.maker_bond = LNPayment.objects.create( concept = LNPayment.Concepts.MAKEBOND, - type = LNPayment.Types.HODL, + type = LNPayment.Types.hold, sender = user, receiver = User.objects.get(username=ESCROW_USERNAME), invoice = invoice, @@ -225,7 +225,7 @@ class Logics(): return True, {'bond_invoice':invoice,'bond_satoshis':bond_satoshis} @classmethod - def gen_taker_hodl_invoice(cls, order, user): + def gen_taker_hold_invoice(cls, order, user): # Do not gen and cancel if a taker invoice is there and older than X minutes and unpaid still if order.taker_bond: @@ -245,12 +245,12 @@ class Logics(): bond_satoshis = int(order.last_satoshis * BOND_SIZE) description = f'RoboSats - Taking {str(order)} - This bond will return to you if you do not cheat.' - # Gen HODL Invoice - invoice, payment_hash, expires_at = LNNode.gen_hodl_invoice(bond_satoshis, description, BOND_EXPIRY*3600) + # Gen hold Invoice + invoice, payment_hash, expires_at = LNNode.gen_hold_invoice(bond_satoshis, description, BOND_EXPIRY*3600) order.taker_bond = LNPayment.objects.create( concept = LNPayment.Concepts.TAKEBOND, - type = LNPayment.Types.HODL, + type = LNPayment.Types.hold, sender = user, receiver = User.objects.get(username=ESCROW_USERNAME), invoice = invoice, @@ -267,7 +267,7 @@ class Logics(): return True, {'bond_invoice':invoice,'bond_satoshis': bond_satoshis} @classmethod - def gen_escrow_hodl_invoice(cls, order, user): + def gen_escrow_hold_invoice(cls, order, user): # Do not generate and cancel if an invoice is there and older than X minutes and unpaid still if order.trade_escrow: # Check if status is INVGEN and still not expired @@ -285,12 +285,12 @@ class Logics(): escrow_satoshis = order.last_satoshis # Trade sats amount was fixed at the time of taker bond generation (order.last_satoshis) description = f'RoboSats - Escrow amount for {str(order)} - This escrow will be released to the buyer once you confirm you received the fiat.' - # Gen HODL Invoice - invoice, payment_hash, expires_at = LNNode.gen_hodl_invoice(escrow_satoshis, description, ESCROW_EXPIRY*3600) + # Gen hold Invoice + invoice, payment_hash, expires_at = LNNode.gen_hold_invoice(escrow_satoshis, description, ESCROW_EXPIRY*3600) order.trade_escrow = LNPayment.objects.create( concept = LNPayment.Concepts.TRESCROW, - type = LNPayment.Types.HODL, + type = LNPayment.Types.hold, sender = user, receiver = User.objects.get(username=ESCROW_USERNAME), invoice = invoice, @@ -307,7 +307,7 @@ class Logics(): ''' Settles the trade escrow HTLC''' # TODO ERROR HANDLING - valid = LNNode.settle_hodl_htlcs(order.trade_escrow.payment_hash) + valid = LNNode.settle_hold_htlcs(order.trade_escrow.payment_hash) return valid def pay_buyer_invoice(order): @@ -338,7 +338,7 @@ class Logics(): return False, {'bad_request':'You cannot confirm to have received the fiat before it is confirmed to be sent by the buyer.'} # Make sure the trade escrow is at least as big as the buyer invoice - if order.trade_escrow.num_satoshis <= order.buyer_invoice.num_satoshis: + if order.trade_escrow.num_satoshis > order.buyer_invoice.num_satoshis: return False, {'bad_request':'Woah, something broke badly. Report in the public channels, or open a Github Issue.'} # Double check the escrow is settled. @@ -350,4 +350,4 @@ class Logics(): return False, {'bad_request':'You cannot confirm the fiat payment at this stage'} order.save() - return True, None + return True, None \ No newline at end of file diff --git a/api/models.py b/api/models.py index e429df5f..db6d9cf8 100644 --- a/api/models.py +++ b/api/models.py @@ -18,8 +18,8 @@ BOND_SIZE = float(config('BOND_SIZE')) class LNPayment(models.Model): class Types(models.IntegerChoices): - NORM = 0, 'Regular invoice' # Only outgoing HTLCs will be regular invoices (Non-hodl) - HODL = 1, 'Hodl invoice' + NORM = 0, 'Regular invoice' # Only outgoing HTLCs will be regular invoices (Non-hold) + hold = 1, 'hold invoice' class Concepts(models.IntegerChoices): MAKEBOND = 0, 'Maker bond' @@ -38,7 +38,7 @@ class LNPayment(models.Model): FAILRO = 7, 'Failed routing' # payment use details - type = models.PositiveSmallIntegerField(choices=Types.choices, null=False, default=Types.HODL) + type = models.PositiveSmallIntegerField(choices=Types.choices, null=False, default=Types.hold) concept = models.PositiveSmallIntegerField(choices=Concepts.choices, null=False, default=Concepts.MAKEBOND) status = models.PositiveSmallIntegerField(choices=Status.choices, null=False, default=Status.INVGEN) routing_retries = models.PositiveSmallIntegerField(null=False, default=0) @@ -133,7 +133,7 @@ class Order(models.Model): return (f'Order {self.id}: {self.Types(self.type).label} BTC for {float(self.amount)} {self.currency_dict[str(self.currency)]}') @receiver(pre_delete, sender=Order) -def delelete_HTLCs_at_order_deletion(sender, instance, **kwargs): +def delete_HTLCs_at_order_deletion(sender, instance, **kwargs): to_delete = (instance.maker_bond, instance.buyer_invoice, instance.taker_bond, instance.trade_escrow) for htlc in to_delete: @@ -193,7 +193,7 @@ class MarketTick(models.Model): It is checked against current CEX price for useful insight on the historical premium of Non-KYC BTC - Price is set when both taker bond is locked. Both + Price is set when taker bond is locked. Both maker and taker are commited with bonds (contract is finished and cancellation has a cost) ''' diff --git a/api/views.py b/api/views.py index ed6dab9e..a11b7ddf 100644 --- a/api/views.py +++ b/api/views.py @@ -136,17 +136,17 @@ class OrderView(viewsets.ViewSet): elif data['is_buyer']: data['trade_satoshis'] = Logics.buyer_invoice_amount(order, request.user)[1]['invoice_amount'] - # 5) If status is 'waiting for maker bond' and user is MAKER, reply with a MAKER HODL invoice. + # 5) If status is 'waiting for maker bond' and user is MAKER, reply with a MAKER hold invoice. if order.status == Order.Status.WFB and data['is_maker']: - valid, context = Logics.gen_maker_hodl_invoice(order, request.user) + valid, context = Logics.gen_maker_hold_invoice(order, request.user) if valid: data = {**data, **context} else: return Response(context, status.HTTP_400_BAD_REQUEST) - # 6) If status is 'waiting for taker bond' and user is TAKER, reply with a TAKER HODL invoice. + # 6) If status is 'waiting for taker bond' and user is TAKER, reply with a TAKER hold invoice. elif order.status == Order.Status.TAK and data['is_taker']: - valid, context = Logics.gen_taker_hodl_invoice(order, request.user) + valid, context = Logics.gen_taker_hold_invoice(order, request.user) if valid: data = {**data, **context} else: @@ -155,9 +155,9 @@ class OrderView(viewsets.ViewSet): # 7 a. ) If seller and status is 'WF2' or 'WFE' elif data['is_seller'] and (order.status == Order.Status.WF2 or order.status == Order.Status.WFE): - # If the two bonds are locked, reply with an ESCROW HODL invoice. + # If the two bonds are locked, reply with an ESCROW hold invoice. if order.maker_bond.status == order.taker_bond.status == LNPayment.Status.LOCKED: - valid, context = Logics.gen_escrow_hodl_invoice(order, request.user) + valid, context = Logics.gen_escrow_hold_invoice(order, request.user) if valid: data = {**data, **context} else: @@ -179,10 +179,7 @@ class OrderView(viewsets.ViewSet): if order.maker_bond.status == order.taker_bond.status == order.trade_escrow.status == LNPayment.Status.LOCKED: # add whether a collaborative cancel is pending data['pending_cancel'] = order.is_pending_cancel - - # 9) if buyer confirmed FIAT SENT - elif order.status == Order.Status.FSE: - data['buyer_confirmed'] + return Response(data, status.HTTP_200_OK) diff --git a/frontend/src/components/BookPage.js b/frontend/src/components/BookPage.js index c119b37b..c423d5c1 100644 --- a/frontend/src/components/BookPage.js +++ b/frontend/src/components/BookPage.js @@ -16,7 +16,6 @@ export default class BookPage extends Component { this.state.currencyCode = this.getCurrencyCode(this.state.currency) } - // Show message to be the first one to make an order getOrderDetails(type,currency) { fetch('/api/book' + '?currency=' + currency + "&type=" + type) .then((response) => response.json()) diff --git a/frontend/src/components/OrderPage.js b/frontend/src/components/OrderPage.js index fd86b7be..32148132 100644 --- a/frontend/src/components/OrderPage.js +++ b/frontend/src/components/OrderPage.js @@ -283,9 +283,8 @@ export default class OrderPage extends Component { ) } - - render (){ - return ( + orderDetailsPage (){ + return( this.state.badRequest ?
@@ -307,6 +306,13 @@ export default class OrderPage extends Component { {this.orderBox()} ) + ) + } + + render (){ + return ( + // Only so nothing shows while requesting the first batch of data + (this.state.statusCode == null & this.state.badRequest == null) ? "" : this.orderDetailsPage() ); } } diff --git a/frontend/src/components/TradeBox.js b/frontend/src/components/TradeBox.js index 397c5aa4..df214749 100644 --- a/frontend/src/components/TradeBox.js +++ b/frontend/src/components/TradeBox.js @@ -58,7 +58,7 @@ export default class TradeBox extends Component { size="small" defaultValue={this.props.data.bondInvoice} disabled="true" - helperText="This is a HODL LN invoice. It will not be charged if the order succeeds or expires. + helperText="This is a hold invoice. It will not be charged if the order succeeds or expires. It will be charged if the order is cancelled or you lose a dispute." color = "secondary" /> @@ -66,6 +66,7 @@ export default class TradeBox extends Component { ); } + showEscrowQRInvoice=()=>{ return ( @@ -84,7 +85,7 @@ export default class TradeBox extends Component { size="small" defaultValue={this.props.data.escrowInvoice} disabled="true" - helperText="This is a HODL LN invoice. It will be charged once the buyer confirms he sent the fiat." + helperText="This is a hold LN invoice. It will be charged once the buyer confirms he sent the fiat." color = "secondary" /> @@ -162,7 +163,7 @@ export default class TradeBox extends Component { }); } - // Fix this, clunky because it takes time. this.props.data does not refresh until next refresh of OrderPage. + // Fix this. It's clunky because it takes time. this.props.data does not refresh until next refresh of OrderPage. handleClickSubmitInvoiceButton=()=>{ const requestOptions = { @@ -215,7 +216,6 @@ export default class TradeBox extends Component { } showWaitingForEscrow(){ - return( @@ -236,7 +236,6 @@ export default class TradeBox extends Component { } showWaitingForBuyerInvoice(){ - return( @@ -257,26 +256,90 @@ export default class TradeBox extends Component { ) } - handleClickFiatConfirmButton=()=>{ + handleClickConfirmButton=()=>{ const requestOptions = { method: 'POST', headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),}, body: JSON.stringify({ - 'action':'confirm', - 'invoice': this.state.invoice, + 'action': "confirm", }), }; fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions) .then((response) => response.json()) .then((data) => (this.props.data = data)); } - +handleClickOpenDisputeButton=()=>{ + const requestOptions = { + method: 'POST', + headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken'),}, + body: JSON.stringify({ + 'action': "dispute", + }), + }; + fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions) + .then((response) => response.json()) + .then((data) => (this.props.data = data)); +} showFiatSentButton(){ return( - + + + + ) + } + + showFiatReceivedButton(){ + // TODO, show alert and ask for double confirmation (Have you check you received the fiat? Confirming fiat received settles the trade.) + // Ask for double confirmation. + return( + + + + + + ) + } + + showOpenDisputeButton(){ + // TODO, show alert about how opening a dispute might involve giving away personal data and might mean losing the bond. Ask for double confirmation. + return( + + + + + + ) + } + + showChat(sendFiatButton, receivedFiatButton, openDisputeButton){ + return( + + + + Chatting with {this.props.data.isMaker ? this.props.data.takerNick : this.props.data.makerNick} + + + + {this.props.data.isSeller ? + + Say hi to your peer robot! Be helpful and concise. Let him know how to send you {this.props.data.currencyCode}. + + : + + Say hi to your peer robot! Ask for payment details and click 'Confirm {this.props.data.currencyCode} sent' as soon as you send the payment. + + } + + + CHAT PLACEHOLDER + + + {sendFiatButton ? this.showFiatSentButton() : ""} + {receivedFiatButton ? this.showFiatReceivedButton() : ""} + {openDisputeButton ? this.showOpenDisputeButton() : ""} ) @@ -316,11 +379,11 @@ export default class TradeBox extends Component { {this.props.data.isBuyer & this.props.data.statusCode == 7 ? this.showWaitingForEscrow() : ""} {this.props.data.isSeller & this.props.data.statusCode == 8 ? this.showWaitingForBuyerInvoice() : ""} - {/* In Chatroom */} - {this.props.data.isBuyer & this.props.data.statusCode == 9 ? this.showChat() & this.showFiatSentButton() : ""} - {this.props.data.isSeller & this.props.data.statusCode ==9 ? this.showChat() : ""} - {this.props.data.isBuyer & this.props.data.statusCode == 10 ? this.showChat() & this.showOpenDisputeButton() : ""} - {this.props.data.isSeller & this.props.data.statusCode == 10 ? this.showChat() & this.showFiatReceivedButton() & this.showOpenDisputeButton(): ""} + {/* In Chatroom - showChat(showSendButton, showReveiceButton, showDisputeButton) */} + {this.props.data.isBuyer & this.props.data.statusCode == 9 ? this.showChat(true,false,true) : ""} + {this.props.data.isSeller & this.props.data.statusCode == 9 ? this.showChat(false,false,true) : ""} + {this.props.data.isBuyer & this.props.data.statusCode == 10 ? this.showChat(false,false,true) : ""} + {this.props.data.isSeller & this.props.data.statusCode == 10 ? this.showChat(false,true,true) : ""} {/* Trade Finished */} {this.props.data.isSeller & this.props.data.statusCode > 12 & this.props.data.statusCode < 15 ? this.showRateSelect() : ""} From 6400921f48a604aa906904ceabb6a92c3a46d1a3 Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Sun, 9 Jan 2022 13:24:48 -0800 Subject: [PATCH 20/29] Make book show all (any/any) --- api/lightning.py | 7 +++++++ api/views.py | 22 ++++++++++++---------- frontend/src/components/BookPage.js | 10 +++++----- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/api/lightning.py b/api/lightning.py index 38230a28..295a3085 100644 --- a/api/lightning.py +++ b/api/lightning.py @@ -84,6 +84,13 @@ class LNNode(): '''Sends sats to buyer, or cancelinvoices''' return True + def check_if_hold_invoice_is_locked(payment_hash): + '''Every hodl invoice that is in state INVGEN + Has to be checked for payment received until + the window expires''' + + return True + def settle_hold_htlcs(payment_hash): '''Charges a LN hold invoice''' return True diff --git a/api/views.py b/api/views.py index a11b7ddf..38fef9b9 100644 --- a/api/views.py +++ b/api/views.py @@ -179,7 +179,7 @@ class OrderView(viewsets.ViewSet): if order.maker_bond.status == order.taker_bond.status == order.trade_escrow.status == LNPayment.Status.LOCKED: # add whether a collaborative cancel is pending data['pending_cancel'] = order.is_pending_cancel - + return Response(data, status.HTTP_200_OK) @@ -343,25 +343,27 @@ class UserView(APIView): class BookView(ListAPIView): serializer_class = ListOrderSerializer + queryset = Order.objects.filter(status=Order.Status.PUB) def get(self,request, format=None): currency = request.GET.get('currency') - print("currency:", currency) - type = request.GET.get('type') - queryset = Order.objects.filter(currency=currency, type=type, status=int(Order.Status.PUB)) + type = request.GET.get('type') + + queryset = Order.objects.filter(status=Order.Status.PUB) + # Currency 0 and type 2 are special cases treated as "ANY". They are not possible choices. + if not (int(currency) == 0 and int(type) == 2): + queryset = Order.objects.filter(currency=currency, type=type, status=Order.Status.PUB) + if len(queryset)== 0: return Response({'not_found':'No orders found, be the first to make one'}, status=status.HTTP_404_NOT_FOUND) - queryset = queryset.order_by('created_at') + # queryset = queryset.order_by('created_at') book_data = [] for order in queryset: data = ListOrderSerializer(order).data - user = User.objects.filter(id=data['maker']) - if len(user) == 1: - data['maker_nick'] = user[0].username + data['maker_nick'] = str(order.maker) - # Non participants should not see the status or who is the taker - for key in ('status','taker'): + for key in ('status','taker'): # Non participants should not see the status or who is the taker del data[key] book_data.append(data) diff --git a/frontend/src/components/BookPage.js b/frontend/src/components/BookPage.js index c423d5c1..158d7671 100644 --- a/frontend/src/components/BookPage.js +++ b/frontend/src/components/BookPage.js @@ -7,9 +7,9 @@ export default class BookPage extends Component { super(props); this.state = { orders: new Array(), - currency: 1, - type: 1, - currencies_dict: {"1":"USD"} + currency: 0, + type: 2, + currencies_dict: {"0":"ANY"} }; this.getCurrencyDict() this.getOrderDetails(this.state.type,this.state.currency) @@ -142,7 +142,7 @@ export default class BookPage extends Component { style: {textAlign:"center"} }} onChange={this.handleTypeChange} - > + > ANY BUY SELL @@ -162,7 +162,7 @@ export default class BookPage extends Component { style: {textAlign:"center"} }} onChange={this.handleCurrencyChange} - > + > ANY { Object.entries(this.state.currencies_dict) .map( ([key, value]) => {value} ) From c08c76b7d880a23717d0c395c011aa73bb09bb2f Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Sun, 9 Jan 2022 13:45:02 -0800 Subject: [PATCH 21/29] Fix text messages for ANY --- frontend/src/components/BookPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/BookPage.js b/frontend/src/components/BookPage.js index 158d7671..5a2b77a2 100644 --- a/frontend/src/components/BookPage.js +++ b/frontend/src/components/BookPage.js @@ -173,7 +173,7 @@ export default class BookPage extends Component { { this.state.not_found ? "" : - You are {this.state.type == 0 ? " selling " : " buying "} BTC for {this.state.currencyCode} + You are {this.state.type == 0 ? " buying " : (this.state.type == 1 ? " selling ":" checking ")} BTC for {this.state.currencyCode} } From a518daf8ccc852db2a2ab15e6a3649ffe3b03c48 Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Sun, 9 Jan 2022 13:54:13 -0800 Subject: [PATCH 22/29] Fix bookview gets either any currency or any type --- api/views.py | 12 +++++++++--- frontend/src/components/BookPage.js | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/api/views.py b/api/views.py index 38fef9b9..8a20c77c 100644 --- a/api/views.py +++ b/api/views.py @@ -1,3 +1,4 @@ +from re import T from rest_framework import status, viewsets from rest_framework.generics import CreateAPIView, ListAPIView from rest_framework.views import APIView @@ -349,9 +350,14 @@ class BookView(ListAPIView): currency = request.GET.get('currency') type = request.GET.get('type') - queryset = Order.objects.filter(status=Order.Status.PUB) - # Currency 0 and type 2 are special cases treated as "ANY". They are not possible choices. - if not (int(currency) == 0 and int(type) == 2): + queryset = Order.objects.filter(status=Order.Status.PUB) + + # Currency 0 and type 2 are special cases treated as "ANY". (These are not really possible choices) + if int(currency) == 0 and int(type) != 2: + queryset = Order.objects.filter(type=type, status=Order.Status.PUB) + elif int(type) == 2 and int(currency) != 0: + queryset = Order.objects.filter(currency=currency, status=Order.Status.PUB) + elif not (int(currency) == 0 and int(type) == 2): queryset = Order.objects.filter(currency=currency, type=type, status=Order.Status.PUB) if len(queryset)== 0: diff --git a/frontend/src/components/BookPage.js b/frontend/src/components/BookPage.js index 5a2b77a2..aa48d435 100644 --- a/frontend/src/components/BookPage.js +++ b/frontend/src/components/BookPage.js @@ -8,7 +8,7 @@ export default class BookPage extends Component { this.state = { orders: new Array(), currency: 0, - type: 2, + type: 1, currencies_dict: {"0":"ANY"} }; this.getCurrencyDict() From bb9cafadd8fcb9dd9839ade3f8c116fbf314ea87 Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Sun, 9 Jan 2022 14:17:15 -0800 Subject: [PATCH 23/29] Upgrade MUI to V5 --- frontend/package-lock.json | 45 +++++++++ frontend/package.json | 1 + frontend/src/components/BookPage.js | 124 ++++++++++++++----------- frontend/src/components/MakerPage.js | 2 +- frontend/src/components/OrderPage.js | 2 +- frontend/src/components/TradeBox.js | 2 +- frontend/src/components/UserGenPage.js | 4 +- setup.md | 2 + 8 files changed, 122 insertions(+), 60 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 51cf6798..47a87ea5 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1567,6 +1567,46 @@ "react-is": "^16.8.0 || ^17.0.0" } }, + "@mui/base": { + "version": "5.0.0-alpha.63", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.63.tgz", + "integrity": "sha512-/jURXlBAYqZaWw92XfJgc6aiHnDcNVuRxBskub57HXWCMK3OiVVdfUEWJEdCjOacCKiw3+Etc5alI9Omaqrg2g==", + "requires": { + "@babel/runtime": "^7.16.3", + "@emotion/is-prop-valid": "^1.1.1", + "@mui/utils": "^5.2.3", + "@popperjs/core": "^2.4.4", + "clsx": "^1.1.1", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + } + }, + "@mui/material": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.2.7.tgz", + "integrity": "sha512-JaDl9GJSV17QLf4OoDUZKvVjZ/7UvqOBAxwLwUTnKZEME4REaGTkaAeHrzLpcKCm0LlNGD2HOKAIeykI6WJiqg==", + "requires": { + "@babel/runtime": "^7.16.3", + "@mui/base": "5.0.0-alpha.63", + "@mui/system": "^5.2.6", + "@mui/types": "^7.1.0", + "@mui/utils": "^5.2.3", + "@types/react-transition-group": "^4.4.4", + "clsx": "^1.1.1", + "csstype": "^3.0.10", + "hoist-non-react-statics": "^3.3.2", + "prop-types": "^15.7.2", + "react-is": "^17.0.2", + "react-transition-group": "^4.4.2" + }, + "dependencies": { + "csstype": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", + "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==" + } + } + }, "@mui/private-theming": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.2.3.tgz", @@ -1626,6 +1666,11 @@ "react-is": "^17.0.2" } }, + "@popperjs/core": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz", + "integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==" + }, "@react-native-community/cli-debugger-ui": { "version": "6.0.0-rc.0", "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-6.0.0-rc.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index a8f164ec..91ef399b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -26,6 +26,7 @@ "@emotion/styled": "^11.6.0", "@material-ui/core": "^4.12.3", "@material-ui/icons": "^4.11.2", + "@mui/material": "^5.2.7", "@mui/system": "^5.2.6", "material-ui-image": "^3.3.2", "react-native": "^0.66.4", diff --git a/frontend/src/components/BookPage.js b/frontend/src/components/BookPage.js index aa48d435..03d5b9d7 100644 --- a/frontend/src/components/BookPage.js +++ b/frontend/src/components/BookPage.js @@ -1,5 +1,5 @@ import React, { Component } from "react"; -import { Button , Divider, Card, CardActionArea, CardContent, Typography, Grid, Select, MenuItem, FormControl, FormHelperText, List, ListItem, ListItemText, Avatar, RouterLink, ListItemAvatar} from "@material-ui/core" +import { Button , Divider, ListItemButton, Typography, Grid, Select, MenuItem, FormControl, FormHelperText, List, ListItem, ListItemText, Avatar, RouterLink, ListItemAvatar} from "@mui/material"; import { Link } from 'react-router-dom' export default class BookPage extends Component { @@ -63,63 +63,72 @@ export default class BookPage extends Component { return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); } - bookCards=()=>{ + bookListItems=()=>{ return (this.state.orders.map((order) => - - - - this.handleCardClick(order.id)}> - - - - - - - - - - {order.maker_nick} - - - - - {/* CARD PARAGRAPH CONTENT */} - - - ◑{order.type == 0 ? Buys : Sells } - {parseFloat(parseFloat(order.amount).toFixed(4))} - {" " +this.getCurrencyCode(order.currency)} worth of bitcoin - - - - ◑ Payment via {order.payment_method} - -{/* - - ◑ Priced {order.is_explicit ? - " explicitly at " + this.pn(order.satoshis) + " Sats" : ( - " at " + - parseFloat(parseFloat(order.premium).toFixed(4)) + "% over the market" - )} - */} - - - ◑ {" 42,354 "}{this.getCurrencyCode(order.currency)}/BTC (Binance API) - - - - - - - - - + + + + + )); } +// +// + +// this.handleCardClick(order.id)}> +// + +// +// +// +// +// +// +// +// {order.maker_nick} +// +// +// + +// {/* CARD PARAGRAPH CONTENT */} +// +// +// ◑{order.type == 0 ? Buys : Sells } +// {parseFloat(parseFloat(order.amount).toFixed(4))} +// {" " +this.getCurrencyCode(order.currency)} worth of bitcoin +// + +// +// ◑ Payment via {order.payment_method} +// +// {/* +// +// ◑ Priced {order.is_explicit ? +// " explicitly at " + this.pn(order.satoshis) + " Sats" : ( +// " at " + +// parseFloat(parseFloat(order.premium).toFixed(4)) + "% over the market" +// )} +// */} + +// +// ◑ {" 42,354 "}{this.getCurrencyCode(order.currency)}/BTC (Binance API) +// +// + +// + +// +// +// +// + render() { return ( @@ -192,7 +201,12 @@ export default class BookPage extends Component { Be the first one to create an order ) - : this.bookCards() + : + + + {this.bookListItems()} + + } - + diff --git a/setup.md b/setup.md index 0a5d2b40..67887df9 100644 --- a/setup.md +++ b/setup.md @@ -69,7 +69,9 @@ npm install @mui/system @emotion/react @emotion/styled npm install react-native npm install react-native-svg npm install react-qr-code +npm install @mui/material ``` +Note we are using mostly MaterialUI V5, but Image loading from V4 extentions (so both V4 and V5 are needed) ### Launch the React render from frontend/ directory From 9bc6757ba302bab51df2ed70f8b490cc3954c91b Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Sun, 9 Jan 2022 17:12:58 -0800 Subject: [PATCH 24/29] Revamp UI --- api/logics.py | 21 ++++- api/utils.py | 4 + api/views.py | 3 + frontend/src/components/BookPage.js | 63 ++++++++++---- frontend/src/components/MakerPage.js | 112 +++++++++++++------------ frontend/src/components/UserGenPage.js | 4 +- setup.md | 1 + 7 files changed, 137 insertions(+), 71 deletions(-) diff --git a/api/logics.py b/api/logics.py index 0dd2f499..8374f17b 100644 --- a/api/logics.py +++ b/api/logics.py @@ -36,9 +36,9 @@ class Logics(): def validate_order_size(order): '''Checks if order is withing limits at t0''' if order.t0_satoshis > MAX_TRADE: - return False, {'bad_request': f'Your order is too big. It is worth {order.t0_satoshis} now. But maximum is {MAX_TRADE}'} + return False, {'bad_request': 'Your order is too big. It is worth '+'{:,}'.format(order.t0_satoshis)+' Sats now. But limit is '+'{:,}'.format(MAX_TRADE)+ ' Sats'} if order.t0_satoshis < MIN_TRADE: - return False, {'bad_request': f'Your order is too small. It is worth {order.t0_satoshis} now. But minimum is {MIN_TRADE}'} + return False, {'bad_request': 'Your order is too small. It is worth '+'{:,}'.format(order.t0_satoshis)+' Sats now. But limit is '+'{:,}'.format(MIN_TRADE)+ ' Sats'} return True, None def take(order, user): @@ -66,7 +66,22 @@ class Logics(): satoshis_now = (float(order.amount) / premium_rate) * 100*1000*1000 return int(satoshis_now) - + + def price_and_premium_now(order): + ''' computes order premium live ''' + exchange_rate = get_exchange_rate(Order.currency_dict[str(order.currency)]) + if not order.is_explicit: + premium = order.premium + price = exchange_rate + else: + exchange_rate = get_exchange_rate(Order.currency_dict[str(order.currency)]) + order_rate = float(order.amount) / (float(order.satoshis) / 100000000) + premium = order_rate / exchange_rate - 1 + price = order_rate + + premium = int(premium*100) # 2 decimals left + return price, premium + def order_expires(order): order.status = Order.Status.EXP order.maker = None diff --git a/api/utils.py b/api/utils.py index 0b1b934b..85333355 100644 --- a/api/utils.py +++ b/api/utils.py @@ -1,7 +1,11 @@ from decouple import config import requests +import ring +storage = {} + +@ring.dict(storage, expire=60) #keeps in cache for 60 secs def get_exchange_rate(currency): # TODO Add fallback Public APIs and error handling # Think about polling price data in a different way (e.g. store locally every t seconds) diff --git a/api/views.py b/api/views.py index 8a20c77c..a4f474d4 100644 --- a/api/views.py +++ b/api/views.py @@ -369,6 +369,9 @@ class BookView(ListAPIView): data = ListOrderSerializer(order).data data['maker_nick'] = str(order.maker) + # Compute current premium for those orders that are explicitly priced. + data['price'], data['premium'] = Logics.price_and_premium_now(order) + for key in ('status','taker'): # Non participants should not see the status or who is the taker del data[key] diff --git a/frontend/src/components/BookPage.js b/frontend/src/components/BookPage.js index 03d5b9d7..f232c0ae 100644 --- a/frontend/src/components/BookPage.js +++ b/frontend/src/components/BookPage.js @@ -1,5 +1,5 @@ import React, { Component } from "react"; -import { Button , Divider, ListItemButton, Typography, Grid, Select, MenuItem, FormControl, FormHelperText, List, ListItem, ListItemText, Avatar, RouterLink, ListItemAvatar} from "@mui/material"; +import { Box, Button , Divider, ListItemButton, Typography, Grid, Select, MenuItem, FormControl, FormHelperText, List, ListItem, ListItemText, Avatar, RouterLink, ListItemAvatar} from "@mui/material"; import { Link } from 'react-router-dom' export default class BookPage extends Component { @@ -65,14 +65,51 @@ export default class BookPage extends Component { bookListItems=()=>{ return (this.state.orders.map((order) => - - - - - + <> + this.handleCardClick(order.id)}> + + + + + + + + {order.maker_nick+" "} + + + + + + {order.type ? " Sells ": " Buys "} BTC for {parseFloat( + parseFloat(order.amount).toFixed(4))+" "+ this.getCurrencyCode(order.currency)+" "} + + + + + + via {order.payment_method} + + + + + + at {this.pn(order.price) + " " + this.getCurrencyCode(order.currency)}/BTC + + + + + + {order.premium > 1 ? "🔴" : "🔵" } {parseFloat(parseFloat(order.premium).toFixed(4))}% + + + + + + + )); } @@ -133,7 +170,7 @@ export default class BookPage extends Component { return ( - + Order Book @@ -202,11 +239,9 @@ export default class BookPage extends Component { ) : - - - {this.bookListItems()} + + {this.bookListItems()} - }