From 1b42d997576d949035fe8a4c4591d32135bbff81 Mon Sep 17 00:00:00 2001 From: m4r71n <151830077+M4r71nW@users.noreply.github.com> Date: Wed, 4 Sep 2024 11:17:23 +0200 Subject: [PATCH 1/5] FIX: csm value issue (#2032) * change comments * add: checking value * FIX: UI notifications * FIX: clean extra comments and logs --------- Co-authored-by: mabasian <54101509+mabasian@users.noreply.github.com> --- launcher/src/backend/Monitoring.js | 13 +++++++++++-- .../src/components/UI/the-control/ControlAlert.vue | 12 +++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/launcher/src/backend/Monitoring.js b/launcher/src/backend/Monitoring.js index 2ace566b0..93f99de8b 100755 --- a/launcher/src/backend/Monitoring.js +++ b/launcher/src/backend/Monitoring.js @@ -3459,7 +3459,7 @@ rm -rf diskoutput /** * Will gather metrics from Prometheus and evaluate. * If thresholds are exceeded, an alert will be generated and added to the retuned array. - * @returns {Object[]} Array of alerts e.g. [{name: "Cluster in Unknown Status", level: "warning"}, {name: "Beacon Node Down", level: "critical"}] + * @returns {Object[]} Array of alerts e.g. [{name: "slashing event", level: "critical"},] */ async fetchCsmAlerts() { try { @@ -3496,7 +3496,16 @@ rm -rf diskoutput return []; } - const value = parseFloat(metric.result.data.result[0].value[1]); + if (!metric.result.data.result || metric.result.data.result.length === 0) { + return []; + } + + const metricData = metric.result.data.result[0]; + if (!metricData || !metricData.value || metricData.value.length < 2) { + return []; + } + + const value = parseFloat(metricData.value[1]); if (metric.key === "lcoms_current_bond") { currentBond = value; diff --git a/launcher/src/components/UI/the-control/ControlAlert.vue b/launcher/src/components/UI/the-control/ControlAlert.vue index ad071fe74..a9a5838de 100755 --- a/launcher/src/components/UI/the-control/ControlAlert.vue +++ b/launcher/src/components/UI/the-control/ControlAlert.vue @@ -511,7 +511,6 @@ export default { async fetchObolCharonAlerts() { try { const alerts = await ControlService.fetchObolCharonAlerts(); - console.log("Obol Charon alerts:", alerts); this.processAlerts(alerts); } catch (error) { @@ -846,4 +845,15 @@ export default { text-transform: uppercase; margin-bottom: 2%; } + +.val-message span { + display: block; + width: 100%; + height: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + text-align: left; + font-size: 42%; +} From 44450ef2001767c250be086a8b1dd4c7d4a382e0 Mon Sep 17 00:00:00 2001 From: stereum-bot <137287432+stereum-bot@users.noreply.github.com> Date: Wed, 4 Sep 2024 11:33:30 +0200 Subject: [PATCH 2/5] New Crowdin updates (#2030) * New translations en.json (French) * New translations en.json (Spanish) * New translations en.json (Arabic) * New translations en.json (Bulgarian) * New translations en.json (Czech) * New translations en.json (German) * New translations en.json (Italian) * New translations en.json (Japanese) * New translations en.json (Korean) * New translations en.json (Mongolian) * New translations en.json (Dutch) * New translations en.json (Portuguese) * New translations en.json (Russian) * New translations en.json (Serbian (Cyrillic)) * New translations en.json (Turkish) * New translations en.json (Chinese Simplified) * New translations en.json (Urdu (Pakistan)) * New translations en.json (Vietnamese) * New translations en.json (Indonesian) * New translations en.json (Persian) * New translations en.json (Tamil) * New translations en.json (Bengali) * New translations en.json (Marathi) * New translations en.json (Hindi) * New translations en.json (Telugu) * New translations en.json (Swahili) --- launcher/src/languages/ar.json | 3 ++- launcher/src/languages/bg.json | 3 ++- launcher/src/languages/bn.json | 3 ++- launcher/src/languages/cs.json | 3 ++- launcher/src/languages/de.json | 3 ++- launcher/src/languages/es.json | 3 ++- launcher/src/languages/fa.json | 3 ++- launcher/src/languages/fr.json | 3 ++- launcher/src/languages/hi.json | 3 ++- launcher/src/languages/id.json | 3 ++- launcher/src/languages/it.json | 3 ++- launcher/src/languages/ja.json | 3 ++- launcher/src/languages/ko.json | 3 ++- launcher/src/languages/mn.json | 3 ++- launcher/src/languages/mr.json | 3 ++- launcher/src/languages/nl.json | 3 ++- launcher/src/languages/pt.json | 3 ++- launcher/src/languages/ru.json | 3 ++- launcher/src/languages/sr.json | 3 ++- launcher/src/languages/sw.json | 3 ++- launcher/src/languages/ta.json | 3 ++- launcher/src/languages/te.json | 3 ++- launcher/src/languages/tr.json | 3 ++- launcher/src/languages/ur.json | 3 ++- launcher/src/languages/vi.json | 3 ++- launcher/src/languages/zh.json | 3 ++- 26 files changed, 52 insertions(+), 26 deletions(-) diff --git a/launcher/src/languages/ar.json b/launcher/src/languages/ar.json index ef44c306f..50697f7cc 100644 --- a/launcher/src/languages/ar.json +++ b/launcher/src/languages/ar.json @@ -499,7 +499,8 @@ "sync": "خطأ في التزامن", "taskFail": "فشل المهمة", "stats": "الحالة: مفتوح", - "clientService": "العميل / الخدمة" + "clientService": "العميل / الخدمة", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "يخزن عميلك بيانات البلوكشين على خادمك حتى تتمكن عقدتك من خدمة الشبكة. هذا ضروري لعقدتك لبدء واجب الشهادة في التخزين. باستخدام هذا الخيار، أنت تحذف بيانات البلوكشين الحالية لعملائك وتستخدم الخيار المحدد كمصدر لمزامنة عقدتك من جديد.", diff --git a/launcher/src/languages/bg.json b/launcher/src/languages/bg.json index c4c2089cf..75ff669b8 100755 --- a/launcher/src/languages/bg.json +++ b/launcher/src/languages/bg.json @@ -499,7 +499,8 @@ "sync": "Грешка при синхронизиране", "taskFail": "Задачата е неуспешна", "stats": "СТАТУС: ОТВОРЕН", - "clientService": "КЛИЕНТ / УСЛУГА" + "clientService": "КЛИЕНТ / УСЛУГА", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "ВАШИЯТ КЛИЕНТ СЪХРАНЯВА данните от блокчейн НА ВАШИЯ СЕРВЪР, ЗА ДА МОЖЕ ВАШИЯТ ВЪЗЕЛ ДА ОБСЛУЖВА МРЕЖАТА. това е необходимо, за да може вашият възел ДА ПОЛУЧИ ЗАДЪЛЖЕНИЕТО СИ ЗА АТЕСТАЦИЯ В СТАКИНГ. С ИЗПОЛЗВАНЕТО НА ТОЗИ ВАРИАНТ ИЗТРИВАТЕ ДАННИТЕ ЗА БЛОКЧАЙНА НА ВАШИЯ КЛИЕНТ И ИЗПОЛЗВАТЕ ИЗБРАНИЯ ВАРИАНТ КАТО ИЗТОЧНИК ЗА СИНХРОНИЗИРАНЕ НА ВАШИЯ ВЪЗЕЛ НА НОВО.", diff --git a/launcher/src/languages/bn.json b/launcher/src/languages/bn.json index dcd04e286..111aecc98 100644 --- a/launcher/src/languages/bn.json +++ b/launcher/src/languages/bn.json @@ -499,7 +499,8 @@ "sync": "সিঙ্ক্রোনাইজেশন ত্রুটি", "taskFail": "কাজ ব্যর্থ হয়েছে", "stats": "অবস্থা: খোলা", - "clientService": "ক্লায়েন্ট / সেবা" + "clientService": "ক্লায়েন্ট / সেবা", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "আপনার ক্লায়েন্ট আপনার সার্ভারে ব্লকচেইন ডেটা সংরক্ষণ করে যাতে আপনার নোড নেটওয়ার্কে সেবা দিতে পারে। এটি আপনার নোডকে স্টেকিং-এ তার প্রমাণীকরণ কর্তব্য গ্রহণ করতে আবশ্যক। এই অপশনটি ব্যবহার করে আপনি আপনার ক্লায়েন্টের বর্তমান ব্লকচেইন ডেটা মুছে ফেলছেন এবং আপনার নোডকে নতুন করে সিঙ্ক্রোনাইজ করার জন্য নির্বাচিত উৎস হিসেবে ব্যবহার করছেন।", diff --git a/launcher/src/languages/cs.json b/launcher/src/languages/cs.json index 7aabdafaf..6a207fb60 100755 --- a/launcher/src/languages/cs.json +++ b/launcher/src/languages/cs.json @@ -499,7 +499,8 @@ "sync": "Chyba synchronizace", "taskFail": "Úkol selhal", "stats": "STAV: OTEVŘENO", - "clientService": "KLIENT / SLUŽBA" + "clientService": "KLIENT / SLUŽBA", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "VÁŠ KLIENT UCHOVÁVÁ DATA BLOKCHAINU NA VAŠEM SERVERU. DÍKY TOMU VÁŠ UZEL MŮŽE PLNIT POVINOSTI V SÍTI. Je to nezbytné pro to, aby váš uzel PLNIL SVOU ÚLOHU ATESTOVÁNÍ V STAKINGU. POUŽITÍ TÉTO VOLBY BUDE ZNAMENAT VYMAZÁNÍ AKTUÁLNÍCH DAT BLOKCHAINU VÁŠEHO KLIENTA A POUŽITÍ VYBRANÉ VOLBY JAKO ZDROJE PRO \n OPĚTOVNÉ ZSYNCHRONIZACI VAŠEHO UZLU.", diff --git a/launcher/src/languages/de.json b/launcher/src/languages/de.json index 33afca51c..b80bf4b92 100755 --- a/launcher/src/languages/de.json +++ b/launcher/src/languages/de.json @@ -499,7 +499,8 @@ "sync": "Synchronisierungsfehler", "taskFail": "Aufgabe fehlgeschlagen", "stats": "STATUS: OFFEN", - "clientService": "CLIENT / DIENST" + "clientService": "CLIENT / DIENST", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "IHR CLIENT speichert Blockchain-Daten AUF IHREM SERVER, damit Ihr Node das Netzwerk bedienen kann. Dies ist notwendig, damit Ihr Node seine BEGUTACHTUNGSPFLICHTEN im Staking aufnehmen kann. MIT DIESER OPTION LÖSCHEN SIE DIE AKTUELLEN BLOCKCHAIN-DATEN IHRES CLIENTS & VERWENDEN DIE AUSGEWÄHLTE OPTION ALS QUELLE, UM IHREN NODE NEU ZU SYNCHRONISIEREN.", diff --git a/launcher/src/languages/es.json b/launcher/src/languages/es.json index 455160ec9..b82955f41 100755 --- a/launcher/src/languages/es.json +++ b/launcher/src/languages/es.json @@ -499,7 +499,8 @@ "sync": "Error de Sincronización", "taskFail": "Tarea Fallida", "stats": "ESTADO: ABIERTO", - "clientService": "CLIENTE / SERVICIO" + "clientService": "CLIENTE / SERVICIO", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "SU CLIENTE Almacena datos de blockchain EN SU SERVIDOR para que SU NODO pueda servir a la red. esto es necesario para que su nodo PUEDA asumir su TAREA DE ATTESTACIÓN en STAKING. AL USAR ESTA OPCIÓN ESTÁ ELIMINANDO LOS DATOS ACTUALES DE BLOCKCHAIN DE SU CLIENTE & USA LA OPCIÓN SELECCIONADA COMO FUENTE PARA SINCRONIZAR SU NODO DE NUEVO.", diff --git a/launcher/src/languages/fa.json b/launcher/src/languages/fa.json index 5e1214502..d9b565ddc 100755 --- a/launcher/src/languages/fa.json +++ b/launcher/src/languages/fa.json @@ -499,7 +499,8 @@ "sync": "خطا در همگام‌سازی", "taskFail": "وظیفه ناموفق", "stats": "وضعیت: باز", - "clientService": "مشتری / خدمت" + "clientService": "مشتری / خدمت", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "مشتری شما داده‌های بلاکچین را روی سرور شما ذخیره می‌کند تا نود شما بتواند به شبکه خدمت کند. این کار برای انجام وظیفه اعتبارسنجی نود شما در استیکینگ ضروری است. با استفاده از این گزینه، شما داده‌های بلاکچین فعلی مشتریان خود را حذف می‌کنید و از گزینه انتخاب شده به عنوان منبع برای همگام‌سازی مجدد نود خود استفاده می‌کنید.", diff --git a/launcher/src/languages/fr.json b/launcher/src/languages/fr.json index 3b8494aa1..c213efa15 100755 --- a/launcher/src/languages/fr.json +++ b/launcher/src/languages/fr.json @@ -499,7 +499,8 @@ "sync": "Erreur de synchronisation", "taskFail": "Tâche échouée", "stats": "STATUT : OUVERT", - "clientService": "CLIENT / SERVICE" + "clientService": "CLIENT / SERVICE", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "VOTRE CLIENT stocke les données de la blockchain SUR VOTRE SERVEUR afin que votre nœud puisse servir le réseau. cela est nécessaire pour que votre nœud REPRENNE son DEVOIR D'ATTESTATION dans la MISE. EN UTILISANT CETTE OPTION, VOUS SUPPRIMEZ LES DONNÉES ACTUELLES DE LA BLOCKCHAIN DE VOS CLIENTS ET UTILISEZ L'OPTION SÉLECTIONNÉE COMME SOURCE POUR SYNCHRONISER VOTRE NŒUD À NOUVEAU.", diff --git a/launcher/src/languages/hi.json b/launcher/src/languages/hi.json index dc69beff6..7c2770a5e 100644 --- a/launcher/src/languages/hi.json +++ b/launcher/src/languages/hi.json @@ -499,7 +499,8 @@ "sync": "सिंक्रनाइज़ेशन त्रुटि", "taskFail": "कार्य विफल", "stats": "स्थिति: खुला", - "clientService": "क्लाइंट / सेवा" + "clientService": "क्लाइंट / सेवा", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "आपका क्लाइंट ब्लॉकचेन डेटा आपके सर्वर पर स्टोर करता है ताकि आपका नोड नेटवर्क की सेवा कर सके। यह आपके नोड को अपने स्टेकिंग कर्तव्य में उठाने के लिए आवश्यक है। इस विकल्प का उपयोग करके आप अपने क्लाइंट के वर्तमान ब्लॉकचेन डेटा को हटा रहे हैं और अपने नोड को नए सिरे से सिंक्रनाइज़ करने के लिए चयनित विकल्प का उपयोग करेंगे।", diff --git a/launcher/src/languages/id.json b/launcher/src/languages/id.json index 30b4ee35b..5798fe2d5 100644 --- a/launcher/src/languages/id.json +++ b/launcher/src/languages/id.json @@ -499,7 +499,8 @@ "sync": "Kesalahan Sinkronisasi", "taskFail": "Tugas Gagal", "stats": "STATUS: BUKA", - "clientService": "KLIEN / LAYANAN" + "clientService": "KLIEN / LAYANAN", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "KLIENT ANDA Menyimpan data blockchain DI SERVER ANDA AGAR NODE ANDA DAPAT melayani jaringan. ini diperlukan agar node ANDA DAPAT MELAKUKAN TUGAS ATTESTASI DALAM STAKING. DENGAN MENGGUNAKAN OPSI INI ANDA MENGHAPUS DATA BLOCKCHAIN KLIENT ANDA SAAT INI & MENGGUNAKAN OPSI YANG DIPILIH SEBAGAI SUMBER UNTUK MENYINKRONKAN NODE ANDA BARU.", diff --git a/launcher/src/languages/it.json b/launcher/src/languages/it.json index d348fc0ee..14a2a2cee 100755 --- a/launcher/src/languages/it.json +++ b/launcher/src/languages/it.json @@ -499,7 +499,8 @@ "sync": "Errore di Sincronizzazione", "taskFail": "Compito Fallito", "stats": "STATO: APERTO", - "clientService": "CLIENT / SERVIZIO" + "clientService": "CLIENT / SERVIZIO", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "IL TUO CLIENT Memorizza i dati della blockchain SUL TUO SERVER COSÌ IL TUO NODO PUÒ servire la rete. questo è necessario affinché il tuo nodo POSSA iniziare il suo DOVERE DI ATTESTAZIONE nello STAKING. UTILIZZANDO QUESTA OPZIONE STAI CANCELLANDO I DATI ATTUALI DELLA BLOCKCHAIN DEL TUO CLIENT & USI L'OPZIONE SELEZIONATA COME FONTE PER SINCRONIZZARE DI NUOVO IL TUO NODO.", diff --git a/launcher/src/languages/ja.json b/launcher/src/languages/ja.json index b5f67c6ae..2eca40957 100755 --- a/launcher/src/languages/ja.json +++ b/launcher/src/languages/ja.json @@ -499,7 +499,8 @@ "sync": "同期エラー", "taskFail": "タスク失敗", "stats": "ステータス:オープン", - "clientService": "クライアント/サービス" + "clientService": "クライアント/サービス", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "クライアントはブロックチェーンデータをサーバーに保存して、ノードがネットワークにサービスを提供できるようにします。これは、ノードがステーキングで証明義務を果たすために必要です。このオプションを使用すると、クライアントの現在のブロックチェーンデータを削除し、選択したオプションをソースとして使用して、ノードを再同期します。", diff --git a/launcher/src/languages/ko.json b/launcher/src/languages/ko.json index 98eacac42..801d45e71 100644 --- a/launcher/src/languages/ko.json +++ b/launcher/src/languages/ko.json @@ -499,7 +499,8 @@ "sync": "동기화 오류", "taskFail": "작업 실패", "stats": "상태: 열림", - "clientService": "클라이언트 / 서비스" + "clientService": "클라이언트 / 서비스", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "클라이언트는 블록체인 데이터를 서버에 저장하여 노드가 네트워크를 서비스할 수 있게 합니다. 이것은 노드가 스테이킹에서 증명 의무를 수행하는 데 필요합니다. 이 옵션을 사용하면 클라이언트의 현재 블록체인 데이터를 삭제하고 선택한 옵션을 소스로 사용하여 노드를 새로 동기화합니다.", diff --git a/launcher/src/languages/mn.json b/launcher/src/languages/mn.json index 4db4cf3d0..262c44025 100755 --- a/launcher/src/languages/mn.json +++ b/launcher/src/languages/mn.json @@ -499,7 +499,8 @@ "sync": "Синхрончлолын Алдаа", "taskFail": "Даалгавар амжилтгүй боллоо", "stats": "СТАТУС: НЭЭЛТТЭЙ", - "clientService": "КЛАЙНТ / СЕРВИС" + "clientService": "КЛАЙНТ / СЕРВИС", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "ТАНЫ КЛАЙНТ блокчейн өгөгдлийг ТАНЫ СЕРВЕР ДЭЭР хадгалдаг тул ТАНЫ НӨҮД СҮЛЖЭЭНД үйлчлэх боломжтой. Энэ нь таны нөүд СТАЙКИНГ дэх ATTESTATION DUTY-гээ авахын тулд зайлшгүй шаардлагатай. ЭНЭ СОНГОЛТЫГ АШИГЛАСНААР ТА КЛАЙНТЫНХАА ОДОО БАЙГАА БЛОКЧЭЙН ӨГӨГДӨЛИЙГ УСТГАЖ & СОНГОГДСОН ТОХИРУУЛГЫГ НӨҮД ШИНЭЭР СИНХРОНЧЛОХ ЭХ ҮҮСВЭР БОЛГОЖ АШИГЛАНА.", diff --git a/launcher/src/languages/mr.json b/launcher/src/languages/mr.json index 68726c41d..a8a97ea33 100644 --- a/launcher/src/languages/mr.json +++ b/launcher/src/languages/mr.json @@ -499,7 +499,8 @@ "sync": "सिंक्रनायझेशन त्रुटी", "taskFail": "कार्य अयशस्वी", "stats": "स्थिती: उघडा", - "clientService": "क्लायंट / सेवा" + "clientService": "क्लायंट / सेवा", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "तुमचा क्लायंट तुमच्या सर्व्हरवर ब्लॉकचेन डेटा संग्रहित करतो जेणेकरून तुमचा नोड नेटवर्कला सेवा देऊ शकेल. हे तुमच्या नोडला स्टेकिंगमध्ये त्याचे अटेस्टेशन कर्तव्य पकडण्यासाठी आवश्यक आहे. हे पर्याय वापरून तुम्ही तुमच्या क्लायंटचे सध्याचे ब्लॉकचेन डेटा हटवता आणि निवडलेल्या पर्यायाचा स्रोत वापरून तुमचा नोड नव्याने सिंक करता.", diff --git a/launcher/src/languages/nl.json b/launcher/src/languages/nl.json index ad5819927..c70c6dbc8 100755 --- a/launcher/src/languages/nl.json +++ b/launcher/src/languages/nl.json @@ -499,7 +499,8 @@ "sync": "Synchronisatiefout", "taskFail": "Taak Mislukt", "stats": "STATUS: OPEN", - "clientService": "CLIENT / SERVICE" + "clientService": "CLIENT / SERVICE", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "UW CLIENT Slaat blockchain data OP UW SERVER OP ZODAT UW NODE het netwerk kan dienen. dit is noodzakelijk voor uw node OM zijn ATTESTATIE PLICHT OP TE PAKKEN IN STAKING. DOOR DEZE OPTIE TE GEBRUIKEN VERWIJDERT U DE HUIDIGE BLOCKCHAIN DATA VAN UW CLIENTS & GEBRUIKT U DE GESELECTEERDE OPTIE ALS EEN BRON OM UW NODE OPNIEUW TE SYNCHRONISEREN.", diff --git a/launcher/src/languages/pt.json b/launcher/src/languages/pt.json index bb313dc01..7f2cabdc8 100755 --- a/launcher/src/languages/pt.json +++ b/launcher/src/languages/pt.json @@ -499,7 +499,8 @@ "sync": "Erro de Sincronização", "taskFail": "Tarefa Falhou", "stats": "STATUS: ABERTO", - "clientService": "CLIENTE / SERVIÇO" + "clientService": "CLIENTE / SERVIÇO", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "SEU CLIENTE Armazena dados da blockchain EM SEU SERVIDOR PARA QUE SEU NÓ POSSA servir a rede. isso é necessário para que seu nó ASSUMA sua FUNÇÃO DE ATTESTAÇÃO EM STAKING. AO USAR ESTA OPÇÃO VOCÊ ESTÁ DELETANDO OS DADOS ATUAIS DA BLOCKCHAIN DO SEU CLIENTE & USARÁ A OPÇÃO SELECIONADA COMO FONTE PARA SINCRONIZAR SEU NÓ NOVAMENTE.", diff --git a/launcher/src/languages/ru.json b/launcher/src/languages/ru.json index fc2ef3431..9a65721fd 100755 --- a/launcher/src/languages/ru.json +++ b/launcher/src/languages/ru.json @@ -499,7 +499,8 @@ "sync": "Ошибка синхронизации", "taskFail": "Задача не выполнена", "stats": "СТАТУС: ОТКРЫТО", - "clientService": "КЛИЕНТ / СЛУЖБА" + "clientService": "КЛИЕНТ / СЛУЖБА", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "ВАШ КЛИЕНТ Хранит данные блокчейна НА ВАШЕМ СЕРВЕРЕ, чтобы ваш узел мог обслуживать сеть. это необходимо для того, чтобы ваш узел МОГ ВЫПОЛНЯТЬ СВОИ ОБЯЗАННОСТИ ПО АТТЕСТАЦИИ В СТЕЙКИНГЕ. ИСПОЛЬЗУЯ ЭТУ ОПЦИЮ, ВЫ УДАЛЯЕТЕ ТЕКУЩИЕ ДАННЫЕ БЛОКЧЕЙНА ВАШИХ КЛИЕНТОВ И ИСПОЛЬЗУЕТЕ ВЫБРАННЫЙ ВАРИАНТ КАК ИСТОЧНИК ДЛЯ НОВОЙ СИНХРОНИЗАЦИИ ВАШЕГО УЗЛА.", diff --git a/launcher/src/languages/sr.json b/launcher/src/languages/sr.json index 563a4c89b..75f49cb42 100755 --- a/launcher/src/languages/sr.json +++ b/launcher/src/languages/sr.json @@ -499,7 +499,8 @@ "sync": "Грешка у синхронизацији", "taskFail": "Задатак није успео", "stats": "СТАТУС: ОТВОРЕН", - "clientService": "КЛИЈЕНТ / УСЛУГА" + "clientService": "КЛИЈЕНТ / УСЛУГА", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "ВАШ КЛИЈЕНТ чува податке о блокчејну НА ВАШЕМ СЕРВЕРУ тако да ваш чвор може служити мрежи. ово је потребно за ваш чвор ДА ПРЕУЗМЕ своју ДУЖНОСТ ПОТВРДЕ у СТЕЈКИНГУ. КОРИШЋЕЊЕМ ОВЕ ОПЦИЈЕ БРИШЕТЕ ТРЕНУТНЕ ПОДАТКЕ О БЛОКЧЕЈНУ ВАШЕГ КЛИЈЕНТА & КОРИСТИТЕ ИЗАБРАНУ ОПЦИЈУ КАО ИЗВОР ЗА ПОНОВНУ СИНХРОНИЗАЦИЈУ ВАШЕГ ЧВОРА.", diff --git a/launcher/src/languages/sw.json b/launcher/src/languages/sw.json index 47019ccc4..fb093ab0a 100644 --- a/launcher/src/languages/sw.json +++ b/launcher/src/languages/sw.json @@ -499,7 +499,8 @@ "sync": "Hitilafu ya Usawazishaji", "taskFail": "Kazi Imeshindwa", "stats": "HADHI: WAZI", - "clientService": "MTEJA / HUDUMA" + "clientService": "MTEJA / HUDUMA", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "MTEJA WAKO Huhifadhi data ya blockchain KWENYE SEVA YAKO ili nodi yako iweze kuhudumia mtandao. hii ni muhimu kwa nodi yako KUCHUKUA jukumu lake la UTHIBITISHO katika KUSTAWISHA. KWA KUTUMIA CHAGUO HILI UNAFUTA DATA YA BLOCKCHAIN YA MTEJA WAKO ILIYOPO & TUMIA CHAGUO LILILOCHAGULIWA KAMA CHANZO CHA KUSAWAZISHA NODI YAKO UPYA.", diff --git a/launcher/src/languages/ta.json b/launcher/src/languages/ta.json index 5091b1294..63787754f 100644 --- a/launcher/src/languages/ta.json +++ b/launcher/src/languages/ta.json @@ -499,7 +499,8 @@ "sync": "ஒத்திசைவு பிழை", "taskFail": "பணி தோல்வி", "stats": "நிலைமை: திறந்த", - "clientService": "கிளையண்ட் / சேவை" + "clientService": "கிளையண்ட் / சேவை", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "உங்கள் கிளையண்ட் உங்கள் சர்வரில் பிளாக்செயின் தரவுகளை சேமிக்கிறது என்பதால் உங்கள் நோட் நெட்வொர்க்கை சேவை செய்ய முடியும். ஸ்டேக்கிங்கில் அதன் சான்று கடமையை ஏற்க உங்கள் நோட் தேவை. இந்த விருப்பத்தை பயன்படுத்துவதன் மூலம் நீங்கள் உங்கள் கிளையண்டின் தற்போதைய பிளாக்செயின் தரவுகளை அழிக்கிறீர்கள் & உங்கள் நோட்டை புதிதாக ஒத்திசைக்க தேர்ந்தெடுத்த விருப்பத்தை ஒரு மூலமாக பயன்படுத்துகிறீர்கள்.", diff --git a/launcher/src/languages/te.json b/launcher/src/languages/te.json index 6cf337572..ebf2e1dfd 100644 --- a/launcher/src/languages/te.json +++ b/launcher/src/languages/te.json @@ -499,7 +499,8 @@ "sync": "సింక్రోనైజేషన్ లోపం", "taskFail": "టాస్క్ విఫలమైంది", "stats": "స్థితి: ఓపెన్", - "clientService": "క్లయింట్ / సేవ" + "clientService": "క్లయింట్ / సేవ", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "మీ క్లయింట్ మీ సర్వర్‌పై బ్లాక్‌చైన్ డేటాను స్టోర్ చేస్తుంది ఎందుకంటే మీ నోడ్ నెట్‌వర్క్‌ని సర్వ్ చేయగలదు. ఇది మీ నోడ్‌ను స్టేకింగ్‌లో దాని అటెస్టేషన్ డ్యూటీ ఎత్తుకోవడానికి అవసరం. ఈ ఎంపికను ఉపయోగించడం ద్వారా మీ క్లయింట్‌లోని ప్రస్తుత బ్లాక్‌చైన్ డేటాను తొలగిస్తారు & మీ నోడ్‌ని కొత్తగా సింక్రోనైజ్ చేస్తారు.", diff --git a/launcher/src/languages/tr.json b/launcher/src/languages/tr.json index 476ec35ab..fd42a9ed0 100755 --- a/launcher/src/languages/tr.json +++ b/launcher/src/languages/tr.json @@ -499,7 +499,8 @@ "sync": "Senkronizasyon Hatası", "taskFail": "Görev Başarısız", "stats": "DURUM: AÇIK", - "clientService": "İSTEMCİ / HİZMET" + "clientService": "İSTEMCİ / HİZMET", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "İSTEMCİNİZ sunucunuzda blok zincir verilerini saklar, böylece düğümünüz ağa hizmet edebilir. Bu, düğümünüzün STAKING'deki ATAMA GÖREVİNİ alabilmesi için gereklidir. BU SEÇENEĞİ KULLANARAK İSTEMCİNİZİN MEVCUT BLOK ZİNCİR VERİLERİNİ SİLİYOR VE SEÇTİĞİNİZ KAYNAK KULLANILARAK DÜĞÜMÜNÜZÜ YENİDEN SENKRONİZE EDİYORSUNUZ.", diff --git a/launcher/src/languages/ur.json b/launcher/src/languages/ur.json index 908314dd9..7ab7bfb4b 100644 --- a/launcher/src/languages/ur.json +++ b/launcher/src/languages/ur.json @@ -499,7 +499,8 @@ "sync": "مطابقت کی غلطی", "taskFail": "کام ناکام", "stats": "حالت: کھلا", - "clientService": "کلائنٹ / خدمت" + "clientService": "کلائنٹ / خدمت", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "آپ کا کلائنٹ آپ کے سرور پر بلاکچین کا ڈیٹا محفوظ کرتا ہے تاکہ آپ کا نوڈ نیٹ ورک کی خدمت کر سکے۔ یہ آپ کے نوڈ کو اپنی ہِسّہ داری کی ڈیوٹی کو پکڑنے کے لیے ضروری ہے۔ اس آپشن کا استعمال کرکے آپ اپنے کلائنٹس کا موجودہ بلاکچین ڈیٹا مٹا دیں گے اور اپنے نوڈ کو نئے سرے سے ہم آہنگ کرنے کے لیے منتخب آپشن کا استعمال کریں گے۔", diff --git a/launcher/src/languages/vi.json b/launcher/src/languages/vi.json index be21caf5e..4205a2188 100755 --- a/launcher/src/languages/vi.json +++ b/launcher/src/languages/vi.json @@ -499,7 +499,8 @@ "sync": "Lỗi Đồng bộ", "taskFail": "Nhiệm vụ Thất bại", "stats": "TRẠNG THÁI: MỞ", - "clientService": "KHÁCH HÀNG / DỊCH VỤ" + "clientService": "KHÁCH HÀNG / DỊCH VỤ", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "CLIENT CỦA BẠN lưu trữ dữ liệu blockchain TRÊN SERVER CỦA BẠN để NODE CỦA BẠN có thể phục vụ mạng. điều này là cần thiết cho NODE CỦA BẠN ĐỂ TIẾP TỤC nhiệm vụ CHỨNG THỰC TRONG STAKING. BẰNG CÁCH SỬ DỤNG TÙY CHỌN NÀY BẠN ĐANG XÓA DỮ LIỆU BLOCKCHAIN HIỆN TẠI CỦA CLIENT & SỬ DỤNG TÙY CHỌN ĐÃ CHỌN LÀM NGUỒN ĐỂ ĐỒNG BỘ NODE MỚI.", diff --git a/launcher/src/languages/zh.json b/launcher/src/languages/zh.json index 2025f5328..b9c3f6c5c 100755 --- a/launcher/src/languages/zh.json +++ b/launcher/src/languages/zh.json @@ -499,7 +499,8 @@ "sync": "同步错误", "taskFail": "任务失败", "stats": "状态:开启", - "clientService": "客户端/服务" + "clientService": "客户端/服务", + "csm": "csm operator monitoring" }, "resyncModal": { "message": "您的客户端将把区块链数据存储在您的服务器上,以便您的节点可以为网络提供服务。这对于您的节点在质押中提高其证明工作是必要的。使用此选项删除您的客户端数据,并使用所选源同步您的节点。", From 39b902327ce03a2ccb90fb604279240c842a5e5f Mon Sep 17 00:00:00 2001 From: NeoPlays <80448387+NeoPlays@users.noreply.github.com> Date: Wed, 4 Sep 2024 12:16:18 +0200 Subject: [PATCH 3/5] ADD: Format Check Action (#2033) * ADD: staking module for ejector, random EC in OneClickInstallation * ADD: Format Check for Repo * FIX: typo --- .github/workflows/code_quality_check.yml | 21 + .vscode/settings.json | 3 + launcher/.prettierignore | 8 + launcher/.prettierrc.json | 4 +- launcher/customsign.js | 17 +- launcher/package.json | 3 +- launcher/public/index.html | 4 +- launcher/public/output.css | 3018 +++++++++-------- launcher/src/StereumUpdater.js | 132 +- launcher/src/backend/AuthenticationService.js | 20 +- launcher/src/backend/ConfigManager.js | 15 +- launcher/src/backend/HetznerServer.js | 44 +- launcher/src/backend/Monitoring.js | 110 +- launcher/src/backend/NodeConnection.js | 207 +- launcher/src/backend/NodeUpdates.js | 6 +- launcher/src/backend/OneClickInstall.js | 129 +- launcher/src/backend/SSHService.js | 14 +- launcher/src/backend/SSHServiceTunnel.js | 18 +- launcher/src/backend/ServiceManager.js | 215 +- launcher/src/backend/TaskManager.js | 9 +- launcher/src/backend/TekuGasLimitConfig.js | 27 +- .../src/backend/ValidatorAccountManager.js | 130 +- .../backend/ethereum-services/BesuService.js | 8 +- .../ethereum-services/CharonService.js | 35 +- .../ethereum-services/CustomService.js | 8 +- .../ethereum-services/ErigonService.js | 20 +- .../ExternalExecutionService.js | 5 +- .../backend/ethereum-services/GethService.js | 5 +- .../ethereum-services/KuboIPFSService.js | 5 +- .../backend/ethereum-services/LCOMService.js | 4 +- .../ethereum-services/LidoObolExitService.js | 17 +- .../LighthouseBeaconService.js | 8 +- .../LighthouseValidatorService.js | 9 +- .../LodestarValidatorService.js | 8 +- .../MetricsExporterService.js | 2 +- .../ethereum-services/NethermindService.js | 8 +- .../NimbusValidatorService.js | 9 +- .../backend/ethereum-services/NodeService.js | 10 +- .../PrometheusNodeExporterService.js | 5 +- .../ethereum-services/PrometheusService.js | 5 +- .../ethereum-services/PrysmBeaconService.js | 16 +- .../PrysmValidatorService.js | 22 +- .../backend/ethereum-services/RethService.js | 12 +- .../ethereum-services/SSVDKGService.js | 10 +- .../ethereum-services/SSVNetworkService.js | 5 +- .../backend/ethereum-services/ServicePort.js | 1 - .../ethereum-services/TekuBeaconService.js | 5 +- .../ethereum-services/TekuValidatorService.js | 10 +- .../ethereum-services/Web3SignerService.js | 10 +- .../tests/integration/BesuService.int.js | 12 +- .../tests/integration/ErigonService.int.js | 12 +- .../FlashbotsMevBoostService.int.js | 16 +- .../tests/integration/GethService.int.js | 13 +- .../LighthouseBeaconService.int.js | 40 +- .../integration/LodestarBeaconService.int.js | 37 +- .../integration/NethermindService.int.js | 12 +- .../integration/NimbusBeaconService.int.js | 34 +- .../tests/integration/NodeConnection.int.js | 11 +- .../integration/PrysmBeaconService.int.js | 49 +- .../integration/TekuBeaconService.int.js | 33 +- .../backend/tests/unit/BesuService.test.js | 22 +- .../backend/tests/unit/ErigonService.test.js | 30 +- .../backend/tests/unit/GethService.test.js | 20 +- .../backend/tests/unit/GrafanaService.test.js | 18 +- .../unit/LighthouseBeaconService.test.js | 20 +- .../unit/LighthouseValidatorService.test.js | 24 +- .../tests/unit/LodestarBeaconService.test.js | 20 +- .../unit/LodestarValidatorService.test.js | 24 +- .../tests/unit/NethermindService.test.js | 20 +- .../tests/unit/NimbusBeaconService.test.js | 20 +- .../PrometheusNodeExporterService.test.js | 3 +- .../tests/unit/PrometheusService.test.js | 8 +- .../tests/unit/PrysmBeaconService.test.js | 32 +- .../tests/unit/PrysmValidatorService.test.js | 4 +- .../tests/unit/SSVNetworkService.test.js | 35 +- .../backend/tests/unit/ServiceManager.test.js | 34 +- .../backend/tests/unit/ServicePort.test.js | 4 +- .../backend/tests/unit/ServiceVolume.test.js | 4 +- .../backend/tests/unit/StringUtils.test.js | 4 +- .../tests/unit/TekuBeaconService.test.js | 20 +- launcher/src/background.js | 7 +- .../components/menu/SingleMenu.vue | 5 +- .../components/modals/LogoutModal.vue | 5 +- .../components/modals/NotifModal.vue | 16 +- .../components/modals/ReconnectModal.vue | 4 +- .../components/modals/SupportModal.vue | 12 +- .../components/modals/UpdatePanel.vue | 60 +- .../components/services/ServiceBody.vue | 30 +- .../base-header/components/tabs/SingleTab.vue | 5 +- .../components/cards/MiniCard.vue | 4 +- .../components/cards/ThinCard.vue | 4 +- .../components/cards/WidgetCard.vue | 4 +- .../control-page/components/node/NodeBody.vue | 6 +- .../UI/credit-page/section/CreditHeader.vue | 7 +- .../components/CustomAnim.vue | 10 +- .../components/CustomFooter.vue | 5 +- .../components/CustomHead.vue | 8 +- .../components/CustomPath.vue | 16 +- .../components/UI/edit-page/EditScreen.vue | 35 +- .../edit-page/components/drawer/DrawerBox.vue | 8 +- .../components/drawer/DrawerFilter.vue | 17 +- .../components/drawer/DrawerMenu.vue | 11 +- .../components/drawer/ServicesDrawer.vue | 17 +- .../components/drawer/SetupsDrawer.vue | 29 +- .../edit-page/components/edit/ConfigBody.vue | 8 +- .../UI/edit-page/components/edit/EditBody.vue | 8 +- .../components/edit/SyncCarousel.vue | 12 +- .../components/edit/clients/ClientLayout.vue | 21 +- .../edit/clients/ConsensusClients.vue | 17 +- .../edit/clients/ExecutionClients.vue | 7 +- .../components/edit/clients/GeneralMenu.vue | 24 +- .../edit/clients/ValidatorClients.vue | 18 +- .../components/edit/header/NetworkDetails.vue | 33 +- .../components/edit/header/ServerDetails.vue | 20 +- .../components/edit/header/SetupDetails.vue | 4 +- .../components/edit/setups/RenameSetup.vue | 2 +- .../components/edit/setups/SetupDropdown.vue | 3 +- .../components/edit/setups/SetupLayout.vue | 15 +- .../components/loader-anime/LoaderAnime.vue | 4 +- .../components/modals/AddConnection.vue | 41 +- .../edit-page/components/modals/AddModal.vue | 10 +- .../components/modals/CustomModal.vue | 6 +- .../components/modals/CustomWarning.vue | 4 +- .../edit-page/components/modals/InfoModal.vue | 12 +- .../components/modals/MevboostRelays.vue | 13 +- .../components/modals/ModifyContent.vue | 41 +- .../components/modals/NetworkModal.vue | 37 +- .../edit-page/components/modals/NukeModal.vue | 4 +- .../components/modals/RelaysCheckbox.vue | 9 +- .../components/modals/StateModal.vue | 8 +- .../components/modals/SwitchContent.vue | 21 +- .../modals/custom-service/CustomConfig.vue | 48 +- .../components/modals/setups/CreateSetup.vue | 90 +- .../components/modals/setups/SetupInfos.vue | 8 +- .../components/service/ServiceBody.vue | 37 +- .../UI/edit-page/sections/ChangesSection.vue | 9 +- .../UI/edit-page/sections/SidebarSection.vue | 50 +- .../components/ImportingList.vue | 66 +- .../components/ImportingSyncing.vue | 42 +- .../components/ImportingVerify.vue | 39 +- .../import-config/components/UploadConfig.vue | 55 +- .../components/footer/ImportFooter.vue | 5 +- .../components/header/ImportHeader.vue | 8 +- .../UI/import-config/configScreen.vue | 10 +- .../UI/language-page/LangScreen.vue | 8 +- .../UI/language-page/components/LogoBody.vue | 10 +- .../UI/language-page/components/MenuBody.vue | 8 +- .../components/UI/node-page/NodeScreen.vue | 4 +- .../node-page/components/NetworkDropdown.vue | 5 +- .../components/alert/AlertSkeleton.vue | 3 +- .../node-page/components/alert/NodeAlert.vue | 38 +- .../UI/node-page/components/logs/LogBody.vue | 12 +- .../node-page/components/logs/LogFooter.vue | 37 +- .../node-page/components/logs/LogHeader.vue | 4 +- .../node-page/components/logs/LogSidebar.vue | 15 +- .../UI/node-page/components/logs/LogsPage.vue | 7 +- .../components/modals/CustomModal.vue | 25 +- .../components/modals/StateModal.vue | 4 +- .../node-page/components/node/ConfigBody.vue | 12 +- .../components/node/ConfirmModal.vue | 5 +- .../UI/node-page/components/node/NodeBody.vue | 47 +- .../node-page/components/node/NodeHeader.vue | 6 +- .../components/node/ServerDetails.vue | 8 +- .../components/node/clients/ClientButtons.vue | 119 +- .../components/node/clients/ClientLayout.vue | 28 +- .../node/clients/ClientSkeleton.vue | 9 +- .../node/clients/ConsensusClients.vue | 23 +- .../node/clients/ExecutionClients.vue | 24 +- .../node/clients/ValidatorClients.vue | 4 +- .../components/node/setups/SetupButtons.vue | 11 +- .../components/node/setups/SetupLayout.vue | 14 +- .../components/node/setups/SingleSetup.vue | 7 +- .../components/service/ClientStatus.vue | 5 +- .../components/service/ServiceBody.vue | 11 +- .../components/service/ServiceButtons.vue | 58 +- .../components/service/ServiceSkeleton.vue | 9 +- .../UI/node-page/sections/ExpertWindow.vue | 106 +- .../UI/node-page/sections/LogsSection.vue | 7 +- .../UI/node-page/sections/PluginLogs.vue | 11 +- .../UI/node-page/sections/SidebarSection.vue | 6 +- .../components/mevboost/MevboostBody.vue | 21 +- .../components/mevboost/MevboostFooter.vue | 5 +- .../components/mevboost/MevboostHeader.vue | 8 +- .../components/plugin/ConfigBody.vue | 33 +- .../components/plugin/ConfigFooter.vue | 5 +- .../components/plugin/ConfigHeader.vue | 9 +- .../components/plugin/InstallationPath.vue | 10 +- .../components/presets/PresetBody.vue | 20 +- .../components/presets/PresetFooter.vue | 5 +- .../components/presets/PresetHeader.vue | 4 +- .../UI/one-click/components/sync/SyncBody.vue | 28 +- .../one-click/components/sync/SyncFooter.vue | 5 +- .../one-click/components/sync/SyncHeader.vue | 9 +- .../sync/components/ConsensusSync.vue | 18 +- .../sync/components/ExecutionSync.vue | 26 +- .../sync/components/TheCarousel.vue | 58 +- .../components/verify/VerifyBody.vue | 20 +- .../components/verify/VerifyFooter.vue | 5 +- .../components/verify/VerifyHeader.vue | 9 +- .../UI/one-click/sections/SelectPreset.vue | 4 +- .../UI/plugin-installation/ConsensusSync.vue | 7 +- .../UI/plugin-installation/FastSync.vue | 8 +- .../UI/plugin-installation/MevboostConfig.vue | 7 +- .../server-management/MultiServerScreen.vue | 25 +- .../components/ServerBody.vue | 12 +- .../components/ServerHeader.vue | 4 +- .../components/login-form/LoginForm.vue | 62 +- .../components/login-form/LoginPanel.vue | 4 +- .../components/modals/ErrorModal.vue | 4 +- .../components/modals/GenerateKey.vue | 72 +- .../components/modals/TwofactorModal.vue | 4 +- .../components/saved-servers/ServerPanel.vue | 21 +- .../server-details/ChangePassword.vue | 20 +- .../server-details/DetailsPanel.vue | 4 +- .../server-details/ServerDetails.vue | 10 +- .../server-settings/ServerSettings.vue | 8 +- .../server-settings/SettingsPanel.vue | 4 +- .../components/server-update/UpdatePanel.vue | 4 +- .../components/server-update/UpdateServer.vue | 31 +- .../components/ssh-management/SshPanel.vue | 10 +- .../two-factor-auth/TwoFactorCheckLine.vue | 10 +- .../UI/services-modal/GrafanaModal.vue | 5 +- .../UI/services-modal/MevboostModal.vue | 18 +- .../UI/services-modal/ObolModal.vue | 35 +- .../UI/services-modal/PrometheusModal.vue | 5 +- .../UI/services-modal/RegisterSsv.vue | 9 +- .../UI/services-modal/SecretkeyRegister.vue | 6 +- .../UI/services-modal/SsvDashboard.vue | 12 +- .../components/UI/services-modal/SsvDkg.vue | 5 +- .../components/UI/services-modal/SsvModal.vue | 40 +- .../UI/services-modal/plugin/DkgGenerator.vue | 5 +- .../UI/setting-page/components/SidebarBtn.vue | 4 +- .../setting-page/components/VolumeSlider.vue | 5 +- .../UI/setting-page/section/SideBar.vue | 9 +- .../UI/staking-page/StakingScreen.vue | 152 +- .../components/header/StakingHeader.vue | 7 +- .../staking-page/components/list/ListBody.vue | 54 +- .../components/list/ListHeader.vue | 29 +- .../components/list/ListPanels.vue | 44 +- .../components/list/RemoteList.vue | 7 +- .../components/list/panels/InsertPanel.vue | 8 +- .../components/list/panels/ManualRemote.vue | 6 +- .../components/list/panels/PasswordPanel.vue | 39 +- .../components/list/panels/SearchPanel.vue | 4 +- .../components/list/panels/ValidatorPanel.vue | 17 +- .../components/list/rows/DoppelGCheckRow.vue | 4 +- .../components/list/rows/KeyRow.vue | 36 +- .../components/management/ClientCommands.vue | 4 +- .../components/management/EpochDuty.vue | 8 +- .../management/ValidatorRewards.vue | 5 +- .../components/client-commands/ButtonBox.vue | 4 +- .../components/client-commands/ButtonRow.vue | 18 +- .../client-commands/ValidatorState.vue | 10 +- .../components/epoch-duty/DutyBody.vue | 4 +- .../components/epoch-duty/DutyFooter.vue | 4 +- .../components/epoch-duty/DutyHeader.vue | 8 +- .../val-rewards/AttestationReward.vue | 28 +- .../components/val-rewards/BlockReward.vue | 15 +- .../val-rewards/CommitteeReward.vue | 15 +- .../components/val-rewards/EpochSlot.vue | 22 +- .../components/val-rewards/TotalBalance.vue | 27 +- .../components/modals/ImportRemote.vue | 12 +- .../components/modals/ImportValidator.vue | 13 +- .../components/modals/RemoveGroup.vue | 4 +- .../components/modals/RemoveValidators.vue | 16 +- .../components/modals/RiskWarning.vue | 8 +- .../components/modals/StakingCustomModal.vue | 5 +- .../components/modals/WithdrawMultiple.vue | 80 +- .../staking-page/sections/DisabledSection.vue | 22 +- .../UI/staking-page/sections/ListSection.vue | 22 +- .../sections/ManagementSection.vue | 6 +- .../staking-page/sections/SidebarSection.vue | 19 +- .../UI/task-manager/TaskManager.vue | 7 +- .../components/TerminalHeader.vue | 5 +- .../UI/the-control/AmsterdamComponent.vue | 22 +- .../UI/the-control/ControlAlert.vue | 19 +- .../UI/the-control/ControlScreen.vue | 23 +- .../src/components/UI/the-control/DataApi.vue | 8 +- .../components/UI/the-control/DiskSpeed.vue | 21 +- .../components/UI/the-control/EpochSlot.vue | 6 +- .../components/UI/the-control/MachineName.vue | 6 +- .../UI/the-control/NewPeerToPeer.vue | 14 +- .../components/UI/the-control/RpcEndpoint.vue | 8 +- .../UI/the-control/SubscribedSubnets.vue | 14 +- .../components/UI/the-control/TheBalance.vue | 13 +- .../components/UI/the-control/TheStaking.vue | 23 +- .../components/UI/the-control/WsEndpoint.vue | 8 +- .../UI/welcome-page/components/CardItem.vue | 7 +- .../welcome-page/components/LogoutModal.vue | 4 +- .../welcome-page/components/WelcomeFooter.vue | 10 +- .../welcome-page/components/WelcomeHeader.vue | 4 +- launcher/src/components/base/BaseLayout.vue | 53 +- .../components/base/InstallationLayout.vue | 8 +- .../src/components/layers/NetworkStatus.vue | 20 +- launcher/src/components/layers/TheFooter.vue | 12 +- launcher/src/composables/monitoring.js | 10 +- launcher/src/composables/pingQuality.js | 4 +- launcher/src/composables/services.js | 15 +- launcher/src/composables/useLogin.js | 4 +- launcher/src/composables/validators.js | 43 +- launcher/src/composables/version.js | 15 +- launcher/src/pages/WelcomePage.vue | 1 - launcher/src/store/connectClients.js | 2 +- launcher/src/store/nodeManage.js | 15 +- launcher/src/store/services.js | 3 +- launcher/vue.config.js | 3 +- 306 files changed, 3076 insertions(+), 5886 deletions(-) create mode 100644 .github/workflows/code_quality_check.yml create mode 100644 launcher/.prettierignore diff --git a/.github/workflows/code_quality_check.yml b/.github/workflows/code_quality_check.yml new file mode 100644 index 000000000..b864e81bf --- /dev/null +++ b/.github/workflows/code_quality_check.yml @@ -0,0 +1,21 @@ +name: Code Quality Check + +on: + pull_request: + branches: [main] + + workflow_dispatch: + +jobs: + prettier: + name: Prettier + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "20" + - run: npm install + working-directory: ./launcher + - run: npm run format:check + working-directory: ./launcher diff --git a/.vscode/settings.json b/.vscode/settings.json index 3150ee826..bf29f43a4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,6 +14,9 @@ "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode" }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, "vue3snippets.enable-compile-vue-file-on-did-save-code": true, "javascript.format.insertSpaceAfterOpeningAndBeforeClosingEmptyBraces": false, "typescript.format.insertSpaceAfterOpeningAndBeforeClosingEmptyBraces": false diff --git a/launcher/.prettierignore b/launcher/.prettierignore new file mode 100644 index 000000000..cd4b6bfb2 --- /dev/null +++ b/launcher/.prettierignore @@ -0,0 +1,8 @@ +**/.git +**/.svn +**/.hg +**/node_modules +**/coverage +**/dist +**/dist_electron +package-lock.json \ No newline at end of file diff --git a/launcher/.prettierrc.json b/launcher/.prettierrc.json index 9a352ee54..4bd9108e1 100755 --- a/launcher/.prettierrc.json +++ b/launcher/.prettierrc.json @@ -2,6 +2,6 @@ "semi": true, "singleQuote": false, "tabWidth": 2, - "printWidth": 120, + "printWidth": 140, "useTabs": false -} \ No newline at end of file +} diff --git a/launcher/customsign.js b/launcher/customsign.js index 08ce5e7b1..d75c893a2 100644 --- a/launcher/customsign.js +++ b/launcher/customsign.js @@ -1,13 +1,8 @@ -'use strict'; +"use strict"; // custom sign script calling digicerts keytool from out of the electron-builder -exports.default = async function(configuration) { - - if(configuration.path){ - - require("child_process").execSync( - `smctl sign --keypair-alias=${process.env.KEYPAIR_ALIAS} --input "${String(configuration.path)}"` - ); - - } - }; \ No newline at end of file +exports.default = async function (configuration) { + if (configuration.path) { + require("child_process").execSync(`smctl sign --keypair-alias=${process.env.KEYPAIR_ALIAS} --input "${String(configuration.path)}"`); + } +}; diff --git a/launcher/package.json b/launcher/package.json index 9815efb45..adbfa7758 100755 --- a/launcher/package.json +++ b/launcher/package.json @@ -21,7 +21,8 @@ "lint:fix": "eslint --ext .js,.vue --ignore-path ../.gitignore --fix src", "stereum": "concurrently \"npm:electron:serve\" \"npm:watch:css\"", "backend:watch": "nodemon --watch 'src/backend' --exec 'npm run electron:serve'", - "format": "prettier . --write" + "format": "prettier . --write", + "format:check": "prettier . --check" }, "dependencies": { "@headlessui/vue": "^1.7.16", diff --git a/launcher/public/index.html b/launcher/public/index.html index 32966587e..6d28892e4 100755 --- a/launcher/public/index.html +++ b/launcher/public/index.html @@ -10,8 +10,8 @@
diff --git a/launcher/public/output.css b/launcher/public/output.css index 6ad9d34d7..9cd44e24d 100755 --- a/launcher/public/output.css +++ b/launcher/public/output.css @@ -13,7 +13,7 @@ ::before, ::after { -webkit-box-sizing: border-box; - box-sizing: border-box; + box-sizing: border-box; /* 1 */ border-width: 0; /* 2 */ @@ -25,7 +25,7 @@ ::before, ::after { - --tw-content: ''; + --tw-content: ""; } /* @@ -47,12 +47,12 @@ html, -moz-tab-size: 4; /* 3 */ -o-tab-size: 4; - tab-size: 4; + tab-size: 4; /* 3 */ font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 4 */ -webkit-font-feature-settings: normal; - font-feature-settings: normal; + font-feature-settings: normal; /* 5 */ font-variation-settings: normal; /* 6 */ @@ -93,7 +93,7 @@ Add the correct text decoration in Chrome, Edge, and Safari. abbr:where([title]) { -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; + text-decoration: underline dotted; } /* @@ -142,7 +142,7 @@ pre { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* 1 */ -webkit-font-feature-settings: normal; - font-feature-settings: normal; + font-feature-settings: normal; /* 2 */ font-variation-settings: normal; /* 3 */ @@ -207,7 +207,7 @@ textarea { font-family: inherit; /* 1 */ -webkit-font-feature-settings: inherit; - font-feature-settings: inherit; + font-feature-settings: inherit; /* 1 */ font-variation-settings: inherit; /* 1 */ @@ -242,9 +242,9 @@ select { */ button, -input:where([type='button']), -input:where([type='reset']), -input:where([type='submit']) { +input:where([type="button"]), +input:where([type="reset"]), +input:where([type="submit"]) { -webkit-appearance: button; /* 1 */ background-color: transparent; @@ -291,7 +291,7 @@ Correct the cursor style of increment and decrement buttons in Safari. 2. Correct the outline style in Safari. */ -[type='search'] { +[type="search"] { -webkit-appearance: textfield; /* 1 */ outline-offset: -2px; @@ -384,28 +384,32 @@ textarea { 2. Set the default placeholder color to the user's configured gray 400 color. */ -input::-webkit-input-placeholder, textarea::-webkit-input-placeholder { +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { opacity: 1; /* 1 */ color: #9ca3af; /* 2 */ } -input::-moz-placeholder, textarea::-moz-placeholder { +input::-moz-placeholder, +textarea::-moz-placeholder { opacity: 1; /* 1 */ color: #9ca3af; /* 2 */ } -input:-ms-input-placeholder, textarea:-ms-input-placeholder { +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { opacity: 1; /* 1 */ color: #9ca3af; /* 2 */ } -input::-ms-input-placeholder, textarea::-ms-input-placeholder { +input::-ms-input-placeholder, +textarea::-ms-input-placeholder { opacity: 1; /* 1 */ color: #9ca3af; @@ -473,12 +477,14 @@ video { display: none; } -*{ +* { scrollbar-color: initial; scrollbar-width: initial; } -*, ::before, ::after{ +*, +::before, +::after { --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; @@ -488,19 +494,19 @@ video { --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgb(59 130 246 / 0.5); @@ -508,31 +514,31 @@ video { --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; -} - -::-ms-backdrop{ + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +::-ms-backdrop { --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; @@ -542,19 +548,19 @@ video { --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgb(59 130 246 / 0.5); @@ -562,31 +568,31 @@ video { --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; -} - -::backdrop{ + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +::backdrop { --tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-translate-x: 0; @@ -596,19 +602,19 @@ video { --tw-skew-y: 0; --tw-scale-x: 1; --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; --tw-ring-offset-width: 0px; --tw-ring-offset-color: #fff; --tw-ring-color: rgb(59 130 246 / 0.5); @@ -616,28 +622,28 @@ video { --tw-ring-shadow: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; } ::-webkit-scrollbar { @@ -657,41 +663,41 @@ video { background-color: transparent; } -.container{ +.container { width: 100%; } -@media (min-width: 640px){ - .container{ +@media (min-width: 640px) { + .container { max-width: 640px; } } -@media (min-width: 768px){ - .container{ +@media (min-width: 768px) { + .container { max-width: 768px; } } -@media (min-width: 1024px){ - .container{ +@media (min-width: 1024px) { + .container { max-width: 1024px; } } -@media (min-width: 1280px){ - .container{ +@media (min-width: 1280px) { + .container { max-width: 1280px; } } -@media (min-width: 1536px){ - .container{ +@media (min-width: 1536px) { + .container { max-width: 1536px; } } -.sr-only{ +.sr-only { position: absolute; width: 1px; height: 1px; @@ -703,4585 +709,4625 @@ video { border-width: 0; } -.pointer-events-none{ +.pointer-events-none { pointer-events: none; } -.visible{ +.visible { visibility: visible; } -.invisible{ +.invisible { visibility: hidden; } -.static{ +.static { position: static; } -.fixed{ +.fixed { position: fixed; } -.absolute{ +.absolute { position: absolute; } -.relative{ +.relative { position: relative; } -.sticky{ +.sticky { position: sticky; } -.inset-0{ +.inset-0 { inset: 0px; } -.inset-x-0{ +.inset-x-0 { left: 0px; right: 0px; } -.inset-x-20{ +.inset-x-20 { left: 5rem; right: 5rem; } -.inset-x-6{ +.inset-x-6 { left: 1.5rem; right: 1.5rem; } -.inset-y-0{ +.inset-y-0 { top: 0px; bottom: 0px; } -.-bottom-2{ +.-bottom-2 { bottom: -0.5rem; } -.-bottom-3{ +.-bottom-3 { bottom: -0.75rem; } -.-bottom-8{ +.-bottom-8 { bottom: -2rem; } -.-left-\[1px\]{ +.-left-\[1px\] { left: -1px; } -.-right-2{ +.-right-2 { right: -0.5rem; } -.-right-24{ +.-right-24 { right: -6rem; } -.-right-4{ +.-right-4 { right: -1rem; } -.-right-5{ +.-right-5 { right: -1.25rem; } -.-top-11{ +.-top-11 { top: -2.75rem; } -.-top-20{ +.-top-20 { top: -5rem; } -.-top-8{ +.-top-8 { top: -2rem; } -.-top-\[90px\]{ +.-top-\[90px\] { top: -90px; } -.bottom-0{ +.bottom-0 { bottom: 0px; } -.bottom-0\.5{ +.bottom-0\.5 { bottom: 0.125rem; } -.bottom-1{ +.bottom-1 { bottom: 0.25rem; } -.bottom-2{ +.bottom-2 { bottom: 0.5rem; } -.bottom-20{ +.bottom-20 { bottom: 5rem; } -.bottom-4{ +.bottom-4 { bottom: 1rem; } -.bottom-\[3rem\]{ +.bottom-\[3rem\] { bottom: 3rem; } -.bottom-\[8px\]{ +.bottom-\[8px\] { bottom: 8px; } -.end-0{ +.end-0 { inset-inline-end: 0px; } -.end-1{ +.end-1 { inset-inline-end: 0.25rem; } -.end-2{ +.end-2 { inset-inline-end: 0.5rem; } -.left-0{ +.left-0 { left: 0px; } -.left-1{ +.left-1 { left: 0.25rem; } -.left-1\/2{ +.left-1\/2 { left: 50%; } -.left-12{ +.left-12 { left: 3rem; } -.left-14{ +.left-14 { left: 3.5rem; } -.left-3{ +.left-3 { left: 0.75rem; } -.left-\[1\.3rem\]{ +.left-\[1\.3rem\] { left: 1.3rem; } -.left-\[17rem\]{ +.left-\[17rem\] { left: 17rem; } -.left-\[1px\]{ +.left-\[1px\] { left: 1px; } -.left-\[40\%\]{ +.left-\[40\%\] { left: 40%; } -.left-\[920px\]{ +.left-\[920px\] { left: 920px; } -.right-0{ +.right-0 { right: 0px; } -.right-1{ +.right-1 { right: 0.25rem; } -.right-10{ +.right-10 { right: 2.5rem; } -.right-2{ +.right-2 { right: 0.5rem; } -.right-3{ +.right-3 { right: 0.75rem; } -.right-4{ +.right-4 { right: 1rem; } -.right-5{ +.right-5 { right: 1.25rem; } -.right-7{ +.right-7 { right: 1.75rem; } -.right-8{ +.right-8 { right: 2rem; } -.right-\[1px\]{ +.right-\[1px\] { right: 1px; } -.right-\[20px\]{ +.right-\[20px\] { right: 20px; } -.right-\[8px\]{ +.right-\[8px\] { right: 8px; } -.start-0{ +.start-0 { inset-inline-start: 0px; } -.top-0{ +.top-0 { top: 0px; } -.top-10{ +.top-10 { top: 2.5rem; } -.top-12{ +.top-12 { top: 3rem; } -.top-14{ +.top-14 { top: 3.5rem; } -.top-16{ +.top-16 { top: 4rem; } -.top-20{ +.top-20 { top: 5rem; } -.top-8{ +.top-8 { top: 2rem; } -.top-9{ +.top-9 { top: 2.25rem; } -.top-\[-18px\]{ +.top-\[-18px\] { top: -18px; } -.top-\[1px\]{ +.top-\[1px\] { top: 1px; } -.top-\[33\%\]{ +.top-\[33\%\] { top: 33%; } -.top-\[42\%\]{ +.top-\[42\%\] { top: 42%; } -.top-\[56px\]{ +.top-\[56px\] { top: 56px; } -.top-\[7rem\]{ +.top-\[7rem\] { top: 7rem; } -.z-0{ +.z-0 { z-index: 0; } -.z-10{ +.z-10 { z-index: 10; } -.z-20{ +.z-20 { z-index: 20; } -.z-30{ +.z-30 { z-index: 30; } -.z-40{ +.z-40 { z-index: 40; } -.z-50{ +.z-50 { z-index: 50; } -.z-\[2\]{ +.z-\[2\] { z-index: 2; } -.col-span-1{ +.col-span-1 { grid-column: span 1 / span 1; } -.col-span-10{ +.col-span-10 { grid-column: span 10 / span 10; } -.col-span-2{ +.col-span-2 { grid-column: span 2 / span 2; } -.col-span-3{ +.col-span-3 { grid-column: span 3 / span 3; } -.col-span-4{ +.col-span-4 { grid-column: span 4 / span 4; } -.col-span-6{ +.col-span-6 { grid-column: span 6 / span 6; } -.col-span-7{ +.col-span-7 { grid-column: span 7 / span 7; } -.col-span-8{ +.col-span-8 { grid-column: span 8 / span 8; } -.col-span-full{ +.col-span-full { grid-column: 1 / -1; } -.col-start-1{ +.col-start-1 { grid-column-start: 1; } -.col-start-10{ +.col-start-10 { grid-column-start: 10; } -.col-start-11{ +.col-start-11 { grid-column-start: 11; } -.col-start-12{ +.col-start-12 { grid-column-start: 12; } -.col-start-13{ +.col-start-13 { grid-column-start: 13; } -.col-start-14{ +.col-start-14 { grid-column-start: 14; } -.col-start-17{ +.col-start-17 { grid-column-start: 17; } -.col-start-18{ +.col-start-18 { grid-column-start: 18; } -.col-start-19{ +.col-start-19 { grid-column-start: 19; } -.col-start-2{ +.col-start-2 { grid-column-start: 2; } -.col-start-20{ +.col-start-20 { grid-column-start: 20; } -.col-start-21{ +.col-start-21 { grid-column-start: 21; } -.col-start-22{ +.col-start-22 { grid-column-start: 22; } -.col-start-23{ +.col-start-23 { grid-column-start: 23; } -.col-start-24{ +.col-start-24 { grid-column-start: 24; } -.col-start-3{ +.col-start-3 { grid-column-start: 3; } -.col-start-4{ +.col-start-4 { grid-column-start: 4; } -.col-start-5{ +.col-start-5 { grid-column-start: 5; } -.col-start-6{ +.col-start-6 { grid-column-start: 6; } -.col-start-7{ +.col-start-7 { grid-column-start: 7; } -.col-start-8{ +.col-start-8 { grid-column-start: 8; } -.col-start-9{ +.col-start-9 { grid-column-start: 9; } -.col-end-10{ +.col-end-10 { grid-column-end: 10; } -.col-end-11{ +.col-end-11 { grid-column-end: 11; } -.col-end-12{ +.col-end-12 { grid-column-end: 12; } -.col-end-13{ +.col-end-13 { grid-column-end: 13; } -.col-end-14{ +.col-end-14 { grid-column-end: 14; } -.col-end-15{ +.col-end-15 { grid-column-end: 15; } -.col-end-16{ +.col-end-16 { grid-column-end: 16; } -.col-end-17{ +.col-end-17 { grid-column-end: 17; } -.col-end-18{ +.col-end-18 { grid-column-end: 18; } -.col-end-19{ +.col-end-19 { grid-column-end: 19; } -.col-end-2{ +.col-end-2 { grid-column-end: 2; } -.col-end-20{ +.col-end-20 { grid-column-end: 20; } -.col-end-21{ +.col-end-21 { grid-column-end: 21; } -.col-end-22{ +.col-end-22 { grid-column-end: 22; } -.col-end-23{ +.col-end-23 { grid-column-end: 23; } -.col-end-24{ +.col-end-24 { grid-column-end: 24; } -.col-end-25{ +.col-end-25 { grid-column-end: 25; } -.col-end-3{ +.col-end-3 { grid-column-end: 3; } -.col-end-4{ +.col-end-4 { grid-column-end: 4; } -.col-end-5{ +.col-end-5 { grid-column-end: 5; } -.col-end-6{ +.col-end-6 { grid-column-end: 6; } -.col-end-7{ +.col-end-7 { grid-column-end: 7; } -.col-end-8{ +.col-end-8 { grid-column-end: 8; } -.col-end-9{ +.col-end-9 { grid-column-end: 9; } -.row-span-1{ +.row-span-1 { grid-row: span 1 / span 1; } -.row-span-10{ +.row-span-10 { grid-row: span 10 / span 10; } -.row-span-2{ +.row-span-2 { grid-row: span 2 / span 2; } -.row-span-3{ +.row-span-3 { grid-row: span 3 / span 3; } -.row-span-4{ +.row-span-4 { grid-row: span 4 / span 4; } -.row-span-5{ +.row-span-5 { grid-row: span 5 / span 5; } -.row-span-6{ +.row-span-6 { grid-row: span 6 / span 6; } -.row-span-8{ +.row-span-8 { grid-row: span 8 / span 8; } -.row-span-full{ +.row-span-full { grid-row: 1 / -1; } -.row-start-1{ +.row-start-1 { grid-row-start: 1; } -.row-start-10{ +.row-start-10 { grid-row-start: 10; } -.row-start-11{ +.row-start-11 { grid-row-start: 11; } -.row-start-12{ +.row-start-12 { grid-row-start: 12; } -.row-start-13{ +.row-start-13 { grid-row-start: 13; } -.row-start-14{ +.row-start-14 { grid-row-start: 14; } -.row-start-2{ +.row-start-2 { grid-row-start: 2; } -.row-start-3{ +.row-start-3 { grid-row-start: 3; } -.row-start-4{ +.row-start-4 { grid-row-start: 4; } -.row-start-5{ +.row-start-5 { grid-row-start: 5; } -.row-start-6{ +.row-start-6 { grid-row-start: 6; } -.row-start-7{ +.row-start-7 { grid-row-start: 7; } -.row-start-8{ +.row-start-8 { grid-row-start: 8; } -.row-start-9{ +.row-start-9 { grid-row-start: 9; } -.row-end-10{ +.row-end-10 { grid-row-end: 10; } -.row-end-11{ +.row-end-11 { grid-row-end: 11; } -.row-end-12{ +.row-end-12 { grid-row-end: 12; } -.row-end-13{ +.row-end-13 { grid-row-end: 13; } -.row-end-14{ +.row-end-14 { grid-row-end: 14; } -.row-end-2{ +.row-end-2 { grid-row-end: 2; } -.row-end-3{ +.row-end-3 { grid-row-end: 3; } -.row-end-4{ +.row-end-4 { grid-row-end: 4; } -.row-end-5{ +.row-end-5 { grid-row-end: 5; } -.row-end-6{ +.row-end-6 { grid-row-end: 6; } -.row-end-7{ +.row-end-7 { grid-row-end: 7; } -.row-end-8{ +.row-end-8 { grid-row-end: 8; } -.row-end-9{ +.row-end-9 { grid-row-end: 9; } -.float-right{ +.float-right { float: right; } -.-m-1{ +.-m-1 { margin: -0.25rem; } -.m-1{ +.m-1 { margin: 0.25rem; } -.m-auto{ +.m-auto { margin: auto; } -.mx-1{ +.mx-1 { margin-left: 0.25rem; margin-right: 0.25rem; } -.mx-2{ +.mx-2 { margin-left: 0.5rem; margin-right: 0.5rem; } -.mx-auto{ +.mx-auto { margin-left: auto; margin-right: auto; } -.my-auto{ +.my-auto { margin-top: auto; margin-bottom: auto; } -.-mb-6{ +.-mb-6 { margin-bottom: -1.5rem; } -.-ml-4{ +.-ml-4 { margin-left: -1rem; } -.mb-1{ +.mb-1 { margin-bottom: 0.25rem; } -.mb-2{ +.mb-2 { margin-bottom: 0.5rem; } -.mb-3{ +.mb-3 { margin-bottom: 0.75rem; } -.mb-\[1px\]{ +.mb-\[1px\] { margin-bottom: 1px; } -.ml-1{ +.ml-1 { margin-left: 0.25rem; } -.ml-2{ +.ml-2 { margin-left: 0.5rem; } -.ml-3{ +.ml-3 { margin-left: 0.75rem; } -.ml-4{ +.ml-4 { margin-left: 1rem; } -.ml-5{ +.ml-5 { margin-left: 1.25rem; } -.ml-\[25px\]{ +.ml-\[25px\] { margin-left: 25px; } -.ml-\[5px\]{ +.ml-\[5px\] { margin-left: 5px; } -.mr-0{ +.mr-0 { margin-right: 0px; } -.mr-1{ +.mr-1 { margin-right: 0.25rem; } -.mr-2{ +.mr-2 { margin-right: 0.5rem; } -.mr-3{ +.mr-3 { margin-right: 0.75rem; } -.mr-4{ +.mr-4 { margin-right: 1rem; } -.mr-5{ +.mr-5 { margin-right: 1.25rem; } -.mr-\[25px\]{ +.mr-\[25px\] { margin-right: 25px; } -.mt-1{ +.mt-1 { margin-top: 0.25rem; } -.mt-10{ +.mt-10 { margin-top: 2.5rem; } -.mt-12{ +.mt-12 { margin-top: 3rem; } -.mt-2{ +.mt-2 { margin-top: 0.5rem; } -.mt-20{ +.mt-20 { margin-top: 5rem; } -.mt-3{ +.mt-3 { margin-top: 0.75rem; } -.mt-4{ +.mt-4 { margin-top: 1rem; } -.mt-5{ +.mt-5 { margin-top: 1.25rem; } -.mt-6{ +.mt-6 { margin-top: 1.5rem; } -.mt-8{ +.mt-8 { margin-top: 2rem; } -.mt-\[9\.5rem\]{ +.mt-\[9\.5rem\] { margin-top: 9.5rem; } -.box-border{ +.box-border { -webkit-box-sizing: border-box; - box-sizing: border-box; + box-sizing: border-box; } -.block{ +.block { display: block; } -.inline-block{ +.inline-block { display: inline-block; } -.inline{ +.inline { display: inline; } -.flex{ +.flex { display: -webkit-box; display: -ms-flexbox; display: flex; } -.inline-flex{ +.inline-flex { display: -webkit-inline-box; display: -ms-inline-flexbox; display: inline-flex; } -.table{ +.table { display: table; } -.table-row{ +.table-row { display: table-row; } -.grid{ +.grid { display: grid; } -.contents{ +.contents { display: contents; } -.hidden{ +.hidden { display: none; } -.h-1\/2{ +.h-1\/2 { height: 50%; } -.h-1\/3{ +.h-1\/3 { height: 33.333333%; } -.h-10{ +.h-10 { height: 2.5rem; } -.h-12{ +.h-12 { height: 3rem; } -.h-14{ +.h-14 { height: 3.5rem; } -.h-16{ +.h-16 { height: 4rem; } -.h-2{ +.h-2 { height: 0.5rem; } -.h-2\/3{ +.h-2\/3 { height: 66.666667%; } -.h-20{ +.h-20 { height: 5rem; } -.h-24{ +.h-24 { height: 6rem; } -.h-28{ +.h-28 { height: 7rem; } -.h-3{ +.h-3 { height: 0.75rem; } -.h-3\/4{ +.h-3\/4 { height: 75%; } -.h-32{ +.h-32 { height: 8rem; } -.h-4{ +.h-4 { height: 1rem; } -.h-4\/5{ +.h-4\/5 { height: 80%; } -.h-5{ +.h-5 { height: 1.25rem; } -.h-5\/6{ +.h-5\/6 { height: 83.333333%; } -.h-6{ +.h-6 { height: 1.5rem; } -.h-64{ +.h-64 { height: 16rem; } -.h-7{ +.h-7 { height: 1.75rem; } -.h-8{ +.h-8 { height: 2rem; } -.h-9{ +.h-9 { height: 2.25rem; } -.h-\[100px\]{ +.h-\[100px\] { height: 100px; } -.h-\[110px\]{ +.h-\[110px\] { height: 110px; } -.h-\[120px\]{ +.h-\[120px\] { height: 120px; } -.h-\[150px\]{ +.h-\[150px\] { height: 150px; } -.h-\[15px\]{ +.h-\[15px\] { height: 15px; } -.h-\[16px\]{ +.h-\[16px\] { height: 16px; } -.h-\[170px\]{ +.h-\[170px\] { height: 170px; } -.h-\[18px\]{ +.h-\[18px\] { height: 18px; } -.h-\[200px\]{ +.h-\[200px\] { height: 200px; } -.h-\[20px\]{ +.h-\[20px\] { height: 20px; } -.h-\[210px\]{ +.h-\[210px\] { height: 210px; } -.h-\[250px\]{ +.h-\[250px\] { height: 250px; } -.h-\[25px\]{ +.h-\[25px\] { height: 25px; } -.h-\[27px\]{ +.h-\[27px\] { height: 27px; } -.h-\[280px\]{ +.h-\[280px\] { height: 280px; } -.h-\[28px\]{ +.h-\[28px\] { height: 28px; } -.h-\[30px\]{ +.h-\[30px\] { height: 30px; } -.h-\[32px\]{ +.h-\[32px\] { height: 32px; } -.h-\[34px\]{ +.h-\[34px\] { height: 34px; } -.h-\[36px\]{ +.h-\[36px\] { height: 36px; } -.h-\[38px\]{ +.h-\[38px\] { height: 38px; } -.h-\[40px\]{ +.h-\[40px\] { height: 40px; } -.h-\[430px\]{ +.h-\[430px\] { height: 430px; } -.h-\[48px\]{ +.h-\[48px\] { height: 48px; } -.h-\[492px\]{ +.h-\[492px\] { height: 492px; } -.h-\[50px\]{ +.h-\[50px\] { height: 50px; } -.h-\[554px\]{ +.h-\[554px\] { height: 554px; } -.h-\[55px\]{ +.h-\[55px\] { height: 55px; } -.h-\[60px\]{ +.h-\[60px\] { height: 60px; } -.h-\[65px\]{ +.h-\[65px\] { height: 65px; } -.h-\[70\%\]{ +.h-\[70\%\] { height: 70%; } -.h-\[70px\]{ +.h-\[70px\] { height: 70px; } -.h-\[8\%\]{ +.h-\[8\%\] { height: 8%; } -.h-\[80px\]{ +.h-\[80px\] { height: 80px; } -.h-\[90px\]{ +.h-\[90px\] { height: 90px; } -.h-\[95\%\]{ +.h-\[95\%\] { height: 95%; } -.h-\[95\.5\%\]{ +.h-\[95\.5\%\] { height: 95.5%; } -.h-fit{ +.h-fit { height: -webkit-fit-content; height: -moz-fit-content; height: fit-content; } -.h-full{ +.h-full { height: 100%; } -.h-screen{ +.h-screen { height: 100vh; } -.max-h-10{ +.max-h-10 { max-height: 2.5rem; } -.max-h-12{ +.max-h-12 { max-height: 3rem; } -.max-h-28{ +.max-h-28 { max-height: 7rem; } -.max-h-32{ +.max-h-32 { max-height: 8rem; } -.max-h-36{ +.max-h-36 { max-height: 9rem; } -.max-h-6{ +.max-h-6 { max-height: 1.5rem; } -.max-h-60{ +.max-h-60 { max-height: 15rem; } -.max-h-8{ +.max-h-8 { max-height: 2rem; } -.max-h-9{ +.max-h-9 { max-height: 2.25rem; } -.max-h-\[100px\]{ +.max-h-\[100px\] { max-height: 100px; } -.max-h-\[110px\]{ +.max-h-\[110px\] { max-height: 110px; } -.max-h-\[120px\]{ +.max-h-\[120px\] { max-height: 120px; } -.max-h-\[144px\]{ +.max-h-\[144px\] { max-height: 144px; } -.max-h-\[150px\]{ +.max-h-\[150px\] { max-height: 150px; } -.max-h-\[160px\]{ +.max-h-\[160px\] { max-height: 160px; } -.max-h-\[165px\]{ +.max-h-\[165px\] { max-height: 165px; } -.max-h-\[170px\]{ +.max-h-\[170px\] { max-height: 170px; } -.max-h-\[185px\]{ +.max-h-\[185px\] { max-height: 185px; } -.max-h-\[200px\]{ +.max-h-\[200px\] { max-height: 200px; } -.max-h-\[210px\]{ +.max-h-\[210px\] { max-height: 210px; } -.max-h-\[28px\]{ +.max-h-\[28px\] { max-height: 28px; } -.max-h-\[300px\]{ +.max-h-\[300px\] { max-height: 300px; } -.max-h-\[319px\]{ +.max-h-\[319px\] { max-height: 319px; } -.max-h-\[320px\]{ +.max-h-\[320px\] { max-height: 320px; } -.max-h-\[32px\]{ +.max-h-\[32px\] { max-height: 32px; } -.max-h-\[35px\]{ +.max-h-\[35px\] { max-height: 35px; } -.max-h-\[40px\]{ +.max-h-\[40px\] { max-height: 40px; } -.max-h-\[420px\]{ +.max-h-\[420px\] { max-height: 420px; } -.max-h-\[423px\]{ +.max-h-\[423px\] { max-height: 423px; } -.max-h-\[428px\]{ +.max-h-\[428px\] { max-height: 428px; } -.max-h-\[430px\]{ +.max-h-\[430px\] { max-height: 430px; } -.max-h-\[450px\]{ +.max-h-\[450px\] { max-height: 450px; } -.max-h-\[491px\]{ +.max-h-\[491px\] { max-height: 491px; } -.max-h-\[492px\]{ +.max-h-\[492px\] { max-height: 492px; } -.max-h-\[503px\]{ +.max-h-\[503px\] { max-height: 503px; } -.max-h-\[60px\]{ +.max-h-\[60px\] { max-height: 60px; } -.max-h-\[78px\]{ +.max-h-\[78px\] { max-height: 78px; } -.max-h-full{ +.max-h-full { max-height: 100%; } -.min-h-11{ +.min-h-11 { min-height: 2.75rem; } -.min-h-20{ +.min-h-20 { min-height: 5rem; } -.min-h-7{ +.min-h-7 { min-height: 1.75rem; } -.min-h-9{ +.min-h-9 { min-height: 2.25rem; } -.min-h-\[100px\]{ +.min-h-\[100px\] { min-height: 100px; } -.min-h-\[146px\]{ +.min-h-\[146px\] { min-height: 146px; } -.min-h-\[18px\]{ +.min-h-\[18px\] { min-height: 18px; } -.min-h-\[30px\]{ +.min-h-\[30px\] { min-height: 30px; } -.min-h-\[400px\]{ +.min-h-\[400px\] { min-height: 400px; } -.min-h-\[40px\]{ +.min-h-\[40px\] { min-height: 40px; } -.min-h-\[450px\]{ +.min-h-\[450px\] { min-height: 450px; } -.min-h-\[55px\]{ +.min-h-\[55px\] { min-height: 55px; } -.w-1\/2{ +.w-1\/2 { width: 50%; } -.w-1\/3{ +.w-1\/3 { width: 33.333333%; } -.w-1\/4{ +.w-1\/4 { width: 25%; } -.w-1\/6{ +.w-1\/6 { width: 16.666667%; } -.w-10{ +.w-10 { width: 2.5rem; } -.w-10\/12{ +.w-10\/12 { width: 83.333333%; } -.w-11\/12{ +.w-11\/12 { width: 91.666667%; } -.w-12{ +.w-12 { width: 3rem; } -.w-14{ +.w-14 { width: 3.5rem; } -.w-16{ +.w-16 { width: 4rem; } -.w-2{ +.w-2 { width: 0.5rem; } -.w-2\/3{ +.w-2\/3 { width: 66.666667%; } -.w-20{ +.w-20 { width: 5rem; } -.w-24{ +.w-24 { width: 6rem; } -.w-28{ +.w-28 { width: 7rem; } -.w-3{ +.w-3 { width: 0.75rem; } -.w-3\/4{ +.w-3\/4 { width: 75%; } -.w-3\/5{ +.w-3\/5 { width: 60%; } -.w-32{ +.w-32 { width: 8rem; } -.w-36{ +.w-36 { width: 9rem; } -.w-4{ +.w-4 { width: 1rem; } -.w-4\/5{ +.w-4\/5 { width: 80%; } -.w-4\/6{ +.w-4\/6 { width: 66.666667%; } -.w-40{ +.w-40 { width: 10rem; } -.w-44{ +.w-44 { width: 11rem; } -.w-48{ +.w-48 { width: 12rem; } -.w-5{ +.w-5 { width: 1.25rem; } -.w-5\/6{ +.w-5\/6 { width: 83.333333%; } -.w-52{ +.w-52 { width: 13rem; } -.w-56{ +.w-56 { width: 14rem; } -.w-6{ +.w-6 { width: 1.5rem; } -.w-60{ +.w-60 { width: 15rem; } -.w-7{ +.w-7 { width: 1.75rem; } -.w-72{ +.w-72 { width: 18rem; } -.w-8{ +.w-8 { width: 2rem; } -.w-9{ +.w-9 { width: 2.25rem; } -.w-9\/12{ +.w-9\/12 { width: 75%; } -.w-\[100px\]{ +.w-\[100px\] { width: 100px; } -.w-\[110px\]{ +.w-\[110px\] { width: 110px; } -.w-\[120px\]{ +.w-\[120px\] { width: 120px; } -.w-\[130px\]{ +.w-\[130px\] { width: 130px; } -.w-\[150px\]{ +.w-\[150px\] { width: 150px; } -.w-\[153px\]{ +.w-\[153px\] { width: 153px; } -.w-\[154px\]{ +.w-\[154px\] { width: 154px; } -.w-\[155px\]{ +.w-\[155px\] { width: 155px; } -.w-\[15px\]{ +.w-\[15px\] { width: 15px; } -.w-\[178px\]{ +.w-\[178px\] { width: 178px; } -.w-\[180px\]{ +.w-\[180px\] { width: 180px; } -.w-\[190px\]{ +.w-\[190px\] { width: 190px; } -.w-\[200px\]{ +.w-\[200px\] { width: 200px; } -.w-\[27px\]{ +.w-\[27px\] { width: 27px; } -.w-\[30\%\]{ +.w-\[30\%\] { width: 30%; } -.w-\[32\%\]{ +.w-\[32\%\] { width: 32%; } -.w-\[32px\]{ +.w-\[32px\] { width: 32px; } -.w-\[38px\]{ +.w-\[38px\] { width: 38px; } -.w-\[390px\]{ +.w-\[390px\] { width: 390px; } -.w-\[400px\]{ +.w-\[400px\] { width: 400px; } -.w-\[48px\]{ +.w-\[48px\] { width: 48px; } -.w-\[49\%\]{ +.w-\[49\%\] { width: 49%; } -.w-\[50px\]{ +.w-\[50px\] { width: 50px; } -.w-\[53px\]{ +.w-\[53px\] { width: 53px; } -.w-\[55px\]{ +.w-\[55px\] { width: 55px; } -.w-\[68\%\]{ +.w-\[68\%\] { width: 68%; } -.w-\[70px\]{ +.w-\[70px\] { width: 70px; } -.w-\[74px\]{ +.w-\[74px\] { width: 74px; } -.w-\[80\%\]{ +.w-\[80\%\] { width: 80%; } -.w-\[8rem\]{ +.w-\[8rem\] { width: 8rem; } -.w-fit{ +.w-fit { width: -webkit-fit-content; width: -moz-fit-content; width: fit-content; } -.w-full{ +.w-full { width: 100%; } -.w-max{ +.w-max { width: -webkit-max-content; width: -moz-max-content; width: max-content; } -.w-screen{ +.w-screen { width: 100vw; } -.min-w-\[100px\]{ +.min-w-\[100px\] { min-width: 100px; } -.min-w-\[120px\]{ +.min-w-\[120px\] { min-width: 120px; } -.min-w-\[170px\]{ +.min-w-\[170px\] { min-width: 170px; } -.max-w-10{ +.max-w-10 { max-width: 2.5rem; } -.max-w-\[180px\]{ +.max-w-\[180px\] { max-width: 180px; } -.max-w-full{ +.max-w-full { max-width: 100%; } -.max-w-lg{ +.max-w-lg { max-width: 32rem; } -.max-w-xs{ +.max-w-xs { max-width: 20rem; } -.flex-auto{ +.flex-auto { -webkit-box-flex: 1; - -ms-flex: 1 1 auto; - flex: 1 1 auto; + -ms-flex: 1 1 auto; + flex: 1 1 auto; } -.flex-none{ +.flex-none { -webkit-box-flex: 0; - -ms-flex: none; - flex: none; + -ms-flex: none; + flex: none; } -.flex-shrink{ +.flex-shrink { -ms-flex-negative: 1; - flex-shrink: 1; + flex-shrink: 1; } -.flex-shrink-0{ +.flex-shrink-0 { -ms-flex-negative: 0; - flex-shrink: 0; + flex-shrink: 0; } -.origin-top-right{ +.origin-top-right { -webkit-transform-origin: top right; - transform-origin: top right; + transform-origin: top right; } -.-translate-x-1\/2{ +.-translate-x-1\/2 { --tw-translate-x: -50%; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.-translate-y-1\/2{ +.-translate-y-1\/2 { --tw-translate-y: -50%; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.translate-x-8{ +.translate-x-8 { --tw-translate-x: 2rem; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.translate-y-0{ +.translate-y-0 { --tw-translate-y: 0px; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.-rotate-90{ +.-rotate-90 { --tw-rotate: -90deg; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.rotate-0{ +.rotate-0 { --tw-rotate: 0deg; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.rotate-180{ +.rotate-180 { --tw-rotate: 180deg; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.rotate-45{ +.rotate-45 { --tw-rotate: 45deg; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.scale-100{ +.scale-100 { --tw-scale-x: 1; --tw-scale-y: 1; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.scale-110{ +.scale-110 { --tw-scale-x: 1.1; --tw-scale-y: 1.1; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.scale-125{ +.scale-125 { --tw-scale-x: 1.25; --tw-scale-y: 1.25; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.scale-90{ - --tw-scale-x: .9; - --tw-scale-y: .9; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +.scale-90 { + --tw-scale-x: 0.9; + --tw-scale-y: 0.9; + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.scale-95{ - --tw-scale-x: .95; - --tw-scale-y: .95; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +.scale-95 { + --tw-scale-x: 0.95; + --tw-scale-y: 0.95; + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.scale-y-0{ +.scale-y-0 { --tw-scale-y: 0; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.scale-y-100{ +.scale-y-100 { --tw-scale-y: 1; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.transform{ - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +.transform { + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -@-webkit-keyframes pulse{ - 50%{ - opacity: .5; +@-webkit-keyframes pulse { + 50% { + opacity: 0.5; } } -@keyframes pulse{ - 50%{ - opacity: .5; +@keyframes pulse { + 50% { + opacity: 0.5; } } -.animate-pulse{ +.animate-pulse { -webkit-animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; - animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; } -@-webkit-keyframes spin{ - to{ +@-webkit-keyframes spin { + to { -webkit-transform: rotate(360deg); - transform: rotate(360deg); + transform: rotate(360deg); } } -@keyframes spin{ - to{ +@keyframes spin { + to { -webkit-transform: rotate(360deg); - transform: rotate(360deg); + transform: rotate(360deg); } } -.animate-spin{ +.animate-spin { -webkit-animation: spin 1s linear infinite; - animation: spin 1s linear infinite; + animation: spin 1s linear infinite; } -.cursor-default{ +.cursor-default { cursor: default; } -.cursor-not-allowed{ +.cursor-not-allowed { cursor: not-allowed; } -.cursor-pointer{ +.cursor-pointer { cursor: pointer; } -.select-none{ +.select-none { -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } -.resize{ +.resize { resize: both; } -.snap-y{ +.snap-y { -ms-scroll-snap-type: y var(--tw-scroll-snap-strictness); - scroll-snap-type: y var(--tw-scroll-snap-strictness); + scroll-snap-type: y var(--tw-scroll-snap-strictness); } -.snap-mandatory{ +.snap-mandatory { --tw-scroll-snap-strictness: mandatory; } -.appearance-none{ +.appearance-none { -webkit-appearance: none; - -moz-appearance: none; - appearance: none; + -moz-appearance: none; + appearance: none; } -.grid-flow-row{ +.grid-flow-row { grid-auto-flow: row; } -.auto-rows-fr{ +.auto-rows-fr { grid-auto-rows: minmax(0, 1fr); } -.auto-rows-max{ +.auto-rows-max { grid-auto-rows: -webkit-max-content; grid-auto-rows: max-content; } -.auto-rows-min{ +.auto-rows-min { grid-auto-rows: -webkit-min-content; grid-auto-rows: min-content; } -.grid-cols-1{ +.grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } -.grid-cols-10{ +.grid-cols-10 { grid-template-columns: repeat(10, minmax(0, 1fr)); } -.grid-cols-11{ +.grid-cols-11 { grid-template-columns: repeat(11, minmax(0, 1fr)); } -.grid-cols-12{ +.grid-cols-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); } -.grid-cols-2{ +.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } -.grid-cols-24{ - grid-template-columns: repeat(24 , minmax(0,1fr)); +.grid-cols-24 { + grid-template-columns: repeat(24, minmax(0, 1fr)); } -.grid-cols-3{ +.grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } -.grid-cols-4{ +.grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } -.grid-cols-5{ +.grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); } -.grid-cols-6{ +.grid-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); } -.grid-cols-7{ +.grid-cols-7 { grid-template-columns: repeat(7, minmax(0, 1fr)); } -.grid-cols-8{ +.grid-cols-8 { grid-template-columns: repeat(8, minmax(0, 1fr)); } -.grid-cols-9{ +.grid-cols-9 { grid-template-columns: repeat(9, minmax(0, 1fr)); } -.grid-rows-1{ +.grid-rows-1 { grid-template-rows: repeat(1, minmax(0, 1fr)); } -.grid-rows-10{ +.grid-rows-10 { grid-template-rows: repeat(10, minmax(0, 1fr)); } -.grid-rows-11{ +.grid-rows-11 { grid-template-rows: repeat(11, minmax(0, 1fr)); } -.grid-rows-12{ - grid-template-rows: repeat(12 , minmax(0,1fr)); +.grid-rows-12 { + grid-template-rows: repeat(12, minmax(0, 1fr)); } -.grid-rows-13{ - grid-template-rows: repeat(13 , minmax(0,1fr)); +.grid-rows-13 { + grid-template-rows: repeat(13, minmax(0, 1fr)); } -.grid-rows-14{ - grid-template-rows: repeat(14 , minmax(0,1fr)); +.grid-rows-14 { + grid-template-rows: repeat(14, minmax(0, 1fr)); } -.grid-rows-15{ - grid-template-rows: repeat(15 , minmax(0,1fr)); +.grid-rows-15 { + grid-template-rows: repeat(15, minmax(0, 1fr)); } -.grid-rows-2{ +.grid-rows-2 { grid-template-rows: repeat(2, minmax(0, 1fr)); } -.grid-rows-3{ +.grid-rows-3 { grid-template-rows: repeat(3, minmax(0, 1fr)); } -.grid-rows-4{ +.grid-rows-4 { grid-template-rows: repeat(4, minmax(0, 1fr)); } -.grid-rows-5{ +.grid-rows-5 { grid-template-rows: repeat(5, minmax(0, 1fr)); } -.grid-rows-6{ +.grid-rows-6 { grid-template-rows: repeat(6, minmax(0, 1fr)); } -.grid-rows-7{ - grid-template-rows: repeat(7 , minmax(0,1fr)); +.grid-rows-7 { + grid-template-rows: repeat(7, minmax(0, 1fr)); } -.grid-rows-8{ - grid-template-rows: repeat(8 , minmax(0,1fr)); +.grid-rows-8 { + grid-template-rows: repeat(8, minmax(0, 1fr)); } -.grid-rows-9{ +.grid-rows-9 { grid-template-rows: repeat(9, minmax(0, 1fr)); } -.flex-col{ +.flex-col { -webkit-box-orient: vertical; -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; } -.flex-wrap{ +.flex-wrap { -ms-flex-wrap: wrap; - flex-wrap: wrap; + flex-wrap: wrap; } -.place-content-center{ +.place-content-center { place-content: center; } -.items-start{ +.items-start { -webkit-box-align: start; - -ms-flex-align: start; - align-items: flex-start; + -ms-flex-align: start; + align-items: flex-start; } -.items-end{ +.items-end { -webkit-box-align: end; - -ms-flex-align: end; - align-items: flex-end; + -ms-flex-align: end; + align-items: flex-end; } -.items-center{ +.items-center { -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; } -.justify-normal{ +.justify-normal { -webkit-box-pack: normal; - -ms-flex-pack: normal; - justify-content: normal; + -ms-flex-pack: normal; + justify-content: normal; } -.justify-start{ +.justify-start { -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; } -.justify-end{ +.justify-end { -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; + -ms-flex-pack: end; + justify-content: flex-end; } -.justify-center{ +.justify-center { -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; + -ms-flex-pack: center; + justify-content: center; } -.justify-between{ +.justify-between { -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; } -.justify-evenly{ +.justify-evenly { -webkit-box-pack: space-evenly; - -ms-flex-pack: space-evenly; - justify-content: space-evenly; + -ms-flex-pack: space-evenly; + justify-content: space-evenly; } -.gap-1{ +.gap-1 { gap: 0.25rem; } -.gap-2{ +.gap-2 { gap: 0.5rem; } -.gap-4{ +.gap-4 { gap: 1rem; } -.gap-5{ +.gap-5 { gap: 1.25rem; } -.gap-x-1{ +.gap-x-1 { -webkit-column-gap: 0.25rem; - -moz-column-gap: 0.25rem; - column-gap: 0.25rem; + -moz-column-gap: 0.25rem; + column-gap: 0.25rem; } -.gap-x-2{ +.gap-x-2 { -webkit-column-gap: 0.5rem; - -moz-column-gap: 0.5rem; - column-gap: 0.5rem; + -moz-column-gap: 0.5rem; + column-gap: 0.5rem; } -.gap-x-8{ +.gap-x-8 { -webkit-column-gap: 2rem; - -moz-column-gap: 2rem; - column-gap: 2rem; + -moz-column-gap: 2rem; + column-gap: 2rem; } -.gap-y-1{ +.gap-y-1 { row-gap: 0.25rem; } -.gap-y-2{ +.gap-y-2 { row-gap: 0.5rem; } -.gap-y-4{ +.gap-y-4 { row-gap: 1rem; } -.gap-y-5{ +.gap-y-5 { row-gap: 1.25rem; } -.space-x-1 > :not([hidden]) ~ :not([hidden]){ +.space-x-1 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(0.25rem * var(--tw-space-x-reverse)); margin-left: calc(0.25rem * calc(1 - var(--tw-space-x-reverse))); } -.space-x-2 > :not([hidden]) ~ :not([hidden]){ +.space-x-2 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(0.5rem * var(--tw-space-x-reverse)); margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse))); } -.space-x-4 > :not([hidden]) ~ :not([hidden]){ +.space-x-4 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(1rem * var(--tw-space-x-reverse)); margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); } -.space-x-6 > :not([hidden]) ~ :not([hidden]){ +.space-x-6 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(1.5rem * var(--tw-space-x-reverse)); margin-left: calc(1.5rem * calc(1 - var(--tw-space-x-reverse))); } -.space-y-1 > :not([hidden]) ~ :not([hidden]){ +.space-y-1 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(0.25rem * var(--tw-space-y-reverse)); } -.space-y-2 > :not([hidden]) ~ :not([hidden]){ +.space-y-2 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)); } -.space-y-3 > :not([hidden]) ~ :not([hidden]){ +.space-y-3 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(0.75rem * var(--tw-space-y-reverse)); } -.space-y-4 > :not([hidden]) ~ :not([hidden]){ +.space-y-4 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(1rem * var(--tw-space-y-reverse)); } -.space-y-6 > :not([hidden]) ~ :not([hidden]){ +.space-y-6 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(1.5rem * var(--tw-space-y-reverse)); } -.space-y-8 > :not([hidden]) ~ :not([hidden]){ +.space-y-8 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(2rem * var(--tw-space-y-reverse)); } -.space-y-\[1px\] > :not([hidden]) ~ :not([hidden]){ +.space-y-\[1px\] > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(1px * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(1px * var(--tw-space-y-reverse)); } -.divide-x > :not([hidden]) ~ :not([hidden]){ +.divide-x > :not([hidden]) ~ :not([hidden]) { --tw-divide-x-reverse: 0; border-right-width: calc(1px * var(--tw-divide-x-reverse)); border-left-width: calc(1px * calc(1 - var(--tw-divide-x-reverse))); } -.divide-y > :not([hidden]) ~ :not([hidden]){ +.divide-y > :not([hidden]) ~ :not([hidden]) { --tw-divide-y-reverse: 0; border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); border-bottom-width: calc(1px * var(--tw-divide-y-reverse)); } -.divide-y-2 > :not([hidden]) ~ :not([hidden]){ +.divide-y-2 > :not([hidden]) ~ :not([hidden]) { --tw-divide-y-reverse: 0; border-top-width: calc(2px * calc(1 - var(--tw-divide-y-reverse))); border-bottom-width: calc(2px * var(--tw-divide-y-reverse)); } -.divide-y-\[1px\] > :not([hidden]) ~ :not([hidden]){ +.divide-y-\[1px\] > :not([hidden]) ~ :not([hidden]) { --tw-divide-y-reverse: 0; border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); border-bottom-width: calc(1px * var(--tw-divide-y-reverse)); } -.divide-gray-300 > :not([hidden]) ~ :not([hidden]){ +.divide-gray-300 > :not([hidden]) ~ :not([hidden]) { --tw-divide-opacity: 1; border-color: rgb(209 213 219 / var(--tw-divide-opacity)); } -.divide-gray-400 > :not([hidden]) ~ :not([hidden]){ +.divide-gray-400 > :not([hidden]) ~ :not([hidden]) { --tw-divide-opacity: 1; border-color: rgb(156 163 175 / var(--tw-divide-opacity)); } -.divide-gray-600 > :not([hidden]) ~ :not([hidden]){ +.divide-gray-600 > :not([hidden]) ~ :not([hidden]) { --tw-divide-opacity: 1; border-color: rgb(75 85 99 / var(--tw-divide-opacity)); } -.divide-gray-700 > :not([hidden]) ~ :not([hidden]){ +.divide-gray-700 > :not([hidden]) ~ :not([hidden]) { --tw-divide-opacity: 1; border-color: rgb(55 65 81 / var(--tw-divide-opacity)); } -.self-start{ +.self-start { -ms-flex-item-align: start; - align-self: flex-start; + align-self: flex-start; } -.self-end{ +.self-end { -ms-flex-item-align: end; - align-self: flex-end; + align-self: flex-end; } -.self-center{ +.self-center { -ms-flex-item-align: center; - align-self: center; + align-self: center; } -.justify-self-start{ +.justify-self-start { justify-self: start; } -.justify-self-end{ +.justify-self-end { justify-self: end; } -.justify-self-center{ +.justify-self-center { justify-self: center; } -.overflow-auto{ +.overflow-auto { overflow: auto; } -.overflow-hidden{ +.overflow-hidden { overflow: hidden; } -.overflow-y-auto{ +.overflow-y-auto { overflow-y: auto; } -.overflow-x-hidden{ +.overflow-x-hidden { overflow-x: hidden; } -.overflow-y-hidden{ +.overflow-y-hidden { overflow-y: hidden; } -.overflow-x-scroll{ +.overflow-x-scroll { overflow-x: scroll; } -.overflow-y-scroll{ +.overflow-y-scroll { overflow-y: scroll; } -.overscroll-y-auto{ +.overscroll-y-auto { overscroll-behavior-y: auto; } -.truncate{ +.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -.whitespace-nowrap{ +.whitespace-nowrap { white-space: nowrap; } -.whitespace-pre{ +.whitespace-pre { white-space: pre; } -.whitespace-pre-wrap{ +.whitespace-pre-wrap { white-space: pre-wrap; } -.text-wrap{ +.text-wrap { text-wrap: wrap; } -.text-nowrap{ +.text-nowrap { text-wrap: nowrap; } -.break-words{ +.break-words { overflow-wrap: break-word; } -.break-all{ +.break-all { word-break: break-all; } -.rounded{ +.rounded { border-radius: 0.25rem; } -.rounded-2xl{ +.rounded-2xl { border-radius: 1rem; } -.rounded-3xl{ +.rounded-3xl { border-radius: 1.5rem; } -.rounded-\[35px\]{ +.rounded-\[35px\] { border-radius: 35px; } -.rounded-\[4px\]{ +.rounded-\[4px\] { border-radius: 4px; } -.rounded-\[55px\]{ +.rounded-\[55px\] { border-radius: 55px; } -.rounded-\[5px\]{ +.rounded-\[5px\] { border-radius: 5px; } -.rounded-\[75px\]{ +.rounded-\[75px\] { border-radius: 75px; } -.rounded-full{ +.rounded-full { border-radius: 9999px; } -.rounded-lg{ +.rounded-lg { border-radius: 0.5rem; } -.rounded-md{ +.rounded-md { border-radius: 0.375rem; } -.rounded-sm{ +.rounded-sm { border-radius: 0.125rem; } -.rounded-xl{ +.rounded-xl { border-radius: 0.75rem; } -.rounded-b-lg{ +.rounded-b-lg { border-bottom-right-radius: 0.5rem; border-bottom-left-radius: 0.5rem; } -.rounded-b-md{ +.rounded-b-md { border-bottom-right-radius: 0.375rem; border-bottom-left-radius: 0.375rem; } -.rounded-b-sm{ +.rounded-b-sm { border-bottom-right-radius: 0.125rem; border-bottom-left-radius: 0.125rem; } -.rounded-l-md{ +.rounded-l-md { border-top-left-radius: 0.375rem; border-bottom-left-radius: 0.375rem; } -.rounded-l-none{ +.rounded-l-none { border-top-left-radius: 0px; border-bottom-left-radius: 0px; } -.rounded-l-xl{ +.rounded-l-xl { border-top-left-radius: 0.75rem; border-bottom-left-radius: 0.75rem; } -.rounded-r-full{ +.rounded-r-full { border-top-right-radius: 9999px; border-bottom-right-radius: 9999px; } -.rounded-r-md{ +.rounded-r-md { border-top-right-radius: 0.375rem; border-bottom-right-radius: 0.375rem; } -.rounded-r-sm{ +.rounded-r-sm { border-top-right-radius: 0.125rem; border-bottom-right-radius: 0.125rem; } -.rounded-t-\[0\.28rem\]{ +.rounded-t-\[0\.28rem\] { border-top-left-radius: 0.28rem; border-top-right-radius: 0.28rem; } -.rounded-t-\[5px\]{ +.rounded-t-\[5px\] { border-top-left-radius: 5px; border-top-right-radius: 5px; } -.rounded-t-lg{ +.rounded-t-lg { border-top-left-radius: 0.5rem; border-top-right-radius: 0.5rem; } -.rounded-t-md{ +.rounded-t-md { border-top-left-radius: 0.375rem; border-top-right-radius: 0.375rem; } -.rounded-bl-\[37px\]{ +.rounded-bl-\[37px\] { border-bottom-left-radius: 37px; } -.rounded-br-\[40px\]{ +.rounded-br-\[40px\] { border-bottom-right-radius: 40px; } -.rounded-tl-lg{ +.rounded-tl-lg { border-top-left-radius: 0.5rem; } -.rounded-tr-\[40px\]{ +.rounded-tr-\[40px\] { border-top-right-radius: 40px; } -.border{ +.border { border-width: 1px; } -.border-0{ +.border-0 { border-width: 0px; } -.border-2{ +.border-2 { border-width: 2px; } -.border-4{ +.border-4 { border-width: 4px; } -.border-y{ +.border-y { border-top-width: 1px; border-bottom-width: 1px; } -.border-b{ +.border-b { border-bottom-width: 1px; } -.border-b-2{ +.border-b-2 { border-bottom-width: 2px; } -.border-l{ +.border-l { border-left-width: 1px; } -.border-r{ +.border-r { border-right-width: 1px; } -.border-r-2{ +.border-r-2 { border-right-width: 2px; } -.border-r-4{ +.border-r-4 { border-right-width: 4px; } -.border-s-4{ +.border-s-4 { border-inline-start-width: 4px; } -.border-t{ +.border-t { border-top-width: 1px; } -.border-t-0{ +.border-t-0 { border-top-width: 0px; } -.border-t-2{ +.border-t-2 { border-top-width: 2px; } -.border-t-4{ +.border-t-4 { border-top-width: 4px; } -.border-dashed{ +.border-dashed { border-style: dashed; } -.border-none{ +.border-none { border-style: none; } -.border-\[\#171D22\]{ +.border-\[\#171D22\] { --tw-border-opacity: 1; border-color: rgb(23 29 34 / var(--tw-border-opacity)); } -.border-\[\#1c3634\]{ +.border-\[\#1c3634\] { --tw-border-opacity: 1; border-color: rgb(28 54 52 / var(--tw-border-opacity)); } -.border-\[\#2c3136\]{ +.border-\[\#2c3136\] { --tw-border-opacity: 1; border-color: rgb(44 49 54 / var(--tw-border-opacity)); } -.border-\[\#33393E\]{ +.border-\[\#33393E\] { --tw-border-opacity: 1; border-color: rgb(51 57 62 / var(--tw-border-opacity)); } -.border-\[\#336666\]{ +.border-\[\#336666\] { --tw-border-opacity: 1; border-color: rgb(51 102 102 / var(--tw-border-opacity)); } -.border-\[\#3e4347\]{ +.border-\[\#3e4347\] { --tw-border-opacity: 1; border-color: rgb(62 67 71 / var(--tw-border-opacity)); } -.border-\[\#4b8585\]{ +.border-\[\#4b8585\] { --tw-border-opacity: 1; border-color: rgb(75 133 133 / var(--tw-border-opacity)); } -.border-\[\#6c7e78\]{ +.border-\[\#6c7e78\] { --tw-border-opacity: 1; border-color: rgb(108 126 120 / var(--tw-border-opacity)); } -.border-blue-100{ +.border-blue-100 { --tw-border-opacity: 1; border-color: rgb(219 234 254 / var(--tw-border-opacity)); } -.border-blue-300{ +.border-blue-300 { --tw-border-opacity: 1; border-color: rgb(147 197 253 / var(--tw-border-opacity)); } -.border-blue-400{ +.border-blue-400 { --tw-border-opacity: 1; border-color: rgb(96 165 250 / var(--tw-border-opacity)); } -.border-blue-500{ +.border-blue-500 { --tw-border-opacity: 1; border-color: rgb(59 130 246 / var(--tw-border-opacity)); } -.border-gray-100{ +.border-gray-100 { --tw-border-opacity: 1; border-color: rgb(243 244 246 / var(--tw-border-opacity)); } -.border-gray-200{ +.border-gray-200 { --tw-border-opacity: 1; border-color: rgb(229 231 235 / var(--tw-border-opacity)); } -.border-gray-300{ +.border-gray-300 { --tw-border-opacity: 1; border-color: rgb(209 213 219 / var(--tw-border-opacity)); } -.border-gray-400{ +.border-gray-400 { --tw-border-opacity: 1; border-color: rgb(156 163 175 / var(--tw-border-opacity)); } -.border-gray-500{ +.border-gray-500 { --tw-border-opacity: 1; border-color: rgb(107 114 128 / var(--tw-border-opacity)); } -.border-gray-600{ +.border-gray-600 { --tw-border-opacity: 1; border-color: rgb(75 85 99 / var(--tw-border-opacity)); } -.border-gray-700{ +.border-gray-700 { --tw-border-opacity: 1; border-color: rgb(55 65 81 / var(--tw-border-opacity)); } -.border-gray-800{ +.border-gray-800 { --tw-border-opacity: 1; border-color: rgb(31 41 55 / var(--tw-border-opacity)); } -.border-gray-950{ +.border-gray-950 { --tw-border-opacity: 1; border-color: rgb(3 7 18 / var(--tw-border-opacity)); } -.border-green-500{ +.border-green-500 { --tw-border-opacity: 1; border-color: rgb(34 197 94 / var(--tw-border-opacity)); } -.border-orange-500{ +.border-orange-500 { --tw-border-opacity: 1; border-color: rgb(249 115 22 / var(--tw-border-opacity)); } -.border-red-400{ +.border-red-400 { --tw-border-opacity: 1; border-color: rgb(248 113 113 / var(--tw-border-opacity)); } -.border-red-500{ +.border-red-500 { --tw-border-opacity: 1; border-color: rgb(239 68 68 / var(--tw-border-opacity)); } -.border-red-600{ +.border-red-600 { --tw-border-opacity: 1; border-color: rgb(220 38 38 / var(--tw-border-opacity)); } -.border-red-800{ +.border-red-800 { --tw-border-opacity: 1; border-color: rgb(153 27 27 / var(--tw-border-opacity)); } -.border-slate-500{ +.border-slate-500 { --tw-border-opacity: 1; border-color: rgb(100 116 139 / var(--tw-border-opacity)); } -.border-teal-200{ +.border-teal-200 { --tw-border-opacity: 1; border-color: rgb(153 246 228 / var(--tw-border-opacity)); } -.border-teal-300{ +.border-teal-300 { --tw-border-opacity: 1; border-color: rgb(94 234 212 / var(--tw-border-opacity)); } -.border-teal-500{ +.border-teal-500 { --tw-border-opacity: 1; border-color: rgb(20 184 166 / var(--tw-border-opacity)); } -.border-teal-600{ +.border-teal-600 { --tw-border-opacity: 1; border-color: rgb(13 148 136 / var(--tw-border-opacity)); } -.border-teal-700{ +.border-teal-700 { --tw-border-opacity: 1; border-color: rgb(15 118 110 / var(--tw-border-opacity)); } -.border-teal-800{ +.border-teal-800 { --tw-border-opacity: 1; border-color: rgb(17 94 89 / var(--tw-border-opacity)); } -.border-transparent{ +.border-transparent { border-color: transparent; } -.border-white{ +.border-white { --tw-border-opacity: 1; border-color: rgb(255 255 255 / var(--tw-border-opacity)); } -.border-b-transparent{ +.border-b-transparent { border-bottom-color: transparent; } -.border-l-gray-200{ +.border-l-gray-200 { --tw-border-opacity: 1; border-left-color: rgb(229 231 235 / var(--tw-border-opacity)); } -.border-r-\[\#264744\]{ +.border-r-\[\#264744\] { --tw-border-opacity: 1; border-right-color: rgb(38 71 68 / var(--tw-border-opacity)); } -.border-r-\[\#88b79a\]{ +.border-r-\[\#88b79a\] { --tw-border-opacity: 1; border-right-color: rgb(136 183 154 / var(--tw-border-opacity)); } -.border-r-blue-600{ +.border-r-blue-600 { --tw-border-opacity: 1; border-right-color: rgb(37 99 235 / var(--tw-border-opacity)); } -.border-r-transparent{ +.border-r-transparent { border-right-color: transparent; } -.border-r-white{ +.border-r-white { --tw-border-opacity: 1; border-right-color: rgb(255 255 255 / var(--tw-border-opacity)); } -.border-t-\[\#88b79a\]{ +.border-t-\[\#88b79a\] { --tw-border-opacity: 1; border-top-color: rgb(136 183 154 / var(--tw-border-opacity)); } -.border-t-blue-600{ +.border-t-blue-600 { --tw-border-opacity: 1; border-top-color: rgb(37 99 235 / var(--tw-border-opacity)); } -.border-t-white{ +.border-t-white { --tw-border-opacity: 1; border-top-color: rgb(255 255 255 / var(--tw-border-opacity)); } -.bg-\[\#0F1217\]{ +.bg-\[\#0F1217\] { --tw-bg-opacity: 1; background-color: rgb(15 18 23 / var(--tw-bg-opacity)); } -.bg-\[\#0d0d0e\]{ +.bg-\[\#0d0d0e\] { --tw-bg-opacity: 1; background-color: rgb(13 13 14 / var(--tw-bg-opacity)); } -.bg-\[\#111213\]{ +.bg-\[\#111213\] { --tw-bg-opacity: 1; background-color: rgb(17 18 19 / var(--tw-bg-opacity)); } -.bg-\[\#111315\]{ +.bg-\[\#111315\] { --tw-bg-opacity: 1; background-color: rgb(17 19 21 / var(--tw-bg-opacity)); } -.bg-\[\#131313\]{ +.bg-\[\#131313\] { --tw-bg-opacity: 1; background-color: rgb(19 19 19 / var(--tw-bg-opacity)); } -.bg-\[\#141516\]{ +.bg-\[\#141516\] { --tw-bg-opacity: 1; background-color: rgb(20 21 22 / var(--tw-bg-opacity)); } -.bg-\[\#14171a\]{ +.bg-\[\#14171a\] { --tw-bg-opacity: 1; background-color: rgb(20 23 26 / var(--tw-bg-opacity)); } -.bg-\[\#151618\]{ +.bg-\[\#151618\] { --tw-bg-opacity: 1; background-color: rgb(21 22 24 / var(--tw-bg-opacity)); } -.bg-\[\#151a1e\]{ +.bg-\[\#151a1e\] { --tw-bg-opacity: 1; background-color: rgb(21 26 30 / var(--tw-bg-opacity)); } -.bg-\[\#161717\]{ +.bg-\[\#161717\] { --tw-bg-opacity: 1; background-color: rgb(22 23 23 / var(--tw-bg-opacity)); } -.bg-\[\#171D22\]{ +.bg-\[\#171D22\] { --tw-bg-opacity: 1; background-color: rgb(23 29 34 / var(--tw-bg-opacity)); } -.bg-\[\#171a1b\]{ +.bg-\[\#171a1b\] { --tw-bg-opacity: 1; background-color: rgb(23 26 27 / var(--tw-bg-opacity)); } -.bg-\[\#171a1c\]{ +.bg-\[\#171a1c\] { --tw-bg-opacity: 1; background-color: rgb(23 26 28 / var(--tw-bg-opacity)); } -.bg-\[\#17A2B8\]{ +.bg-\[\#17A2B8\] { --tw-bg-opacity: 1; background-color: rgb(23 162 184 / var(--tw-bg-opacity)); } -.bg-\[\#18191a\]{ +.bg-\[\#18191a\] { --tw-bg-opacity: 1; background-color: rgb(24 25 26 / var(--tw-bg-opacity)); } -.bg-\[\#191b1e\]{ +.bg-\[\#191b1e\] { --tw-bg-opacity: 1; background-color: rgb(25 27 30 / var(--tw-bg-opacity)); } -.bg-\[\#191c21\]{ +.bg-\[\#191c21\] { --tw-bg-opacity: 1; background-color: rgb(25 28 33 / var(--tw-bg-opacity)); } -.bg-\[\#1BA5F8\]{ +.bg-\[\#1BA5F8\] { --tw-bg-opacity: 1; background-color: rgb(27 165 248 / var(--tw-bg-opacity)); } -.bg-\[\#1E2429\]{ +.bg-\[\#1E2429\] { --tw-bg-opacity: 1; background-color: rgb(30 36 41 / var(--tw-bg-opacity)); } -.bg-\[\#1a2e2c\]{ +.bg-\[\#1a2e2c\] { --tw-bg-opacity: 1; background-color: rgb(26 46 44 / var(--tw-bg-opacity)); } -.bg-\[\#1b1b1d\]{ +.bg-\[\#1b1b1d\] { --tw-bg-opacity: 1; background-color: rgb(27 27 29 / var(--tw-bg-opacity)); } -.bg-\[\#1b1c1c\]{ +.bg-\[\#1b1c1c\] { --tw-bg-opacity: 1; background-color: rgb(27 28 28 / var(--tw-bg-opacity)); } -.bg-\[\#1b1d1f\]{ +.bg-\[\#1b1d1f\] { --tw-bg-opacity: 1; background-color: rgb(27 29 31 / var(--tw-bg-opacity)); } -.bg-\[\#1b3231\]{ +.bg-\[\#1b3231\] { --tw-bg-opacity: 1; background-color: rgb(27 50 49 / var(--tw-bg-opacity)); } -.bg-\[\#1c1d1d\]{ +.bg-\[\#1c1d1d\] { --tw-bg-opacity: 1; background-color: rgb(28 29 29 / var(--tw-bg-opacity)); } -.bg-\[\#1c2021\]{ +.bg-\[\#1c2021\] { --tw-bg-opacity: 1; background-color: rgb(28 32 33 / var(--tw-bg-opacity)); } -.bg-\[\#1d1d1e\]{ +.bg-\[\#1d1d1e\] { --tw-bg-opacity: 1; background-color: rgb(29 29 30 / var(--tw-bg-opacity)); } -.bg-\[\#1d1e1f\]{ +.bg-\[\#1d1e1f\] { --tw-bg-opacity: 1; background-color: rgb(29 30 31 / var(--tw-bg-opacity)); } -.bg-\[\#1d1f20\]{ +.bg-\[\#1d1f20\] { --tw-bg-opacity: 1; background-color: rgb(29 31 32 / var(--tw-bg-opacity)); } -.bg-\[\#1d1f21\]{ +.bg-\[\#1d1f21\] { --tw-bg-opacity: 1; background-color: rgb(29 31 33 / var(--tw-bg-opacity)); } -.bg-\[\#1f2123\]{ +.bg-\[\#1f2123\] { --tw-bg-opacity: 1; background-color: rgb(31 33 35 / var(--tw-bg-opacity)); } -.bg-\[\#1f2226\]{ +.bg-\[\#1f2226\] { --tw-bg-opacity: 1; background-color: rgb(31 34 38 / var(--tw-bg-opacity)); } -.bg-\[\#202123\]{ +.bg-\[\#202123\] { --tw-bg-opacity: 1; background-color: rgb(32 33 35 / var(--tw-bg-opacity)); } -.bg-\[\#202225\]{ +.bg-\[\#202225\] { --tw-bg-opacity: 1; background-color: rgb(32 34 37 / var(--tw-bg-opacity)); } -.bg-\[\#202632\]{ +.bg-\[\#202632\] { --tw-bg-opacity: 1; background-color: rgb(32 38 50 / var(--tw-bg-opacity)); } -.bg-\[\#212225\]{ +.bg-\[\#212225\] { --tw-bg-opacity: 1; background-color: rgb(33 34 37 / var(--tw-bg-opacity)); } -.bg-\[\#212629\]{ +.bg-\[\#212629\] { --tw-bg-opacity: 1; background-color: rgb(33 38 41 / var(--tw-bg-opacity)); } -.bg-\[\#21272c\]{ +.bg-\[\#21272c\] { --tw-bg-opacity: 1; background-color: rgb(33 39 44 / var(--tw-bg-opacity)); } -.bg-\[\#222526\]{ +.bg-\[\#222526\] { --tw-bg-opacity: 1; background-color: rgb(34 37 38 / var(--tw-bg-opacity)); } -.bg-\[\#224141\]{ +.bg-\[\#224141\] { --tw-bg-opacity: 1; background-color: rgb(34 65 65 / var(--tw-bg-opacity)); } -.bg-\[\#232428\]{ +.bg-\[\#232428\] { --tw-bg-opacity: 1; background-color: rgb(35 36 40 / var(--tw-bg-opacity)); } -.bg-\[\#232528\]{ +.bg-\[\#232528\] { --tw-bg-opacity: 1; background-color: rgb(35 37 40 / var(--tw-bg-opacity)); } -.bg-\[\#242529\]{ +.bg-\[\#242529\] { --tw-bg-opacity: 1; background-color: rgb(36 37 41 / var(--tw-bg-opacity)); } -.bg-\[\#242628\]{ +.bg-\[\#242628\] { --tw-bg-opacity: 1; background-color: rgb(36 38 40 / var(--tw-bg-opacity)); } -.bg-\[\#243535\]{ +.bg-\[\#243535\] { --tw-bg-opacity: 1; background-color: rgb(36 53 53 / var(--tw-bg-opacity)); } -.bg-\[\#243d36\]{ +.bg-\[\#243d36\] { --tw-bg-opacity: 1; background-color: rgb(36 61 54 / var(--tw-bg-opacity)); } -.bg-\[\#252525\]{ +.bg-\[\#252525\] { --tw-bg-opacity: 1; background-color: rgb(37 37 37 / var(--tw-bg-opacity)); } -.bg-\[\#264744\]{ +.bg-\[\#264744\] { --tw-bg-opacity: 1; background-color: rgb(38 71 68 / var(--tw-bg-opacity)); } -.bg-\[\#282a2c\]{ +.bg-\[\#282a2c\] { --tw-bg-opacity: 1; background-color: rgb(40 42 44 / var(--tw-bg-opacity)); } -.bg-\[\#292e32\]{ +.bg-\[\#292e32\] { --tw-bg-opacity: 1; background-color: rgb(41 46 50 / var(--tw-bg-opacity)); } -.bg-\[\#2a2e30\]{ +.bg-\[\#2a2e30\] { --tw-bg-opacity: 1; background-color: rgb(42 46 48 / var(--tw-bg-opacity)); } -.bg-\[\#2c3136\]{ +.bg-\[\#2c3136\] { --tw-bg-opacity: 1; background-color: rgb(44 49 54 / var(--tw-bg-opacity)); } -.bg-\[\#2d3035\]{ +.bg-\[\#2d3035\] { --tw-bg-opacity: 1; background-color: rgb(45 48 53 / var(--tw-bg-opacity)); } -.bg-\[\#2d3438\]{ +.bg-\[\#2d3438\] { --tw-bg-opacity: 1; background-color: rgb(45 52 56 / var(--tw-bg-opacity)); } -.bg-\[\#2e5151\]{ +.bg-\[\#2e5151\] { --tw-bg-opacity: 1; background-color: rgb(46 81 81 / var(--tw-bg-opacity)); } -.bg-\[\#2f373c\]{ +.bg-\[\#2f373c\] { --tw-bg-opacity: 1; background-color: rgb(47 55 60 / var(--tw-bg-opacity)); } -.bg-\[\#2f5a5a\]{ +.bg-\[\#2f5a5a\] { --tw-bg-opacity: 1; background-color: rgb(47 90 90 / var(--tw-bg-opacity)); } -.bg-\[\#303232\]{ +.bg-\[\#303232\] { --tw-bg-opacity: 1; background-color: rgb(48 50 50 / var(--tw-bg-opacity)); } -.bg-\[\#313539\]{ +.bg-\[\#313539\] { --tw-bg-opacity: 1; background-color: rgb(49 53 57 / var(--tw-bg-opacity)); } -.bg-\[\#32363A\]{ +.bg-\[\#32363A\] { --tw-bg-opacity: 1; background-color: rgb(50 54 58 / var(--tw-bg-opacity)); } -.bg-\[\#333539\]{ +.bg-\[\#333539\] { --tw-bg-opacity: 1; background-color: rgb(51 53 57 / var(--tw-bg-opacity)); } -.bg-\[\#33393E\]{ +.bg-\[\#33393E\] { --tw-bg-opacity: 1; background-color: rgb(51 57 62 / var(--tw-bg-opacity)); } -.bg-\[\#33393e\]{ +.bg-\[\#33393e\] { --tw-bg-opacity: 1; background-color: rgb(51 57 62 / var(--tw-bg-opacity)); } -.bg-\[\#334B3F\]{ +.bg-\[\#334B3F\] { --tw-bg-opacity: 1; background-color: rgb(51 75 63 / var(--tw-bg-opacity)); } -.bg-\[\#334d4d\]{ +.bg-\[\#334d4d\] { --tw-bg-opacity: 1; background-color: rgb(51 77 77 / var(--tw-bg-opacity)); } -.bg-\[\#336666\]{ +.bg-\[\#336666\] { --tw-bg-opacity: 1; background-color: rgb(51 102 102 / var(--tw-bg-opacity)); } -.bg-\[\#343434\]{ +.bg-\[\#343434\] { --tw-bg-opacity: 1; background-color: rgb(52 52 52 / var(--tw-bg-opacity)); } -.bg-\[\#387272\]{ +.bg-\[\#387272\] { --tw-bg-opacity: 1; background-color: rgb(56 114 114 / var(--tw-bg-opacity)); } -.bg-\[\#393939\]{ +.bg-\[\#393939\] { --tw-bg-opacity: 1; background-color: rgb(57 57 57 / var(--tw-bg-opacity)); } -.bg-\[\#3d4244\]{ +.bg-\[\#3d4244\] { --tw-bg-opacity: 1; background-color: rgb(61 66 68 / var(--tw-bg-opacity)); } -.bg-\[\#3d4449\]{ +.bg-\[\#3d4449\] { --tw-bg-opacity: 1; background-color: rgb(61 68 73 / var(--tw-bg-opacity)); } -.bg-\[\#3e4347\]{ +.bg-\[\#3e4347\] { --tw-bg-opacity: 1; background-color: rgb(62 67 71 / var(--tw-bg-opacity)); } -.bg-\[\#495056\]{ +.bg-\[\#495056\] { --tw-bg-opacity: 1; background-color: rgb(73 80 86 / var(--tw-bg-opacity)); } -.bg-\[\#4D56CB\]{ +.bg-\[\#4D56CB\] { --tw-bg-opacity: 1; background-color: rgb(77 86 203 / var(--tw-bg-opacity)); } -.bg-\[\#4d7575\]{ +.bg-\[\#4d7575\] { --tw-bg-opacity: 1; background-color: rgb(77 117 117 / var(--tw-bg-opacity)); } -.bg-\[\#503C3C\]{ +.bg-\[\#503C3C\] { --tw-bg-opacity: 1; background-color: rgb(80 60 60 / var(--tw-bg-opacity)); } -.bg-\[\#505f6d\]{ +.bg-\[\#505f6d\] { --tw-bg-opacity: 1; background-color: rgb(80 95 109 / var(--tw-bg-opacity)); } -.bg-\[\#537263\]{ +.bg-\[\#537263\] { --tw-bg-opacity: 1; background-color: rgb(83 114 99 / var(--tw-bg-opacity)); } -.bg-\[\#578f84\]{ +.bg-\[\#578f84\] { --tw-bg-opacity: 1; background-color: rgb(87 143 132 / var(--tw-bg-opacity)); } -.bg-\[\#609879\]{ +.bg-\[\#609879\] { --tw-bg-opacity: 1; background-color: rgb(96 152 121 / var(--tw-bg-opacity)); } -.bg-\[\#A0A0A0\]{ +.bg-\[\#A0A0A0\] { --tw-bg-opacity: 1; background-color: rgb(160 160 160 / var(--tw-bg-opacity)); } -.bg-\[\#D1BB9E\]{ +.bg-\[\#D1BB9E\] { --tw-bg-opacity: 1; background-color: rgb(209 187 158 / var(--tw-bg-opacity)); } -.bg-\[\#F7C566\]{ +.bg-\[\#F7C566\] { --tw-bg-opacity: 1; background-color: rgb(247 197 102 / var(--tw-bg-opacity)); } -.bg-\[\#a7aeb5\]{ +.bg-\[\#a7aeb5\] { --tw-bg-opacity: 1; background-color: rgb(167 174 181 / var(--tw-bg-opacity)); } -.bg-\[\#a846b8\]{ +.bg-\[\#a846b8\] { --tw-bg-opacity: 1; background-color: rgb(168 70 184 / var(--tw-bg-opacity)); } -.bg-\[\#caced1\]{ +.bg-\[\#caced1\] { --tw-bg-opacity: 1; background-color: rgb(202 206 209 / var(--tw-bg-opacity)); } -.bg-\[\#e8ebeb\]{ +.bg-\[\#e8ebeb\] { --tw-bg-opacity: 1; background-color: rgb(232 235 235 / var(--tw-bg-opacity)); } -.bg-\[\#eaecee\]{ +.bg-\[\#eaecee\] { --tw-bg-opacity: 1; background-color: rgb(234 236 238 / var(--tw-bg-opacity)); } -.bg-\[\#fb923c\]{ +.bg-\[\#fb923c\] { --tw-bg-opacity: 1; background-color: rgb(251 146 60 / var(--tw-bg-opacity)); } -.bg-amber-400{ +.bg-amber-400 { --tw-bg-opacity: 1; background-color: rgb(251 191 36 / var(--tw-bg-opacity)); } -.bg-black{ +.bg-black { --tw-bg-opacity: 1; background-color: rgb(0 0 0 / var(--tw-bg-opacity)); } -.bg-blue-300{ +.bg-blue-300 { --tw-bg-opacity: 1; background-color: rgb(147 197 253 / var(--tw-bg-opacity)); } -.bg-blue-400{ +.bg-blue-400 { --tw-bg-opacity: 1; background-color: rgb(96 165 250 / var(--tw-bg-opacity)); } -.bg-blue-500{ +.bg-blue-500 { --tw-bg-opacity: 1; background-color: rgb(59 130 246 / var(--tw-bg-opacity)); } -.bg-blue-900{ +.bg-blue-900 { --tw-bg-opacity: 1; background-color: rgb(30 58 138 / var(--tw-bg-opacity)); } -.bg-cyan-300{ +.bg-cyan-300 { --tw-bg-opacity: 1; background-color: rgb(103 232 249 / var(--tw-bg-opacity)); } -.bg-gray-100{ +.bg-gray-100 { --tw-bg-opacity: 1; background-color: rgb(243 244 246 / var(--tw-bg-opacity)); } -.bg-gray-200{ +.bg-gray-200 { --tw-bg-opacity: 1; background-color: rgb(229 231 235 / var(--tw-bg-opacity)); } -.bg-gray-300{ +.bg-gray-300 { --tw-bg-opacity: 1; background-color: rgb(209 213 219 / var(--tw-bg-opacity)); } -.bg-gray-400{ +.bg-gray-400 { --tw-bg-opacity: 1; background-color: rgb(156 163 175 / var(--tw-bg-opacity)); } -.bg-gray-50{ +.bg-gray-50 { --tw-bg-opacity: 1; background-color: rgb(249 250 251 / var(--tw-bg-opacity)); } -.bg-gray-500{ +.bg-gray-500 { --tw-bg-opacity: 1; background-color: rgb(107 114 128 / var(--tw-bg-opacity)); } -.bg-gray-600{ +.bg-gray-600 { --tw-bg-opacity: 1; background-color: rgb(75 85 99 / var(--tw-bg-opacity)); } -.bg-gray-700{ +.bg-gray-700 { --tw-bg-opacity: 1; background-color: rgb(55 65 81 / var(--tw-bg-opacity)); } -.bg-gray-800{ +.bg-gray-800 { --tw-bg-opacity: 1; background-color: rgb(31 41 55 / var(--tw-bg-opacity)); } -.bg-gray-900{ +.bg-gray-900 { --tw-bg-opacity: 1; background-color: rgb(17 24 39 / var(--tw-bg-opacity)); } -.bg-green-400{ +.bg-green-400 { --tw-bg-opacity: 1; background-color: rgb(74 222 128 / var(--tw-bg-opacity)); } -.bg-green-500{ +.bg-green-500 { --tw-bg-opacity: 1; background-color: rgb(34 197 94 / var(--tw-bg-opacity)); } -.bg-green-600{ +.bg-green-600 { --tw-bg-opacity: 1; background-color: rgb(22 163 74 / var(--tw-bg-opacity)); } -.bg-green-700{ +.bg-green-700 { --tw-bg-opacity: 1; background-color: rgb(21 128 61 / var(--tw-bg-opacity)); } -.bg-green-800{ +.bg-green-800 { --tw-bg-opacity: 1; background-color: rgb(22 101 52 / var(--tw-bg-opacity)); } -.bg-lime-900{ +.bg-lime-900 { --tw-bg-opacity: 1; background-color: rgb(54 83 20 / var(--tw-bg-opacity)); } -.bg-orange-500{ +.bg-orange-500 { --tw-bg-opacity: 1; background-color: rgb(249 115 22 / var(--tw-bg-opacity)); } -.bg-red-100{ +.bg-red-100 { --tw-bg-opacity: 1; background-color: rgb(254 226 226 / var(--tw-bg-opacity)); } -.bg-red-300{ +.bg-red-300 { --tw-bg-opacity: 1; background-color: rgb(252 165 165 / var(--tw-bg-opacity)); } -.bg-red-500{ +.bg-red-500 { --tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity)); } -.bg-red-600{ +.bg-red-600 { --tw-bg-opacity: 1; background-color: rgb(220 38 38 / var(--tw-bg-opacity)); } -.bg-red-700{ +.bg-red-700 { --tw-bg-opacity: 1; background-color: rgb(185 28 28 / var(--tw-bg-opacity)); } -.bg-red-800{ +.bg-red-800 { --tw-bg-opacity: 1; background-color: rgb(153 27 27 / var(--tw-bg-opacity)); } -.bg-slate-200{ +.bg-slate-200 { --tw-bg-opacity: 1; background-color: rgb(226 232 240 / var(--tw-bg-opacity)); } -.bg-slate-400{ +.bg-slate-400 { --tw-bg-opacity: 1; background-color: rgb(148 163 184 / var(--tw-bg-opacity)); } -.bg-slate-600{ +.bg-slate-600 { --tw-bg-opacity: 1; background-color: rgb(71 85 105 / var(--tw-bg-opacity)); } -.bg-teal-500{ +.bg-teal-500 { --tw-bg-opacity: 1; background-color: rgb(20 184 166 / var(--tw-bg-opacity)); } -.bg-teal-600{ +.bg-teal-600 { --tw-bg-opacity: 1; background-color: rgb(13 148 136 / var(--tw-bg-opacity)); } -.bg-teal-700{ +.bg-teal-700 { --tw-bg-opacity: 1; background-color: rgb(15 118 110 / var(--tw-bg-opacity)); } -.bg-teal-800{ +.bg-teal-800 { --tw-bg-opacity: 1; background-color: rgb(17 94 89 / var(--tw-bg-opacity)); } -.bg-transparent{ +.bg-transparent { background-color: transparent; } -.bg-violet-500{ +.bg-violet-500 { --tw-bg-opacity: 1; background-color: rgb(139 92 246 / var(--tw-bg-opacity)); } -.bg-violet-900{ +.bg-violet-900 { --tw-bg-opacity: 1; background-color: rgb(76 29 149 / var(--tw-bg-opacity)); } -.bg-white{ +.bg-white { --tw-bg-opacity: 1; background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } -.bg-yellow-400{ +.bg-yellow-400 { --tw-bg-opacity: 1; background-color: rgb(250 204 21 / var(--tw-bg-opacity)); } -.bg-zinc-700{ +.bg-zinc-700 { --tw-bg-opacity: 1; background-color: rgb(63 63 70 / var(--tw-bg-opacity)); } -.bg-opacity-80{ +.bg-opacity-80 { --tw-bg-opacity: 0.8; } -.bg-gradient-to-b{ +.bg-gradient-to-b { background-image: -webkit-gradient(linear, left top, left bottom, from(var(--tw-gradient-stops))); background-image: linear-gradient(to bottom, var(--tw-gradient-stops)); } -.from-\[\#264744\]{ +.from-\[\#264744\] { --tw-gradient-from: #264744 var(--tw-gradient-from-position); --tw-gradient-to: rgb(38 71 68 / 0) var(--tw-gradient-to-position); --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); } -.from-10\%{ +.from-10\% { --tw-gradient-from-position: 10%; } -.via-\[\#325d5a\]{ - --tw-gradient-to: rgb(50 93 90 / 0) var(--tw-gradient-to-position); +.via-\[\#325d5a\] { + --tw-gradient-to: rgb(50 93 90 / 0) var(--tw-gradient-to-position); --tw-gradient-stops: var(--tw-gradient-from), #325d5a var(--tw-gradient-via-position), var(--tw-gradient-to); } -.to-\[\#264744\]{ +.to-\[\#264744\] { --tw-gradient-to: #264744 var(--tw-gradient-to-position); } -.to-95\%{ +.to-95\% { --tw-gradient-to-position: 95%; } -.bg-contain{ +.bg-contain { background-size: contain; } -.bg-cover{ +.bg-cover { background-size: cover; } -.bg-fixed{ +.bg-fixed { background-attachment: fixed; } -.bg-center{ +.bg-center { background-position: center; } -.bg-no-repeat{ +.bg-no-repeat { background-repeat: no-repeat; } -.fill-current{ +.fill-current { fill: currentColor; } -.object-cover{ +.object-cover { -o-object-fit: cover; - object-fit: cover; + object-fit: cover; } -.p-1{ +.p-1 { padding: 0.25rem; } -.p-2{ +.p-2 { padding: 0.5rem; } -.p-3{ +.p-3 { padding: 0.75rem; } -.p-4{ +.p-4 { padding: 1rem; } -.p-5{ +.p-5 { padding: 1.25rem; } -.p-8{ +.p-8 { padding: 2rem; } -.p-\[1px\]{ +.p-\[1px\] { padding: 1px; } -.p-\[2px\]{ +.p-\[2px\] { padding: 2px; } -.p-\[3px\]{ +.p-\[3px\] { padding: 3px; } -.p-\[4px\]{ +.p-\[4px\] { padding: 4px; } -.px-1{ +.px-1 { padding-left: 0.25rem; padding-right: 0.25rem; } -.px-2{ +.px-2 { padding-left: 0.5rem; padding-right: 0.5rem; } -.px-20{ +.px-20 { padding-left: 5rem; padding-right: 5rem; } -.px-3{ +.px-3 { padding-left: 0.75rem; padding-right: 0.75rem; } -.px-4{ +.px-4 { padding-left: 1rem; padding-right: 1rem; } -.px-5{ +.px-5 { padding-left: 1.25rem; padding-right: 1.25rem; } -.px-6{ +.px-6 { padding-left: 1.5rem; padding-right: 1.5rem; } -.px-8{ +.px-8 { padding-left: 2rem; padding-right: 2rem; } -.px-\[1px\]{ +.px-\[1px\] { padding-left: 1px; padding-right: 1px; } -.px-\[2px\]{ +.px-\[2px\] { padding-left: 2px; padding-right: 2px; } -.py-1{ +.py-1 { padding-top: 0.25rem; padding-bottom: 0.25rem; } -.py-2{ +.py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; } -.py-2\.5{ +.py-2\.5 { padding-top: 0.625rem; padding-bottom: 0.625rem; } -.py-3{ +.py-3 { padding-top: 0.75rem; padding-bottom: 0.75rem; } -.py-4{ +.py-4 { padding-top: 1rem; padding-bottom: 1rem; } -.py-\[2px\]{ +.py-\[2px\] { padding-top: 2px; padding-bottom: 2px; } -.py-\[3px\]{ +.py-\[3px\] { padding-top: 3px; padding-bottom: 3px; } -.pb-1{ +.pb-1 { padding-bottom: 0.25rem; } -.pb-2{ +.pb-2 { padding-bottom: 0.5rem; } -.pe-10{ +.pe-10 { -webkit-padding-end: 2.5rem; - padding-inline-end: 2.5rem; + padding-inline-end: 2.5rem; } -.pl-1{ +.pl-1 { padding-left: 0.25rem; } -.pl-2{ +.pl-2 { padding-left: 0.5rem; } -.pl-3{ +.pl-3 { padding-left: 0.75rem; } -.pl-4{ +.pl-4 { padding-left: 1rem; } -.pr-0{ +.pr-0 { padding-right: 0px; } -.pr-1{ +.pr-1 { padding-right: 0.25rem; } -.pr-2{ +.pr-2 { padding-right: 0.5rem; } -.pr-4{ +.pr-4 { padding-right: 1rem; } -.pt-0{ +.pt-0 { padding-top: 0px; } -.pt-0\.5{ +.pt-0\.5 { padding-top: 0.125rem; } -.pt-1{ +.pt-1 { padding-top: 0.25rem; } -.pt-10{ +.pt-10 { padding-top: 2.5rem; } -.pt-2{ +.pt-2 { padding-top: 0.5rem; } -.pt-4{ +.pt-4 { padding-top: 1rem; } -.pt-5{ +.pt-5 { padding-top: 1.25rem; } -.pt-8{ +.pt-8 { padding-top: 2rem; } -.text-left{ +.text-left { text-align: left; } -.text-center{ +.text-center { text-align: center; } -.indent-0{ +.indent-0 { text-indent: 0px; } -.font-mono{ +.font-mono { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } -.font-sans{ +.font-sans { font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } -.font-serif{ +.font-serif { font-family: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; } -.text-2xl{ +.text-2xl { font-size: 1.5rem; line-height: 2rem; } -.text-2xs{ +.text-2xs { font-size: 10px; } -.text-3xl{ +.text-3xl { font-size: 1.875rem; line-height: 2.25rem; } -.text-\[10px\]{ +.text-\[10px\] { font-size: 10px; } -.text-\[11px\]{ +.text-\[11px\] { font-size: 11px; } -.text-\[12px\]{ +.text-\[12px\] { font-size: 12px; } -.text-\[18px\]{ +.text-\[18px\] { font-size: 18px; } -.text-\[20px\]{ +.text-\[20px\] { font-size: 20px; } -.text-\[22px\]{ +.text-\[22px\] { font-size: 22px; } -.text-\[24px\]{ +.text-\[24px\] { font-size: 24px; } -.text-\[26px\]{ +.text-\[26px\] { font-size: 26px; } -.text-\[8px\]{ +.text-\[8px\] { font-size: 8px; } -.text-\[9px\]{ +.text-\[9px\] { font-size: 9px; } -.text-base{ +.text-base { font-size: 1rem; line-height: 1.5rem; } -.text-lg{ +.text-lg { font-size: 1.125rem; line-height: 1.75rem; } -.text-sm{ +.text-sm { font-size: 0.875rem; line-height: 1.25rem; } -.text-sm\/none{ +.text-sm\/none { font-size: 0.875rem; line-height: 1; } -.text-xl{ +.text-xl { font-size: 1.25rem; line-height: 1.75rem; } -.text-xs{ +.text-xs { font-size: 0.75rem; line-height: 1rem; } -.font-\[400\]{ +.font-\[400\] { font-weight: 400; } -.font-\[500\]{ +.font-\[500\] { font-weight: 500; } -.font-bold{ +.font-bold { font-weight: 700; } -.font-light{ +.font-light { font-weight: 300; } -.font-medium{ +.font-medium { font-weight: 500; } -.font-normal{ +.font-normal { font-weight: 400; } -.font-semibold{ +.font-semibold { font-weight: 600; } -.uppercase{ +.uppercase { text-transform: uppercase; } -.lowercase{ +.lowercase { text-transform: lowercase; } -.capitalize{ +.capitalize { text-transform: capitalize; } -.leading-5{ +.leading-5 { line-height: 1.25rem; } -.leading-6{ +.leading-6 { line-height: 1.5rem; } -.leading-8{ +.leading-8 { line-height: 2rem; } -.leading-tight{ +.leading-tight { line-height: 1.25; } -.tracking-wide{ +.tracking-wide { letter-spacing: 0.025em; } -.tracking-wider{ +.tracking-wider { letter-spacing: 0.05em; } -.text-\[\#14171a\]{ +.text-\[\#14171a\] { --tw-text-opacity: 1; color: rgb(20 23 26 / var(--tw-text-opacity)); } -.text-\[\#336666\]{ +.text-\[\#336666\] { --tw-text-opacity: 1; color: rgb(51 102 102 / var(--tw-text-opacity)); } -.text-\[\#4B878D\]{ +.text-\[\#4B878D\] { --tw-text-opacity: 1; color: rgb(75 135 141 / var(--tw-text-opacity)); } -.text-\[\#dee3e3\]{ +.text-\[\#dee3e3\] { --tw-text-opacity: 1; color: rgb(222 227 227 / var(--tw-text-opacity)); } -.text-\[\#e6e4e4\]{ +.text-\[\#e6e4e4\] { --tw-text-opacity: 1; color: rgb(230 228 228 / var(--tw-text-opacity)); } -.text-\[greenyellow\]{ +.text-\[greenyellow\] { --tw-text-opacity: 1; color: rgb(173 255 47 / var(--tw-text-opacity)); } -.text-amber-200{ +.text-amber-200 { --tw-text-opacity: 1; color: rgb(253 230 138 / var(--tw-text-opacity)); } -.text-amber-300{ +.text-amber-300 { --tw-text-opacity: 1; color: rgb(252 211 77 / var(--tw-text-opacity)); } -.text-amber-400{ +.text-amber-400 { --tw-text-opacity: 1; color: rgb(251 191 36 / var(--tw-text-opacity)); } -.text-amber-500{ +.text-amber-500 { --tw-text-opacity: 1; color: rgb(245 158 11 / var(--tw-text-opacity)); } -.text-amber-600{ +.text-amber-600 { --tw-text-opacity: 1; color: rgb(217 119 6 / var(--tw-text-opacity)); } -.text-black{ +.text-black { --tw-text-opacity: 1; color: rgb(0 0 0 / var(--tw-text-opacity)); } -.text-blue-400{ +.text-blue-400 { --tw-text-opacity: 1; color: rgb(96 165 250 / var(--tw-text-opacity)); } -.text-cyan-400{ +.text-cyan-400 { --tw-text-opacity: 1; color: rgb(34 211 238 / var(--tw-text-opacity)); } -.text-cyan-600{ +.text-cyan-600 { --tw-text-opacity: 1; color: rgb(8 145 178 / var(--tw-text-opacity)); } -.text-gray-100{ +.text-gray-100 { --tw-text-opacity: 1; color: rgb(243 244 246 / var(--tw-text-opacity)); } -.text-gray-200{ +.text-gray-200 { --tw-text-opacity: 1; color: rgb(229 231 235 / var(--tw-text-opacity)); } -.text-gray-300{ +.text-gray-300 { --tw-text-opacity: 1; color: rgb(209 213 219 / var(--tw-text-opacity)); } -.text-gray-400{ +.text-gray-400 { --tw-text-opacity: 1; color: rgb(156 163 175 / var(--tw-text-opacity)); } -.text-gray-50{ +.text-gray-50 { --tw-text-opacity: 1; color: rgb(249 250 251 / var(--tw-text-opacity)); } -.text-gray-500{ +.text-gray-500 { --tw-text-opacity: 1; color: rgb(107 114 128 / var(--tw-text-opacity)); } -.text-gray-600{ +.text-gray-600 { --tw-text-opacity: 1; color: rgb(75 85 99 / var(--tw-text-opacity)); } -.text-gray-700{ +.text-gray-700 { --tw-text-opacity: 1; color: rgb(55 65 81 / var(--tw-text-opacity)); } -.text-gray-800{ +.text-gray-800 { --tw-text-opacity: 1; color: rgb(31 41 55 / var(--tw-text-opacity)); } -.text-gray-900{ +.text-gray-900 { --tw-text-opacity: 1; color: rgb(17 24 39 / var(--tw-text-opacity)); } -.text-green-400{ +.text-green-400 { --tw-text-opacity: 1; color: rgb(74 222 128 / var(--tw-text-opacity)); } -.text-green-500{ +.text-green-500 { --tw-text-opacity: 1; color: rgb(34 197 94 / var(--tw-text-opacity)); } -.text-green-600{ +.text-green-600 { --tw-text-opacity: 1; color: rgb(22 163 74 / var(--tw-text-opacity)); } -.text-green-700{ +.text-green-700 { --tw-text-opacity: 1; color: rgb(21 128 61 / var(--tw-text-opacity)); } -.text-orange-500{ +.text-orange-500 { --tw-text-opacity: 1; color: rgb(249 115 22 / var(--tw-text-opacity)); } -.text-red-400{ +.text-red-400 { --tw-text-opacity: 1; color: rgb(248 113 113 / var(--tw-text-opacity)); } -.text-red-500{ +.text-red-500 { --tw-text-opacity: 1; color: rgb(239 68 68 / var(--tw-text-opacity)); } -.text-red-600{ +.text-red-600 { --tw-text-opacity: 1; color: rgb(220 38 38 / var(--tw-text-opacity)); } -.text-red-700{ +.text-red-700 { --tw-text-opacity: 1; color: rgb(185 28 28 / var(--tw-text-opacity)); } -.text-red-800{ +.text-red-800 { --tw-text-opacity: 1; color: rgb(153 27 27 / var(--tw-text-opacity)); } -.text-teal-400{ +.text-teal-400 { --tw-text-opacity: 1; color: rgb(45 212 191 / var(--tw-text-opacity)); } -.text-teal-500{ +.text-teal-500 { --tw-text-opacity: 1; color: rgb(20 184 166 / var(--tw-text-opacity)); } -.text-teal-600{ +.text-teal-600 { --tw-text-opacity: 1; color: rgb(13 148 136 / var(--tw-text-opacity)); } -.text-teal-700{ +.text-teal-700 { --tw-text-opacity: 1; color: rgb(15 118 110 / var(--tw-text-opacity)); } -.text-white{ +.text-white { --tw-text-opacity: 1; color: rgb(255 255 255 / var(--tw-text-opacity)); } -.text-yellow-400{ +.text-yellow-400 { --tw-text-opacity: 1; color: rgb(250 204 21 / var(--tw-text-opacity)); } -.text-yellow-500{ +.text-yellow-500 { --tw-text-opacity: 1; color: rgb(234 179 8 / var(--tw-text-opacity)); } -.placeholder-gray-400\/70::-webkit-input-placeholder{ +.placeholder-gray-400\/70::-webkit-input-placeholder { color: rgb(156 163 175 / 0.7); } -.placeholder-gray-400\/70::-moz-placeholder{ +.placeholder-gray-400\/70::-moz-placeholder { color: rgb(156 163 175 / 0.7); } -.placeholder-gray-400\/70:-ms-input-placeholder{ +.placeholder-gray-400\/70:-ms-input-placeholder { color: rgb(156 163 175 / 0.7); } -.placeholder-gray-400\/70::-ms-input-placeholder{ +.placeholder-gray-400\/70::-ms-input-placeholder { color: rgb(156 163 175 / 0.7); } -.placeholder-gray-400\/70::placeholder{ +.placeholder-gray-400\/70::placeholder { color: rgb(156 163 175 / 0.7); } -.placeholder-gray-500::-webkit-input-placeholder{ +.placeholder-gray-500::-webkit-input-placeholder { --tw-placeholder-opacity: 1; color: rgb(107 114 128 / var(--tw-placeholder-opacity)); } -.placeholder-gray-500::-moz-placeholder{ +.placeholder-gray-500::-moz-placeholder { --tw-placeholder-opacity: 1; color: rgb(107 114 128 / var(--tw-placeholder-opacity)); } -.placeholder-gray-500:-ms-input-placeholder{ +.placeholder-gray-500:-ms-input-placeholder { --tw-placeholder-opacity: 1; color: rgb(107 114 128 / var(--tw-placeholder-opacity)); } -.placeholder-gray-500::-ms-input-placeholder{ +.placeholder-gray-500::-ms-input-placeholder { --tw-placeholder-opacity: 1; color: rgb(107 114 128 / var(--tw-placeholder-opacity)); } -.placeholder-gray-500::placeholder{ +.placeholder-gray-500::placeholder { --tw-placeholder-opacity: 1; color: rgb(107 114 128 / var(--tw-placeholder-opacity)); } -.placeholder-red-500::-webkit-input-placeholder{ +.placeholder-red-500::-webkit-input-placeholder { --tw-placeholder-opacity: 1; color: rgb(239 68 68 / var(--tw-placeholder-opacity)); } -.placeholder-red-500::-moz-placeholder{ +.placeholder-red-500::-moz-placeholder { --tw-placeholder-opacity: 1; color: rgb(239 68 68 / var(--tw-placeholder-opacity)); } -.placeholder-red-500:-ms-input-placeholder{ +.placeholder-red-500:-ms-input-placeholder { --tw-placeholder-opacity: 1; color: rgb(239 68 68 / var(--tw-placeholder-opacity)); } -.placeholder-red-500::-ms-input-placeholder{ +.placeholder-red-500::-ms-input-placeholder { --tw-placeholder-opacity: 1; color: rgb(239 68 68 / var(--tw-placeholder-opacity)); } -.placeholder-red-500::placeholder{ +.placeholder-red-500::placeholder { --tw-placeholder-opacity: 1; color: rgb(239 68 68 / var(--tw-placeholder-opacity)); } -.opacity-0{ +.opacity-0 { opacity: 0; } -.opacity-100{ +.opacity-100 { opacity: 1; } -.opacity-25{ +.opacity-25 { opacity: 0.25; } -.opacity-30{ +.opacity-30 { opacity: 0.3; } -.opacity-40{ +.opacity-40 { opacity: 0.4; } -.opacity-45{ +.opacity-45 { opacity: 0.45; } -.opacity-50{ +.opacity-50 { opacity: 0.5; } -.opacity-65{ +.opacity-65 { opacity: 0.65; } -.opacity-70{ +.opacity-70 { opacity: 0.7; } -.opacity-80{ +.opacity-80 { opacity: 0.8; } -.shadow{ +.shadow { --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); -webkit-box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.shadow-2xl{ +.shadow-2xl { --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25); --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color); -webkit-box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.shadow-lg{ +.shadow-lg { --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); -webkit-box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.shadow-md{ +.shadow-md { --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); -webkit-box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.shadow-none{ +.shadow-none { --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; -webkit-box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.shadow-sm{ +.shadow-sm { --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); -webkit-box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.shadow-xl{ +.shadow-xl { --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color); -webkit-box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.shadow-\[\#101010\]{ +.shadow-\[\#101010\] { --tw-shadow-color: #101010; --tw-shadow: var(--tw-shadow-colored); } -.shadow-\[\#111010\]{ +.shadow-\[\#111010\] { --tw-shadow-color: #111010; --tw-shadow: var(--tw-shadow-colored); } -.shadow-\[\#141414\]{ +.shadow-\[\#141414\] { --tw-shadow-color: #141414; --tw-shadow: var(--tw-shadow-colored); } -.shadow-\[\#141516\]{ +.shadow-\[\#141516\] { --tw-shadow-color: #141516; --tw-shadow: var(--tw-shadow-colored); } -.shadow-\[\#182020\]{ +.shadow-\[\#182020\] { --tw-shadow-color: #182020; --tw-shadow: var(--tw-shadow-colored); } -.shadow-\[\#191a1b\]{ +.shadow-\[\#191a1b\] { --tw-shadow-color: #191a1b; --tw-shadow: var(--tw-shadow-colored); } -.shadow-\[\#1c3634\]{ +.shadow-\[\#1c3634\] { --tw-shadow-color: #1c3634; --tw-shadow: var(--tw-shadow-colored); } -.shadow-\[\#1e2b2b\]{ +.shadow-\[\#1e2b2b\] { --tw-shadow-color: #1e2b2b; --tw-shadow: var(--tw-shadow-colored); } -.shadow-\[\#1f2021\]{ +.shadow-\[\#1f2021\] { --tw-shadow-color: #1f2021; --tw-shadow: var(--tw-shadow-colored); } -.shadow-\[\#23272a\]{ +.shadow-\[\#23272a\] { --tw-shadow-color: #23272a; --tw-shadow: var(--tw-shadow-colored); } -.shadow-\[\#242c29\]{ +.shadow-\[\#242c29\] { --tw-shadow-color: #242c29; --tw-shadow: var(--tw-shadow-colored); } -.shadow-\[\#252525\]{ +.shadow-\[\#252525\] { --tw-shadow-color: #252525; --tw-shadow: var(--tw-shadow-colored); } -.shadow-\[\#303232\]{ +.shadow-\[\#303232\] { --tw-shadow-color: #303232; --tw-shadow: var(--tw-shadow-colored); } -.shadow-\[\#3a3a3b\]{ +.shadow-\[\#3a3a3b\] { --tw-shadow-color: #3a3a3b; --tw-shadow: var(--tw-shadow-colored); } -.shadow-black{ +.shadow-black { --tw-shadow-color: #000; --tw-shadow: var(--tw-shadow-colored); } -.shadow-gray-600{ +.shadow-gray-600 { --tw-shadow-color: #4b5563; --tw-shadow: var(--tw-shadow-colored); } -.shadow-gray-800{ +.shadow-gray-800 { --tw-shadow-color: #1f2937; --tw-shadow: var(--tw-shadow-colored); } -.shadow-zinc-800{ +.shadow-zinc-800 { --tw-shadow-color: #27272a; --tw-shadow: var(--tw-shadow-colored); } -.outline-none{ +.outline-none { outline: 2px solid transparent; outline-offset: 2px; } -.outline{ +.outline { outline-style: solid; } -.outline-0{ +.outline-0 { outline-width: 0px; } -.outline-transparent{ +.outline-transparent { outline-color: transparent; } -.ring-1{ +.ring-1 { --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); -webkit-box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); - box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); } -.ring-black{ +.ring-black { --tw-ring-opacity: 1; --tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity)); } -.ring-opacity-5{ +.ring-opacity-5 { --tw-ring-opacity: 0.05; } -.invert{ +.invert { --tw-invert: invert(100%); - -webkit-filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); + -webkit-filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) + var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) + var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); } -.filter{ - -webkit-filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +.filter { + -webkit-filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) + var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) + var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); } -.filter-none{ +.filter-none { -webkit-filter: none; - filter: none; -} - -.transition{ - -webkit-transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, -webkit-box-shadow, -webkit-transform, -webkit-filter, -webkit-backdrop-filter; - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, -webkit-box-shadow, -webkit-transform, -webkit-filter, -webkit-backdrop-filter; - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-box-shadow, -webkit-transform, -webkit-filter, -webkit-backdrop-filter; + filter: none; +} + +.transition { + -webkit-transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, -webkit-box-shadow, + -webkit-transform, -webkit-filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, -webkit-box-shadow, + -webkit-transform, -webkit-filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, + backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, + backdrop-filter, -webkit-box-shadow, -webkit-transform, -webkit-filter, -webkit-backdrop-filter; -webkit-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); -webkit-transition-duration: 150ms; - transition-duration: 150ms; + transition-duration: 150ms; } -.transition-all{ +.transition-all { -webkit-transition-property: all; transition-property: all; -webkit-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); -webkit-transition-duration: 150ms; - transition-duration: 150ms; + transition-duration: 150ms; } -.transition-colors{ +.transition-colors { -webkit-transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; -webkit-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); -webkit-transition-duration: 150ms; - transition-duration: 150ms; + transition-duration: 150ms; } -.transition-transform{ +.transition-transform { -webkit-transition-property: -webkit-transform; transition-property: -webkit-transform; transition-property: transform; transition-property: transform, -webkit-transform; -webkit-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); -webkit-transition-duration: 150ms; - transition-duration: 150ms; + transition-duration: 150ms; } -.delay-100{ +.delay-100 { -webkit-transition-delay: 100ms; - transition-delay: 100ms; + transition-delay: 100ms; } -.duration-100{ +.duration-100 { -webkit-transition-duration: 100ms; - transition-duration: 100ms; + transition-duration: 100ms; } -.duration-1000{ +.duration-1000 { -webkit-transition-duration: 1000ms; - transition-duration: 1000ms; + transition-duration: 1000ms; } -.duration-150{ +.duration-150 { -webkit-transition-duration: 150ms; - transition-duration: 150ms; + transition-duration: 150ms; } -.duration-200{ +.duration-200 { -webkit-transition-duration: 200ms; - transition-duration: 200ms; + transition-duration: 200ms; } -.duration-300{ +.duration-300 { -webkit-transition-duration: 300ms; - transition-duration: 300ms; + transition-duration: 300ms; } -.duration-500{ +.duration-500 { -webkit-transition-duration: 500ms; - transition-duration: 500ms; + transition-duration: 500ms; } -.ease-in{ +.ease-in { -webkit-transition-timing-function: cubic-bezier(0.4, 0, 1, 1); - transition-timing-function: cubic-bezier(0.4, 0, 1, 1); + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); } -.ease-in-out{ +.ease-in-out { -webkit-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); } -.ease-out{ +.ease-out { -webkit-transition-timing-function: cubic-bezier(0, 0, 0.2, 1); - transition-timing-function: cubic-bezier(0, 0, 0.2, 1); + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); } -.scrollbar::-webkit-scrollbar-track{ +.scrollbar::-webkit-scrollbar-track { background-color: var(--scrollbar-track); border-radius: var(--scrollbar-track-radius); } -.scrollbar::-webkit-scrollbar-track:hover{ +.scrollbar::-webkit-scrollbar-track:hover { background-color: var(--scrollbar-track-hover, var(--scrollbar-track)); } -.scrollbar::-webkit-scrollbar-track:active{ +.scrollbar::-webkit-scrollbar-track:active { background-color: var(--scrollbar-track-active, var(--scrollbar-track-hover, var(--scrollbar-track))); } -.scrollbar::-webkit-scrollbar-thumb{ +.scrollbar::-webkit-scrollbar-thumb { background-color: var(--scrollbar-thumb); border-radius: var(--scrollbar-thumb-radius); } -.scrollbar::-webkit-scrollbar-thumb:hover{ +.scrollbar::-webkit-scrollbar-thumb:hover { background-color: var(--scrollbar-thumb-hover, var(--scrollbar-thumb)); } -.scrollbar::-webkit-scrollbar-thumb:active{ +.scrollbar::-webkit-scrollbar-thumb:active { background-color: var(--scrollbar-thumb-active, var(--scrollbar-thumb-hover, var(--scrollbar-thumb))); } -.scrollbar::-webkit-scrollbar-corner{ +.scrollbar::-webkit-scrollbar-corner { background-color: var(--scrollbar-corner); border-radius: var(--scrollbar-corner-radius); } -.scrollbar::-webkit-scrollbar-corner:hover{ +.scrollbar::-webkit-scrollbar-corner:hover { background-color: var(--scrollbar-corner-hover, var(--scrollbar-corner)); } -.scrollbar::-webkit-scrollbar-corner:active{ +.scrollbar::-webkit-scrollbar-corner:active { background-color: var(--scrollbar-corner-active, var(--scrollbar-corner-hover, var(--scrollbar-corner))); } -.scrollbar{ +.scrollbar { scrollbar-width: auto; scrollbar-color: var(--scrollbar-thumb, initial) var(--scrollbar-track, initial); } -.scrollbar::-webkit-scrollbar{ +.scrollbar::-webkit-scrollbar { display: block; width: var(--scrollbar-width, 16px); height: var(--scrollbar-height, 16px); } -.scrollbar-thin::-webkit-scrollbar-track{ +.scrollbar-thin::-webkit-scrollbar-track { background-color: var(--scrollbar-track); border-radius: var(--scrollbar-track-radius); } -.scrollbar-thin::-webkit-scrollbar-track:hover{ +.scrollbar-thin::-webkit-scrollbar-track:hover { background-color: var(--scrollbar-track-hover, var(--scrollbar-track)); } -.scrollbar-thin::-webkit-scrollbar-track:active{ +.scrollbar-thin::-webkit-scrollbar-track:active { background-color: var(--scrollbar-track-active, var(--scrollbar-track-hover, var(--scrollbar-track))); } -.scrollbar-thin::-webkit-scrollbar-thumb{ +.scrollbar-thin::-webkit-scrollbar-thumb { background-color: var(--scrollbar-thumb); border-radius: var(--scrollbar-thumb-radius); } -.scrollbar-thin::-webkit-scrollbar-thumb:hover{ +.scrollbar-thin::-webkit-scrollbar-thumb:hover { background-color: var(--scrollbar-thumb-hover, var(--scrollbar-thumb)); } -.scrollbar-thin::-webkit-scrollbar-thumb:active{ +.scrollbar-thin::-webkit-scrollbar-thumb:active { background-color: var(--scrollbar-thumb-active, var(--scrollbar-thumb-hover, var(--scrollbar-thumb))); } -.scrollbar-thin::-webkit-scrollbar-corner{ +.scrollbar-thin::-webkit-scrollbar-corner { background-color: var(--scrollbar-corner); border-radius: var(--scrollbar-corner-radius); } -.scrollbar-thin::-webkit-scrollbar-corner:hover{ +.scrollbar-thin::-webkit-scrollbar-corner:hover { background-color: var(--scrollbar-corner-hover, var(--scrollbar-corner)); } -.scrollbar-thin::-webkit-scrollbar-corner:active{ +.scrollbar-thin::-webkit-scrollbar-corner:active { background-color: var(--scrollbar-corner-active, var(--scrollbar-corner-hover, var(--scrollbar-corner))); } -.scrollbar-thin{ +.scrollbar-thin { scrollbar-width: thin; scrollbar-color: var(--scrollbar-thumb, initial) var(--scrollbar-track, initial); } -.scrollbar-thin::-webkit-scrollbar{ +.scrollbar-thin::-webkit-scrollbar { display: block; width: 8px; height: 8px; } -.scrollbar-track-gray-100{ +.scrollbar-track-gray-100 { --scrollbar-track: #f3f4f6 !important; } -.scrollbar-track-gray-800{ +.scrollbar-track-gray-800 { --scrollbar-track: #1f2937 !important; } -.scrollbar-track-transparent{ +.scrollbar-track-transparent { --scrollbar-track: transparent !important; } -.scrollbar-thumb-gray-300{ +.scrollbar-thumb-gray-300 { --scrollbar-thumb: #d1d5db !important; } -.scrollbar-thumb-gray-500{ +.scrollbar-thumb-gray-500 { --scrollbar-thumb: #6b7280 !important; } -.scrollbar-thumb-teal-800{ +.scrollbar-thumb-teal-800 { --scrollbar-thumb: #115e59 !important; } -.\[-webkit-tap-highlight-color\:_transparent\]{ +.\[-webkit-tap-highlight-color\:_transparent\] { -webkit-tap-highlight-color: transparent; } @@ -5292,755 +5338,775 @@ html body { margin: 0; font-family: "Noto Sans", sans-serif; -webkit-box-sizing: border-box; - box-sizing: border-box; + box-sizing: border-box; background-color: rgb(31, 31, 31); } -.placeholder\:text-gray-400::-webkit-input-placeholder{ +.placeholder\:text-gray-400::-webkit-input-placeholder { --tw-text-opacity: 1; color: rgb(156 163 175 / var(--tw-text-opacity)); } -.placeholder\:text-gray-400::-moz-placeholder{ +.placeholder\:text-gray-400::-moz-placeholder { --tw-text-opacity: 1; color: rgb(156 163 175 / var(--tw-text-opacity)); } -.placeholder\:text-gray-400:-ms-input-placeholder{ +.placeholder\:text-gray-400:-ms-input-placeholder { --tw-text-opacity: 1; color: rgb(156 163 175 / var(--tw-text-opacity)); } -.placeholder\:text-gray-400::-ms-input-placeholder{ +.placeholder\:text-gray-400::-ms-input-placeholder { --tw-text-opacity: 1; color: rgb(156 163 175 / var(--tw-text-opacity)); } -.placeholder\:text-gray-400::placeholder{ +.placeholder\:text-gray-400::placeholder { --tw-text-opacity: 1; color: rgb(156 163 175 / var(--tw-text-opacity)); } -.placeholder\:text-gray-500::-webkit-input-placeholder{ +.placeholder\:text-gray-500::-webkit-input-placeholder { --tw-text-opacity: 1; color: rgb(107 114 128 / var(--tw-text-opacity)); } -.placeholder\:text-gray-500::-moz-placeholder{ +.placeholder\:text-gray-500::-moz-placeholder { --tw-text-opacity: 1; color: rgb(107 114 128 / var(--tw-text-opacity)); } -.placeholder\:text-gray-500:-ms-input-placeholder{ +.placeholder\:text-gray-500:-ms-input-placeholder { --tw-text-opacity: 1; color: rgb(107 114 128 / var(--tw-text-opacity)); } -.placeholder\:text-gray-500::-ms-input-placeholder{ +.placeholder\:text-gray-500::-ms-input-placeholder { --tw-text-opacity: 1; color: rgb(107 114 128 / var(--tw-text-opacity)); } -.placeholder\:text-gray-500::placeholder{ +.placeholder\:text-gray-500::placeholder { --tw-text-opacity: 1; color: rgb(107 114 128 / var(--tw-text-opacity)); } -.after\:absolute::after{ +.after\:absolute::after { content: var(--tw-content); position: absolute; } -.after\:left-\[2px\]::after{ +.after\:left-\[2px\]::after { content: var(--tw-content); left: 2px; } -.after\:top-0::after{ +.after\:top-0::after { content: var(--tw-content); top: 0px; } -.after\:top-0\.5::after{ +.after\:top-0\.5::after { content: var(--tw-content); top: 0.125rem; } -.after\:h-4::after{ +.after\:h-4::after { content: var(--tw-content); height: 1rem; } -.after\:w-4::after{ +.after\:w-4::after { content: var(--tw-content); width: 1rem; } -.after\:rounded-full::after{ +.after\:rounded-full::after { content: var(--tw-content); border-radius: 9999px; } -.after\:border::after{ +.after\:border::after { content: var(--tw-content); border-width: 1px; } -.after\:border-gray-300::after{ +.after\:border-gray-300::after { content: var(--tw-content); --tw-border-opacity: 1; border-color: rgb(209 213 219 / var(--tw-border-opacity)); } -.after\:bg-white::after{ +.after\:bg-white::after { content: var(--tw-content); --tw-bg-opacity: 1; background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } -.after\:transition-all::after{ +.after\:transition-all::after { content: var(--tw-content); -webkit-transition-property: all; transition-property: all; -webkit-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); -webkit-transition-duration: 150ms; - transition-duration: 150ms; + transition-duration: 150ms; } -.after\:content-\[\'\'\]::after{ - --tw-content: ''; +.after\:content-\[\'\'\]::after { + --tw-content: ""; content: var(--tw-content); } -.peer:checked ~ .peer-checked\:start-6{ +.peer:checked ~ .peer-checked\:start-6 { inset-inline-start: 1.5rem; } -.peer:checked ~ .peer-checked\:border-green-600{ +.peer:checked ~ .peer-checked\:border-green-600 { --tw-border-opacity: 1; border-color: rgb(22 163 74 / var(--tw-border-opacity)); } -.peer:checked ~ .peer-checked\:bg-green-500{ +.peer:checked ~ .peer-checked\:bg-green-500 { --tw-bg-opacity: 1; background-color: rgb(34 197 94 / var(--tw-bg-opacity)); } -.peer:checked ~ .peer-checked\:bg-green-600{ +.peer:checked ~ .peer-checked\:bg-green-600 { --tw-bg-opacity: 1; background-color: rgb(22 163 74 / var(--tw-bg-opacity)); } -.peer:checked ~ .peer-checked\:text-green-600{ +.peer:checked ~ .peer-checked\:text-green-600 { --tw-text-opacity: 1; color: rgb(22 163 74 / var(--tw-text-opacity)); } -.peer:checked ~ .peer-checked\:shadow-inner{ +.peer:checked ~ .peer-checked\:shadow-inner { --tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); --tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color); -webkit-box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.peer:checked ~ .peer-checked\:shadow-gray-600{ +.peer:checked ~ .peer-checked\:shadow-gray-600 { --tw-shadow-color: #4b5563; --tw-shadow: var(--tw-shadow-colored); } -.peer:checked ~ .peer-checked\:after\:translate-x-7::after{ +.peer:checked ~ .peer-checked\:after\:translate-x-7::after { content: var(--tw-content); --tw-translate-x: 1.75rem; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.peer:checked ~ .peer-checked\:after\:border-white::after{ +.peer:checked ~ .peer-checked\:after\:border-white::after { content: var(--tw-content); --tw-border-opacity: 1; border-color: rgb(255 255 255 / var(--tw-border-opacity)); } -.hover\:scale-105:hover{ +.hover\:scale-105:hover { --tw-scale-x: 1.05; --tw-scale-y: 1.05; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.hover\:scale-110:hover{ +.hover\:scale-110:hover { --tw-scale-x: 1.1; --tw-scale-y: 1.1; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.hover\:scale-125:hover{ +.hover\:scale-125:hover { --tw-scale-x: 1.25; --tw-scale-y: 1.25; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.hover\:scale-95:hover{ - --tw-scale-x: .95; - --tw-scale-y: .95; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +.hover\:scale-95:hover { + --tw-scale-x: 0.95; + --tw-scale-y: 0.95; + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.hover\:overflow-y-auto:hover{ +.hover\:overflow-y-auto:hover { overflow-y: auto; } -.hover\:scroll-auto:hover{ +.hover\:scroll-auto:hover { scroll-behavior: auto; } -.hover\:border:hover{ +.hover\:border:hover { border-width: 1px; } -.hover\:border-\[\#3f4851\]:hover{ +.hover\:border-\[\#3f4851\]:hover { --tw-border-opacity: 1; border-color: rgb(63 72 81 / var(--tw-border-opacity)); } -.hover\:border-\[\#4d7575\]:hover{ +.hover\:border-\[\#4d7575\]:hover { --tw-border-opacity: 1; border-color: rgb(77 117 117 / var(--tw-border-opacity)); } -.hover\:border-amber-300:hover{ +.hover\:border-amber-300:hover { --tw-border-opacity: 1; border-color: rgb(252 211 77 / var(--tw-border-opacity)); } -.hover\:border-blue-400:hover{ +.hover\:border-blue-400:hover { --tw-border-opacity: 1; border-color: rgb(96 165 250 / var(--tw-border-opacity)); } -.hover\:border-gray-100:hover{ +.hover\:border-gray-100:hover { --tw-border-opacity: 1; border-color: rgb(243 244 246 / var(--tw-border-opacity)); } -.hover\:border-gray-200:hover{ +.hover\:border-gray-200:hover { --tw-border-opacity: 1; border-color: rgb(229 231 235 / var(--tw-border-opacity)); } -.hover\:border-gray-300:hover{ +.hover\:border-gray-300:hover { --tw-border-opacity: 1; border-color: rgb(209 213 219 / var(--tw-border-opacity)); } -.hover\:border-gray-500:hover{ +.hover\:border-gray-500:hover { --tw-border-opacity: 1; border-color: rgb(107 114 128 / var(--tw-border-opacity)); } -.hover\:border-gray-600:hover{ +.hover\:border-gray-600:hover { --tw-border-opacity: 1; border-color: rgb(75 85 99 / var(--tw-border-opacity)); } -.hover\:border-red-500:hover{ +.hover\:border-red-500:hover { --tw-border-opacity: 1; border-color: rgb(239 68 68 / var(--tw-border-opacity)); } -.hover\:border-teal-200:hover{ +.hover\:border-teal-200:hover { --tw-border-opacity: 1; border-color: rgb(153 246 228 / var(--tw-border-opacity)); } -.hover\:border-teal-500:hover{ +.hover\:border-teal-500:hover { --tw-border-opacity: 1; border-color: rgb(20 184 166 / var(--tw-border-opacity)); } -.hover\:border-teal-600:hover{ +.hover\:border-teal-600:hover { --tw-border-opacity: 1; border-color: rgb(13 148 136 / var(--tw-border-opacity)); } -.hover\:bg-\[\#212325\]:hover{ +.hover\:bg-\[\#212325\]:hover { --tw-bg-opacity: 1; background-color: rgb(33 35 37 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#222425\]:hover{ +.hover\:bg-\[\#222425\]:hover { --tw-bg-opacity: 1; background-color: rgb(34 36 37 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#224141\]:hover{ +.hover\:bg-\[\#224141\]:hover { --tw-bg-opacity: 1; background-color: rgb(34 65 65 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#23272a\]:hover{ +.hover\:bg-\[\#23272a\]:hover { --tw-bg-opacity: 1; background-color: rgb(35 39 42 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#234545\]:hover{ +.hover\:bg-\[\#234545\]:hover { --tw-bg-opacity: 1; background-color: rgb(35 69 69 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#243535\]:hover{ +.hover\:bg-\[\#243535\]:hover { --tw-bg-opacity: 1; background-color: rgb(36 53 53 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#244343\]:hover{ +.hover\:bg-\[\#244343\]:hover { --tw-bg-opacity: 1; background-color: rgb(36 67 67 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#264e4e\]:hover{ +.hover\:bg-\[\#264e4e\]:hover { --tw-bg-opacity: 1; background-color: rgb(38 78 78 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#282a2d\]:hover{ +.hover\:bg-\[\#282a2d\]:hover { --tw-bg-opacity: 1; background-color: rgb(40 42 45 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#2b3034\]:hover{ +.hover\:bg-\[\#2b3034\]:hover { --tw-bg-opacity: 1; background-color: rgb(43 48 52 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#325e5a\]:hover{ +.hover\:bg-\[\#325e5a\]:hover { --tw-bg-opacity: 1; background-color: rgb(50 94 90 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#336666\]:hover{ +.hover\:bg-\[\#336666\]:hover { --tw-bg-opacity: 1; background-color: rgb(51 102 102 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#374045\]:hover{ +.hover\:bg-\[\#374045\]:hover { --tw-bg-opacity: 1; background-color: rgb(55 64 69 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#383c3f\]:hover{ +.hover\:bg-\[\#383c3f\]:hover { --tw-bg-opacity: 1; background-color: rgb(56 60 63 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#3c434a\]:hover{ +.hover\:bg-\[\#3c434a\]:hover { --tw-bg-opacity: 1; background-color: rgb(60 67 74 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#447a75\]:hover{ +.hover\:bg-\[\#447a75\]:hover { --tw-bg-opacity: 1; background-color: rgb(68 122 117 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#4c7960\]:hover{ +.hover\:bg-\[\#4c7960\]:hover { --tw-bg-opacity: 1; background-color: rgb(76 121 96 / var(--tw-bg-opacity)); } -.hover\:bg-\[\#4d7575\]:hover{ +.hover\:bg-\[\#4d7575\]:hover { --tw-bg-opacity: 1; background-color: rgb(77 117 117 / var(--tw-bg-opacity)); } -.hover\:bg-black:hover{ +.hover\:bg-black:hover { --tw-bg-opacity: 1; background-color: rgb(0 0 0 / var(--tw-bg-opacity)); } -.hover\:bg-blue-100:hover{ +.hover\:bg-blue-100:hover { --tw-bg-opacity: 1; background-color: rgb(219 234 254 / var(--tw-bg-opacity)); } -.hover\:bg-blue-300:hover{ +.hover\:bg-blue-300:hover { --tw-bg-opacity: 1; background-color: rgb(147 197 253 / var(--tw-bg-opacity)); } -.hover\:bg-blue-400:hover{ +.hover\:bg-blue-400:hover { --tw-bg-opacity: 1; background-color: rgb(96 165 250 / var(--tw-bg-opacity)); } -.hover\:bg-blue-500:hover{ +.hover\:bg-blue-500:hover { --tw-bg-opacity: 1; background-color: rgb(59 130 246 / var(--tw-bg-opacity)); } -.hover\:bg-cyan-600:hover{ +.hover\:bg-cyan-600:hover { --tw-bg-opacity: 1; background-color: rgb(8 145 178 / var(--tw-bg-opacity)); } -.hover\:bg-gray-100:hover{ +.hover\:bg-gray-100:hover { --tw-bg-opacity: 1; background-color: rgb(243 244 246 / var(--tw-bg-opacity)); } -.hover\:bg-gray-300:hover{ +.hover\:bg-gray-300:hover { --tw-bg-opacity: 1; background-color: rgb(209 213 219 / var(--tw-bg-opacity)); } -.hover\:bg-gray-500:hover{ +.hover\:bg-gray-500:hover { --tw-bg-opacity: 1; background-color: rgb(107 114 128 / var(--tw-bg-opacity)); } -.hover\:bg-gray-600:hover{ +.hover\:bg-gray-600:hover { --tw-bg-opacity: 1; background-color: rgb(75 85 99 / var(--tw-bg-opacity)); } -.hover\:bg-gray-700:hover{ +.hover\:bg-gray-700:hover { --tw-bg-opacity: 1; background-color: rgb(55 65 81 / var(--tw-bg-opacity)); } -.hover\:bg-green-600:hover{ +.hover\:bg-green-600:hover { --tw-bg-opacity: 1; background-color: rgb(22 163 74 / var(--tw-bg-opacity)); } -.hover\:bg-lime-900:hover{ +.hover\:bg-lime-900:hover { --tw-bg-opacity: 1; background-color: rgb(54 83 20 / var(--tw-bg-opacity)); } -.hover\:bg-red-500:hover{ +.hover\:bg-red-500:hover { --tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity)); } -.hover\:bg-red-600:hover{ +.hover\:bg-red-600:hover { --tw-bg-opacity: 1; background-color: rgb(220 38 38 / var(--tw-bg-opacity)); } -.hover\:bg-red-700:hover{ +.hover\:bg-red-700:hover { --tw-bg-opacity: 1; background-color: rgb(185 28 28 / var(--tw-bg-opacity)); } -.hover\:bg-red-800:hover{ +.hover\:bg-red-800:hover { --tw-bg-opacity: 1; background-color: rgb(153 27 27 / var(--tw-bg-opacity)); } -.hover\:bg-red-950:hover{ +.hover\:bg-red-950:hover { --tw-bg-opacity: 1; background-color: rgb(69 10 10 / var(--tw-bg-opacity)); } -.hover\:bg-slate-300:hover{ +.hover\:bg-slate-300:hover { --tw-bg-opacity: 1; background-color: rgb(203 213 225 / var(--tw-bg-opacity)); } -.hover\:bg-teal-600:hover{ +.hover\:bg-teal-600:hover { --tw-bg-opacity: 1; background-color: rgb(13 148 136 / var(--tw-bg-opacity)); } -.hover\:bg-teal-700:hover{ +.hover\:bg-teal-700:hover { --tw-bg-opacity: 1; background-color: rgb(15 118 110 / var(--tw-bg-opacity)); } -.hover\:bg-teal-800:hover{ +.hover\:bg-teal-800:hover { --tw-bg-opacity: 1; background-color: rgb(17 94 89 / var(--tw-bg-opacity)); } -.hover\:bg-teal-900:hover{ +.hover\:bg-teal-900:hover { --tw-bg-opacity: 1; background-color: rgb(19 78 74 / var(--tw-bg-opacity)); } -.hover\:bg-teal-950:hover{ +.hover\:bg-teal-950:hover { --tw-bg-opacity: 1; background-color: rgb(4 47 46 / var(--tw-bg-opacity)); } -.hover\:bg-opacity-10:hover{ +.hover\:bg-opacity-10:hover { --tw-bg-opacity: 0.1; } -.hover\:text-black:hover{ +.hover\:text-black:hover { --tw-text-opacity: 1; color: rgb(0 0 0 / var(--tw-text-opacity)); } -.hover\:text-gray-100:hover{ +.hover\:text-gray-100:hover { --tw-text-opacity: 1; color: rgb(243 244 246 / var(--tw-text-opacity)); } -.hover\:text-gray-200:hover{ +.hover\:text-gray-200:hover { --tw-text-opacity: 1; color: rgb(229 231 235 / var(--tw-text-opacity)); } -.hover\:text-gray-300:hover{ +.hover\:text-gray-300:hover { --tw-text-opacity: 1; color: rgb(209 213 219 / var(--tw-text-opacity)); } -.hover\:text-gray-700:hover{ +.hover\:text-gray-700:hover { --tw-text-opacity: 1; color: rgb(55 65 81 / var(--tw-text-opacity)); } -.hover\:text-teal-500:hover{ +.hover\:text-teal-500:hover { --tw-text-opacity: 1; color: rgb(20 184 166 / var(--tw-text-opacity)); } -.hover\:text-white:hover{ +.hover\:text-white:hover { --tw-text-opacity: 1; color: rgb(255 255 255 / var(--tw-text-opacity)); } -.hover\:shadow-2xl:hover{ +.hover\:shadow-2xl:hover { --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25); --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color); -webkit-box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.hover\:shadow-lg:hover{ +.hover\:shadow-lg:hover { --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); -webkit-box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.hover\:shadow-md:hover{ +.hover\:shadow-md:hover { --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); -webkit-box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.hover\:shadow-sm:hover{ +.hover\:shadow-sm:hover { --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); -webkit-box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.hover\:shadow-\[\#050505\]:hover{ +.hover\:shadow-\[\#050505\]:hover { --tw-shadow-color: #050505; --tw-shadow: var(--tw-shadow-colored); } -.hover\:shadow-\[\#101214\]:hover{ +.hover\:shadow-\[\#101214\]:hover { --tw-shadow-color: #101214; --tw-shadow: var(--tw-shadow-colored); } -.hover\:shadow-\[\#191a1a\]:hover{ +.hover\:shadow-\[\#191a1a\]:hover { --tw-shadow-color: #191a1a; --tw-shadow: var(--tw-shadow-colored); } -.hover\:shadow-\[\#1b1c1c\]:hover{ +.hover\:shadow-\[\#1b1c1c\]:hover { --tw-shadow-color: #1b1c1c; --tw-shadow: var(--tw-shadow-colored); } -.hover\:shadow-\[\#1b1d20\]:hover{ +.hover\:shadow-\[\#1b1d20\]:hover { --tw-shadow-color: #1b1d20; --tw-shadow: var(--tw-shadow-colored); } -.hover\:shadow-\[\#1e2a29\]:hover{ +.hover\:shadow-\[\#1e2a29\]:hover { --tw-shadow-color: #1e2a29; --tw-shadow: var(--tw-shadow-colored); } -.hover\:shadow-\[\#303232\]:hover{ +.hover\:shadow-\[\#303232\]:hover { --tw-shadow-color: #303232; --tw-shadow: var(--tw-shadow-colored); } -.hover\:shadow-\[\#3a3a3b\]:hover{ +.hover\:shadow-\[\#3a3a3b\]:hover { --tw-shadow-color: #3a3a3b; --tw-shadow: var(--tw-shadow-colored); } -.hover\:shadow-black:hover{ +.hover\:shadow-black:hover { --tw-shadow-color: #000; --tw-shadow: var(--tw-shadow-colored); } -.hover\:shadow-gray-800:hover{ +.hover\:shadow-gray-800:hover { --tw-shadow-color: #1f2937; --tw-shadow: var(--tw-shadow-colored); } -.hover\:shadow-gray-900:hover{ +.hover\:shadow-gray-900:hover { --tw-shadow-color: #111827; --tw-shadow: var(--tw-shadow-colored); } -.hover\:shadow-gray-950:hover{ +.hover\:shadow-gray-950:hover { --tw-shadow-color: #030712; --tw-shadow: var(--tw-shadow-colored); } -.hover\:brightness-110:hover{ +.hover\:brightness-110:hover { --tw-brightness: brightness(1.1); - -webkit-filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); + -webkit-filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) + var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) + var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); } -.hover\:scrollbar-thumb-teal-800{ +.hover\:scrollbar-thumb-teal-800 { --scrollbar-thumb-hover: #115e59 !important; } -.focus\:border-blue-500:focus{ +.focus\:border-blue-500:focus { --tw-border-opacity: 1; border-color: rgb(59 130 246 / var(--tw-border-opacity)); } -.focus\:border-teal-500:focus{ +.focus\:border-teal-500:focus { --tw-border-opacity: 1; border-color: rgb(20 184 166 / var(--tw-border-opacity)); } -.focus\:outline-none:focus{ +.focus\:outline-none:focus { outline: 2px solid transparent; outline-offset: 2px; } -.focus\:ring:focus{ +.focus\:ring:focus { --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color); -webkit-box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); - box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); } -.focus\:ring-blue-300:focus{ +.focus\:ring-blue-300:focus { --tw-ring-opacity: 1; --tw-ring-color: rgb(147 197 253 / var(--tw-ring-opacity)); } -.focus\:ring-opacity-40:focus{ +.focus\:ring-opacity-40:focus { --tw-ring-opacity: 0.4; } -.active\:scale-100:active{ +.active\:scale-100:active { --tw-scale-x: 1; --tw-scale-y: 1; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.active\:scale-75:active{ - --tw-scale-x: .75; - --tw-scale-y: .75; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +.active\:scale-75:active { + --tw-scale-x: 0.75; + --tw-scale-y: 0.75; + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.active\:scale-90:active{ - --tw-scale-x: .9; - --tw-scale-y: .9; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +.active\:scale-90:active { + --tw-scale-x: 0.9; + --tw-scale-y: 0.9; + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.active\:scale-95:active{ - --tw-scale-x: .95; - --tw-scale-y: .95; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +.active\:scale-95:active { + --tw-scale-x: 0.95; + --tw-scale-y: 0.95; + -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) + skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.active\:border-none:active{ +.active\:border-none:active { border-style: none; } -.active\:bg-\[\#1b1c1c\]:active{ +.active\:bg-\[\#1b1c1c\]:active { --tw-bg-opacity: 1; background-color: rgb(27 28 28 / var(--tw-bg-opacity)); } -.active\:shadow-none:active{ +.active\:shadow-none:active { --tw-shadow: 0 0 #0000; --tw-shadow-colored: 0 0 #0000; -webkit-box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.active\:shadow-gray-800:active{ +.active\:shadow-gray-800:active { --tw-shadow-color: #1f2937; --tw-shadow: var(--tw-shadow-colored); } -@media (min-width: 640px){ - .sm\:text-sm{ +@media (min-width: 640px) { + .sm\:text-sm { font-size: 0.875rem; line-height: 1.25rem; } } -@media (min-width: 768px){ - .md\:mb-0{ +@media (min-width: 768px) { + .md\:mb-0 { margin-bottom: 0px; } } -.rtl\:left-0:where([dir="rtl"], [dir="rtl"] *){ +.rtl\:left-0:where([dir="rtl"], [dir="rtl"] *) { left: 0px; } -.rtl\:right-auto:where([dir="rtl"], [dir="rtl"] *){ +.rtl\:right-auto:where([dir="rtl"], [dir="rtl"] *) { right: auto; } -@media (prefers-color-scheme: dark){ - .dark\:text-gray-300{ +@media (prefers-color-scheme: dark) { + .dark\:text-gray-300 { --tw-text-opacity: 1; color: rgb(209 213 219 / var(--tw-text-opacity)); } - .dark\:text-gray-400{ + .dark\:text-gray-400 { --tw-text-opacity: 1; color: rgb(156 163 175 / var(--tw-text-opacity)); } - .dark\:hover\:bg-gray-700:hover{ + .dark\:hover\:bg-gray-700:hover { --tw-bg-opacity: 1; background-color: rgb(55 65 81 / var(--tw-bg-opacity)); } - .dark\:hover\:text-white:hover{ + .dark\:hover\:text-white:hover { --tw-text-opacity: 1; color: rgb(255 255 255 / var(--tw-text-opacity)); } } -.\[\&\:checked_\+_span_svg\[data-checked-icon\]\]\:block:checked + span svg[data-checked-icon]{ +.\[\&\:checked_\+_span_svg\[data-checked-icon\]\]\:block:checked + span svg[data-checked-icon] { display: block; } -.\[\&\:checked_\+_span_svg\[data-unchecked-icon\]\]\:hidden:checked + span svg[data-unchecked-icon]{ +.\[\&\:checked_\+_span_svg\[data-unchecked-icon\]\]\:hidden:checked + span svg[data-unchecked-icon] { display: none; } diff --git a/launcher/src/StereumUpdater.js b/launcher/src/StereumUpdater.js index 73e9902ec..0c28a60e0 100644 --- a/launcher/src/StereumUpdater.js +++ b/launcher/src/StereumUpdater.js @@ -1,78 +1,84 @@ import { autoUpdater } from "electron-updater"; import { app, BrowserWindow } from "electron"; - export class StereumUpdater { - constructor(logger, createWindow) { - this.updater = autoUpdater - this.updateWindow = null - this.logger = logger - this.createWindow = createWindow - } + constructor(logger, createWindow) { + this.updater = autoUpdater; + this.updateWindow = null; + this.logger = logger; + this.createWindow = createWindow; + } - checkForUpdates() { - app.showExitPrompt = true; - this.updater.checkForUpdates() - } + checkForUpdates() { + app.showExitPrompt = true; + this.updater.checkForUpdates(); + } - initUpdater() { - this.updater.logger = this.logger; - this.updater.logger.transports.file.level = "debug"; + initUpdater() { + this.updater.logger = this.logger; + this.updater.logger.transports.file.level = "debug"; - this.updater.on("checking-for-update", () => { - this.logger.info("Stereum is checking for updates."); - }); + this.updater.on("checking-for-update", () => { + this.logger.info("Stereum is checking for updates."); + }); - this.updater.on("update-available", async () => { - this.updateWindow = await this.createWindow("update") - if (this.updateWindow) - this.updateWindow.webContents.send('UpdateEvents', { message: "Update available.", type: "available" }) - this.logger.info("Update available."); - }); + this.updater.on("update-available", async () => { + this.updateWindow = await this.createWindow("update"); + if (this.updateWindow) this.updateWindow.webContents.send("UpdateEvents", { message: "Update available.", type: "available" }); + this.logger.info("Update available."); + }); - this.updater.on("update-not-available", () => { - app.showExitPrompt = false; - this.createWindow(); - this.logger.info("No updates available. Stereum is Up-to-date."); - }); + this.updater.on("update-not-available", () => { + app.showExitPrompt = false; + this.createWindow(); + this.logger.info("No updates available. Stereum is Up-to-date."); + }); - this.updater.on("download-progress", (data) => { - if (this.updateWindow) - this.updateWindow.webContents.send('UpdateEvents', { message: "Downloading update...", type: "downloading", data: { percent: data.percent, MBps: data.bytesPerSecond / 1000000 } }) - this.logger.info("Update progress", data); + this.updater.on("download-progress", (data) => { + if (this.updateWindow) + this.updateWindow.webContents.send("UpdateEvents", { + message: "Downloading update...", + type: "downloading", + data: { percent: data.percent, MBps: data.bytesPerSecond / 1000000 }, }); + this.logger.info("Update progress", data); + }); - this.updater.on("update-downloaded", async (data) => { - app.showExitPrompt = false - if (this.updateWindow) - this.updateWindow.webContents.send('UpdateEvents', { message: "Update downloaded. " + data.version, type: "downloaded" }) - this.updater.quitAndInstall() - this.logger.info("Update downloaded.", data); - }); + this.updater.on("update-downloaded", async (data) => { + app.showExitPrompt = false; + if (this.updateWindow) + this.updateWindow.webContents.send("UpdateEvents", { message: "Update downloaded. " + data.version, type: "downloaded" }); + this.updater.quitAndInstall(); + this.logger.info("Update downloaded.", data); + }); - this.updater.on("error", async (error) => { - app.showExitPrompt = false; - const allWindows = await BrowserWindow.getAllWindows(); - for (const win of allWindows) { - await win.close() - } - this.createWindow(); - this.logger.error("Error: ", error) - }); - } + this.updater.on("error", async (error) => { + app.showExitPrompt = false; + const allWindows = await BrowserWindow.getAllWindows(); + for (const win of allWindows) { + await win.close(); + } + this.createWindow(); + this.logger.error("Error: ", error); + }); + } - async runDebug() { - async function Sleep(ms) { - return new Promise((resolve) => setTimeout(resolve, ms)); - } - this.updateWindow = await this.createWindow("update"); - await Sleep(5000) - for (let i = 0; i < 10; i++) { - this.updateWindow.webContents.send('UpdateEvents', { message: "Downloading update...", type: "downloading", data: { percent: i * 10, MBps: i * 10.11 } }) - await Sleep(1000) - } - this.updateWindow.webContents.send('UpdateEvents', { message: "Update downloaded. " + "2.0.0-rc.20", type: "downloaded" }) - await Sleep(1000) - this.updateWindow.close() + async runDebug() { + async function Sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } + this.updateWindow = await this.createWindow("update"); + await Sleep(5000); + for (let i = 0; i < 10; i++) { + this.updateWindow.webContents.send("UpdateEvents", { + message: "Downloading update...", + type: "downloading", + data: { percent: i * 10, MBps: i * 10.11 }, + }); + await Sleep(1000); } -} \ No newline at end of file + this.updateWindow.webContents.send("UpdateEvents", { message: "Update downloaded. " + "2.0.0-rc.20", type: "downloaded" }); + await Sleep(1000); + this.updateWindow.close(); + } +} diff --git a/launcher/src/backend/AuthenticationService.js b/launcher/src/backend/AuthenticationService.js index 67d78ba4b..f96e95a62 100644 --- a/launcher/src/backend/AuthenticationService.js +++ b/launcher/src/backend/AuthenticationService.js @@ -49,16 +49,16 @@ export class AuthenticationService { outputArray.push( outputString[ - outputString.findIndex(function (item) { - return item.indexOf("https") !== -1; - }) + outputString.findIndex(function (item) { + return item.indexOf("https") !== -1; + }) ] ); outputArray.push( outputString[ - outputString.findIndex(function (item) { - return item.indexOf("secret key") !== -1; - }) + outputString.findIndex(function (item) { + return item.indexOf("secret key") !== -1; + }) ] ); win.send("2FAEvents", outputArray); @@ -96,9 +96,9 @@ export class AuthenticationService { outputArray.push( outputString[ - outputString.findIndex(function (item) { - return item.indexOf("https") !== -1; - }) + outputString.findIndex(function (item) { + return item.indexOf("https") !== -1; + }) ] ); @@ -165,7 +165,7 @@ export class AuthenticationService { async create2FAQRCode(type, name, ip, secret) { let otpauth = `otpauth://${type}/${ip}@${name}?secret=${secret}&issuer=${name}`; - const url = await QRCode.toDataURL(otpauth) + const url = await QRCode.toDataURL(otpauth); return url; } } diff --git a/launcher/src/backend/ConfigManager.js b/launcher/src/backend/ConfigManager.js index b641202d3..ce6d45adc 100644 --- a/launcher/src/backend/ConfigManager.js +++ b/launcher/src/backend/ConfigManager.js @@ -7,12 +7,7 @@ export class ConfigManager { this.nodeConnection = nodeConnection; this.serviceManager = null; this.multiSetupPath = "/etc/stereum/multisetup.yaml"; - this.commonServices = [ - "PrometheusService", - "GrafanaService", - "PrometheusNodeExporterService", - "NotificationService", - ]; + this.commonServices = ["PrometheusService", "GrafanaService", "PrometheusNodeExporterService", "NotificationService"]; } setServiceManager(serviceManager) { this.serviceManager = serviceManager; @@ -56,9 +51,7 @@ export class ConfigManager { * @returns {Promise} Resolves with command execution result, indicating file existence. */ async checkFileExistence() { - const fileExistResult = await this.nodeConnection.sshService.exec( - `test -f ${this.multiSetupPath} && echo "exist" || echo "notExist"` - ); + const fileExistResult = await this.nodeConnection.sshService.exec(`test -f ${this.multiSetupPath} && echo "exist" || echo "notExist"`); return fileExistResult; } @@ -166,9 +159,7 @@ export class ConfigManager { } if (commonServices.length > 0) { - commonServicesObj[setupId].services = commonServicesObj[setupId].services.concat( - commonServices.map((service) => service.id) - ); + commonServicesObj[setupId].services = commonServicesObj[setupId].services.concat(commonServices.map((service) => service.id)); } return commonServicesObj; } diff --git a/launcher/src/backend/HetznerServer.js b/launcher/src/backend/HetznerServer.js index 7c914d7da..a62f71b4d 100755 --- a/launcher/src/backend/HetznerServer.js +++ b/launcher/src/backend/HetznerServer.js @@ -1,4 +1,6 @@ -const { utils: { generateKeyPairSync } } = require('ssh2'); +const { + utils: { generateKeyPairSync }, +} = require("ssh2"); const log = require("electron-log"); const https = require("https"); @@ -9,26 +11,28 @@ export class HetznerServer { this.serverName = null; this.serverIPv4 = null; this.serverRootPassword = null; - this.sshKeyPair = generateKeyPairSync("ed25519") + this.sshKeyPair = generateKeyPairSync("ed25519"); this.sshKeyName = null; } async Sleep(ms) { - let interval - await new Promise((resolve) => { interval = setTimeout(resolve, ms) }); + let interval; + await new Promise((resolve) => { + interval = setTimeout(resolve, ms); + }); clearInterval(interval); } async checkServerConnection(nodeConnection) { let tries = 0; - let connected = false + let connected = false; while (!connected && tries < 300) { try { - tries++ - log.info(`Trying to connect (${tries})`) - connected = await nodeConnection.sshService.checkSSHConnection(nodeConnection.nodeConnectionParams, 5000) + tries++; + log.info(`Trying to connect (${tries})`); + connected = await nodeConnection.sshService.checkSSHConnection(nodeConnection.nodeConnectionParams, 5000); } catch (err) { - log.info(err) + log.info(err); } } } @@ -71,16 +75,16 @@ export class HetznerServer { data += d; }); res.on("end", () => { - log.debug(`${options.method} ${options.path} ${res.statusCode} ${res.statusMessage}`) + log.debug(`${options.method} ${options.path} ${res.statusCode} ${res.statusMessage}`); if (res.statusCode >= 300) { - log.error(data) + log.error(data); } resolve(data); }); }); req.on("error", (err) => { - log.info(`${method} ${path} ${query} ${body}`) + log.info(`${method} ${path} ${query} ${body}`); log.error(err); reject(err); }); @@ -137,7 +141,7 @@ export class HetznerServer { * Destroys Server via API call */ async destroy() { - log.info("Destroying Server with ID " + this.serverID + " ...") + log.info("Destroying Server with ID " + this.serverID + " ..."); await this.makeRequest("DELETE", `/v1/servers/${this.serverID}`); @@ -177,7 +181,7 @@ export class HetznerServer { ip: ip, network: networkID, }; - await this.makeRequest("POST", `/v1/servers/${this.serverID}/actions/attach_to_network`, "", JSON.stringify(settings)) + await this.makeRequest("POST", `/v1/servers/${this.serverID}/actions/attach_to_network`, "", JSON.stringify(settings)); } async getSSHKeyByName(name) { @@ -203,16 +207,18 @@ export class HetznerServer { const existing = response.ssh_keys.find((key) => key.name === name); if (existing && existing.id) { await this.deleteSSHKey(existing.id); - log.debug("deleted existing ssh key with name " + name + " and id " + existing.id) + log.debug("deleted existing ssh key with name " + name + " and id " + existing.id); } - return JSON.parse(await this.makeRequest("POST", "/v1/ssh_keys", "", JSON.stringify({ name: name, public_key: this.sshKeyPair.public }))); + return JSON.parse( + await this.makeRequest("POST", "/v1/ssh_keys", "", JSON.stringify({ name: name, public_key: this.sshKeyPair.public })) + ); } async finishTestGracefully(nodeConnection) { - clearInterval(nodeConnection.sshService.checkPoolPolling) - await this.Sleep(10000) + clearInterval(nodeConnection.sshService.checkPoolPolling); + await this.Sleep(10000); await nodeConnection.sshService.disconnect(); - await this.deleteSSHKey() + await this.deleteSSHKey(); await this.destroy(); } } diff --git a/launcher/src/backend/Monitoring.js b/launcher/src/backend/Monitoring.js index 93f99de8b..a9a627ff1 100755 --- a/launcher/src/backend/Monitoring.js +++ b/launcher/src/backend/Monitoring.js @@ -248,13 +248,7 @@ export class Monitoring { if (await this.checkStereumInstallation()) { var serviceConfigs = await this.serviceManagerProm.readServiceConfigurations(); const serviceStates = await this.nodeConnectionProm.listServices(); - if ( - serviceConfigs && - Array.isArray(serviceConfigs) && - serviceConfigs.length > 0 && - serviceStates && - Array.isArray(serviceStates) - ) { + if (serviceConfigs && Array.isArray(serviceConfigs) && serviceConfigs.length > 0 && serviceStates && Array.isArray(serviceStates)) { serviceConfigs = args.length < 1 ? serviceConfigs : serviceConfigs.filter((s) => args.includes(s.service)); serviceConfigs = serviceConfigs .map((config) => { @@ -663,8 +657,7 @@ export class Monitoring { let requestdata = d ? `-d '${d}'` : ""; // Build curl command - const cmd = - `curl -s --location --request ${method} -w "\\n%{http_code}" '${url}' ${requestheaders} ${requestdata}`.trim(); + const cmd = `curl -s --location --request ${method} -w "\\n%{http_code}" '${url}' ${requestheaders} ${requestdata}`.trim(); // Execute the CURL command on the node and return the result let result = null; @@ -804,8 +797,7 @@ export class Monitoring { let requestdata = d ? `-d '${d}'` : ""; // Build curl command - const cmd = - `curl -s --location --request ${method} -w "\\n%{http_code}" '${url}' ${requestheaders} ${requestdata}`.trim(); + const cmd = `curl -s --location --request ${method} -w "\\n%{http_code}" '${url}' ${requestheaders} ${requestdata}`.trim(); // Execute the CURL command on the node and return the result let result = null; @@ -1083,8 +1075,7 @@ export class Monitoring { // Respond success return { code: 0, - info: - "success: rpc data" + (addinfo ? addinfo : " for all running execution clients") + " successfully retrieved", + info: "success: rpc data" + (addinfo ? addinfo : " for all running execution clients") + " successfully retrieved", data: data, }; } @@ -1171,11 +1162,7 @@ export class Monitoring { // Query Prometehus for all possible labels const prometheus_result = await this.queryPrometheus('{__name__=~"' + serviceLabels.join("|") + '"}'); - if ( - typeof prometheus_result !== "object" || - !prometheus_result.hasOwnProperty("status") || - prometheus_result.status != "success" - ) { + if (typeof prometheus_result !== "object" || !prometheus_result.hasOwnProperty("status") || prometheus_result.status != "success") { return { code: 113, info: "error: prometheus query for syncstatus failed", @@ -1224,9 +1211,7 @@ export class Monitoring { let head_block_number = 0; if (typeof ecBlockNumberByRPC == "object") { last_known_head_block_number = await this.getLastKnownHeadBlock(network); - last_known_head_block_number = !this.is_numeric(last_known_head_block_number) - ? 0 - : last_known_head_block_number; + last_known_head_block_number = !this.is_numeric(last_known_head_block_number) ? 0 : last_known_head_block_number; head_block_number = await this.getExecutionHeadBlockFromBeaconApi(consensus.config.serviceID); await this.setLastKnownHeadBlock(head_block_number, network); // does update only if head_block_number is a number and higher if (!this.is_numeric(head_block_number)) { @@ -1240,9 +1225,7 @@ export class Monitoring { let labels = services[clientType][clt.service]; let xx = prometheus_result.data.result.filter( (s) => - labels.includes(s.metric.__name__) && - s.metric.instance.includes(clt.config.instanceID) && - s.metric.job == jobs[clt.service] + labels.includes(s.metric.__name__) && s.metric.instance.includes(clt.config.instanceID) && s.metric.job == jobs[clt.service] ); let frstVal = 0, scndVal = 0; @@ -1269,9 +1252,7 @@ export class Monitoring { const ecbfilt = ecBlockNumberByRPC.data.filter((s) => s.instance_id == clt.config.instanceID).pop(); chain_head_block = ecbfilt.query_result.data.api_reponse; chain_head_block = - typeof chain_head_block === "string" && chain_head_block.startsWith("0x") - ? parseInt(chain_head_block, 16) - : 0; + typeof chain_head_block === "string" && chain_head_block.startsWith("0x") ? parseInt(chain_head_block, 16) : 0; } catch (e) {} let stay_on_hold_till_first_block = false; // true = enabled | false = disabled if (stay_on_hold_till_first_block && !chain_head_block) { @@ -1377,11 +1358,7 @@ export class Monitoring { // Query Prometehus for all possible labels const prometheus_result = await this.queryPrometheus('{__name__=~"' + serviceLabels.join("|") + '"}'); - if ( - typeof prometheus_result !== "object" || - !prometheus_result.hasOwnProperty("status") || - prometheus_result.status != "success" - ) { + if (typeof prometheus_result !== "object" || !prometheus_result.hasOwnProperty("status") || prometheus_result.status != "success") { return { code: 223, info: "error: prometheus query for p2pstatus failed", @@ -1599,9 +1576,7 @@ export class Monitoring { details[clientType]["numPeer"] > details[clientType]["maxPeer"] ? details[clientType]["maxPeer"] : details[clientType]["numPeer"]; - details[clientType]["valPeer"] = Math.round( - (details[clientType]["numPeer"] / details[clientType]["maxPeer"]) * 100 - ); + details[clientType]["valPeer"] = Math.round((details[clientType]["numPeer"] / details[clientType]["maxPeer"]) * 100); details[clientType]["valPeer"] = details[clientType]["valPeer"] > 100 ? 100 : details[clientType]["valPeer"]; // Summarize totals @@ -1654,10 +1629,7 @@ export class Monitoring { // By default return cached data (if available) if (!live) { - if ( - !this.globalMonitoringCache.hasOwnProperty("storagestatus") || - !this.globalMonitoringCache.storagestatus.hasOwnProperty("data") - ) { + if (!this.globalMonitoringCache.hasOwnProperty("storagestatus") || !this.globalMonitoringCache.storagestatus.hasOwnProperty("data")) { return { code: 330, info: "error: storagestatus not available (waiting for updated cache)", @@ -1789,8 +1761,7 @@ export class Monitoring { const rewardsPerValidator = attestationResult.data.api_reponse.data.total_rewards.map((data) => { return { ...data, - total_rewards: - parseInt(data.head) + parseInt(data.source) + parseInt(data.target) + parseInt(data.inactivity), + total_rewards: parseInt(data.head) + parseInt(data.source) + parseInt(data.target) + parseInt(data.inactivity), }; }); @@ -1839,12 +1810,7 @@ export class Monitoring { const baseURL = `http://127.0.0.1:${beaconResult.data.port}`; // Get attestation rewards for given validators - const blockResult = await this.queryBeaconApi( - baseURL, - "/eth/v1/beacon/rewards/sync_committee/" + slot, - validators, - "POST" - ); + const blockResult = await this.queryBeaconApi(baseURL, "/eth/v1/beacon/rewards/sync_committee/" + slot, validators, "POST"); return blockResult.data.api_httpcode == 200 ? blockResult.data.api_reponse.data : []; } catch (error) { log.error("Getting Block Rewards Failed:\n" + error); @@ -2620,11 +2586,7 @@ export class Monitoring { } // Check and format addr - const addr_type = Array.isArray(addr) - ? "arr" - : typeof addr === "string" && ["public", "local"].includes(addr) - ? "str" - : "invalid"; + const addr_type = Array.isArray(addr) ? "arr" : typeof addr === "string" && ["public", "local"].includes(addr) ? "str" : "invalid"; addr = addr_type == "str" ? addr.toLowerCase().trim() : addr; if (addr_type == "invalid") { return { @@ -2644,11 +2606,7 @@ export class Monitoring { if (ports.length < 1) continue; for (let n = 0; n < ports.length; n++) { if (addr == "public" && addresses.some((w) => ports[n].destinationIp.toLowerCase().includes(w))) continue; - if ( - (addr_type == "arr" || addr == "local") && - !addresses.some((w) => ports[n].destinationIp.toLowerCase().includes(w)) - ) - continue; + if ((addr_type == "arr" || addr == "local") && !addresses.some((w) => ports[n].destinationIp.toLowerCase().includes(w))) continue; data.push({ name: svc.service.replace(/Beacon|Service/gi, "").toUpperCase(), port: ports[n].destinationPort, @@ -2666,8 +2624,7 @@ export class Monitoring { // ); // Return success - const addinfo = - addr_type === "str" ? "that are " + addr + "ly available" : "that are available thru ip " + addr.join(" or "); + const addinfo = addr_type === "str" ? "that are " + addr + "ly available" : "that are available thru ip " + addr.join(" or "); return { code: 0, info: "success: open ports " + addinfo + " retrieved", @@ -2711,8 +2668,7 @@ export class Monitoring { const easyInfos = []; for (let i = 0; i < serviceInfos.length; i++) { const hashDependencies = - serviceInfos[i].config.dependencies.consensusClients.length || - serviceInfos[i].config.dependencies.executionClients.length + serviceInfos[i].config.dependencies.consensusClients.length || serviceInfos[i].config.dependencies.executionClients.length ? "yes" : "no"; easyInfos.push({ @@ -2996,23 +2952,11 @@ rm -rf diskoutput const { current_epoch, current_slot } = await this.getCurrentEpochandSlot(); - let proposerDutiesRes = await this.queryBeaconApi( - baseURL, - "/eth/v1/validator/duties/proposer/" + current_epoch, - [], - "GET" - ); - let syncDutiesRes = await this.queryBeaconApi( - baseURL, - "/eth/v1/validator/duties/sync/" + current_epoch, - validatorIndices, - "POST" - ); + let proposerDutiesRes = await this.queryBeaconApi(baseURL, "/eth/v1/validator/duties/proposer/" + current_epoch, [], "GET"); + let syncDutiesRes = await this.queryBeaconApi(baseURL, "/eth/v1/validator/duties/sync/" + current_epoch, validatorIndices, "POST"); return { - proposerDuties: proposerDutiesRes.data.api_reponse.data.filter((d) => - validatorIndices.some((i) => i === d.validator_index) - ), // filter out duties for validators that are not in the validatorIndices (imported vals) array + proposerDuties: proposerDutiesRes.data.api_reponse.data.filter((d) => validatorIndices.some((i) => i === d.validator_index)), // filter out duties for validators that are not in the validatorIndices (imported vals) array syncDuties: syncDutiesRes.data.api_reponse.data, currentEpoch: current_epoch, currentSlot: current_slot, @@ -3052,9 +2996,7 @@ rm -rf diskoutput //check response validatorNotFound = - beaconAPIRunCmd.rc != 0 || - beaconAPIRunCmd.stderr || - JSON.parse(beaconAPIRunCmd.stdout).hasOwnProperty("message"); + beaconAPIRunCmd.rc != 0 || beaconAPIRunCmd.stderr || JSON.parse(beaconAPIRunCmd.stdout).hasOwnProperty("message"); if (!validatorNotFound) data = data.concat(JSON.parse(beaconAPIRunCmd.stdout).data); //merge all gathered stats in one array } const beaconAPICmdLastEpoch = `curl -s -X GET 'http://localhost:${beaconAPIPort}/eth/v1/beacon/states/head/finality_checkpoints' -H 'accept: application/json'`; @@ -3112,9 +3054,7 @@ rm -rf diskoutput let notFound = ":404"; let beaconAPISlotRunCmd = await this.nodeConnection.sshService.exec(`${APIBegin}headers/head${cmdEnd}`); - let beaconAPIEpochRunCmd = await this.nodeConnection.sshService.exec( - `${APIBegin}states/head/finality_checkpoints${cmdEnd}` - ); + let beaconAPIEpochRunCmd = await this.nodeConnection.sshService.exec(`${APIBegin}states/head/finality_checkpoints${cmdEnd}`); let currentSlot = parseInt(JSON.parse(beaconAPISlotRunCmd.stdout).data.header.message.slot); let currentEpoch = Math.floor(currentSlot / epochLength); @@ -3151,8 +3091,7 @@ rm -rf diskoutput }; for (const slots in firstSlots) { - let slotsNumberInEpoch = - `${slots}` === "firstSlotInCurrentEpoch" ? (currentSlot % epochLength) + 1 : epochLength; + let slotsNumberInEpoch = `${slots}` === "firstSlotInCurrentEpoch" ? (currentSlot % epochLength) + 1 : epochLength; for (let i = 0; i < slotsNumberInEpoch; i++) { let beaconAPISlotStatusCmd = @@ -3355,8 +3294,7 @@ rm -rf diskoutput } const queries = { app_monitoring_readyz: "max((app_monitoring_readyz)) by (cluster_name, cluster_hash, cluster_peer)", - cluster_missed_attestations: - "max(increase(core_tracker_failed_duties_total[10m])) by (cluster_hash, cluster_name)", + cluster_missed_attestations: "max(increase(core_tracker_failed_duties_total[10m])) by (cluster_hash, cluster_name)", cluster_failure_rate: "floor(100 * (max(increase(core_tracker_success_duties_total[15m])) by (cluster_hash, cluster_name) / max(increase(core_tracker_expect_duties_total[15m])) by (cluster_hash, cluster_name)))", percentage_failed_sync_message_duty: diff --git a/launcher/src/backend/NodeConnection.js b/launcher/src/backend/NodeConnection.js index a5565984b..8193ea950 100755 --- a/launcher/src/backend/NodeConnection.js +++ b/launcher/src/backend/NodeConnection.js @@ -385,9 +385,7 @@ export class NodeConnection { } if (SSHService.checkExecError(statusResult)) { - throw new Error( - "Failed reading status of ref '" + playbookRunRef + "': " + SSHService.extractExecError(statusResult) - ); + throw new Error("Failed reading status of ref '" + playbookRunRef + "': " + SSHService.extractExecError(statusResult)); } return statusResult.stdout; @@ -426,9 +424,7 @@ export class NodeConnection { } if (SSHService.checkExecError(serviceConfig)) { - throw new Error( - "Failed reading service configuration " + serviceId + ": " + SSHService.extractExecError(serviceConfig) - ); + throw new Error("Failed reading service configuration " + serviceId + ": " + SSHService.extractExecError(serviceConfig)); } return YAML.parse(serviceConfig.stdout); @@ -576,9 +572,7 @@ export class NodeConnection { async getSSVLastKnownOperatorIdFilePath(serviceID, getSsvServiceCfg = null, getSsvNetworkCfg = null) { try { - const getSSVNetworkConfig = getSsvNetworkCfg - ? getSsvNetworkCfg - : await this.getSSVNetworkConfig(serviceID, getSsvServiceCfg); + const getSSVNetworkConfig = getSsvNetworkCfg ? getSsvNetworkCfg : await this.getSSVNetworkConfig(serviceID, getSsvServiceCfg); const ssvNetworkConfigDir = getSSVNetworkConfig.ssvNetworkConfigDir; return ssvNetworkConfigDir + "/last_known_operator_id"; } catch (err) { @@ -599,27 +593,16 @@ export class NodeConnection { try { try { if (!force) { - const existing = await this.getSSVLastKnownOperatorId( - serviceID, - return_details, - getSsvServiceCfg, - getSsvNetworkCfg - ); + const existing = await this.getSSVLastKnownOperatorId(serviceID, return_details, getSsvServiceCfg, getSsvNetworkCfg); const existingLastKnownOperatorId = return_details ? existing.lastKnownOperatorIdFileData : existing; if (existingLastKnownOperatorId == strOperatorId.trim()) { return existing; } } } catch (err) {} - const lastKnownOperatorIdFilePath = await this.getSSVLastKnownOperatorIdFilePath( - serviceID, - getSsvServiceCfg, - getSsvNetworkCfg - ); + const lastKnownOperatorIdFilePath = await this.getSSVLastKnownOperatorIdFilePath(serviceID, getSsvServiceCfg, getSsvNetworkCfg); const lastKnownOperatorIdFileData = strOperatorId.trim(); - const result = await this.sshService.exec( - `echo -n "${lastKnownOperatorIdFileData}" > "${lastKnownOperatorIdFilePath}"` - ); + const result = await this.sshService.exec(`echo -n "${lastKnownOperatorIdFileData}" > "${lastKnownOperatorIdFilePath}"`); if (SSHService.checkExecError(result, true)) { throw new Error(SSHService.extractExecError(result)); } @@ -636,11 +619,7 @@ export class NodeConnection { async getSSVLastKnownOperatorId(serviceID, return_details = false, getSsvServiceCfg = null, getSsvNetworkCfg = null) { try { - const lastKnownOperatorIdFilePath = await this.getSSVLastKnownOperatorIdFilePath( - serviceID, - getSsvServiceCfg, - getSsvNetworkCfg - ); + const lastKnownOperatorIdFilePath = await this.getSSVLastKnownOperatorIdFilePath(serviceID, getSsvServiceCfg, getSsvNetworkCfg); let lastKnownOperatorIdFileContent = ""; if (lastKnownOperatorIdFilePath) { let lastKnownOperatorIdFileRequest = await this.sshService.exec( @@ -665,9 +644,7 @@ export class NodeConnection { async getSSVLastBackedPublicKeyFilePath(serviceID, getSsvServiceCfg = null, getSsvNetworkCfg = null) { try { - const getSSVNetworkConfig = getSsvNetworkCfg - ? getSsvNetworkCfg - : await this.getSSVNetworkConfig(serviceID, getSsvServiceCfg); + const getSSVNetworkConfig = getSsvNetworkCfg ? getSsvNetworkCfg : await this.getSSVNetworkConfig(serviceID, getSsvServiceCfg); const ssvNetworkConfigDir = getSSVNetworkConfig.ssvNetworkConfigDir; return ssvNetworkConfigDir + "/last_backed_public_key"; } catch (err) { @@ -676,23 +653,11 @@ export class NodeConnection { } } - async setSSVLastBackedPublicKey( - serviceID, - strPublicKey, - return_details = false, - getSsvServiceCfg = null, - getSsvNetworkCfg = null - ) { + async setSSVLastBackedPublicKey(serviceID, strPublicKey, return_details = false, getSsvServiceCfg = null, getSsvNetworkCfg = null) { try { - const lastBackedPublicKeyFilePath = await this.getSSVLastBackedPublicKeyFilePath( - serviceID, - getSsvServiceCfg, - getSsvNetworkCfg - ); + const lastBackedPublicKeyFilePath = await this.getSSVLastBackedPublicKeyFilePath(serviceID, getSsvServiceCfg, getSsvNetworkCfg); const lastBackedPublicKeyFileData = strPublicKey.trim(); - const result = await this.sshService.exec( - `echo -n "${lastBackedPublicKeyFileData}" > "${lastBackedPublicKeyFilePath}"` - ); + const result = await this.sshService.exec(`echo -n "${lastBackedPublicKeyFileData}" > "${lastBackedPublicKeyFilePath}"`); if (SSHService.checkExecError(result, true)) { throw new Error(SSHService.extractExecError(result)); } @@ -709,11 +674,7 @@ export class NodeConnection { async getSSVLastBackedPublicKey(serviceID, return_details = false, getSsvServiceCfg = null, getSsvNetworkCfg = null) { try { - const lastBackedPublicKeyFilePath = await this.getSSVLastBackedPublicKeyFilePath( - serviceID, - getSsvServiceCfg, - getSsvNetworkCfg - ); + const lastBackedPublicKeyFilePath = await this.getSSVLastBackedPublicKeyFilePath(serviceID, getSsvServiceCfg, getSsvNetworkCfg); let lastBackedPublicKeyFileContent = ""; if (lastBackedPublicKeyFilePath) { let lastBackedPublicKeyFileRequest = await this.sshService.exec( @@ -812,9 +773,7 @@ export class NodeConnection { throw new Error(SSHService.extractExecError(service_config_read)); } const escapedServiceConfigFile = StringUtils.escapeStringForShell( - service_config_read.stdout - .replace(/^(ssv_pk|ssv_sk|# BEGIN ANSIBLE MANAGED BLOCK|# END ANSIBLE MANAGED BLOCK).*/gm, "") - .trim() + service_config_read.stdout.replace(/^(ssv_pk|ssv_sk|# BEGIN ANSIBLE MANAGED BLOCK|# END ANSIBLE MANAGED BLOCK).*/gm, "").trim() ); const service_config_write = await this.sshService.exec(` mkdir -p ${service_config_dir} && @@ -978,9 +937,7 @@ export class NodeConnection { // Check (unencrypted) SSV secret key (private_key) if (!private_key) { - throw new Error( - "Unencrypted SSV secret key (private key) is invalid (neither given as argument nor found on the server)" - ); + throw new Error("Unencrypted SSV secret key (private key) is invalid (neither given as argument nor found on the server)"); } if (!StringUtils.isBase64(private_key)) { throw new Error("Unencrypted SSV secret key (private key) is invalid (not base 64 encoded)"); @@ -1059,9 +1016,7 @@ export class NodeConnection { } const service_config_content = service_config_read.stdout; const escapedServiceConfigFile = StringUtils.escapeStringForShell( - service_config_content - .replace(/^(ssv_pk|ssv_sk|# BEGIN ANSIBLE MANAGED BLOCK|# END ANSIBLE MANAGED BLOCK).*/gm, "") - .trim() + service_config_content.replace(/^(ssv_pk|ssv_sk|# BEGIN ANSIBLE MANAGED BLOCK|# END ANSIBLE MANAGED BLOCK).*/gm, "").trim() ); const service_config_write = await this.sshService.exec( `mkdir -p ${service_config_dir} && echo ${escapedServiceConfigFile} > ${service_config_file} && @@ -1171,9 +1126,7 @@ export class NodeConnection { throw new Error(SSHService.extractExecError(service_config_read)); } const escapedServiceConfigFile = StringUtils.escapeStringForShell( - service_config_read.stdout - .replace(/^(ssv_pk|ssv_sk|# BEGIN ANSIBLE MANAGED BLOCK|# END ANSIBLE MANAGED BLOCK).*/gm, "") - .trim() + service_config_read.stdout.replace(/^(ssv_pk|ssv_sk|# BEGIN ANSIBLE MANAGED BLOCK|# END ANSIBLE MANAGED BLOCK).*/gm, "").trim() ); const service_config_write = await this.sshService.exec(` mkdir -p ${service_config_dir} && @@ -1252,9 +1205,7 @@ export class NodeConnection { async getSSVLastKnownPublicKeyFilePath(serviceID, getSsvServiceCfg = null, getSsvNetworkCfg = null) { try { - const getSSVNetworkConfig = getSsvNetworkCfg - ? getSsvNetworkCfg - : await this.getSSVNetworkConfig(serviceID, getSsvServiceCfg); + const getSSVNetworkConfig = getSsvNetworkCfg ? getSsvNetworkCfg : await this.getSSVNetworkConfig(serviceID, getSsvServiceCfg); const ssvNetworkConfigDir = getSSVNetworkConfig.ssvNetworkConfigDir; return ssvNetworkConfigDir + "/last_known_public_key"; } catch (err) { @@ -1265,15 +1216,9 @@ export class NodeConnection { async writeSSVLastKnownPublicKeyFile(serviceID, strPublicKey, getSsvServiceCfg = null, getSsvNetworkCfg = null) { try { - const lastKnownPublicKeyFilePath = await this.getSSVLastKnownPublicKeyFilePath( - serviceID, - getSsvServiceCfg, - getSsvNetworkCfg - ); + const lastKnownPublicKeyFilePath = await this.getSSVLastKnownPublicKeyFilePath(serviceID, getSsvServiceCfg, getSsvNetworkCfg); const lastKnownPublicKeyFileData = strPublicKey.trim(); - const result = await this.sshService.exec( - `echo -n "${lastKnownPublicKeyFileData}" > "${lastKnownPublicKeyFilePath}"` - ); + const result = await this.sshService.exec(`echo -n "${lastKnownPublicKeyFileData}" > "${lastKnownPublicKeyFilePath}"`); if (SSHService.checkExecError(result, true)) { throw new Error(SSHService.extractExecError(result)); } @@ -1289,11 +1234,7 @@ export class NodeConnection { async getSSVLastKnownPublicKeyFile(serviceID, getSsvServiceCfg = null, getSsvNetworkCfg = null) { try { - const lastKnownPublicKeyFilePath = await this.getSSVLastKnownPublicKeyFilePath( - serviceID, - getSsvServiceCfg, - getSsvNetworkCfg - ); + const lastKnownPublicKeyFilePath = await this.getSSVLastKnownPublicKeyFilePath(serviceID, getSsvServiceCfg, getSsvNetworkCfg); let lastKnownPublicKeyFileContent = ""; if (lastKnownPublicKeyFilePath) { let lastKnownPublicKeyFileRequest = await this.sshService.exec( @@ -1317,9 +1258,7 @@ export class NodeConnection { async getSSVTotalConfig(serviceID, getSsvServiceCfg = null, getSsvNetworkCfg = null) { try { - const getSsvNetworkConfig = getSsvNetworkCfg - ? getSsvNetworkCfg - : await this.getSSVNetworkConfig(serviceID, getSsvServiceCfg); + const getSsvNetworkConfig = getSsvNetworkCfg ? getSsvNetworkCfg : await this.getSSVNetworkConfig(serviceID, getSsvServiceCfg); const getSsvServiceConfig = getSsvNetworkConfig.getSsvServiceConfig; const ssvServiceConfig = getSsvNetworkConfig.ssvServiceConfig; const ssvServiceConfigDir = getSsvNetworkConfig.ssvServiceConfigDir; @@ -1344,9 +1283,7 @@ export class NodeConnection { } else if (regexS.test(keyStorePasswordFile)) { keyStorePasswordFile = ssvSecretsDir + "/" + keyStorePasswordFile.replace(regexS, ""); // password file found in secrets dir } - let keyStorePrivateKeyFile = ssvNetworkConfig?.KeyStore?.PrivateKeyFile - ? ssvNetworkConfig.KeyStore.PrivateKeyFile - : ""; + let keyStorePrivateKeyFile = ssvNetworkConfig?.KeyStore?.PrivateKeyFile ? ssvNetworkConfig.KeyStore.PrivateKeyFile : ""; if (regexC.test(keyStorePrivateKeyFile)) { keyStorePrivateKeyFile = ssvNetworkConfigDir + "/" + keyStorePrivateKeyFile.replace(regexC, ""); // keystore file found in config dir } else if (regexS.test(keyStorePrivateKeyFile)) { @@ -1359,10 +1296,7 @@ export class NodeConnection { `if [ -f "${keyStorePasswordFile}" ]; then cat "${keyStorePasswordFile}"; else echo ""; fi` ); if (SSHService.checkExecError(keyStorePasswordFileRequest, true)) { - log.error( - "Can't read SSV keystore password file content from service " + serviceID, - keyStorePasswordFileRequest.stderr - ); + log.error("Can't read SSV keystore password file content from service " + serviceID, keyStorePasswordFileRequest.stderr); } else { keyStorePasswordFileContent = keyStorePasswordFileRequest.stdout; } @@ -1374,10 +1308,7 @@ export class NodeConnection { `if [ -f "${keyStorePrivateKeyFile}" ]; then cat "${keyStorePrivateKeyFile}"; else echo ""; fi` ); if (SSHService.checkExecError(keyStorePrivateKeyFileRequest, true)) { - log.error( - "Can't read SSV keystore private key file content from service " + serviceID, - keyStorePrivateKeyFileRequest.stderr - ); + log.error("Can't read SSV keystore private key file content from service " + serviceID, keyStorePrivateKeyFileRequest.stderr); } else { keyStorePrivateKeyFileContent = keyStorePrivateKeyFileRequest.stdout; } @@ -1386,34 +1317,20 @@ export class NodeConnection { let operatorPrivateKey = ssvNetworkConfig?.OperatorPrivateKey ? ssvNetworkConfig.OperatorPrivateKey : ""; // Last known public key that was generated or imported by the end-user via ssv modal generate/import buttons - const getSSVLastKnownPublicKeyFile = await this.getSSVLastKnownPublicKeyFile( - serviceID, - getSsvServiceConfig, - getSsvNetworkConfig - ); + const getSSVLastKnownPublicKeyFile = await this.getSSVLastKnownPublicKeyFile(serviceID, getSsvServiceConfig, getSsvNetworkConfig); const lastKnownPublicKeyFilePath = getSSVLastKnownPublicKeyFile.lastKnownPublicKeyFilePath; const lastKnownPublicKeyFileData = getSSVLastKnownPublicKeyFile.lastKnownPublicKeyFileData; // Last backed public key (empty as long as user did not do any backup) let lastBackedPublicKey = ""; try { - lastBackedPublicKey = await this.getSSVLastBackedPublicKey( - serviceID, - false, - getSsvServiceConfig, - getSsvNetworkConfig - ); + lastBackedPublicKey = await this.getSSVLastBackedPublicKey(serviceID, false, getSsvServiceConfig, getSsvNetworkConfig); } catch (err) {} // Last known operator id that was responded by SSV API (empty as long as operator is not registered or SSV-API is unreachable) let lastKnownOperatorId = ""; try { - lastKnownOperatorId = await this.getSSVLastKnownOperatorId( - serviceID, - false, - getSsvServiceConfig, - getSsvNetworkConfig - ); + lastKnownOperatorId = await this.getSSVLastKnownOperatorId(serviceID, false, getSsvServiceConfig, getSsvNetworkConfig); } catch (err) {} return { @@ -1458,9 +1375,7 @@ export class NodeConnection { let SSVNetworkConfig; try { const service = await this.readServiceConfiguration(serviceID); - let configPath = ServiceVolume.buildByConfig( - service.volumes.find((v) => v.split(":").slice(-1) == "/data") - ).destinationPath; + let configPath = ServiceVolume.buildByConfig(service.volumes.find((v) => v.split(":").slice(-1) == "/data")).destinationPath; if (configPath.endsWith("/")) configPath = configPath.slice(0, -1, ""); //if path ends with '/' remove it SSVNetworkConfig = await this.sshService.exec(`cat ${configPath}/config.yaml`); @@ -1482,9 +1397,7 @@ export class NodeConnection { this.taskManager.tasks.push({ name: "write SSV config", otherRunRef: ref }); const service = await this.readServiceConfiguration(serviceID); try { - let configPath = ServiceVolume.buildByConfig( - service.volumes.find((v) => v.split(":").slice(-1) == "/data") - ).destinationPath; + let configPath = ServiceVolume.buildByConfig(service.volumes.find((v) => v.split(":").slice(-1) == "/data")).destinationPath; if (configPath.endsWith("/")) configPath = configPath.slice(0, -1, ""); //if path ends with '/' remove it configStatus = await this.sshService.exec( "echo -e " + StringUtils.escapeStringForShell(config.trim()) + ` > ${configPath}/config.yaml` @@ -1535,9 +1448,7 @@ export class NodeConnection { async getSSVDKGConfig(serviceID, getSsvDkgServiceCfg = null) { try { - const getSsvDkgServiceConfig = getSsvDkgServiceCfg - ? getSsvDkgServiceCfg - : await this.getSSVDKGServiceConfig(serviceID); + const getSsvDkgServiceConfig = getSsvDkgServiceCfg ? getSsvDkgServiceCfg : await this.getSSVDKGServiceConfig(serviceID); const ssvDkgServiceConfig = getSsvDkgServiceConfig.ssvDkgServiceConfig; const ssvDkgServiceConfigDir = getSsvDkgServiceConfig.ssvDkgServiceConfigDir; let ssvDkgConfigDir = "."; @@ -1602,10 +1513,7 @@ export class NodeConnection { `if [ -f "${keyStorePasswordFile}" ]; then cat "${keyStorePasswordFile}"; else echo ""; fi` ); if (SSHService.checkExecError(keyStorePasswordFileRequest, true)) { - log.error( - "Can't read SSVDKG keystore password file content from service " + serviceID, - keyStorePasswordFileRequest.stderr - ); + log.error("Can't read SSVDKG keystore password file content from service " + serviceID, keyStorePasswordFileRequest.stderr); } else { keyStorePasswordFileContent = keyStorePasswordFileRequest.stdout; } @@ -1616,10 +1524,7 @@ export class NodeConnection { `if [ -f "${keyStorePrivateKeyFile}" ]; then cat "${keyStorePrivateKeyFile}"; else echo ""; fi` ); if (SSHService.checkExecError(keyStorePrivateKeyFileRequest, true)) { - log.error( - "Can't read SSVDKG keystore private key file content from service " + serviceID, - keyStorePrivateKeyFileRequest.stderr - ); + log.error("Can't read SSVDKG keystore private key file content from service " + serviceID, keyStorePrivateKeyFileRequest.stderr); } else { keyStorePrivateKeyFileContent = keyStorePrivateKeyFileRequest.stdout; } @@ -1657,9 +1562,7 @@ export class NodeConnection { let SSVDKGConfig; try { const service = await this.readServiceConfiguration(serviceID); - let configPath = ServiceVolume.buildByConfig( - service.volumes.find((v) => v.split(":").slice(-1) == "/data") - ).destinationPath; + let configPath = ServiceVolume.buildByConfig(service.volumes.find((v) => v.split(":").slice(-1) == "/data")).destinationPath; if (configPath.endsWith("/")) configPath = configPath.slice(0, -1, ""); //if path ends with '/' remove it SSVDKGConfig = await this.sshService.exec(`cat ${configPath}/config.yaml`); @@ -1681,9 +1584,7 @@ export class NodeConnection { this.taskManager.tasks.push({ name: "write SSVDKG config", otherRunRef: ref }); const service = await this.readServiceConfiguration(serviceID); try { - let configPath = ServiceVolume.buildByConfig( - service.volumes.find((v) => v.split(":").slice(-1) == "/data") - ).destinationPath; + let configPath = ServiceVolume.buildByConfig(service.volumes.find((v) => v.split(":").slice(-1) == "/data")).destinationPath; if (configPath.endsWith("/")) configPath = configPath.slice(0, -1, ""); //if path ends with '/' remove it configStatus = await this.sshService.exec( "echo -e " + StringUtils.escapeStringForShell(config.trim()) + ` > ${configPath}/config.yaml` @@ -1735,9 +1636,7 @@ export class NodeConnection { } if (SSHService.checkExecError(prometheusConfig)) { - throw new Error( - "Failed reading Prometheus config " + serviceID + ": " + SSHService.extractExecError(prometheusConfig) - ); + throw new Error("Failed reading Prometheus config " + serviceID + ": " + SSHService.extractExecError(prometheusConfig)); } return prometheusConfig.stdout; @@ -1799,11 +1698,7 @@ export class NodeConnection { throw new Error("Config is not in the right format!"); } configStatus = await this.sshService.exec( - "echo -e " + - StringUtils.escapeStringForShell(service.data.trim()) + - " > /etc/stereum/services/" + - service.id + - ".yaml" + "echo -e " + StringUtils.escapeStringForShell(service.data.trim()) + " > /etc/stereum/services/" + service.id + ".yaml" ); } catch (err) { this.taskManager.otherSubTasks.push({ @@ -1824,9 +1719,7 @@ export class NodeConnection { status: false, }); this.taskManager.finishedOtherTasks.push({ otherRunRef: ref }); - throw new Error( - "Failed writing service configuration " + service.id + ": " + SSHService.extractExecError(configStatus) - ); + throw new Error("Failed writing service configuration " + service.id + ": " + SSHService.extractExecError(configStatus)); } this.taskManager.otherSubTasks.push({ name: "write " + service.service + " config", @@ -1874,12 +1767,7 @@ export class NodeConnection { status: false, }); this.taskManager.finishedOtherTasks.push({ otherRunRef: ref }); - throw new Error( - "Failed writing service configuration " + - serviceConfiguration.id + - ": " + - SSHService.extractExecError(configStatus) - ); + throw new Error("Failed writing service configuration " + serviceConfiguration.id + ": " + SSHService.extractExecError(configStatus)); } this.taskManager.otherSubTasks.push({ name: "write " + serviceConfiguration.service + " config", @@ -1929,9 +1817,7 @@ export class NodeConnection { } if (SSHService.checkExecError(serviceJson)) { - throw new Error( - "Failed getting service details of '" + serviceId + "': " + SSHService.extractExecError(serviceJson) - ); + throw new Error("Failed getting service details of '" + serviceId + "': " + SSHService.extractExecError(serviceJson)); } return JSON.parse(serviceJson.stdout); @@ -2115,9 +2001,7 @@ export class NodeConnection { async getCurrentStereumVersion() { let response; try { - response = await this.sshService.exec( - `cd ${this.settings.stereum.settings.controls_install_path}/ansible && git rev-parse HEAD` - ); + response = await this.sshService.exec(`cd ${this.settings.stereum.settings.controls_install_path}/ansible && git rev-parse HEAD`); } catch (err) { log.error("Couldn't get Stereum Version:", err); throw new Error("Couldn't get Stereum Version:\n" + err); @@ -2136,9 +2020,7 @@ export class NodeConnection { async getLargestVolumePath() { try { - const dfOutput = await this.sshService.exec( - "df | grep -wv /var/lib/docker | tail -n +2 | sort -k 4 -rn | head -n 1" - ); + const dfOutput = await this.sshService.exec("df | grep -wv /var/lib/docker | tail -n +2 | sort -k 4 -rn | head -n 1"); if (SSHService.checkExecError(dfOutput)) { throw new Error("Failed reading df command: " + SSHService.extractExecError(dfOutput)); @@ -2432,16 +2314,13 @@ export class NodeConnection { // Calculate the timestamp for the 'since' days ago const sinceDate = new Date(Date.now() - 1000 * 60 * 60 * 24 * since).toISOString(); // Calculate the timestamp for the 'until' days ago - const untilDate = - until === 0 ? new Date().toISOString() : new Date(Date.now() - 1000 * 60 * 60 * 24 * until).toISOString(); + const untilDate = until === 0 ? new Date().toISOString() : new Date(Date.now() - 1000 * 60 * 60 * 24 * until).toISOString(); try { if (dateOrLines === "lines") { logResult = await this.sshService.exec(`docker logs ${containerName} --tail=${lines} 2>&1`); } else { - logResult = await this.sshService.exec( - `docker logs ${containerName} --since=${sinceDate} --until=${untilDate} 2>&1` - ); + logResult = await this.sshService.exec(`docker logs ${containerName} --since=${sinceDate} --until=${untilDate} 2>&1`); } if (logResult.rc || !logResult.stdout || logResult.stderr) { diff --git a/launcher/src/backend/NodeUpdates.js b/launcher/src/backend/NodeUpdates.js index 289488a7f..9d7c7e775 100644 --- a/launcher/src/backend/NodeUpdates.js +++ b/launcher/src/backend/NodeUpdates.js @@ -150,9 +150,7 @@ export class NodeUpdates { */ async getCountOfUpdatableOSUpdate() { try { - const res = await this.nodeConnection.sshService.exec( - `LANG=C apt-get upgrade -s |grep -P '^\\d+ upgraded'|cut -d" " -f1` - ); + const res = await this.nodeConnection.sshService.exec(`LANG=C apt-get upgrade -s |grep -P '^\\d+ upgraded'|cut -d" " -f1`); return res.stdout; } catch (err) { @@ -185,7 +183,7 @@ export class NodeUpdates { * @returns {number} - playbook runtime */ async updatePackage(packages) { - let packagesListString = packages.join(','); + let packagesListString = packages.join(","); let extraVars = { stereum_role: "update-package", packages_list: packagesListString, diff --git a/launcher/src/backend/OneClickInstall.js b/launcher/src/backend/OneClickInstall.js index bc201e611..d1c2ba8e2 100755 --- a/launcher/src/backend/OneClickInstall.js +++ b/launcher/src/backend/OneClickInstall.js @@ -35,46 +35,13 @@ export class OneClickInstall { echo -e ${StringUtils.escapeStringForShell(YAML.stringify(settings))} > /etc/stereum/stereum.yaml`); await this.configManager.createMultiSetupYaml({}, ""); await this.nodeConnection.findStereumSettings(); - return await this.nodeConnection.prepareStereumNode( - this.nodeConnection.settings.stereum.settings.controls_install_path - ); + return await this.nodeConnection.prepareStereumNode(this.nodeConnection.settings.stereum.settings.controls_install_path); } //this is broken - async chooseClient(clients) { - clients = { - PRYSM: 24, - LIGHTHOUSE: 24, - NIMBUS: 24, - TEKU: 20, - }; - let buffer = []; - let clientDistribution = []; - let sum = 0; - let range = 0; - - Object.keys(clients).forEach((key) => { - buffer.push({ name: key, coverage: clients[key] }); - }); - - buffer.forEach((client) => { - sum += 100 / client.coverage; - }); - - buffer.forEach((client) => { - clientDistribution.push({ name: client.name, percentage: (100 / client.coverage / sum) * 100 }); - }); - - clientDistribution.forEach((client) => { - client.min = range; - range = range + client.percentage; - client.max = range; - }); - - const ran = Math.random() * 100; - const winner = clientDistribution.find((client) => client.min <= ran && client.max >= ran); - log.info(winner, ran); - return winner.name.toLowerCase(); + chooseClient(clients) { + let client = clients[Math.floor(Math.random() * clients.length)].toLowerCase(); + return client.charAt(0).toUpperCase() + client.slice(1); } clearSetup() { @@ -83,7 +50,6 @@ export class OneClickInstall { this.installDir = undefined; this.executionClient = undefined; this.setup = undefined; - this.choosenClient = undefined; this.network = undefined; this.mevboost = undefined; this.needsKeystore = []; @@ -293,9 +259,7 @@ export class OneClickInstall { this.extraServices.push( this.serviceManager.getService("LidoObolExitService", { ...args, - consensusClients: [this.beaconService].concat( - this.extraServices.filter((s) => s.service === "CharonService") - ), + consensusClients: [this.beaconService].concat(this.extraServices.filter((s) => s.service === "CharonService")), otherServices: this.extraServices.filter((s) => s.service === "ValidatorEjectorService"), }) ); @@ -378,17 +342,13 @@ export class OneClickInstall { this.executionClient.command = this.executionClient.command.filter((c) => !c.includes("--prune")); break; case "BesuService": - this.executionClient.command[this.executionClient.command.findIndex((c) => c.includes("--sync-mode=SNAP"))] = - "--sync-mode=FULL"; + this.executionClient.command[this.executionClient.command.findIndex((c) => c.includes("--sync-mode=SNAP"))] = "--sync-mode=FULL"; break; case "NethermindService": - this.executionClient.command[this.executionClient.command.findIndex((c) => c.includes("--config"))] += - "_archive"; + this.executionClient.command[this.executionClient.command.findIndex((c) => c.includes("--config"))] += "_archive"; this.executionClient.command[this.executionClient.command.findIndex((c) => c.includes("--Pruning.Mode="))] = "--Pruning.Mode=None"; - this.executionClient.command = this.executionClient.command.filter( - (c) => !c.includes("--Pruning.FullPruningTrigger") - ); + this.executionClient.command = this.executionClient.command.filter((c) => !c.includes("--Pruning.FullPruningTrigger")); break; } switch (this.beaconService.service) { @@ -419,20 +379,30 @@ export class OneClickInstall { } handleLidoTags(selectedPreset) { - if (selectedPreset == "obol") { + if (/lidocsm/.test(selectedPreset)) { const networkFeeAdress = { mainnet: "0x388C818CA8B9251b393131C08a736A67ccB19297", holesky: "0xE73a3602b99f1f913e72F8bdcBC235e206794Ac8", - } + }; const serviceFeeAdressCommand = { LighthouseValidatorService: "--suggested-fee-recipient=", LodestarValidatorService: "--suggestedFeeRecipient=", NimbusValidatorService: "--suggested-fee-recipient=", PrysmValidatorService: "--suggested-fee-recipient=", TekuValidatorService: "--validators-proposer-default-fee-recipient=", - } - this.validatorService.command[this.validatorService.command.findIndex((c) => c.includes(serviceFeeAdressCommand[this.validatorService.service]))] = - serviceFeeAdressCommand[this.validatorService.service] + networkFeeAdress[this.network]; + }; + this.validatorService.command[ + this.validatorService.command.findIndex((c) => c.includes(serviceFeeAdressCommand[this.validatorService.service])) + ] = serviceFeeAdressCommand[this.validatorService.service] + networkFeeAdress[this.network]; + } + if (this.extraServices.some((s) => s.service === "ValidatorEjectorService")) { + const moduleIDs = { + lidocsm: "4", + lidossv: "2", + lidoobol: "2", + }; + let ejector = this.extraServices.find((s) => s.service === "ValidatorEjectorService"); + ejector.env.STAKING_MODULE_ID = moduleIDs[selectedPreset]; } } @@ -483,19 +453,16 @@ export class OneClickInstall { this.clearSetup(); this.setup = setup; this.network = network; - let services = [ - "GethService", - "GrafanaService", - "PrometheusNodeExporterService", - "PrometheusService", - "NotificationService", - ]; + let services = ["GrafanaService", "PrometheusNodeExporterService", "PrometheusService", "NotificationService"]; - this.choosenClient = await this.chooseClient(); - this.choosenClient = this.choosenClient.charAt(0).toUpperCase() + this.choosenClient.slice(1); + const selectedCC_VC = this.chooseClient(["PRYSM", "LIGHTHOUSE", "NIMBUS", "TEKU", "LODESTAR"]); - services.push(this.choosenClient + "ValidatorService"); - services.push(this.choosenClient + "BeaconService"); + services.push(selectedCC_VC + "ValidatorService"); + services.push(selectedCC_VC + "BeaconService"); + + const selectedEC = this.chooseClient(["GETH", "BESU", "NETHERMIND"]); + + services.push(selectedEC + "Service"); if (network === "gnosis") services = [ @@ -518,51 +485,23 @@ export class OneClickInstall { services.push("SSVNetworkService"); break; case "obol": - services = [ - "GethService", - "LighthouseBeaconService", - "TekuValidatorService", - "CharonService", - "GrafanaService", - "PrometheusNodeExporterService", - "PrometheusService", - "NotificationService", - ]; - break; - case "rocketpool": - services.push("ROCKETPOOL"); + services.push("FlashbotsMevBoostService", "CharonService"); break; case "stereum on arm": services = services.filter( - (s) => - !["GrafanaService", "PrometheusNodeExporterService", "PrometheusService", "NotificationService"].includes(s) + (s) => !["GrafanaService", "PrometheusNodeExporterService", "PrometheusService", "NotificationService"].includes(s) ); break; case "archive": break; case "lidoobol": - services = [ - "NethermindService", - "LighthouseBeaconService", - "LodestarValidatorService", - "GrafanaService", - "PrometheusNodeExporterService", - "PrometheusService", - "NotificationService", - ]; services.push("LidoObolExitService", "CharonService", "ValidatorEjectorService", "FlashbotsMevBoostService"); break; case "lidossv": services.push("SSVNetworkService", "SSVDKGService", "FlashbotsMevBoostService"); break; case "lidocsm": - services.push( - "FlashbotsMevBoostService", - "KeysAPIService", - "ValidatorEjectorService", - "KuboIPFSService", - "LCOMService" - ); + services.push("FlashbotsMevBoostService", "KeysAPIService", "ValidatorEjectorService", "KuboIPFSService", "LCOMService"); } return services; } diff --git a/launcher/src/backend/SSHService.js b/launcher/src/backend/SSHService.js index 29211b56d..6c59c4ede 100755 --- a/launcher/src/backend/SSHService.js +++ b/launcher/src/backend/SSHService.js @@ -211,8 +211,7 @@ export class SSHService { } async exec(command, useSudo = true, useRoot = true) { - const ensureSudoCommand = - `sudo -u ${useRoot ? "root" : this.connectionInfo.user} -i <<'=====EOF'\n` + command + `\n=====EOF`; + const ensureSudoCommand = `sudo -u ${useRoot ? "root" : this.connectionInfo.user} -i <<'=====EOF'\n` + command + `\n=====EOF`; return this.execCommand(useSudo ? ensureSudoCommand : command); } @@ -298,11 +297,7 @@ export class SSHService { while (i--) { // loop backwards to splice array from specific ports let tunnel = this.tunnels[i]; - if ( - Array.isArray(onlySpecificPorts) && - onlySpecificPorts.length && - !onlySpecificPorts.includes(tunnel.config.localPort) - ) { + if (Array.isArray(onlySpecificPorts) && onlySpecificPorts.length && !onlySpecificPorts.includes(tunnel.config.localPort)) { continue; } tunnel.server.close(); @@ -399,10 +394,7 @@ export class SSHService { try { if (sshDirPath.endsWith("/")) sshDirPath = sshDirPath.slice(0, -1, ""); //if path ends with '/' remove it let newKeys = keys.join("\n"); - let result = await this.exec( - `echo -e ${StringUtils.escapeStringForShell(newKeys)} > ${sshDirPath}/authorized_keys`, - false - ); + let result = await this.exec(`echo -e ${StringUtils.escapeStringForShell(newKeys)} > ${sshDirPath}/authorized_keys`, false); if (SSHService.checkExecError(result)) { throw new Error("Failed writing authorized keys:\n" + SSHService.extractExecError(result)); } diff --git a/launcher/src/backend/SSHServiceTunnel.js b/launcher/src/backend/SSHServiceTunnel.js index ad77d8d18..91ea7224e 100755 --- a/launcher/src/backend/SSHServiceTunnel.js +++ b/launcher/src/backend/SSHServiceTunnel.js @@ -55,25 +55,19 @@ async function createTunnel(tunnelOptions, serverOptions, sshOptions, forwardOpt autoClose(server, connection); } try { - conn.forwardOut( - forwardOptions.srcAddr, - forwardOptions.srcPort, - forwardOptions.dstAddr, - forwardOptions.dstPort, - (err, stream) => { - if (err) { - return err; - } - connection.pipe(stream).pipe(connection); + conn.forwardOut(forwardOptions.srcAddr, forwardOptions.srcPort, forwardOptions.dstAddr, forwardOptions.dstPort, (err, stream) => { + if (err) { + return err; } - ); + connection.pipe(stream).pipe(connection); + }); } catch (e) { return e; } }); server.on("close", () => conn.end()); - return [server, conn] + return [server, conn]; } exports.createTunnel = createTunnel; diff --git a/launcher/src/backend/ServiceManager.js b/launcher/src/backend/ServiceManager.js index 2a349d64c..98a66afe1 100755 --- a/launcher/src/backend/ServiceManager.js +++ b/launcher/src/backend/ServiceManager.js @@ -310,8 +310,7 @@ export class ServiceManager { //add checkpointSync if Url was send if (checkpointUrl) { command.push(checkpointCommands[client.service] + checkpointUrl); - if (genesisSyncCommands[client.service]) - command = command.filter((c) => !c.includes(genesisSyncCommands[client.service])); + if (genesisSyncCommands[client.service]) command = command.filter((c) => !c.includes(genesisSyncCommands[client.service])); } else { //add genesisSync if no Url was send if (genesisSyncCommands[client.service]) command.push(genesisSyncCommands[client.service]); @@ -331,8 +330,7 @@ export class ServiceManager { getWorkindDir(service) { if (service.volumes.length > 0) { let volumeWithID = service.volumes.find((v) => v.destinationPath.includes(service.id)); - if (volumeWithID && volumeWithID.destinationPath) - return volumeWithID.destinationPath.replace(new RegExp(`(?<=${service.id}).*`), ""); + if (volumeWithID && volumeWithID.destinationPath) return volumeWithID.destinationPath.replace(new RegExp(`(?<=${service.id}).*`), ""); } return undefined; } @@ -351,28 +349,24 @@ export class ServiceManager { for (let task of tasks) { let ssvConfig; let service = services.find((s) => s.id === task.service.config.serviceID); - let dependencies = task.data.executionClients - .concat(task.data.consensusClients, task.data.otherServices) - .map((s) => - services.find((e) => { - if (e.id === s.config.serviceID) { - return true; - } else if ( - newInstallTasks && - newInstallTasks.length > 0 && - e.id === newInstallTasks.find((i) => i.service.id === s.id).service.config.serviceID - ) { - return true; - } - return false; - }) - ); + let dependencies = task.data.executionClients.concat(task.data.consensusClients, task.data.otherServices).map((s) => + services.find((e) => { + if (e.id === s.config.serviceID) { + return true; + } else if ( + newInstallTasks && + newInstallTasks.length > 0 && + e.id === newInstallTasks.find((i) => i.service.id === s.id).service.config.serviceID + ) { + return true; + } + return false; + }) + ); if (service.service === "FlashbotsMevBoostService") { modifiedServices.push(service); - let dependenciesToRemove = services.filter((s) => - s.dependencies.mevboost.map((m) => m.id).includes(service.id) - ); + let dependenciesToRemove = services.filter((s) => s.dependencies.mevboost.map((m) => m.id).includes(service.id)); dependenciesToRemove.forEach((dependency) => { modifiedServices.push(this.removeDependencies(dependency, service)); }); @@ -499,12 +493,8 @@ export class ServiceManager { }, ]; this.addENVConnction(service, dependencies, keyValuePairs); - service.dependencies.executionClients = dependencies.filter( - (d) => typeof d.buildExecutionClientHttpEndpointUrl === "function" - ); - service.dependencies.consensusClients = dependencies.filter( - (d) => typeof d.buildConsensusClientHttpEndpointUrl === "function" - ); + service.dependencies.executionClients = dependencies.filter((d) => typeof d.buildExecutionClientHttpEndpointUrl === "function"); + service.dependencies.consensusClients = dependencies.filter((d) => typeof d.buildConsensusClientHttpEndpointUrl === "function"); return service; case "KeysAPI": // create a new function to handle dependencies for env vars @@ -521,12 +511,8 @@ export class ServiceManager { }, ]; this.addENVConnction(service, dependencies, keyValuePairs); - service.dependencies.executionClients = dependencies.filter( - (d) => typeof d.buildExecutionClientHttpEndpointUrl === "function" - ); - service.dependencies.consensusClients = dependencies.filter( - (d) => typeof d.buildConsensusClientHttpEndpointUrl === "function" - ); + service.dependencies.executionClients = dependencies.filter((d) => typeof d.buildExecutionClientHttpEndpointUrl === "function"); + service.dependencies.consensusClients = dependencies.filter((d) => typeof d.buildConsensusClientHttpEndpointUrl === "function"); return service; default: return service; @@ -565,9 +551,7 @@ export class ServiceManager { command = command.filter((c) => !c.includes(endpointCommand)); let newProps; if (fullCommand) { - newProps = [this.formatCommand(fullCommand, endpointCommand, filter, dependencies)].filter( - (c) => c !== undefined - ); + newProps = [this.formatCommand(fullCommand, endpointCommand, filter, dependencies)].filter((c) => c !== undefined); } else { newProps = endpointCommand + dependencies.map(filter).join(); } @@ -773,9 +757,7 @@ export class ServiceManager { ); } if (serviceToDelete.service === "KeysAPIService") { - await this.nodeConnection.sshService.exec( - `docker stop cachingDB-${serviceToDelete.id} && docker rm cachingDB-${serviceToDelete.id}` - ); + await this.nodeConnection.sshService.exec(`docker stop cachingDB-${serviceToDelete.id} && docker rm cachingDB-${serviceToDelete.id}`); } await this.nodeConnection.runPlaybook("Delete Service", { stereum_role: "delete-service", @@ -921,12 +903,7 @@ export class ServiceManager { case "LighthouseValidatorService": ports = [new ServicePort("127.0.0.1", args.port ? args.port : 5062, 5062, servicePortProtocol.tcp)]; - return LighthouseValidatorService.buildByUserInput( - args.network, - ports, - args.installDir + "/lighthouse", - args.consensusClients - ); + return LighthouseValidatorService.buildByUserInput(args.network, ports, args.installDir + "/lighthouse", args.consensusClients); case "PrysmBeaconService": ports = [ @@ -946,12 +923,7 @@ export class ServiceManager { case "PrysmValidatorService": ports = [new ServicePort("127.0.0.1", args.port ? args.port : 7500, 7500, servicePortProtocol.tcp)]; - return PrysmValidatorService.buildByUserInput( - args.network, - ports, - args.installDir + "/prysm", - args.consensusClients - ); + return PrysmValidatorService.buildByUserInput(args.network, ports, args.installDir + "/prysm", args.consensusClients); case "LodestarBeaconService": //LodestarBeaconService @@ -972,12 +944,7 @@ export class ServiceManager { case "LodestarValidatorService": //LodestarValidatorService ports = [new ServicePort("127.0.0.1", args.port ? args.port : 5062, 5062, servicePortProtocol.tcp)]; - return LodestarValidatorService.buildByUserInput( - args.network, - ports, - args.installDir + "/lodestar", - args.consensusClients - ); + return LodestarValidatorService.buildByUserInput(args.network, ports, args.installDir + "/lodestar", args.consensusClients); case "NimbusBeaconService": ports = [ @@ -996,12 +963,7 @@ export class ServiceManager { case "NimbusValidatorService": ports = []; - return NimbusValidatorService.buildByUserInput( - args.network, - ports, - args.installDir + "/nimbus", - args.consensusClients - ); + return NimbusValidatorService.buildByUserInput(args.network, ports, args.installDir + "/nimbus", args.consensusClients); case "TekuBeaconService": ports = [ @@ -1021,12 +983,7 @@ export class ServiceManager { case "TekuValidatorService": ports = []; - return TekuValidatorService.buildByUserInput( - args.network, - ports, - args.installDir + "/teku", - args.consensusClients - ); + return TekuValidatorService.buildByUserInput(args.network, ports, args.installDir + "/teku", args.consensusClients); case "PrometheusNodeExporterService": return PrometheusNodeExporterService.buildByUserInput(args.network); @@ -1081,12 +1038,7 @@ export class ServiceManager { case "ExternalExecutionService": ports = []; - return ExternalExecutionService.buildByUserInput( - args.network, - args.installDir + "/externalExecution", - args.source, - args.jwtToken - ); + return ExternalExecutionService.buildByUserInput(args.network, args.installDir + "/externalExecution", args.source, args.jwtToken); case "ExternalConsensusService": ports = []; return ExternalConsensusService.buildByUserInput( @@ -1116,10 +1068,7 @@ export class ServiceManager { args.otherServices ); case "SSVDKGService": - ports = [ - new ServicePort(null, 3030, 3030, servicePortProtocol.udp), - new ServicePort(null, 3030, 3030, servicePortProtocol.tcp), - ]; + ports = [new ServicePort(null, 3030, 3030, servicePortProtocol.udp), new ServicePort(null, 3030, 3030, servicePortProtocol.tcp)]; return SSVDKGService.buildByUserInput( args.network, ports, @@ -1164,9 +1113,7 @@ export class ServiceManager { keyAPI.env.DB_HOST = `cachingDB-${keyAPI.id}`; } catch (err) { log.error("Creating CachingDB failed: ", err); - await this.nodeConnection.sshService.exec( - `docker stop cachingDB-${keyAPI.id} && docker rm cachingDB-${keyAPI.id}` - ); + await this.nodeConnection.sshService.exec(`docker stop cachingDB-${keyAPI.id} && docker rm cachingDB-${keyAPI.id}`); } } @@ -1202,9 +1149,7 @@ export class ServiceManager { ); } catch (err) { log.error("Creating SlashingDB failed: ", err); - await this.nodeConnection.sshService.exec( - `docker stop slashingdb-${web3signer.id} && docker rm slashingdb-${web3signer.id}` - ); + await this.nodeConnection.sshService.exec(`docker stop slashingdb-${web3signer.id} && docker rm slashingdb-${web3signer.id}`); } } @@ -1212,9 +1157,7 @@ export class ServiceManager { for (const service of services) { await this.manageServiceState(service.id, "started"); const workingDir = this.getWorkindDir(service); - await this.nodeConnection.sshService.exec( - "docker cp stereum-" + service.id + ":/opt/web3signer/migrations/postgresql " + workingDir - ); + await this.nodeConnection.sshService.exec("docker cp stereum-" + service.id + ":/opt/web3signer/migrations/postgresql " + workingDir); await this.manageServiceState(service.id, "stopped"); service.command = service.command.filter((c) => c != "--slashing-protection-enabled=false"); await this.createSlashingDB(service, workingDir); @@ -1224,18 +1167,12 @@ export class ServiceManager { async createKeystores(services) { for (const service of services) { - if ( - service.service === "NimbusValidatorService" || - (service.service === "NimbusBeaconService" && service.configVersion < 2) - ) { + if (service.service === "NimbusValidatorService" || (service.service === "NimbusBeaconService" && service.configVersion < 2)) { const valDir = service.volumes.find((vol) => vol.servicePath === "/opt/app/validators").destinationPath; const token = StringUtils.createRandomString(); await this.nodeConnection.sshService.exec(`mkdir -p ${valDir}`); await this.nodeConnection.sshService.exec(`echo ${token} > ${valDir}/api-token.txt`); - } else if ( - service.service === "TekuValidatorService" || - (service.service === "TekuBeaconService" && service.configVersion < 2) - ) { + } else if (service.service === "TekuValidatorService" || (service.service === "TekuBeaconService" && service.configVersion < 2)) { const dataDir = service.volumes.find((vol) => vol.servicePath === "/opt/app/data").destinationPath; const password = StringUtils.createRandomString(); await this.nodeConnection.sshService.exec("apt install -y openjdk-8-jre-headless"); @@ -1259,18 +1196,13 @@ export class ServiceManager { if (config.ssv_sk) { replacementString = "OperatorPrivateKey: " + config.ssv_sk; } else { - replacementString = - "KeyStore:\n PrivateKeyFile: /secrets/encrypted_private_key.json\n PasswordFile: /secrets/password"; + replacementString = "KeyStore:\n PrivateKeyFile: /secrets/encrypted_private_key.json\n PasswordFile: /secrets/password"; } // prepare service's config file const dataDir = service.volumes.find((vol) => vol.servicePath === "/data").destinationPath; - const escapedConfigFile = StringUtils.escapeStringForShell( - ssvConfig.replace(/^OperatorPrivateKey.*/gm, replacementString) - ); - this.nodeConnection.sshService.exec( - `mkdir -p ${dataDir} && echo ${escapedConfigFile} > ${dataDir}/config.yaml` - ); + const escapedConfigFile = StringUtils.escapeStringForShell(ssvConfig.replace(/^OperatorPrivateKey.*/gm, replacementString)); + this.nodeConnection.sshService.exec(`mkdir -p ${dataDir} && echo ${escapedConfigFile} > ${dataDir}/config.yaml`); } else if (service.service.includes("External")) { const extConnDir = service.volumes .find((vol) => vol.destinationPath.includes("link.txt")) @@ -1344,10 +1276,7 @@ export class ServiceManager { }); let DVTInstalls = tasks.filter((t) => /SSVNetwork|Charon/.test(t.service.service)); DVTInstalls.forEach((t) => { - if ( - t.service.service == "SSVNetworkService" && - services.filter((s) => s.service === "SSVNetworkService").length - ) { + if (t.service.service == "SSVNetworkService" && services.filter((s) => s.service === "SSVNetworkService").length) { // TODO: Make SSVNetworkService multiservice (which depends also on SSVDKGService) log.error("Multiple SSVNetworkService services currently not supported - ignoring setup!"); return; @@ -1358,9 +1287,7 @@ export class ServiceManager { setupAndServiceIds[service.id] = t.data.setupId; newServices.push(service); }); - let VLInstalls = tasks.filter( - (t) => t.service.category === "validator" && !/SSVNetwork|Charon/.test(t.service.service) - ); + let VLInstalls = tasks.filter((t) => t.service.category === "validator" && !/SSVNetwork|Charon/.test(t.service.service)); VLInstalls.forEach((t) => { this.updateInfoForDependencies(t, services, newServices, ELInstalls, CLInstalls, undefined, DVTInstalls); let service = this.getService(t.service.service, t.data); @@ -1457,10 +1384,7 @@ export class ServiceManager { await this.createKeystores( newServices.filter( (s) => - s.service.includes("Teku") || - s.service.includes("Nimbus") || - s.service.includes("SSVNetwork") || - s.service.includes("External") + s.service.includes("Teku") || s.service.includes("Nimbus") || s.service.includes("SSVNetwork") || s.service.includes("External") ) ); await this.prepareSSVDKG(newServices.find((s) => s.service === "SSVDKGService")); @@ -1658,10 +1582,7 @@ export class ServiceManager { // 2. Adjust SSV operator ID in DKG config if (ssvTotalConfig) { // Set operator ID to last known operator ID (revert or 0) in DKG config file (if needed) - if ( - ssvTotalConfig.lastKnownOperatorId && - ssvDkgTotalConfig.operatorId != ssvTotalConfig.lastKnownOperatorId - ) { + if (ssvTotalConfig.lastKnownOperatorId && ssvDkgTotalConfig.operatorId != ssvTotalConfig.lastKnownOperatorId) { log.silly("SSVNetworkService exists"); log.info(`Update operator ID in DKG config file to ${ssvTotalConfig.lastKnownOperatorId}`); ssvDkgTotalConfig.ssvDkgConfig.operatorID = parseInt(ssvTotalConfig.lastKnownOperatorId, 10); @@ -1720,8 +1641,7 @@ export class ServiceManager { //make sure there are no double tasks (for example: TekuBeaconService, TekuValidatorService share the same id) static uniqueByID(job) { return (value, index, self) => - self.map((t) => t.service.config.serviceID).indexOf(value.service.config.serviceID) === index && - value.content === job; + self.map((t) => t.service.config.serviceID).indexOf(value.service.config.serviceID) === index && value.content === job; } //remove all service data @@ -1912,12 +1832,7 @@ export class ServiceManager { return serviceNameConfig; } catch (error) { - this.nodeConnection.taskManager.otherTasksHandler( - ref, - `Export Failed`, - false, - `Failed to export setup: ${error}` - ); + this.nodeConnection.taskManager.otherTasksHandler(ref, `Export Failed`, false, `Failed to export setup: ${error}`); console.error(`Failed to export setup: ${error}`); } finally { this.nodeConnection.taskManager.otherTasksHandler(ref); @@ -1950,12 +1865,7 @@ export class ServiceManager { this.nodeConnection.taskManager.otherTasksHandler(ref, `Export Configuration Completed`, true); return serviceNameConfig; } catch (error) { - this.nodeConnection.taskManager.otherTasksHandler( - ref, - `Export Failed`, - false, - `Failed to export config: ${error}` - ); + this.nodeConnection.taskManager.otherTasksHandler(ref, `Export Failed`, false, `Failed to export config: ${error}`); console.error(`Failed to export config: ${error}`); } finally { this.nodeConnection.taskManager.otherTasksHandler(ref); @@ -2018,9 +1928,7 @@ export class ServiceManager { this.nodeConnection.taskManager.otherTasksHandler(ref, `Wrote multi setup`, true); let services = await this.readServiceConfigurations(); - let importingSetupServices = services.filter((service) => - multiSetup[Object.keys(multiSetup)[0]].services.includes(service.id) - ); + let importingSetupServices = services.filter((service) => multiSetup[Object.keys(multiSetup)[0]].services.includes(service.id)); await Promise.all( importingSetupServices.map(async (service) => { @@ -2043,12 +1951,7 @@ export class ServiceManager { this.nodeConnection.taskManager.otherTasksHandler(ref, `Import Configuration Completed`, true); return runRefs; } catch (error) { - this.nodeConnection.taskManager.otherTasksHandler( - ref, - `Import Failed`, - false, - `Failed to import config: ${error}` - ); + this.nodeConnection.taskManager.otherTasksHandler(ref, `Import Failed`, false, `Failed to import config: ${error}`); console.error(`Failed to import config: ${error}`); } finally { this.nodeConnection.taskManager.otherTasksHandler(ref); @@ -2151,12 +2054,7 @@ export class ServiceManager { this.nodeConnection.taskManager.otherTasksHandler(ref, `Import Configuration Completed`, true); return runRefs; } catch (error) { - this.nodeConnection.taskManager.otherTasksHandler( - ref, - `Import Failed`, - false, - `Failed to import config: ${error}` - ); + this.nodeConnection.taskManager.otherTasksHandler(ref, `Import Failed`, false, `Failed to import config: ${error}`); console.error(`Failed to import config: ${error}`); } finally { this.nodeConnection.taskManager.otherTasksHandler(ref); @@ -2197,9 +2095,7 @@ export class ServiceManager { async beaconchainMonitoringModification(data) { let services = await this.readServiceConfigurations(); let selectedValidator = services.find((service) => service.id === data.selectedVal); - let firstConsensusClient = services.find( - (service) => service.id === selectedValidator.dependencies.consensusClients[0].id - ); + let firstConsensusClient = services.find((service) => service.id === selectedValidator.dependencies.consensusClients[0].id); const metricsExporterCommands = { LighthouseValidatorService: "--monitoring-endpoint=", @@ -2275,10 +2171,7 @@ export class ServiceManager { `--system.partition=/host/rootfs` ); if (selectedValidator.service == "PrysmValidatorService") { - metricsExporter.command.push( - `--validator.type=prysm`, - `--validator.address=http://stereum-${selectedValidator.id}:8081/metrics` - ); + metricsExporter.command.push(`--validator.type=prysm`, `--validator.address=http://stereum-${selectedValidator.id}:8081/metrics`); } if (firstConsensusClient.service == "PrysmBeaconService") { metricsExporter.command.push( @@ -2350,18 +2243,14 @@ export class ServiceManager { let services = await this.readServiceConfigurations(); let selectedValidator = services.find((service) => service.id === data.selectedVal); - let firstConsensusClient = services.find( - (service) => service.id === selectedValidator.dependencies.consensusClients[0].id - ); + let firstConsensusClient = services.find((service) => service.id === selectedValidator.dependencies.consensusClients[0].id); switch (selectedValidator.service) { case "LighthouseValidatorService": case "TekuValidatorService": case "LodestarValidatorService": await this.manageServiceState(selectedValidator.id, "stopped"); - metricsCommandIndex = selectedValidator.command.findIndex((c) => - c.includes(metricsExporterCommands[selectedValidator.service]) - ); + metricsCommandIndex = selectedValidator.command.findIndex((c) => c.includes(metricsExporterCommands[selectedValidator.service])); if (metricsCommandIndex > -1) { selectedValidator.command.splice(metricsCommandIndex, 1); } diff --git a/launcher/src/backend/TaskManager.js b/launcher/src/backend/TaskManager.js index b24f04442..6c92f80f4 100755 --- a/launcher/src/backend/TaskManager.js +++ b/launcher/src/backend/TaskManager.js @@ -1,6 +1,6 @@ export class TaskManager { constructor(nodeConnection) { - this.nodeConnection = nodeConnection + this.nodeConnection = nodeConnection; this.tasks = []; //all tasks this.polishedTasks = []; //all tasks prepared for displaying this.finishedPlaybooks = []; //finished playbook tasks @@ -59,7 +59,7 @@ export class TaskManager { let logs = ""; try { logs = await this.nodeConnection.playbookStatus(task.ref); - } catch (err) { } + } catch (err) {} let buffer = logs.split("\n\n"); buffer.pop(); task.subTasks = []; @@ -127,8 +127,9 @@ export class TaskManager { name: subTask.name, action: subTask.name, status: subTask.status ? "OK" : "FAILED", - data: `TASK: ${subTask.name}\nACTION: ${subTask.name}\nCATEGORY: ${subTask.status ? "OK" : "FAILED" - }\nDATA: ${subTask.data ? subTask.data : "There is no data for these kind of tasks ¯\\_(ツ)_/¯"}`, + data: `TASK: ${subTask.name}\nACTION: ${subTask.name}\nCATEGORY: ${subTask.status ? "OK" : "FAILED"}\nDATA: ${ + subTask.data ? subTask.data : "There is no data for these kind of tasks ¯\\_(ツ)_/¯" + }`, }; }); if (this.finishedOtherTasks.map((other) => other.otherRunRef).includes(task.otherRunRef)) { diff --git a/launcher/src/backend/TekuGasLimitConfig.js b/launcher/src/backend/TekuGasLimitConfig.js index b939d8abb..1f2bd1bcc 100644 --- a/launcher/src/backend/TekuGasLimitConfig.js +++ b/launcher/src/backend/TekuGasLimitConfig.js @@ -1,11 +1,10 @@ -export class TekuGasLimitConfig{ +export class TekuGasLimitConfig { constructor(nodeConnection) { this.nodeConnection = nodeConnection; } - async createGasConfigFile(gasLimit, feeRecipient, configPath){ - const configContent = - `{ + async createGasConfigFile(gasLimit, feeRecipient, configPath) { + const configContent = `{ "default_config": { "fee_recipient": "${feeRecipient}", "builder": { @@ -17,23 +16,21 @@ export class TekuGasLimitConfig{ await this.nodeConnection.sshService.exec(`echo '${configContent}' > ${configPath}/gas_config.json`); } - async removeGasConfigFile(configPath){ + async removeGasConfigFile(configPath) { await this.nodeConnection.sshService.exec(`rm -f ${configPath}/gas_config.json`); } - async readGasConfigFile(configPath){ - let result = await this.nodeConnection.sshService.exec(`test -f ${configPath}/gas_config.json`) - if(result.rc == 0){ - let gasLimit = await this.nodeConnection.sshService.exec(`cat ${configPath}/gas_config.json`) - if(gasLimit.includes("gas_limit")){ - gasLimit = gasLimit.stdout.match(/^.*gas_limit.*$/gm)[0].split(':')[1]; + async readGasConfigFile(configPath) { + let result = await this.nodeConnection.sshService.exec(`test -f ${configPath}/gas_config.json`); + if (result.rc == 0) { + let gasLimit = await this.nodeConnection.sshService.exec(`cat ${configPath}/gas_config.json`); + if (gasLimit.includes("gas_limit")) { + gasLimit = gasLimit.stdout.match(/^.*gas_limit.*$/gm)[0].split(":")[1]; return gasLimit; - } - else{ + } else { return ""; } - } - else{ + } else { return ""; } } diff --git a/launcher/src/backend/ValidatorAccountManager.js b/launcher/src/backend/ValidatorAccountManager.js index 438fa035a..a799ff926 100755 --- a/launcher/src/backend/ValidatorAccountManager.js +++ b/launcher/src/backend/ValidatorAccountManager.js @@ -27,9 +27,7 @@ export class ValidatorAccountManager { if (slashingDB) var slashing_protection_content = JSON.parse(readFileSync(slashingDB, { encoding: "utf8" })); let passwords = Array(files.length).fill(password); const content = files.map((file, index) => { - const passwordFile = passwordFiles.find( - (p) => path.basename(p.name, ".txt") === path.basename(file.name, ".json") - ); + const passwordFile = passwordFiles.find((p) => path.basename(p.name, ".txt") === path.basename(file.name, ".json")); if (passwordFile) { passwords[index] = readFileSync(passwordFile.path, { encoding: "utf8" }); } @@ -65,9 +63,7 @@ export class ValidatorAccountManager { if (pubkeys && pubkeys.length < 11) { try { for (const pubkey of pubkeys) { - let latestEpochsResponse = await axios.get( - networks[client.network].dataEndpoint + "/validator/" + pubkey + "/attestations" - ); + let latestEpochsResponse = await axios.get(networks[client.network].dataEndpoint + "/validator/" + pubkey + "/attestations"); if (latestEpochsResponse.status === 200 && latestEpochsResponse.data.data.length > 0) { for (let i = 0; i < 2; i++) { @@ -98,22 +94,15 @@ export class ValidatorAccountManager { .volumes.find((volume) => volume.includes("passwords")) .split(":")[0]; - const walletPassword = await this.nodeConnection.sshService.exec(`cat ${passwords_path}/wallet-password`) - const walletDir = await this.nodeConnection.sshService.exec(`ls ${wallet_path}/direct/accounts`) + const walletPassword = await this.nodeConnection.sshService.exec(`cat ${passwords_path}/wallet-password`); + const walletDir = await this.nodeConnection.sshService.exec(`ls ${wallet_path}/direct/accounts`); if (walletPassword.rc != 0 || walletDir.rc != 0) { log.error("No Wallet found"); log.info("Generating one"); - this.nodeConnection.taskManager.otherTasksHandler( - ref, - `Check Wallet`, - true, - "No Wallet found, generating one" - ); + this.nodeConnection.taskManager.otherTasksHandler(ref, `Check Wallet`, true, "No Wallet found, generating one"); //generate wallet password - await this.nodeConnection.sshService.exec( - `echo ${StringUtils.createRandomString()} > ${passwords_path}/wallet-password` - ); + await this.nodeConnection.sshService.exec(`echo ${StringUtils.createRandomString()} > ${passwords_path}/wallet-password`); await this.nodeConnection.sshService.exec(`chmod 700 ${passwords_path}/wallet-password`); await this.nodeConnection.sshService.exec(`chown 2000:2000 ${passwords_path}/wallet-password`); //Prysm - Create wallet for account(s) @@ -126,15 +115,8 @@ export class ValidatorAccountManager { await Promise.all([this.serviceManager.manageServiceState(client.id, "stopped")]); await Promise.all([this.serviceManager.manageServiceState(client.id, "started")]); - await this.nodeConnection.sshService.exec( - `chmod 600 ${wallet_path}/direct/accounts/all-accounts.keystore.json` - ); - this.nodeConnection.taskManager.otherTasksHandler( - ref, - `Generated Wallet`, - true, - "Waiting 30 Seconds for Client" - ); + await this.nodeConnection.sshService.exec(`chmod 600 ${wallet_path}/direct/accounts/all-accounts.keystore.json`); + this.nodeConnection.taskManager.otherTasksHandler(ref, `Generated Wallet`, true, "Waiting 30 Seconds for Client"); await Sleep(30000); } break; @@ -150,9 +132,7 @@ export class ValidatorAccountManager { if ((await this.nodeConnection.sshService.exec(`cat ${validator_path}/api-token.txt`)).rc === 1) { log.error("Couldn't read API-Token"); log.info("Generating one"); - await this.nodeConnection.sshService.exec( - `echo ${StringUtils.createRandomString()} > ${validator_path}/api-token.txt` - ); + await this.nodeConnection.sshService.exec(`echo ${StringUtils.createRandomString()} > ${validator_path}/api-token.txt`); await this.serviceManager.manageServiceState(client.id, "stopped"); await this.serviceManager.manageServiceState(client.id, "started"); await Sleep(30000); @@ -182,10 +162,7 @@ export class ValidatorAccountManager { async importKey(serviceID) { const ref = StringUtils.createRandomString(); - this.nodeConnection.taskManager.otherTasksHandler( - ref, - `Importing ${this.batches.map((b) => b.keystores).flat().length} Keys` - ); + this.nodeConnection.taskManager.otherTasksHandler(ref, `Importing ${this.batches.map((b) => b.keystores).flat().length} Keys`); let services = await this.serviceManager.readServiceConfigurations(); let client = services.find((service) => service.id === serviceID); @@ -232,12 +209,7 @@ export class ValidatorAccountManager { this.nodeConnection.taskManager.otherTasksHandler(ref); return message; } catch (err) { - this.nodeConnection.taskManager.otherTasksHandler( - ref, - `Import Failed`, - false, - "Validator Import Failed:\n" + err - ); + this.nodeConnection.taskManager.otherTasksHandler(ref, `Import Failed`, false, "Validator Import Failed:\n" + err); this.nodeConnection.taskManager.otherTasksHandler(ref); log.error("Validator Import Failed:\n", err); return "Validator Import Failed:\n" + err; @@ -271,12 +243,7 @@ export class ValidatorAccountManager { this.nodeConnection.taskManager.otherTasksHandler(ref); return data; } catch (err) { - this.nodeConnection.taskManager.otherTasksHandler( - ref, - `Listing Keys Failed`, - false, - "Listing Validators Failed:\n" + err - ); + this.nodeConnection.taskManager.otherTasksHandler(ref, `Listing Keys Failed`, false, "Listing Validators Failed:\n" + err); this.nodeConnection.taskManager.otherTasksHandler(ref); log.error("Listing Validators Failed:\n", err); return { data: [] }; @@ -309,12 +276,7 @@ export class ValidatorAccountManager { if (picked) return data.slashing_protection; return data; } catch (err) { - this.nodeConnection.taskManager.otherTasksHandler( - ref, - `Deleting Keys Failed`, - false, - "Deleting Validators Failed:\n" + err - ); + this.nodeConnection.taskManager.otherTasksHandler(ref, `Deleting Keys Failed`, false, "Deleting Validators Failed:\n" + err); this.nodeConnection.taskManager.otherTasksHandler(ref); log.error("Deleting Validators Failed:\n", err); return err; @@ -327,7 +289,8 @@ export class ValidatorAccountManager { const curlTag = await this.nodeConnection.ensureCurlImage(); let command = [ "docker run --rm --network=stereum curlimages/curl:" + curlTag, - `curl ${service.service.includes("Teku") ? "--insecure https" : "http"}://stereum-${service.id}:${validatorPorts[service.service] + `curl ${service.service.includes("Teku") ? "--insecure https" : "http"}://stereum-${service.id}:${ + validatorPorts[service.service] }${apiPath}`, `-X ${method.toUpperCase()}`, `-H 'Content-Type: application/json'`, @@ -419,13 +382,7 @@ export class ValidatorAccountManager { this.nodeConnection.taskManager.otherTasksHandler(ref, `Setting Fee Recipient`); //Push the task to the task manager try { let client = await this.nodeConnection.readServiceConfiguration(serviceID); - const result = await this.keymanagerAPI( - client, - "POST", - `/eth/v1/validator/${pubKey}/feerecipient`, - { ethaddress: address }, - ["-i"] - ); + const result = await this.keymanagerAPI(client, "POST", `/eth/v1/validator/${pubKey}/feerecipient`, { ethaddress: address }, ["-i"]); //Error handling if (SSHService.checkExecError(result) && result.stderr) throw SSHService.extractExecError(result); @@ -456,9 +413,7 @@ export class ValidatorAccountManager { this.nodeConnection.taskManager.otherTasksHandler(ref, `Deleting Fee Recipient`); //Push the task to the task manager try { let client = await this.nodeConnection.readServiceConfiguration(serviceID); - const result = await this.keymanagerAPI(client, "DELETE", `/eth/v1/validator/${pubKey}/feerecipient`, null, [ - "-i", - ]); + const result = await this.keymanagerAPI(client, "DELETE", `/eth/v1/validator/${pubKey}/feerecipient`, null, ["-i"]); //Error handling if (SSHService.checkExecError(result) && result.stderr) throw SSHService.extractExecError(result); @@ -498,16 +453,12 @@ export class ValidatorAccountManager { switch (service) { case "lighthouse": config = `default: ${graffiti}`; - await this.nodeConnection.sshService.exec( - "echo " + StringUtils.escapeStringForShell(config) + " > " + graffitiDir - ); + await this.nodeConnection.sshService.exec("echo " + StringUtils.escapeStringForShell(config) + " > " + graffitiDir); break; case "prysm": config = `default: "${graffiti}"`; - await this.nodeConnection.sshService.exec( - "echo " + StringUtils.escapeStringForShell(config) + " > " + graffitiDir - ); + await this.nodeConnection.sshService.exec("echo " + StringUtils.escapeStringForShell(config) + " > " + graffitiDir); break; case "nimbus": { @@ -529,9 +480,7 @@ export class ValidatorAccountManager { case "teku": config = graffiti; - await this.nodeConnection.sshService.exec( - "echo " + StringUtils.escapeStringForShell(config) + " > " + graffitiDir - ); + await this.nodeConnection.sshService.exec("echo " + StringUtils.escapeStringForShell(config) + " > " + graffitiDir); break; default: @@ -550,8 +499,7 @@ export class ValidatorAccountManager { //if the argument is an array of keys, add them to the current keys if they don't exist if (Array.isArray(keys)) { keys.forEach((key) => { - if (!currentKeys[key]) - currentKeys[key] = { keyName: "", groupName: "", groupID: null, validatorClientID: null }; + if (!currentKeys[key]) currentKeys[key] = { keyName: "", groupName: "", groupID: null, validatorClientID: null }; }); await this.nodeConnection.sshService.exec( "echo -e " + StringUtils.escapeStringForShell(YAML.stringify(currentKeys)) + " > /etc/stereum/keys.yaml" @@ -584,16 +532,12 @@ export class ValidatorAccountManager { case "PrysmValidatorService": { let walletPath = ""; if (typeof service.volumes[0] == "string") { - walletPath = ServiceVolume.buildByConfig( - service.volumes.find((v) => v.includes("/opt/app/data/wallets")) - ).destinationPath; + walletPath = ServiceVolume.buildByConfig(service.volumes.find((v) => v.includes("/opt/app/data/wallets"))).destinationPath; } else { walletPath = service.volumes.find((v) => v.servicePath == "/opt/app/data/wallets").destinationPath; } //Make sure keystores have correct permissions - const chmodResult = await this.nodeConnection.sshService.exec( - "chmod -Rv 600 " + walletPath + "/direct/accounts/*" - ); + const chmodResult = await this.nodeConnection.sshService.exec("chmod -Rv 600 " + walletPath + "/direct/accounts/*"); log.info(chmodResult.stdout); if (walletPath) { result = await this.nodeConnection.sshService.exec("cat " + walletPath + "/auth-token"); @@ -629,9 +573,7 @@ export class ValidatorAccountManager { ); break; case "Web3SignerService": - result = await this.nodeConnection.sshService.exec( - `docker exec stereum-${service.id} curl -X POST http://localhost:9000/reload` - ); + result = await this.nodeConnection.sshService.exec(`docker exec stereum-${service.id} curl -X POST http://localhost:9000/reload`); result.stdout = ""; break; } @@ -661,12 +603,7 @@ export class ValidatorAccountManager { } //Push successful task - this.nodeConnection.taskManager.otherTasksHandler( - ref, - `Get signed voluntary exit message`, - true, - JSON.stringify(data) - ); + this.nodeConnection.taskManager.otherTasksHandler(ref, `Get signed voluntary exit message`, true, JSON.stringify(data)); this.nodeConnection.taskManager.otherTasksHandler(ref); return data; } catch (error) { @@ -693,10 +630,9 @@ export class ValidatorAccountManager { if (key.status === "duplicate") duplicate++; if (key.status === "error") error++; return ( - `${pubkeys[index].substring(0, 20)}...${pubkeys[index].substring( - pubkeys[index].length - 6, - pubkeys[index].length - )}:\t${key.status}` + (key.status == "error" ? `:\n${key.message}\n` : "") + `${pubkeys[index].substring(0, 20)}...${pubkeys[index].substring(pubkeys[index].length - 6, pubkeys[index].length)}:\t${ + key.status + }` + (key.status == "error" ? `:\n${key.message}\n` : "") ); }) .join("\n"); @@ -751,12 +687,7 @@ export class ValidatorAccountManager { this.nodeConnection.taskManager.otherTasksHandler(ref); return message; } catch (err) { - this.nodeConnection.taskManager.otherTasksHandler( - ref, - `Remote Import Failed`, - false, - "Remote Validator Import Failed:\n" + err - ); + this.nodeConnection.taskManager.otherTasksHandler(ref, `Remote Import Failed`, false, "Remote Validator Import Failed:\n" + err); this.nodeConnection.taskManager.otherTasksHandler(ref); log.error("Remote Validator Import Failed:\n", err); return "Remote Validator Import Failed:\n" + err; @@ -1064,8 +995,7 @@ export class ValidatorAccountManager { if (!charonClient) throw "Couldn't find CharonService"; let contentResult = await this.nodeConnection.sshService.exec(charonClient.getListCharonFolderContentsCommand()); - if (SSHService.checkExecError(contentResult) && contentResult.stderr) - throw SSHService.extractExecError(contentResult); + if (SSHService.checkExecError(contentResult) && contentResult.stderr) throw SSHService.extractExecError(contentResult); const content = contentResult.stdout; const dkgCommand = charonClient.getDKGCommand( content.includes("cluster-definition.json") ? "" : input.match(/http(s)?:.*\/[0-9a-zA-z]*/)[0] diff --git a/launcher/src/backend/ethereum-services/BesuService.js b/launcher/src/backend/ethereum-services/BesuService.js index 64d6333f6..3d5f8bcc2 100755 --- a/launcher/src/backend/ethereum-services/BesuService.js +++ b/launcher/src/backend/ethereum-services/BesuService.js @@ -8,10 +8,7 @@ export class BesuService extends NodeService { const workingDir = service.buildWorkingDir(dir); const dataDir = "/opt/app/data"; const JWTDir = "/engine.jwt"; - const volumes = [ - new ServiceVolume(workingDir + "/data", "/opt/app/data"), - new ServiceVolume(workingDir + "/engine.jwt", JWTDir), - ]; + const volumes = [new ServiceVolume(workingDir + "/data", "/opt/app/data"), new ServiceVolume(workingDir + "/engine.jwt", JWTDir)]; service.init( "BesuService", // service @@ -83,8 +80,7 @@ export class BesuService extends NodeService { } buildPrometheusJob() { - return `\n - job_name: stereum-${this.id - }\n static_configs:\n - targets: [${this.buildExecutionClientMetricsEndpoint()}]`; + return `\n - job_name: stereum-${this.id}\n static_configs:\n - targets: [${this.buildExecutionClientMetricsEndpoint()}]`; } } diff --git a/launcher/src/backend/ethereum-services/CharonService.js b/launcher/src/backend/ethereum-services/CharonService.js index ff1061b70..5d0af7cab 100755 --- a/launcher/src/backend/ethereum-services/CharonService.js +++ b/launcher/src/backend/ethereum-services/CharonService.js @@ -8,9 +8,7 @@ export class CharonService extends NodeService { const workingDir = service.buildWorkingDir(dir); const dataDir = "/opt/charon"; - const volumes = [ - new ServiceVolume(workingDir, dataDir), - ]; + const volumes = [new ServiceVolume(workingDir, dataDir)]; const beaconNodes = consensusClients .map((client) => { @@ -33,7 +31,7 @@ export class CharonService extends NodeService { "--p2p-tcp-address=0.0.0.0:3610", "--validator-api-address=0.0.0.0:3600", "--monitoring-address=0.0.0.0:3620", - "--builder-api" + "--builder-api", ], // command ["/usr/local/bin/charon"], // entrypoint null, // env @@ -42,23 +40,24 @@ export class CharonService extends NodeService { null, // user network, // network null, // executionClients - consensusClients // consensusClients + consensusClients // consensusClients ); - if (consensusClients.map(s => s.service).includes("NimbusBeaconService")) { - service.command.push("--feature-set-enable=json_requests") + if (consensusClients.map((s) => s.service).includes("NimbusBeaconService")) { + service.command.push("--feature-set-enable=json_requests"); } - if (consensusClients.map(s => s.service).includes("TekuBeaconService")) { - consensusClients.filter(s => s.service === "TekuBeaconService").forEach(s => { - s.command.push(`--validators-graffiti-client-append-format=DISABLED`) - }) + if (consensusClients.map((s) => s.service).includes("TekuBeaconService")) { + consensusClients + .filter((s) => s.service === "TekuBeaconService") + .forEach((s) => { + s.command.push(`--validators-graffiti-client-append-format=DISABLED`); + }); } return service; } - static buildByConfiguration(config) { const service = new CharonService(); @@ -79,7 +78,6 @@ export class CharonService extends NodeService { return "stereum-" + this.id + ":3600"; } - getDataDir() { return this.volumes.find((volume) => volume.servicePath === "/opt/charon").destinationPath; } @@ -105,20 +103,21 @@ export class CharonService extends NodeService { } getWriteENRPrivateKeyCommand(privateKey) { - return `echo "${privateKey}" > ${this.getDataDir()}/.charon/charon-enr-private-key` + return `echo "${privateKey}" > ${this.getDataDir()}/.charon/charon-enr-private-key`; } getReadENRPrivateKeyCommand() { - return `cat ${this.getDataDir()}/.charon/charon-enr-private-key` + return `cat ${this.getDataDir()}/.charon/charon-enr-private-key`; } getListCharonFolderContentsCommand() { - return `ls -1 -a ${this.getDataDir()}/.charon` + return `ls -1 -a ${this.getDataDir()}/.charon`; } //definitionFile as URL or Path to file (default ".charon/cluster-definition.json" by dkg command) getDKGCommand(definitionFile) { - return `docker run -u 0 --name "dkg-container" -d -v "${this.getDataDir()}:/opt/charon" ${this.image + ":" + this.imageVersion} dkg ${definitionFile ? "--definition-file=" + definitionFile : ""} --publish`; - + return `docker run -u 0 --name "dkg-container" -d -v "${this.getDataDir()}:/opt/charon" ${this.image + ":" + this.imageVersion} dkg ${ + definitionFile ? "--definition-file=" + definitionFile : "" + } --publish`; } } diff --git a/launcher/src/backend/ethereum-services/CustomService.js b/launcher/src/backend/ethereum-services/CustomService.js index e3bc2091c..8871c1294 100644 --- a/launcher/src/backend/ethereum-services/CustomService.js +++ b/launcher/src/backend/ethereum-services/CustomService.js @@ -10,18 +10,18 @@ export class CustomService extends NodeService { const image = CustomService.parseImageString(imageString); - command = command.replace(/\s\s+/g, ' ').trim(); + command = command.replace(/\s\s+/g, " ").trim(); - const finalPorts = ports.map(p => { + const finalPorts = ports.map((p) => { return ServicePort.buildByConfig(p); }); - const finalVolumes = volumes.map(v => { + const finalVolumes = volumes.map((v) => { if (v.includes("")) { v = v.replace("", workingDir); } return ServiceVolume.buildByConfig(v); - }) + }); service.init( "CustomService", // service diff --git a/launcher/src/backend/ethereum-services/ErigonService.js b/launcher/src/backend/ethereum-services/ErigonService.js index 8f75e1d49..bc064d8d6 100755 --- a/launcher/src/backend/ethereum-services/ErigonService.js +++ b/launcher/src/backend/ethereum-services/ErigonService.js @@ -9,10 +9,7 @@ export class ErigonService extends NodeService { const JWTDir = "/engine.jwt"; const dataDir = "/opt/data/erigon"; - const volumes = [ - new ServiceVolume(workingDir + "/data", dataDir), - new ServiceVolume(workingDir + "/engine.jwt", JWTDir), - ]; + const volumes = [new ServiceVolume(workingDir + "/data", dataDir), new ServiceVolume(workingDir + "/engine.jwt", JWTDir)]; service.init( "ErigonService", // service @@ -28,7 +25,7 @@ export class ErigonService extends NodeService { `--authrpc.vhosts=*`, `--authrpc.port=8551`, `--authrpc.jwtsecret=/engine.jwt`, - '--rpc.returndata.limit=1000000', + "--rpc.returndata.limit=1000000", `--ws`, `--http`, `--http.vhosts=*`, @@ -39,8 +36,8 @@ export class ErigonService extends NodeService { `--metrics`, `--metrics.addr=0.0.0.0`, `--metrics.port=6060`, - '--db.pagesize=16K', - '--db.size.limit=8TB', + "--db.pagesize=16K", + "--db.size.limit=8TB", ], // command [], // entrypoint null, // env @@ -85,12 +82,12 @@ export class ErigonService extends NodeService { } switchImageTag(arch) { - const armArchs = ["arm", "arm64", "aarch64_be", "aarch64", "armv8b", "armv8l"] //Possible arm architectures: https://stackoverflow.com/questions/45125516/possible-values-for-uname-m + const armArchs = ["arm", "arm64", "aarch64_be", "aarch64", "armv8b", "armv8l"]; //Possible arm architectures: https://stackoverflow.com/questions/45125516/possible-values-for-uname-m if (armArchs.includes(arch)) { this.imageVersion = this.imageVersion.endsWith("-arm64") ? this.imageVersion : this.imageVersion + "-arm64"; this.imageVersion = this.imageVersion.startsWith("v") ? this.imageVersion.slice(1) : this.imageVersion; } else { - this.imageVersion = this.imageVersion.endsWith("-arm64") ? this.imageVersion.replace("-arm64", "") : this.imageVersion + this.imageVersion = this.imageVersion.endsWith("-arm64") ? this.imageVersion.replace("-arm64", "") : this.imageVersion; this.imageVersion = this.imageVersion.startsWith("v") ? this.imageVersion : "v" + this.imageVersion; } } @@ -116,8 +113,9 @@ export class ErigonService extends NodeService { } buildPrometheusJob() { - return `\n - job_name: stereum-${this.id - }\n metrics_path: /debug/metrics/prometheus\n static_configs:\n - targets: [${this.buildExecutionClientMetricsEndpoint()}]`; + return `\n - job_name: stereum-${ + this.id + }\n metrics_path: /debug/metrics/prometheus\n static_configs:\n - targets: [${this.buildExecutionClientMetricsEndpoint()}]`; } } diff --git a/launcher/src/backend/ethereum-services/ExternalExecutionService.js b/launcher/src/backend/ethereum-services/ExternalExecutionService.js index 14623cc12..328949728 100644 --- a/launcher/src/backend/ethereum-services/ExternalExecutionService.js +++ b/launcher/src/backend/ethereum-services/ExternalExecutionService.js @@ -7,10 +7,7 @@ export class ExternalExecutionService extends NodeService { service.setId(); const workingDir = service.buildWorkingDir(dir); - const volumes = [ - new ServiceVolume(workingDir + "/link.txt", ""), - new ServiceVolume(workingDir + "/engine.jwt", ""), - ]; + const volumes = [new ServiceVolume(workingDir + "/link.txt", ""), new ServiceVolume(workingDir + "/engine.jwt", "")]; service.init( "ExternalExecutionService", // service diff --git a/launcher/src/backend/ethereum-services/GethService.js b/launcher/src/backend/ethereum-services/GethService.js index 37ba5e8cd..b940268a8 100755 --- a/launcher/src/backend/ethereum-services/GethService.js +++ b/launcher/src/backend/ethereum-services/GethService.js @@ -9,10 +9,7 @@ export class GethService extends NodeService { const JWTDir = "/engine.jwt"; const dataDir = "/opt/data/geth"; - const volumes = [ - new ServiceVolume(workingDir + "/data", dataDir), - new ServiceVolume(workingDir + "/engine.jwt", JWTDir), - ]; + const volumes = [new ServiceVolume(workingDir + "/data", dataDir), new ServiceVolume(workingDir + "/engine.jwt", JWTDir)]; service.init( "GethService", // service diff --git a/launcher/src/backend/ethereum-services/KuboIPFSService.js b/launcher/src/backend/ethereum-services/KuboIPFSService.js index b1b4d7b6a..ad1bafe98 100644 --- a/launcher/src/backend/ethereum-services/KuboIPFSService.js +++ b/launcher/src/backend/ethereum-services/KuboIPFSService.js @@ -12,10 +12,7 @@ export class KuboIPFSService extends NodeService { const dataDir = "/data/ipfs"; const exportDir = "/export"; - const volumes = [ - new ServiceVolume(workingDir + dataDir, dataDir), - new ServiceVolume(workingDir + exportDir, exportDir), - ]; + const volumes = [new ServiceVolume(workingDir + dataDir, dataDir), new ServiceVolume(workingDir + exportDir, exportDir)]; service.init( "KuboIPFSService", //service diff --git a/launcher/src/backend/ethereum-services/LCOMService.js b/launcher/src/backend/ethereum-services/LCOMService.js index 934f240f4..848aece27 100644 --- a/launcher/src/backend/ethereum-services/LCOMService.js +++ b/launcher/src/backend/ethereum-services/LCOMService.js @@ -25,9 +25,7 @@ export class LCOMService extends NodeService { ["python", "main.py"], // entrypoint { RPC_API: executionClients[0] ? executionClients[0].buildExecutionClientHttpEndpointUrl() : "http://RPC-api", - BEACON_API: consensusClients[0] - ? consensusClients[0].buildConsensusClientHttpEndpointUrl() - : "http://beacon-api", + BEACON_API: consensusClients[0] ? consensusClients[0].buildConsensusClientHttpEndpointUrl() : "http://beacon-api", IPFS_API: ipfs ? ipfs.buildIPFSHttpEndpointUrl() : "http://IPFS-api", NO_ID: "123456", LOG_LEVEL: "INFO", diff --git a/launcher/src/backend/ethereum-services/LidoObolExitService.js b/launcher/src/backend/ethereum-services/LidoObolExitService.js index 95b1c278a..ac07b9aea 100644 --- a/launcher/src/backend/ethereum-services/LidoObolExitService.js +++ b/launcher/src/backend/ethereum-services/LidoObolExitService.js @@ -3,11 +3,9 @@ import { ServiceVolume } from "./ServiceVolume"; export class LidoObolExitService extends NodeService { static buildByUserInput(network, ports, dir, consensusClients, otherServices) { - let ejector = otherServices.find((service) => service.service === "ValidatorEjectorService"); let charon = consensusClients.find((service) => service.service === "CharonService"); - if (charon) - otherServices.push(charon); + if (charon) otherServices.push(charon); consensusClients = consensusClients.filter((service) => !(service.service === "CharonService")); const service = new LidoObolExitService(); @@ -19,19 +17,12 @@ export class LidoObolExitService extends NodeService { const exitmessagesDir = "/exitmessages"; const charonDir = "/charon"; - const charonFoler = charon ? `${charon.getDataDir()}/.charon` : workingDir + "/charon"; - let messageVolume = ejector ? ejector.volumes.find((volume) => volume.servicePath === '/app/messages') : ""; + let messageVolume = ejector ? ejector.volumes.find((volume) => volume.servicePath === "/app/messages") : ""; const messageDir = messageVolume ? messageVolume.destinationPath : workingDir + "/exitmessages"; - const volumes = [ - new ServiceVolume(messageDir, exitmessagesDir), - new ServiceVolume(charonFoler, charonDir), - ]; - - - + const volumes = [new ServiceVolume(messageDir, exitmessagesDir), new ServiceVolume(charonFoler, charonDir)]; service.init( "LidoObolExitService", //service @@ -49,7 +40,7 @@ export class LidoObolExitService extends NodeService { "--log-format=console", "--log-level=info", "--obol-api-url=https://api.obol.tech", - "--validator-query-chunk-size=50" + "--validator-query-chunk-size=50", ], // command ["/usr/local/bin/lido-dv-exit"], // entrypoint null, // env diff --git a/launcher/src/backend/ethereum-services/LighthouseBeaconService.js b/launcher/src/backend/ethereum-services/LighthouseBeaconService.js index 48467aefb..202224e4a 100755 --- a/launcher/src/backend/ethereum-services/LighthouseBeaconService.js +++ b/launcher/src/backend/ethereum-services/LighthouseBeaconService.js @@ -14,10 +14,7 @@ export class LighthouseBeaconService extends NodeService { const slasherDir = "/opt/app/slasher"; // volumes - const volumes = [ - new ServiceVolume(workingDir + "/beacon", dataDir), - new ServiceVolume(workingDir + "/slasher", slasherDir), - ]; + const volumes = [new ServiceVolume(workingDir + "/beacon", dataDir), new ServiceVolume(workingDir + "/slasher", slasherDir)]; // eth1 nodes const eth1Nodes = executionClients @@ -110,8 +107,7 @@ export class LighthouseBeaconService extends NodeService { } buildPrometheusJob() { - return `\n - job_name: stereum-${this.id - }\n static_configs:\n - targets: [${this.buildConsensusClientMetricsEndpoint()}]`; + return `\n - job_name: stereum-${this.id}\n static_configs:\n - targets: [${this.buildConsensusClientMetricsEndpoint()}]`; } getAvailablePorts() { diff --git a/launcher/src/backend/ethereum-services/LighthouseValidatorService.js b/launcher/src/backend/ethereum-services/LighthouseValidatorService.js index 8be8ce760..b390263e3 100755 --- a/launcher/src/backend/ethereum-services/LighthouseValidatorService.js +++ b/launcher/src/backend/ethereum-services/LighthouseValidatorService.js @@ -13,10 +13,7 @@ export class LighthouseValidatorService extends NodeService { const dataDir = "/opt/app/validator"; const graffitiDir = "/opt/app/graffitis"; - const volumes = [ - new ServiceVolume(workingDir + "/validator", dataDir), - new ServiceVolume(workingDir + "/graffitis", graffitiDir), - ]; + const volumes = [new ServiceVolume(workingDir + "/validator", dataDir), new ServiceVolume(workingDir + "/graffitis", graffitiDir)]; const eth2Nodes = consensusClients .map((client) => { @@ -60,8 +57,8 @@ export class LighthouseValidatorService extends NodeService { consensusClients //consensusClients ); - if (consensusClients.some(c => c.service === "CharonService")) { - service.command = service.command.filter(c => c !== "--enable-doppelganger-protection"); + if (consensusClients.some((c) => c.service === "CharonService")) { + service.command = service.command.filter((c) => c !== "--enable-doppelganger-protection"); } return service; diff --git a/launcher/src/backend/ethereum-services/LodestarValidatorService.js b/launcher/src/backend/ethereum-services/LodestarValidatorService.js index 2ed1dcf7b..662d7d6b0 100755 --- a/launcher/src/backend/ethereum-services/LodestarValidatorService.js +++ b/launcher/src/backend/ethereum-services/LodestarValidatorService.js @@ -52,10 +52,10 @@ export class LodestarValidatorService extends NodeService { consensusClients //consensusClients ); - if (consensusClients.some(c => c.service === "CharonService")) { - service.command.push("--distributed") - service.command[service.command.findIndex(c => c === "--doppelgangerProtection=true")] = "--doppelgangerProtection=false" - service.command.push("--builder.selection=builderalways") + if (consensusClients.some((c) => c.service === "CharonService")) { + service.command.push("--distributed"); + service.command[service.command.findIndex((c) => c === "--doppelgangerProtection=true")] = "--doppelgangerProtection=false"; + service.command.push("--builder.selection=builderalways"); } return service; diff --git a/launcher/src/backend/ethereum-services/MetricsExporterService.js b/launcher/src/backend/ethereum-services/MetricsExporterService.js index 2ea30477e..61458c50b 100644 --- a/launcher/src/backend/ethereum-services/MetricsExporterService.js +++ b/launcher/src/backend/ethereum-services/MetricsExporterService.js @@ -38,7 +38,7 @@ export class MetricsExporterService extends NodeService { return service; } - static buildByConfiguration(config) { + static buildByConfiguration(config) { const service = new MetricsExporterService(); service.initByConfig(config); diff --git a/launcher/src/backend/ethereum-services/NethermindService.js b/launcher/src/backend/ethereum-services/NethermindService.js index 3f4da44a1..1605b61d6 100755 --- a/launcher/src/backend/ethereum-services/NethermindService.js +++ b/launcher/src/backend/ethereum-services/NethermindService.js @@ -9,10 +9,7 @@ export class NethermindService extends NodeService { const dataDir = "/opt/app/data"; const JWTDir = "/engine.jwt"; - const volumes = [ - new ServiceVolume(workingDir + "/data", dataDir), - new ServiceVolume(workingDir + "/engine.jwt", JWTDir), - ]; + const volumes = [new ServiceVolume(workingDir + "/data", dataDir), new ServiceVolume(workingDir + "/engine.jwt", JWTDir)]; service.init( "NethermindService", // service @@ -83,7 +80,6 @@ export class NethermindService extends NodeService { } buildPrometheusJob() { - return `\n - job_name: stereum-${this.id - }\n static_configs:\n - targets: [${this.buildExecutionClientMetricsEndpoint()}]`; + return `\n - job_name: stereum-${this.id}\n static_configs:\n - targets: [${this.buildExecutionClientMetricsEndpoint()}]`; } } diff --git a/launcher/src/backend/ethereum-services/NimbusValidatorService.js b/launcher/src/backend/ethereum-services/NimbusValidatorService.js index 933d07b20..e6b934b21 100755 --- a/launcher/src/backend/ethereum-services/NimbusValidatorService.js +++ b/launcher/src/backend/ethereum-services/NimbusValidatorService.js @@ -58,8 +58,8 @@ export class NimbusValidatorService extends NodeService { consensusClients //consensusClients ); - if (consensusClients.some(c => c.service === "CharonService")) { - service.command[service.command.findIndex(c => c === "--doppelganger-detection=true")] = "--doppelganger-detection=false" + if (consensusClients.some((c) => c.service === "CharonService")) { + service.command[service.command.findIndex((c) => c === "--doppelganger-detection=true")] = "--doppelganger-detection=false"; } return service; @@ -78,9 +78,6 @@ export class NimbusValidatorService extends NodeService { } getAvailablePorts() { - return [ - new ServicePortDefinition(8108, "tcp", "Metrics Port"), - new ServicePortDefinition(5052, "tcp", "Keymanager Port"), - ]; + return [new ServicePortDefinition(8108, "tcp", "Metrics Port"), new ServicePortDefinition(5052, "tcp", "Keymanager Port")]; } } diff --git a/launcher/src/backend/ethereum-services/NodeService.js b/launcher/src/backend/ethereum-services/NodeService.js index e86567a3b..d460eee44 100755 --- a/launcher/src/backend/ethereum-services/NodeService.js +++ b/launcher/src/backend/ethereum-services/NodeService.js @@ -63,7 +63,7 @@ export class NodeService { executionClients, consensusClients, mevboost, - otherServices, + otherServices ) { this.service = service; this.setId(id); @@ -135,12 +135,8 @@ export class NodeService { network: this.network, dependencies: { - executionClients: (this.dependencies.executionClients || []).map((service) => - service.buildMinimalConfiguration() - ), - consensusClients: (this.dependencies.consensusClients || []).map((service) => - service.buildMinimalConfiguration() - ), + executionClients: (this.dependencies.executionClients || []).map((service) => service.buildMinimalConfiguration()), + consensusClients: (this.dependencies.consensusClients || []).map((service) => service.buildMinimalConfiguration()), mevboost: (this.dependencies.mevboost || []).map((service) => service.buildMinimalConfiguration()), otherServices: (this.dependencies.otherServices || []).map((service) => service.buildMinimalConfiguration()), }, diff --git a/launcher/src/backend/ethereum-services/PrometheusNodeExporterService.js b/launcher/src/backend/ethereum-services/PrometheusNodeExporterService.js index 26f5aea26..c87a8b167 100755 --- a/launcher/src/backend/ethereum-services/PrometheusNodeExporterService.js +++ b/launcher/src/backend/ethereum-services/PrometheusNodeExporterService.js @@ -42,7 +42,8 @@ export class PrometheusNodeExporterService extends NodeService { } buildPrometheusJob() { - return `\n - job_name: stereum-${this.id - }\n static_configs:\n - targets: [${this.buildPrometheusNodeExporterClientMetricsEndpoint()}]`; + return `\n - job_name: stereum-${ + this.id + }\n static_configs:\n - targets: [${this.buildPrometheusNodeExporterClientMetricsEndpoint()}]`; } } diff --git a/launcher/src/backend/ethereum-services/PrometheusService.js b/launcher/src/backend/ethereum-services/PrometheusService.js index 478e8c316..94e4d868f 100755 --- a/launcher/src/backend/ethereum-services/PrometheusService.js +++ b/launcher/src/backend/ethereum-services/PrometheusService.js @@ -13,10 +13,7 @@ export class PrometheusService extends NodeService { const dataDir = "/prometheus"; const configDir = "/etc/prometheus"; - const volumes = [ - new ServiceVolume(workingDir + "/data/prometheus", dataDir), - new ServiceVolume(workingDir + "/config", configDir), - ]; + const volumes = [new ServiceVolume(workingDir + "/data/prometheus", dataDir), new ServiceVolume(workingDir + "/config", configDir)]; service.init( "PrometheusService", diff --git a/launcher/src/backend/ethereum-services/PrysmBeaconService.js b/launcher/src/backend/ethereum-services/PrysmBeaconService.js index 01c16a662..c46138c14 100755 --- a/launcher/src/backend/ethereum-services/PrysmBeaconService.js +++ b/launcher/src/backend/ethereum-services/PrysmBeaconService.js @@ -15,10 +15,7 @@ export class PrysmBeaconService extends NodeService { const genesisDir = "/opt/app/genesis"; //volumes - const volumes = [ - new ServiceVolume(workingDir + "/beacon", dataDir), - new ServiceVolume(workingDir + "/genesis", genesisDir), - ]; + const volumes = [new ServiceVolume(workingDir + "/beacon", dataDir), new ServiceVolume(workingDir + "/genesis", genesisDir)]; //execution endpoint const executionEndpoint = executionClients @@ -59,7 +56,7 @@ export class PrysmBeaconService extends NodeService { "--p2p-tcp-port=13001", "--p2p-udp-port=12001", ], //command - ['/app/cmd/beacon-chain/beacon-chain'], //entrypoint + ["/app/cmd/beacon-chain/beacon-chain"], //entrypoint null, //env ports, //ports volumes, //volumes @@ -71,15 +68,15 @@ export class PrysmBeaconService extends NodeService { ); if (network == "holesky" || network == "sepolia") { - service.command.push(`--genesis-state=/opt/app/genesis/prysm-${network}-genesis.ssz`) + service.command.push(`--genesis-state=/opt/app/genesis/prysm-${network}-genesis.ssz`); } if (checkpointURL) { - service.command.push(`--checkpoint-sync-url=${checkpointURL}`) + service.command.push(`--checkpoint-sync-url=${checkpointURL}`); } if (mevboostEndpoint) { - service.command.push(`--http-mev-relay=${mevboostEndpoint}`) + service.command.push(`--http-mev-relay=${mevboostEndpoint}`); } return service; @@ -110,8 +107,7 @@ export class PrysmBeaconService extends NodeService { } buildPrometheusJob() { - return `\n - job_name: stereum-${this.id - }\n static_configs:\n - targets: [${this.buildConsensusClientMetricsEndpoint()}]`; + return `\n - job_name: stereum-${this.id}\n static_configs:\n - targets: [${this.buildConsensusClientMetricsEndpoint()}]`; } getAvailablePorts() { diff --git a/launcher/src/backend/ethereum-services/PrysmValidatorService.js b/launcher/src/backend/ethereum-services/PrysmValidatorService.js index 94828f4a1..2373cf013 100755 --- a/launcher/src/backend/ethereum-services/PrysmValidatorService.js +++ b/launcher/src/backend/ethereum-services/PrysmValidatorService.js @@ -40,27 +40,27 @@ export class PrysmValidatorService extends NodeService { image, //image "v5.1.0", //imageVersion [ - '--accept-terms-of-use=true', + "--accept-terms-of-use=true", `--beacon-rpc-provider=${provider}`, `--beacon-rpc-gateway-provider=${providerGateway}`, - '--web', + "--web", `--${network}`, `--datadir=${dataDir}`, `--keymanager-token-file=${walletDir + "/auth-token"}`, `--wallet-dir=${walletDir}`, `--wallet-password-file=${passwordDir + "/wallet-password"}`, - '--monitoring-host=0.0.0.0', - '--grpc-gateway-port=7500', - '--grpc-gateway-host=0.0.0.0', + "--monitoring-host=0.0.0.0", + "--grpc-gateway-port=7500", + "--grpc-gateway-host=0.0.0.0", '--grpc-gateway-corsdomain="*"', - '--monitoring-host=0.0.0.0', - '--monitoring-port=8081', - '--suggested-fee-recipient=0x0000000000000000000000000000000000000000', + "--monitoring-host=0.0.0.0", + "--monitoring-port=8081", + "--suggested-fee-recipient=0x0000000000000000000000000000000000000000", `--graffiti-file=${graffitiDir + "/graffitis.yaml"}`, - '--enable-builder=true', - '--enable-doppelganger=true', + "--enable-builder=true", + "--enable-doppelganger=true", ], //command - ['/app/cmd/validator/validator'], // entrypoint + ["/app/cmd/validator/validator"], // entrypoint null, // env ports, //ports volumes, //volumes diff --git a/launcher/src/backend/ethereum-services/RethService.js b/launcher/src/backend/ethereum-services/RethService.js index aa8c6d664..9894e9996 100644 --- a/launcher/src/backend/ethereum-services/RethService.js +++ b/launcher/src/backend/ethereum-services/RethService.js @@ -8,10 +8,7 @@ export class RethService extends NodeService { const workingDir = service.buildWorkingDir(dir); const dataDir = "/opt/data/reth"; const JWTDir = "/engine.jwt"; - const volumes = [ - new ServiceVolume(workingDir + "/data", dataDir), - new ServiceVolume(workingDir + "/engine.jwt", JWTDir), - ]; + const volumes = [new ServiceVolume(workingDir + "/data", dataDir), new ServiceVolume(workingDir + "/engine.jwt", JWTDir)]; service.init( "RethService", // service @@ -26,12 +23,12 @@ export class RethService extends NodeService { "--http", "--http.port=8545", "--http.addr=0.0.0.0", - '--http.api=debug,web3,eth,net', + "--http.api=debug,web3,eth,net", "--http.corsdomain=*", "--ws", "--ws.port=8546", "--ws.addr=0.0.0.0", - '--ws.api=debug,web3,eth,net', + "--ws.api=debug,web3,eth,net", "--ws.origins=*", "--authrpc.port=8551", "--authrpc.addr=0.0.0.0", @@ -80,8 +77,7 @@ export class RethService extends NodeService { } buildPrometheusJob() { - return `\n - job_name: stereum-${this.id - }\n static_configs:\n - targets: [${this.buildExecutionClientMetricsEndpoint()}]`; + return `\n - job_name: stereum-${this.id}\n static_configs:\n - targets: [${this.buildExecutionClientMetricsEndpoint()}]`; } } diff --git a/launcher/src/backend/ethereum-services/SSVDKGService.js b/launcher/src/backend/ethereum-services/SSVDKGService.js index f4b4afe0a..f47706a1a 100644 --- a/launcher/src/backend/ethereum-services/SSVDKGService.js +++ b/launcher/src/backend/ethereum-services/SSVDKGService.js @@ -25,10 +25,7 @@ outputPath: /data/output`; // Note that local secrets volume will be replaced with // shared volume from SSVNetworkService later on... - const volumes = [ - new ServiceVolume(workingDir + "/data", "/data"), - new ServiceVolume(workingDir + "/secrets", "/secrets"), - ]; + const volumes = [new ServiceVolume(workingDir + "/data", "/data"), new ServiceVolume(workingDir + "/secrets", "/secrets")]; console.log("-------> TTT :: otherServices", otherServices); @@ -64,10 +61,7 @@ outputPath: /data/output`; } getAvailablePorts() { - return [ - new ServicePortDefinition(3030, "tcp", "TCP connections"), - new ServicePortDefinition(3030, "udp", "UDP connections"), - ]; + return [new ServicePortDefinition(3030, "tcp", "TCP connections"), new ServicePortDefinition(3030, "udp", "UDP connections")]; } } diff --git a/launcher/src/backend/ethereum-services/SSVNetworkService.js b/launcher/src/backend/ethereum-services/SSVNetworkService.js index 90a2038ed..5945caf77 100755 --- a/launcher/src/backend/ethereum-services/SSVNetworkService.js +++ b/launcher/src/backend/ethereum-services/SSVNetworkService.js @@ -53,10 +53,7 @@ MetricsAPIPort: 15000`; const image = "bloxstaking/ssv-node"; - const volumes = [ - new ServiceVolume(workingDir + "/data", "/data"), - new ServiceVolume(workingDir + "/secrets", "/secrets"), - ]; + const volumes = [new ServiceVolume(workingDir + "/data", "/data"), new ServiceVolume(workingDir + "/secrets", "/secrets")]; // build service service.init( diff --git a/launcher/src/backend/ethereum-services/ServicePort.js b/launcher/src/backend/ethereum-services/ServicePort.js index 8a923faa5..47a4bf4e4 100755 --- a/launcher/src/backend/ethereum-services/ServicePort.js +++ b/launcher/src/backend/ethereum-services/ServicePort.js @@ -49,7 +49,6 @@ export class ServicePort { const servicePort = servicePortSettings?.length >= 1 ? servicePortSettings[0] : ""; const servicePortProtocol = servicePortSettings?.length >= 2 ? servicePortSettings[1] : ""; - return new ServicePort(destinationIp, destinationPort, servicePort, servicePortProtocol); } diff --git a/launcher/src/backend/ethereum-services/TekuBeaconService.js b/launcher/src/backend/ethereum-services/TekuBeaconService.js index 44c8868a3..ca7b1c7d3 100755 --- a/launcher/src/backend/ethereum-services/TekuBeaconService.js +++ b/launcher/src/backend/ethereum-services/TekuBeaconService.js @@ -104,8 +104,9 @@ export class TekuBeaconService extends NodeService { } buildPrometheusJob() { - return `\n - job_name: stereum-${this.id - }\n scrape_timeout: 10s\n metrics_path: /metrics\n scheme: http\n static_configs:\n - targets: [${this.buildConsensusClientMetricsEndpoint()}]`; + return `\n - job_name: stereum-${ + this.id + }\n scrape_timeout: 10s\n metrics_path: /metrics\n scheme: http\n static_configs:\n - targets: [${this.buildConsensusClientMetricsEndpoint()}]`; } getAvailablePorts() { diff --git a/launcher/src/backend/ethereum-services/TekuValidatorService.js b/launcher/src/backend/ethereum-services/TekuValidatorService.js index a585586b6..087050c79 100755 --- a/launcher/src/backend/ethereum-services/TekuValidatorService.js +++ b/launcher/src/backend/ethereum-services/TekuValidatorService.js @@ -19,10 +19,7 @@ export class TekuValidatorService extends NodeService { const dataDir = "/opt/app/data"; const graffitiDir = "/opt/app/graffitis"; - const volumes = [ - new ServiceVolume(workingDir + "/data", dataDir), - new ServiceVolume(workingDir + "/graffitis", graffitiDir), - ]; + const volumes = [new ServiceVolume(workingDir + "/data", dataDir), new ServiceVolume(workingDir + "/graffitis", graffitiDir)]; service.init( "TekuValidatorService", // service @@ -65,8 +62,9 @@ export class TekuValidatorService extends NodeService { consensusClients //consensusClients ); - if (consensusClients.some(c => c.service === "CharonService")) { - service.command[service.command.findIndex(c => c === "--doppelganger-detection-enabled=true")] = "--doppelganger-detection-enabled=false" + if (consensusClients.some((c) => c.service === "CharonService")) { + service.command[service.command.findIndex((c) => c === "--doppelganger-detection-enabled=true")] = + "--doppelganger-detection-enabled=false"; } return service; diff --git a/launcher/src/backend/ethereum-services/Web3SignerService.js b/launcher/src/backend/ethereum-services/Web3SignerService.js index 2ada032bb..bdaa8602f 100755 --- a/launcher/src/backend/ethereum-services/Web3SignerService.js +++ b/launcher/src/backend/ethereum-services/Web3SignerService.js @@ -13,10 +13,7 @@ export class Web3SignerService extends NodeService { const dataDir = "/opt/web3signer/data"; const keysDir = "/opt/web3signer/keys"; - const volumes = [ - new ServiceVolume(workingDir + "/data", dataDir), - new ServiceVolume(workingDir + "/keys", keysDir), - ]; + const volumes = [new ServiceVolume(workingDir + "/data", dataDir), new ServiceVolume(workingDir + "/keys", keysDir)]; service.init( "Web3SignerService", // service @@ -75,10 +72,7 @@ export class Web3SignerService extends NodeService { } getAvailablePorts() { - return [ - new ServicePortDefinition(9000, "tcp", "REST API Port"), - new ServicePortDefinition(9001, "tcp", "METRICS Port"), - ]; + return [new ServicePortDefinition(9000, "tcp", "REST API Port"), new ServicePortDefinition(9001, "tcp", "METRICS Port")]; } } diff --git a/launcher/src/backend/tests/integration/BesuService.int.js b/launcher/src/backend/tests/integration/BesuService.int.js index 5e9070ac6..8c56c26da 100755 --- a/launcher/src/backend/tests/integration/BesuService.int.js +++ b/launcher/src/backend/tests/integration/BesuService.int.js @@ -11,16 +11,14 @@ jest.setTimeout(500000); test("besu installation", async () => { const testServer = new HetznerServer(); - const keyResponse = await testServer.createSSHKey("Besu--integration-test--ubuntu-2204") + const keyResponse = await testServer.createSSHKey("Besu--integration-test--ubuntu-2204"); const serverSettings = { name: "Besu--integration-test--ubuntu-2204", image: "ubuntu-22.04", server_type: "cpx21", start_after_create: true, - ssh_keys: [ - keyResponse.ssh_key.id - ], + ssh_keys: [keyResponse.ssh_key.id], }; await testServer.create(serverSettings); @@ -38,7 +36,7 @@ test("besu installation", async () => { const serviceManager = new ServiceManager(nodeConnection); await testServer.checkServerConnection(nodeConnection); - await nodeConnection.establish(taskManager) + await nodeConnection.establish(taskManager); //prepare node await nodeConnection.sshService.exec(` mkdir /etc/stereum && @@ -55,7 +53,7 @@ test("besu installation", async () => { await nodeConnection.prepareStereumNode(nodeConnection.settings.stereum.settings.controls_install_path); //install besu - let executionClient = serviceManager.getService("BesuService", { network: "holesky", installDir: "/opt/stereum" }) + let executionClient = serviceManager.getService("BesuService", { network: "holesky", installDir: "/opt/stereum" }); let versions = await nodeConnection.nodeUpdates.checkUpdates(); executionClient.imageVersion = versions[executionClient.network][executionClient.service].slice(-1).pop(); @@ -89,7 +87,7 @@ test("besu installation", async () => { const docker = await nodeConnection.sshService.exec("docker ps"); // destroy - await testServer.finishTestGracefully(nodeConnection) + await testServer.finishTestGracefully(nodeConnection); //check ufw expect(ufw.stdout).toMatch(/30303\/tcp/); diff --git a/launcher/src/backend/tests/integration/ErigonService.int.js b/launcher/src/backend/tests/integration/ErigonService.int.js index f84d1c5ff..3e130e2e3 100755 --- a/launcher/src/backend/tests/integration/ErigonService.int.js +++ b/launcher/src/backend/tests/integration/ErigonService.int.js @@ -11,16 +11,14 @@ jest.setTimeout(500000); test("erigon installation", async () => { const testServer = new HetznerServer(); - const keyResponse = await testServer.createSSHKey("Erigon--integration-test--ubuntu-2204") + const keyResponse = await testServer.createSSHKey("Erigon--integration-test--ubuntu-2204"); const serverSettings = { name: "Erigon--integration-test--ubuntu-2204", image: "ubuntu-22.04", server_type: "cpx21", start_after_create: true, - ssh_keys: [ - keyResponse.ssh_key.id - ], + ssh_keys: [keyResponse.ssh_key.id], }; await testServer.create(serverSettings); @@ -38,7 +36,7 @@ test("erigon installation", async () => { const serviceManager = new ServiceManager(nodeConnection); await testServer.checkServerConnection(nodeConnection); - await nodeConnection.establish(taskManager) + await nodeConnection.establish(taskManager); //prepare node await nodeConnection.sshService.exec(` mkdir /etc/stereum && @@ -55,7 +53,7 @@ test("erigon installation", async () => { await nodeConnection.prepareStereumNode(nodeConnection.settings.stereum.settings.controls_install_path); //install erigon - let executionClient = serviceManager.getService("ErigonService", { network: "holesky", installDir: "/opt/stereum" }) + let executionClient = serviceManager.getService("ErigonService", { network: "holesky", installDir: "/opt/stereum" }); let versions = await nodeConnection.nodeUpdates.checkUpdates(); executionClient.imageVersion = versions[executionClient.network][executionClient.service].slice(-1).pop(); @@ -85,7 +83,7 @@ test("erigon installation", async () => { const docker = await nodeConnection.sshService.exec("docker ps"); // destroy - await testServer.finishTestGracefully(nodeConnection) + await testServer.finishTestGracefully(nodeConnection); //check ufw expect(ufw.stdout).toMatch(/30303\/tcp/); diff --git a/launcher/src/backend/tests/integration/FlashbotsMevBoostService.int.js b/launcher/src/backend/tests/integration/FlashbotsMevBoostService.int.js index 49514568b..8a5b9b15c 100755 --- a/launcher/src/backend/tests/integration/FlashbotsMevBoostService.int.js +++ b/launcher/src/backend/tests/integration/FlashbotsMevBoostService.int.js @@ -11,16 +11,14 @@ jest.setTimeout(600000); test("mevboost installation", async () => { const testServer = new HetznerServer(); - const keyResponse = await testServer.createSSHKey("Mevboost--integration-test--ubuntu-2204") + const keyResponse = await testServer.createSSHKey("Mevboost--integration-test--ubuntu-2204"); const serverSettings = { name: "Mevboost--integration-test--ubuntu-2204", image: "ubuntu-22.04", server_type: "cpx21", start_after_create: true, - ssh_keys: [ - keyResponse.ssh_key.id - ], + ssh_keys: [keyResponse.ssh_key.id], }; await testServer.create(serverSettings); @@ -38,7 +36,7 @@ test("mevboost installation", async () => { const serviceManager = new ServiceManager(nodeConnection); await testServer.checkServerConnection(nodeConnection); - await nodeConnection.establish(taskManager) + await nodeConnection.establish(taskManager); //prepare node await nodeConnection.sshService.exec(` mkdir /etc/stereum && @@ -55,7 +53,11 @@ test("mevboost installation", async () => { await nodeConnection.prepareStereumNode(nodeConnection.settings.stereum.settings.controls_install_path); //install mevboost - let mevboost = serviceManager.getService("FlashbotsMevBoostService", { network: "holesky", relays: "https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-holesky.flashbots.net" }) + let mevboost = serviceManager.getService("FlashbotsMevBoostService", { + network: "holesky", + relays: + "https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-holesky.flashbots.net", + }); let versions = await nodeConnection.nodeUpdates.checkUpdates(); mevboost.imageVersion = versions[mevboost.network][mevboost.service].slice(-1).pop(); @@ -82,7 +84,7 @@ test("mevboost installation", async () => { const docker = await nodeConnection.sshService.exec("docker ps"); // destroy - await testServer.finishTestGracefully(nodeConnection) + await testServer.finishTestGracefully(nodeConnection); //check docker container expect(docker.stdout).toMatch(/flashbots\/mev-boost/); diff --git a/launcher/src/backend/tests/integration/GethService.int.js b/launcher/src/backend/tests/integration/GethService.int.js index 9321452ca..36d2fb12c 100755 --- a/launcher/src/backend/tests/integration/GethService.int.js +++ b/launcher/src/backend/tests/integration/GethService.int.js @@ -11,16 +11,14 @@ jest.setTimeout(500000); test("geth installation", async () => { const testServer = new HetznerServer(); - const keyResponse = await testServer.createSSHKey("Geth--integration-test--ubuntu-2204") + const keyResponse = await testServer.createSSHKey("Geth--integration-test--ubuntu-2204"); const serverSettings = { name: "Geth--integration-test--ubuntu-2204", image: "ubuntu-22.04", server_type: "cpx21", start_after_create: true, - ssh_keys: [ - keyResponse.ssh_key.id - ], + ssh_keys: [keyResponse.ssh_key.id], }; await testServer.create(serverSettings); @@ -38,7 +36,7 @@ test("geth installation", async () => { const serviceManager = new ServiceManager(nodeConnection); await testServer.checkServerConnection(nodeConnection); - await nodeConnection.establish(taskManager) + await nodeConnection.establish(taskManager); //prepare node await nodeConnection.sshService.exec(` mkdir /etc/stereum && @@ -55,7 +53,7 @@ test("geth installation", async () => { await nodeConnection.prepareStereumNode(nodeConnection.settings.stereum.settings.controls_install_path); //install geth - let executionClient = serviceManager.getService("GethService", { network: "holesky", installDir: "/opt/stereum" }) + let executionClient = serviceManager.getService("GethService", { network: "holesky", installDir: "/opt/stereum" }); let versions = await nodeConnection.nodeUpdates.checkUpdates(); executionClient.imageVersion = versions[executionClient.network][executionClient.service].slice(-1).pop(); @@ -86,7 +84,7 @@ test("geth installation", async () => { const docker = await nodeConnection.sshService.exec("docker ps"); // destroy - await testServer.finishTestGracefully(nodeConnection) + await testServer.finishTestGracefully(nodeConnection); //check ufw expect(ufw.stdout).toMatch(/30303\/tcp/); @@ -107,5 +105,4 @@ test("geth installation", async () => { expect(status.stderr).toMatch(/Loaded JWT secret file/); expect(status.stderr).toMatch(/Looking for peers/); expect(status.stderr).toMatch(/HTTP server started/); - }); diff --git a/launcher/src/backend/tests/integration/LighthouseBeaconService.int.js b/launcher/src/backend/tests/integration/LighthouseBeaconService.int.js index 0814a8da9..f0b743498 100755 --- a/launcher/src/backend/tests/integration/LighthouseBeaconService.int.js +++ b/launcher/src/backend/tests/integration/LighthouseBeaconService.int.js @@ -12,16 +12,14 @@ jest.setTimeout(1000000); test("lighthouse validator import", async () => { const testServer = new HetznerServer(); - const keyResponse = await testServer.createSSHKey("Lighthouse--integration-test--ubuntu-2204") + const keyResponse = await testServer.createSSHKey("Lighthouse--integration-test--ubuntu-2204"); const serverSettings = { name: "Lighthouse--integration-test--ubuntu-2204", image: "ubuntu-22.04", server_type: "cpx31", start_after_create: true, - ssh_keys: [ - keyResponse.ssh_key.id - ], + ssh_keys: [keyResponse.ssh_key.id], }; await testServer.create(serverSettings); @@ -39,7 +37,7 @@ test("lighthouse validator import", async () => { const serviceManager = new ServiceManager(nodeConnection); await testServer.checkServerConnection(nodeConnection); - await nodeConnection.establish(taskManager) + await nodeConnection.establish(taskManager); //prepare node await nodeConnection.sshService.exec(` mkdir /etc/stereum && @@ -55,22 +53,27 @@ test("lighthouse validator import", async () => { await nodeConnection.findStereumSettings(); await nodeConnection.prepareStereumNode(nodeConnection.settings.stereum.settings.controls_install_path); - let geth = serviceManager.getService("GethService", { network: "holesky", installDir: "/opt/stereum" }) - + let geth = serviceManager.getService("GethService", { network: "holesky", installDir: "/opt/stereum" }); - let lhBC = serviceManager.getService("LighthouseBeaconService", { network: "holesky", installDir: "/opt/stereum", executionClients: [geth] }) + let lhBC = serviceManager.getService("LighthouseBeaconService", { + network: "holesky", + installDir: "/opt/stereum", + executionClients: [geth], + }); - - let lhVC = serviceManager.getService("LighthouseValidatorService", { network: "holesky", installDir: "/opt/stereum", consensusClients: [lhBC] }) + let lhVC = serviceManager.getService("LighthouseValidatorService", { + network: "holesky", + installDir: "/opt/stereum", + consensusClients: [lhBC], + }); //get latest versions let versions = await nodeConnection.nodeUpdates.checkUpdates(); geth.imageVersion = versions[geth.network][geth.service].slice(-1).pop(); - lhBC.imageVersion = versions[lhBC.network][lhBC.service].slice(-1).pop() - lhVC.imageVersion = versions[lhVC.network][lhVC.service].slice(-1).pop() + lhBC.imageVersion = versions[lhBC.network][lhBC.service].slice(-1).pop(); + lhVC.imageVersion = versions[lhVC.network][lhVC.service].slice(-1).pop(); - await nodeConnection.writeServiceConfiguration(geth.buildConfiguration()), - await serviceManager.manageServiceState(geth.id, "started"); + await nodeConnection.writeServiceConfiguration(geth.buildConfiguration()), await serviceManager.manageServiceState(geth.id, "started"); //write configs for lighhouse BC and VC await nodeConnection.writeServiceConfiguration(lhBC.buildConfiguration()); @@ -92,7 +95,7 @@ test("lighthouse validator import", async () => { '{"crypto": {"kdf": {"function": "scrypt", "params": {"dklen": 32, "n": 262144, "r": 8, "p": 1, "salt": "de4b32f49572c01146afb11a82c326fdc03be6cf447983daf9eb7ec0f868a116"}, "message": ""}, "checksum": {"function": "sha256", "params": {}, "message": "fa52987837af01ec48e2b21f2078acef3368983943751013758052e07dae841d"}, "cipher": {"function": "aes-128-ctr", "params": {"iv": "a24857026939492f49444679544cb6bb"}, "message": "8c055c8c504cd3ad20bcb1101431b2b1a506b1a4d0efdbd294d75c39c0f2268b"}}, "description": "", "pubkey": "948f092cb5b5cae121fdc14af0e4e5a90d03ab661266b700ded1c1ca4fd6f0a76f8dac187815409197bf036675571458", "path": "m/12381/3600/2/0/0", "uuid": "c7521eed-533a-4fd1-90b7-ad1aa0f24a2d", "version": 4}', ], passwords: ["MyTestPassword", "MyTestPassword", "MyTestPassword"], - }) + }); await validatorAccountManager.importKey(lhVC.id); //get logs @@ -127,12 +130,10 @@ test("lighthouse validator import", async () => { const ufw = await nodeConnection.sshService.exec("ufw status"); const docker = await nodeConnection.sshService.exec("docker ps"); - const api_token = await nodeConnection.sshService.exec( - `cat /opt/stereum/lighthouse-${lhVC.id}/validator/validators/api-token.txt` - ); + const api_token = await nodeConnection.sshService.exec(`cat /opt/stereum/lighthouse-${lhVC.id}/validator/validators/api-token.txt`); // destroy - await testServer.finishTestGracefully(nodeConnection) + await testServer.finishTestGracefully(nodeConnection); //check ufw expect(ufw.stdout).toMatch(/9000\/tcp/); @@ -169,5 +170,4 @@ test("lighthouse validator import", async () => { expect(VCstatus.stderr).toMatch(/HTTP API started/); expect(VCstatus.stderr).toMatch(/Importing keystores via standard HTTP API, count: 3/); expect(VCstatus.stderr).toMatch(/Enabled validator/); - }); diff --git a/launcher/src/backend/tests/integration/LodestarBeaconService.int.js b/launcher/src/backend/tests/integration/LodestarBeaconService.int.js index 4bced3d6f..95fab45a9 100755 --- a/launcher/src/backend/tests/integration/LodestarBeaconService.int.js +++ b/launcher/src/backend/tests/integration/LodestarBeaconService.int.js @@ -13,16 +13,14 @@ jest.setTimeout(1000000); test("lodestar validator import", async () => { //create server const testServer = new HetznerServer(); - const keyResponse = await testServer.createSSHKey("Lodestar--integration-test--ubuntu-2204") + const keyResponse = await testServer.createSSHKey("Lodestar--integration-test--ubuntu-2204"); const serverSettings = { name: "Lodestar--integration-test--ubuntu-2204", image: "ubuntu-22.04", server_type: "cpx31", start_after_create: true, - ssh_keys: [ - keyResponse.ssh_key.id - ], + ssh_keys: [keyResponse.ssh_key.id], }; await testServer.create(serverSettings); @@ -40,7 +38,7 @@ test("lodestar validator import", async () => { const serviceManager = new ServiceManager(nodeConnection); await testServer.checkServerConnection(nodeConnection); - await nodeConnection.establish(taskManager) + await nodeConnection.establish(taskManager); //prepare node await nodeConnection.sshService.exec(` mkdir /etc/stereum && @@ -56,20 +54,27 @@ test("lodestar validator import", async () => { await nodeConnection.findStereumSettings(); await nodeConnection.prepareStereumNode(nodeConnection.settings.stereum.settings.controls_install_path); - let geth = serviceManager.getService("GethService", { network: "holesky", installDir: "/opt/stereum" }) + let geth = serviceManager.getService("GethService", { network: "holesky", installDir: "/opt/stereum" }); - let lBC = serviceManager.getService("LodestarBeaconService", { network: "holesky", installDir: "/opt/stereum", executionClients: [geth] }); + let lBC = serviceManager.getService("LodestarBeaconService", { + network: "holesky", + installDir: "/opt/stereum", + executionClients: [geth], + }); - let lVC = serviceManager.getService("LodestarValidatorService", { network: "holesky", installDir: "/opt/stereum", consensusClients: [lBC] }); + let lVC = serviceManager.getService("LodestarValidatorService", { + network: "holesky", + installDir: "/opt/stereum", + consensusClients: [lBC], + }); //get latest versions let versions = await nodeConnection.nodeUpdates.checkUpdates(); geth.imageVersion = versions[geth.network][geth.service].slice(-1).pop(); - lBC.imageVersion = versions[lBC.network][lBC.service].slice(-1).pop() - lVC.imageVersion = versions[lVC.network][lVC.service].slice(-1).pop() + lBC.imageVersion = versions[lBC.network][lBC.service].slice(-1).pop(); + lVC.imageVersion = versions[lVC.network][lVC.service].slice(-1).pop(); - await nodeConnection.writeServiceConfiguration(geth.buildConfiguration()), - await serviceManager.manageServiceState(geth.id, "started"); + await nodeConnection.writeServiceConfiguration(geth.buildConfiguration()), await serviceManager.manageServiceState(geth.id, "started"); //write configs for lodestar BC and VC await nodeConnection.writeServiceConfiguration(lBC.buildConfiguration()); @@ -91,7 +96,7 @@ test("lodestar validator import", async () => { '{"crypto": {"kdf": {"function": "scrypt", "params": {"dklen": 32, "n": 262144, "r": 8, "p": 1, "salt": "de4b32f49572c01146afb11a82c326fdc03be6cf447983daf9eb7ec0f868a116"}, "message": ""}, "checksum": {"function": "sha256", "params": {}, "message": "fa52987837af01ec48e2b21f2078acef3368983943751013758052e07dae841d"}, "cipher": {"function": "aes-128-ctr", "params": {"iv": "a24857026939492f49444679544cb6bb"}, "message": "8c055c8c504cd3ad20bcb1101431b2b1a506b1a4d0efdbd294d75c39c0f2268b"}}, "description": "", "pubkey": "948f092cb5b5cae121fdc14af0e4e5a90d03ab661266b700ded1c1ca4fd6f0a76f8dac187815409197bf036675571458", "path": "m/12381/3600/2/0/0", "uuid": "c7521eed-533a-4fd1-90b7-ad1aa0f24a2d", "version": 4}', ], passwords: ["MyTestPassword", "MyTestPassword", "MyTestPassword"], - }) + }); await validatorAccountManager.importKey(lVC.id); //get logs @@ -119,12 +124,10 @@ test("lodestar validator import", async () => { const ufw = await nodeConnection.sshService.exec("ufw status"); const docker = await nodeConnection.sshService.exec("docker ps"); - const api_token = await nodeConnection.sshService.exec( - `cat /opt/stereum/lodestar-${lVC.id}/validator/validator-db/api-token.txt` - ); + const api_token = await nodeConnection.sshService.exec(`cat /opt/stereum/lodestar-${lVC.id}/validator/validator-db/api-token.txt`); // destroy - await testServer.finishTestGracefully(nodeConnection) + await testServer.finishTestGracefully(nodeConnection); //check ufw expect(ufw.stdout).toMatch(/30303\/tcp/); diff --git a/launcher/src/backend/tests/integration/NethermindService.int.js b/launcher/src/backend/tests/integration/NethermindService.int.js index a1b1bdbce..b5bb170c9 100755 --- a/launcher/src/backend/tests/integration/NethermindService.int.js +++ b/launcher/src/backend/tests/integration/NethermindService.int.js @@ -11,16 +11,14 @@ jest.setTimeout(500000); test("nethermind installationm", async () => { const testServer = new HetznerServer(); - const keyResponse = await testServer.createSSHKey("Nethermind--integration-test--ubuntu-2204") + const keyResponse = await testServer.createSSHKey("Nethermind--integration-test--ubuntu-2204"); const serverSettings = { name: "Nethermind--integration-test--ubuntu-2204", image: "ubuntu-22.04", server_type: "cpx21", start_after_create: true, - ssh_keys: [ - keyResponse.ssh_key.id - ], + ssh_keys: [keyResponse.ssh_key.id], }; await testServer.create(serverSettings); @@ -38,7 +36,7 @@ test("nethermind installationm", async () => { const serviceManager = new ServiceManager(nodeConnection); await testServer.checkServerConnection(nodeConnection); - await nodeConnection.establish(taskManager) + await nodeConnection.establish(taskManager); //prepare node await nodeConnection.sshService.exec(` mkdir /etc/stereum && @@ -55,7 +53,7 @@ test("nethermind installationm", async () => { await nodeConnection.prepareStereumNode(nodeConnection.settings.stereum.settings.controls_install_path); //install nethermind - let executionClient = serviceManager.getService("NethermindService", { network: "holesky", installDir: "/opt/stereum" }) + let executionClient = serviceManager.getService("NethermindService", { network: "holesky", installDir: "/opt/stereum" }); let versions = await nodeConnection.nodeUpdates.checkUpdates(); executionClient.imageVersion = versions[executionClient.network][executionClient.service].slice(-1).pop(); @@ -84,7 +82,7 @@ test("nethermind installationm", async () => { const docker = await nodeConnection.sshService.exec("docker ps"); // destroy - await testServer.finishTestGracefully(nodeConnection) + await testServer.finishTestGracefully(nodeConnection); //check ufw expect(ufw.stdout).toMatch(/30303\/tcp/); diff --git a/launcher/src/backend/tests/integration/NimbusBeaconService.int.js b/launcher/src/backend/tests/integration/NimbusBeaconService.int.js index 7fc092803..514ea73a7 100755 --- a/launcher/src/backend/tests/integration/NimbusBeaconService.int.js +++ b/launcher/src/backend/tests/integration/NimbusBeaconService.int.js @@ -13,16 +13,14 @@ jest.setTimeout(1000000); test("nimbus validator import", async () => { //create server const testServer = new HetznerServer(); - const keyResponse = await testServer.createSSHKey("Nimbus--integration-test--ubuntu-2204") + const keyResponse = await testServer.createSSHKey("Nimbus--integration-test--ubuntu-2204"); const serverSettings = { name: "Nimbus--integration-test--ubuntu-2204", image: "ubuntu-22.04", server_type: "cpx31", start_after_create: true, - ssh_keys: [ - keyResponse.ssh_key.id - ], + ssh_keys: [keyResponse.ssh_key.id], }; await testServer.create(serverSettings); @@ -40,7 +38,7 @@ test("nimbus validator import", async () => { const serviceManager = new ServiceManager(nodeConnection); await testServer.checkServerConnection(nodeConnection); - await nodeConnection.establish(taskManager) + await nodeConnection.establish(taskManager); //prepare node await nodeConnection.sshService.exec(` mkdir /etc/stereum && @@ -57,18 +55,25 @@ test("nimbus validator import", async () => { await nodeConnection.prepareStereumNode(nodeConnection.settings.stereum.settings.controls_install_path); //install geth - let geth = serviceManager.getService("GethService", { network: "holesky", installDir: "/opt/stereum" }) + let geth = serviceManager.getService("GethService", { network: "holesky", installDir: "/opt/stereum" }); //install nimbus - let nimbusBC = serviceManager.getService("NimbusBeaconService", { network: "holesky", installDir: "/opt/stereum", executionClients: [geth] }) - - let nimbusVC = serviceManager.getService("NimbusValidatorService", { network: "holesky", installDir: "/opt/stereum", consensusClients: [nimbusBC] }) + let nimbusBC = serviceManager.getService("NimbusBeaconService", { + network: "holesky", + installDir: "/opt/stereum", + executionClients: [geth], + }); + + let nimbusVC = serviceManager.getService("NimbusValidatorService", { + network: "holesky", + installDir: "/opt/stereum", + consensusClients: [nimbusBC], + }); let versions = await nodeConnection.nodeUpdates.checkUpdates(); geth.imageVersion = versions[geth.network][geth.service].slice(-1).pop(); - nimbusBC.imageVersion = versions[nimbusBC.network][nimbusBC.service].slice(-1).pop() - nimbusVC.imageVersion = versions[nimbusVC.network][nimbusVC.service].slice(-1).pop() - + nimbusBC.imageVersion = versions[nimbusBC.network][nimbusBC.service].slice(-1).pop(); + nimbusVC.imageVersion = versions[nimbusVC.network][nimbusVC.service].slice(-1).pop(); //write config and start geth await nodeConnection.writeServiceConfiguration(geth.buildConfiguration()); @@ -92,7 +97,7 @@ test("nimbus validator import", async () => { '{"crypto": {"kdf": {"function": "scrypt", "params": {"dklen": 32, "n": 262144, "r": 8, "p": 1, "salt": "de4b32f49572c01146afb11a82c326fdc03be6cf447983daf9eb7ec0f868a116"}, "message": ""}, "checksum": {"function": "sha256", "params": {}, "message": "fa52987837af01ec48e2b21f2078acef3368983943751013758052e07dae841d"}, "cipher": {"function": "aes-128-ctr", "params": {"iv": "a24857026939492f49444679544cb6bb"}, "message": "8c055c8c504cd3ad20bcb1101431b2b1a506b1a4d0efdbd294d75c39c0f2268b"}}, "description": "", "pubkey": "948f092cb5b5cae121fdc14af0e4e5a90d03ab661266b700ded1c1ca4fd6f0a76f8dac187815409197bf036675571458", "path": "m/12381/3600/2/0/0", "uuid": "c7521eed-533a-4fd1-90b7-ad1aa0f24a2d", "version": 4}', ], passwords: ["MyTestPassword", "MyTestPassword", "MyTestPassword"], - }) + }); await validatorAccountManager.importKey(nimbusVC.id); //get logs @@ -123,7 +128,7 @@ test("nimbus validator import", async () => { const docker = await nodeConnection.sshService.exec("docker ps"); // destroy - await testServer.finishTestGracefully(nodeConnection) + await testServer.finishTestGracefully(nodeConnection); //check ufw expect(ufw.stdout).toMatch(/9000\/tcp/); @@ -150,5 +155,4 @@ test("nimbus validator import", async () => { expect(VCstatus.stdout).toMatch(/Local validator attached/); expect(VCstatus.stdout).toMatch(/REST service started/); expect(VCstatus.stdout).toMatch(/Slot start/); - }); diff --git a/launcher/src/backend/tests/integration/NodeConnection.int.js b/launcher/src/backend/tests/integration/NodeConnection.int.js index c6a188bec..2d044437c 100755 --- a/launcher/src/backend/tests/integration/NodeConnection.int.js +++ b/launcher/src/backend/tests/integration/NodeConnection.int.js @@ -11,16 +11,14 @@ jest.setTimeout(500000); test("prepareStereumNode on ubuntu", async () => { const testServer = new HetznerServer(); - const keyResponse = await testServer.createSSHKey("NodeConnection--integration-test--ubuntu-2204") + const keyResponse = await testServer.createSSHKey("NodeConnection--integration-test--ubuntu-2204"); const serverSettings = { name: "NodeConnection--integration-test--ubuntu-2204", image: "ubuntu-22.04", server_type: "cpx21", start_after_create: true, - ssh_keys: [ - keyResponse.ssh_key.id - ], + ssh_keys: [keyResponse.ssh_key.id], }; await testServer.create(serverSettings); @@ -37,8 +35,7 @@ test("prepareStereumNode on ubuntu", async () => { const taskManager = new TaskManager(nodeConnection); await testServer.checkServerConnection(nodeConnection); - await nodeConnection.establish(taskManager) - + await nodeConnection.establish(taskManager); await nodeConnection.findOS(); @@ -58,7 +55,7 @@ test("prepareStereumNode on ubuntu", async () => { const ansibleRoles = await nodeConnection.sshService.exec("ls /opt/stereum/ansible/controls"); const ansibleVersion = await nodeConnection.sshService.exec("ansible --version"); - await testServer.finishTestGracefully(nodeConnection) + await testServer.finishTestGracefully(nodeConnection); const ansible = ansibleVersion.stdout.split("\n")[0].split(" "); ansible[2] = ansible[2].split("."); diff --git a/launcher/src/backend/tests/integration/PrysmBeaconService.int.js b/launcher/src/backend/tests/integration/PrysmBeaconService.int.js index 99629f04c..43bba1ebc 100755 --- a/launcher/src/backend/tests/integration/PrysmBeaconService.int.js +++ b/launcher/src/backend/tests/integration/PrysmBeaconService.int.js @@ -12,16 +12,14 @@ jest.setTimeout(1000000); test("prysm validator import", async () => { const testServer = new HetznerServer(); - const keyResponse = await testServer.createSSHKey("Prysm--integration-test--ubuntu-2204") + const keyResponse = await testServer.createSSHKey("Prysm--integration-test--ubuntu-2204"); const serverSettings = { name: "Prysm--integration-test--ubuntu-2204", image: "ubuntu-22.04", server_type: "cpx31", start_after_create: true, - ssh_keys: [ - keyResponse.ssh_key.id - ], + ssh_keys: [keyResponse.ssh_key.id], }; await testServer.create(serverSettings); @@ -39,7 +37,7 @@ test("prysm validator import", async () => { const serviceManager = new ServiceManager(nodeConnection); await testServer.checkServerConnection(nodeConnection); - await nodeConnection.establish(taskManager) + await nodeConnection.establish(taskManager); //prepare node // create stereum settings @@ -56,18 +54,25 @@ test("prysm validator import", async () => { await nodeConnection.findStereumSettings(); await nodeConnection.prepareStereumNode(nodeConnection.settings.stereum.settings.controls_install_path); - //install geth - let geth = serviceManager.getService("GethService", { network: "holesky", installDir: "/opt/stereum" }) + let geth = serviceManager.getService("GethService", { network: "holesky", installDir: "/opt/stereum" }); - let prysmBC = serviceManager.getService("PrysmBeaconService", { network: "holesky", installDir: "/opt/stereum", executionClients: [geth] }) + let prysmBC = serviceManager.getService("PrysmBeaconService", { + network: "holesky", + installDir: "/opt/stereum", + executionClients: [geth], + }); - let prysmVC = serviceManager.getService("PrysmValidatorService", { network: "holesky", installDir: "/opt/stereum", consensusClients: [prysmBC] }) + let prysmVC = serviceManager.getService("PrysmValidatorService", { + network: "holesky", + installDir: "/opt/stereum", + consensusClients: [prysmBC], + }); let versions = await nodeConnection.nodeUpdates.checkUpdates(); geth.imageVersion = versions[geth.network][geth.service].slice(-1).pop(); - prysmBC.imageVersion = versions[prysmBC.network][prysmBC.service].slice(-1).pop() - prysmVC.imageVersion = versions[prysmVC.network][prysmVC.service].slice(-1).pop() + prysmBC.imageVersion = versions[prysmBC.network][prysmBC.service].slice(-1).pop(); + prysmVC.imageVersion = versions[prysmVC.network][prysmVC.service].slice(-1).pop(); //write config and start geth await nodeConnection.writeServiceConfiguration(geth.buildConfiguration()); @@ -91,18 +96,12 @@ test("prysm validator import", async () => { '{"crypto": {"kdf": {"function": "scrypt", "params": {"dklen": 32, "n": 262144, "r": 8, "p": 1, "salt": "de4b32f49572c01146afb11a82c326fdc03be6cf447983daf9eb7ec0f868a116"}, "message": ""}, "checksum": {"function": "sha256", "params": {}, "message": "fa52987837af01ec48e2b21f2078acef3368983943751013758052e07dae841d"}, "cipher": {"function": "aes-128-ctr", "params": {"iv": "a24857026939492f49444679544cb6bb"}, "message": "8c055c8c504cd3ad20bcb1101431b2b1a506b1a4d0efdbd294d75c39c0f2268b"}}, "description": "", "pubkey": "948f092cb5b5cae121fdc14af0e4e5a90d03ab661266b700ded1c1ca4fd6f0a76f8dac187815409197bf036675571458", "path": "m/12381/3600/2/0/0", "uuid": "c7521eed-533a-4fd1-90b7-ad1aa0f24a2d", "version": 4}', ], passwords: ["MyTestPassword", "MyTestPassword", "MyTestPassword"], - }) + }); await validatorAccountManager.importKey(prysmVC.id); - await Promise.all([ - serviceManager.manageServiceState(prysmBC.id, "stopped"), - serviceManager.manageServiceState(prysmVC.id, "stopped"), - ]); + await Promise.all([serviceManager.manageServiceState(prysmBC.id, "stopped"), serviceManager.manageServiceState(prysmVC.id, "stopped")]); - await Promise.all([ - serviceManager.manageServiceState(prysmBC.id, "started"), - serviceManager.manageServiceState(prysmVC.id, "started"), - ]); + await Promise.all([serviceManager.manageServiceState(prysmBC.id, "started"), serviceManager.manageServiceState(prysmVC.id, "started")]); //get logs let condition = false; @@ -140,20 +139,18 @@ test("prysm validator import", async () => { log.debug(passwords_path); const ufw = await nodeConnection.sshService.exec("ufw status"); - const validatorAccounts = await nodeConnection.sshService.exec( - `cat ${wallet_path}/direct/accounts/all-accounts.keystore.json` - ); + const validatorAccounts = await nodeConnection.sshService.exec(`cat ${wallet_path}/direct/accounts/all-accounts.keystore.json`); const auth_token = await nodeConnection.sshService.exec(`cat ${wallet_path}/auth-token`); const docker = await nodeConnection.sshService.exec("docker ps"); let responseValidator = await nodeConnection.sshService.exec( "docker exec stereum-" + - prysmVC.id + - " /app/cmd/validator/validator accounts list --wallet-dir=/opt/app/data/wallets --wallet-password-file=/opt/app/data/passwords/wallet-password --accept-terms-of-use" + prysmVC.id + + " /app/cmd/validator/validator accounts list --wallet-dir=/opt/app/data/wallets --wallet-password-file=/opt/app/data/passwords/wallet-password --accept-terms-of-use" ); const runningValidator = responseValidator.stdout.replace("\x1B[93m3\x1B[0m", "3"); //remove yellow color coding // destroy - await testServer.finishTestGracefully(nodeConnection) + await testServer.finishTestGracefully(nodeConnection); //check ufw expect(ufw.stdout).toMatch(/13001\/tcp/); diff --git a/launcher/src/backend/tests/integration/TekuBeaconService.int.js b/launcher/src/backend/tests/integration/TekuBeaconService.int.js index ad76e50bb..31d76c22a 100755 --- a/launcher/src/backend/tests/integration/TekuBeaconService.int.js +++ b/launcher/src/backend/tests/integration/TekuBeaconService.int.js @@ -12,16 +12,14 @@ jest.setTimeout(1000000); test("teku validator import", async () => { const testServer = new HetznerServer(); - const keyResponse = await testServer.createSSHKey("Teku--integration-test--ubuntu-2204") + const keyResponse = await testServer.createSSHKey("Teku--integration-test--ubuntu-2204"); const serverSettings = { name: "Teku--integration-test--ubuntu-2204", image: "ubuntu-22.04", server_type: "cpx31", start_after_create: true, - ssh_keys: [ - keyResponse.ssh_key.id - ], + ssh_keys: [keyResponse.ssh_key.id], }; await testServer.create(serverSettings); @@ -39,7 +37,7 @@ test("teku validator import", async () => { const serviceManager = new ServiceManager(nodeConnection); await testServer.checkServerConnection(nodeConnection); - await nodeConnection.establish(taskManager) + await nodeConnection.establish(taskManager); //prepare node await nodeConnection.sshService.exec(` mkdir /etc/stereum && @@ -55,20 +53,23 @@ test("teku validator import", async () => { await nodeConnection.findStereumSettings(); await nodeConnection.prepareStereumNode(nodeConnection.settings.stereum.settings.controls_install_path); - //install geth - let geth = serviceManager.getService("GethService", { network: "holesky", installDir: "/opt/stereum" }) + let geth = serviceManager.getService("GethService", { network: "holesky", installDir: "/opt/stereum" }); //install tekuBC - let tekuBC = serviceManager.getService("TekuBeaconService", { network: "holesky", installDir: "/opt/stereum", executionClients: [geth] }) + let tekuBC = serviceManager.getService("TekuBeaconService", { network: "holesky", installDir: "/opt/stereum", executionClients: [geth] }); //install tekuVC - let tekuVC = serviceManager.getService("TekuValidatorService", { network: "holesky", installDir: "/opt/stereum", consensusClients: [tekuBC] }) + let tekuVC = serviceManager.getService("TekuValidatorService", { + network: "holesky", + installDir: "/opt/stereum", + consensusClients: [tekuBC], + }); let versions = await nodeConnection.nodeUpdates.checkUpdates(); geth.imageVersion = versions[geth.network][geth.service].slice(-1).pop(); - tekuBC.imageVersion = versions[tekuBC.network][tekuBC.service].slice(-1).pop() - tekuVC.imageVersion = versions[tekuVC.network][tekuVC.service].slice(-1).pop() + tekuBC.imageVersion = versions[tekuBC.network][tekuBC.service].slice(-1).pop(); + tekuVC.imageVersion = versions[tekuVC.network][tekuVC.service].slice(-1).pop(); //write config and start geth await nodeConnection.writeServiceConfiguration(geth.buildConfiguration()); @@ -92,7 +93,7 @@ test("teku validator import", async () => { '{"crypto": {"kdf": {"function": "scrypt", "params": {"dklen": 32, "n": 262144, "r": 8, "p": 1, "salt": "de4b32f49572c01146afb11a82c326fdc03be6cf447983daf9eb7ec0f868a116"}, "message": ""}, "checksum": {"function": "sha256", "params": {}, "message": "fa52987837af01ec48e2b21f2078acef3368983943751013758052e07dae841d"}, "cipher": {"function": "aes-128-ctr", "params": {"iv": "a24857026939492f49444679544cb6bb"}, "message": "8c055c8c504cd3ad20bcb1101431b2b1a506b1a4d0efdbd294d75c39c0f2268b"}}, "description": "", "pubkey": "948f092cb5b5cae121fdc14af0e4e5a90d03ab661266b700ded1c1ca4fd6f0a76f8dac187815409197bf036675571458", "path": "m/12381/3600/2/0/0", "uuid": "c7521eed-533a-4fd1-90b7-ad1aa0f24a2d", "version": 4}', ], passwords: ["MyTestPassword", "MyTestPassword", "MyTestPassword"], - }) + }); await validatorAccountManager.importKey(tekuVC.id); //get logs @@ -130,12 +131,10 @@ test("teku validator import", async () => { const docker = await nodeConnection.sshService.exec("docker ps"); const teku_api_keystore = await nodeConnection.sshService.exec(`cat ${dataDir}/teku_api_keystore`); const teku_api_password = await nodeConnection.sshService.exec(`cat ${dataDir}/teku_api_password.txt`); - const validator_api_bearer = await nodeConnection.sshService.exec( - `cat ${dataDir}/validator/key-manager/validator-api-bearer` - ); + const validator_api_bearer = await nodeConnection.sshService.exec(`cat ${dataDir}/validator/key-manager/validator-api-bearer`); // destroy - await testServer.finishTestGracefully(nodeConnection) + await testServer.finishTestGracefully(nodeConnection); //check ufw expect(ufw.stdout).toMatch(/9001\/tcp/); @@ -161,8 +160,6 @@ test("teku validator import", async () => { expect(VCstatus.stdout).toMatch(/Successfully connected to beacon node event stream/); expect(VCstatus.stdout).toMatch(/Starting doppelganger detection for public keys: .{7}, .{7}, .{7}/); - - //check docker container expect(docker.stdout).toMatch(/consensys\/teku/); expect(docker.stdout).toMatch(/5051-5052->5051-5052/); diff --git a/launcher/src/backend/tests/unit/BesuService.test.js b/launcher/src/backend/tests/unit/BesuService.test.js index 0b44540c9..dec4cb66b 100755 --- a/launcher/src/backend/tests/unit/BesuService.test.js +++ b/launcher/src/backend/tests/unit/BesuService.test.js @@ -22,37 +22,23 @@ test("buildByUserInput", () => { }); test("buildExecutionClientHttpEndpointUrl", () => { - const besuHttpEndpoint = BesuService.buildByUserInput( - "goerli", - [], - "/opt/stereum/besu" - ).buildExecutionClientHttpEndpointUrl(); + const besuHttpEndpoint = BesuService.buildByUserInput("goerli", [], "/opt/stereum/besu").buildExecutionClientHttpEndpointUrl(); expect(besuHttpEndpoint).toMatch(/http:\/\/stereum-.{36}:8545/); }); test("buildExecutionClientWsEndpointUrl", () => { - const besuWsEndpoint = BesuService.buildByUserInput( - "goerli", - [], - "/opt/stereum/besu" - ).buildExecutionClientWsEndpointUrl(); + const besuWsEndpoint = BesuService.buildByUserInput("goerli", [], "/opt/stereum/besu").buildExecutionClientWsEndpointUrl(); expect(besuWsEndpoint).toMatch(/ws:\/\/stereum-.{36}:8546/); }); test("buildExecutionClientMetricsEndpoint", () => { - const besuMetricsEndpoint = BesuService.buildByUserInput( - "goerli", - [], - "/opt/stereum/besu" - ).buildExecutionClientMetricsEndpoint(); + const besuMetricsEndpoint = BesuService.buildByUserInput("goerli", [], "/opt/stereum/besu").buildExecutionClientMetricsEndpoint(); expect(besuMetricsEndpoint).toMatch(/stereum-.{36}:9545/); }); test("buildPrometheusJob", () => { const besuPrometheusJob = BesuService.buildByUserInput("goerli", [], "/opt/stereum/besu").buildPrometheusJob(); - expect(besuPrometheusJob).toMatch( - /\n {2}- job_name: stereum-.{36}\n {4}static_configs:\n {6}- targets: \[stereum-.{36}:9545]/ - ); + expect(besuPrometheusJob).toMatch(/\n {2}- job_name: stereum-.{36}\n {4}static_configs:\n {6}- targets: \[stereum-.{36}:9545]/); }); test("buildByConfiguration", () => { diff --git a/launcher/src/backend/tests/unit/ErigonService.test.js b/launcher/src/backend/tests/unit/ErigonService.test.js index 59136aa4e..0e83d235a 100755 --- a/launcher/src/backend/tests/unit/ErigonService.test.js +++ b/launcher/src/backend/tests/unit/ErigonService.test.js @@ -6,15 +6,11 @@ test("id test", () => { }); test("network test goerli", () => { - expect(ErigonService.buildByUserInput("goerli", null, null).buildConfiguration().command).toContain( - "--chain=goerli" - ); + expect(ErigonService.buildByUserInput("goerli", null, null).buildConfiguration().command).toContain("--chain=goerli"); }); test("network test mainnet", () => { - expect(ErigonService.buildByUserInput("mainnet", null, null).buildConfiguration().command).not.toContain( - "--chain=goerli" - ); + expect(ErigonService.buildByUserInput("mainnet", null, null).buildConfiguration().command).not.toContain("--chain=goerli"); }); test("user", () => { @@ -22,9 +18,7 @@ test("user", () => { }); test("image", () => { - expect(ErigonService.buildByUserInput("mainnet", null, null).buildConfiguration().image).toMatch( - /thorax\/erigon/ - ); + expect(ErigonService.buildByUserInput("mainnet", null, null).buildConfiguration().image).toMatch(/thorax\/erigon/); }); test("endpoint url", () => { @@ -45,18 +39,10 @@ test("empty ports", () => { test("ports", () => { expect( - ErigonService.buildByUserInput( - "goerli", - [new ServicePort(null, 100, 200, servicePortProtocol.tcp)], - null - ).buildConfiguration().ports + ErigonService.buildByUserInput("goerli", [new ServicePort(null, 100, 200, servicePortProtocol.tcp)], null).buildConfiguration().ports ).toHaveLength(1); expect( - ErigonService.buildByUserInput( - "goerli", - [new ServicePort(null, 100, 200, servicePortProtocol.tcp)], - null - ).buildConfiguration().ports + ErigonService.buildByUserInput("goerli", [new ServicePort(null, 100, 200, servicePortProtocol.tcp)], null).buildConfiguration().ports ).toContain("0.0.0.0:100:200/tcp"); }); @@ -76,11 +62,7 @@ test("multiple ports", () => { }); test("workingDir", () => { - const erigonConfig = ErigonService.buildByUserInput( - "goerli", - null, - "/opt/stereum/erigon" - ).buildConfiguration(); + const erigonConfig = ErigonService.buildByUserInput("goerli", null, "/opt/stereum/erigon").buildConfiguration(); expect(erigonConfig.volumes).toHaveLength(2); expect(erigonConfig.volumes).toContain("/opt/stereum/erigon-" + erigonConfig.id + "/data:/opt/data/erigon"); diff --git a/launcher/src/backend/tests/unit/GethService.test.js b/launcher/src/backend/tests/unit/GethService.test.js index 613463f2e..d57251a00 100755 --- a/launcher/src/backend/tests/unit/GethService.test.js +++ b/launcher/src/backend/tests/unit/GethService.test.js @@ -10,9 +10,7 @@ test("network test goerli", () => { }); test("network test mainnet", () => { - expect(GethService.buildByUserInput("mainnet", null, null).buildConfiguration().command).not.toContain( - "--goerli" - ); + expect(GethService.buildByUserInput("mainnet", null, null).buildConfiguration().command).not.toContain("--goerli"); }); test("user", () => { @@ -20,9 +18,7 @@ test("user", () => { }); test("image", () => { - expect(GethService.buildByUserInput("mainnet", null, null).buildConfiguration().image).toMatch( - /ethereum\/client-go/ - ); + expect(GethService.buildByUserInput("mainnet", null, null).buildConfiguration().image).toMatch(/ethereum\/client-go/); }); test("endpoint url", () => { @@ -43,18 +39,10 @@ test("empty ports", () => { test("ports", () => { expect( - GethService.buildByUserInput( - "goerli", - [new ServicePort(null, 100, 200, servicePortProtocol.tcp)], - null - ).buildConfiguration().ports + GethService.buildByUserInput("goerli", [new ServicePort(null, 100, 200, servicePortProtocol.tcp)], null).buildConfiguration().ports ).toHaveLength(1); expect( - GethService.buildByUserInput( - "goerli", - [new ServicePort(null, 100, 200, servicePortProtocol.tcp)], - null - ).buildConfiguration().ports + GethService.buildByUserInput("goerli", [new ServicePort(null, 100, 200, servicePortProtocol.tcp)], null).buildConfiguration().ports ).toContain("0.0.0.0:100:200/tcp"); }); diff --git a/launcher/src/backend/tests/unit/GrafanaService.test.js b/launcher/src/backend/tests/unit/GrafanaService.test.js index cb9eca997..c52d3f023 100755 --- a/launcher/src/backend/tests/unit/GrafanaService.test.js +++ b/launcher/src/backend/tests/unit/GrafanaService.test.js @@ -4,17 +4,10 @@ import { ServicePort, servicePortProtocol } from "../../ethereum-services/Servic test("buildConfiguration", () => { const ports = [new ServicePort("127.0.0.1", 3000, 3000, servicePortProtocol.tcp)]; - const grafanaService = GrafanaService.buildByUserInput( - "prater", - ports, - "/opt/stereum/grafana", - "nimbus" - ).buildConfiguration(); + const grafanaService = GrafanaService.buildByUserInput("prater", ports, "/opt/stereum/grafana", "nimbus").buildConfiguration(); expect(grafanaService.volumes).toHaveLength(3); - expect(grafanaService.volumes).toContain( - "/opt/stereum/grafana-" + grafanaService.id + "/provisioning:/etc/grafana/provisioning" - ); + expect(grafanaService.volumes).toContain("/opt/stereum/grafana-" + grafanaService.id + "/provisioning:/etc/grafana/provisioning"); expect(grafanaService.volumes).toContain("/opt/stereum/grafana-" + grafanaService.id + "/data:/var/lib/grafana"); expect(grafanaService.volumes).toContain("/opt/stereum/grafana-" + grafanaService.id + ":/etc/grafana"); expect(grafanaService.ports).toHaveLength(1); @@ -25,12 +18,7 @@ test("buildConfiguration", () => { }); test("getAvailablePorts", () => { - const grafanaServicePorts = GrafanaService.buildByUserInput( - "prater", - [], - "/opt/stereum/grafana", - "nimbus" - ).getAvailablePorts(); + const grafanaServicePorts = GrafanaService.buildByUserInput("prater", [], "/opt/stereum/grafana", "nimbus").getAvailablePorts(); expect(grafanaServicePorts).toHaveLength(1); }); diff --git a/launcher/src/backend/tests/unit/LighthouseBeaconService.test.js b/launcher/src/backend/tests/unit/LighthouseBeaconService.test.js index e876ff9db..f12c6cb9d 100755 --- a/launcher/src/backend/tests/unit/LighthouseBeaconService.test.js +++ b/launcher/src/backend/tests/unit/LighthouseBeaconService.test.js @@ -23,10 +23,7 @@ test("buildConfiguration", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); @@ -75,10 +72,7 @@ test("buildConsensusClientHttpEndpointUrl", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); const ports = [ @@ -113,10 +107,7 @@ test("getAvailablePorts", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); const lhServicePorts = LighthouseBeaconService.buildByUserInput( @@ -145,10 +136,7 @@ test("network", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); const lhServicePorts = LighthouseBeaconService.buildByUserInput( diff --git a/launcher/src/backend/tests/unit/LighthouseValidatorService.test.js b/launcher/src/backend/tests/unit/LighthouseValidatorService.test.js index 19bc6e3cf..ee3d5c676 100755 --- a/launcher/src/backend/tests/unit/LighthouseValidatorService.test.js +++ b/launcher/src/backend/tests/unit/LighthouseValidatorService.test.js @@ -39,39 +39,21 @@ test("LighthouseValidatorService buildConfiguration", () => { test("LighthouseValidatorService getAvailablePorts", () => { const ports = [new ServicePort("1.2.3.4", 303, 404, servicePortProtocol.udp)]; - const lhService = LighthouseValidatorService.buildByUserInput( - "prater", - ports, - "/opt/stereum/lh", - [], - "foobar" - ).getAvailablePorts(); + const lhService = LighthouseValidatorService.buildByUserInput("prater", ports, "/opt/stereum/lh", [], "foobar").getAvailablePorts(); expect(lhService).toHaveLength(1); }); test("LighthouseValidatorService autoupdate", () => { const ports = [new ServicePort("1.2.3.4", 303, 404, servicePortProtocol.udp)]; - const lhService = LighthouseValidatorService.buildByUserInput( - "prater", - ports, - "/opt/stereum/lh", - [], - "foobar" - ).buildConfiguration(); + const lhService = LighthouseValidatorService.buildByUserInput("prater", ports, "/opt/stereum/lh", [], "foobar").buildConfiguration(); expect(lhService.autoupdate).toBe(true); }); test("LighthouseValidatorService network", () => { const ports = [new ServicePort("1.2.3.4", 303, 404, servicePortProtocol.udp)]; - const lhService = LighthouseValidatorService.buildByUserInput( - "mainnet", - ports, - "/opt/stereum/lh", - [], - "foobar" - ).buildConfiguration(); + const lhService = LighthouseValidatorService.buildByUserInput("mainnet", ports, "/opt/stereum/lh", [], "foobar").buildConfiguration(); expect(lhService.network).toBe("mainnet"); }); diff --git a/launcher/src/backend/tests/unit/LodestarBeaconService.test.js b/launcher/src/backend/tests/unit/LodestarBeaconService.test.js index 7f4632449..6b4b979c8 100755 --- a/launcher/src/backend/tests/unit/LodestarBeaconService.test.js +++ b/launcher/src/backend/tests/unit/LodestarBeaconService.test.js @@ -23,10 +23,7 @@ test("buildConfiguration", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); @@ -63,10 +60,7 @@ test("buildConsensusClientHttpEndpointUrl", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); const ports = [ @@ -101,10 +95,7 @@ test("getAvailablePorts", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); const lServicePorts = LodestarBeaconService.buildByUserInput( @@ -133,10 +124,7 @@ test("network", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); const lServicePorts = LodestarBeaconService.buildByUserInput( diff --git a/launcher/src/backend/tests/unit/LodestarValidatorService.test.js b/launcher/src/backend/tests/unit/LodestarValidatorService.test.js index 529b81871..6454202d2 100755 --- a/launcher/src/backend/tests/unit/LodestarValidatorService.test.js +++ b/launcher/src/backend/tests/unit/LodestarValidatorService.test.js @@ -38,39 +38,21 @@ test("LodestarValidatorService buildConfiguration", () => { test("LodestarValidatorService getAvailablePorts", () => { const ports = [new ServicePort("1.2.3.4", 303, 404, servicePortProtocol.udp)]; - const lService = LodestarValidatorService.buildByUserInput( - "prater", - ports, - "/opt/stereum/l", - [], - "foobar" - ).getAvailablePorts(); + const lService = LodestarValidatorService.buildByUserInput("prater", ports, "/opt/stereum/l", [], "foobar").getAvailablePorts(); expect(lService).toHaveLength(1); }); test("LodestarValidatorService autoupdate", () => { const ports = [new ServicePort("1.2.3.4", 303, 404, servicePortProtocol.udp)]; - const lService = LodestarValidatorService.buildByUserInput( - "prater", - ports, - "/opt/stereum/l", - [], - "foobar" - ).buildConfiguration(); + const lService = LodestarValidatorService.buildByUserInput("prater", ports, "/opt/stereum/l", [], "foobar").buildConfiguration(); expect(lService.autoupdate).toBe(true); }); test("LodestarValidatorService network", () => { const ports = [new ServicePort("1.2.3.4", 303, 404, servicePortProtocol.udp)]; - const lService = LodestarValidatorService.buildByUserInput( - "mainnet", - ports, - "/opt/stereum/l", - [], - "foobar" - ).buildConfiguration(); + const lService = LodestarValidatorService.buildByUserInput("mainnet", ports, "/opt/stereum/l", [], "foobar").buildConfiguration(); expect(lService.network).toBe("mainnet"); }); diff --git a/launcher/src/backend/tests/unit/NethermindService.test.js b/launcher/src/backend/tests/unit/NethermindService.test.js index 738159ae1..f2872e894 100755 --- a/launcher/src/backend/tests/unit/NethermindService.test.js +++ b/launcher/src/backend/tests/unit/NethermindService.test.js @@ -4,11 +4,7 @@ import { ServicePort, servicePortProtocol } from "../../ethereum-services/Servic test("buildByUserInput", () => { const ports = [new ServicePort(null, 4040, 4040, servicePortProtocol.tcp)]; - const nethermindService = NethermindService.buildByUserInput( - "goerli", - ports, - "/opt/stereum/nethermind" - ).buildConfiguration(); + const nethermindService = NethermindService.buildByUserInput("goerli", ports, "/opt/stereum/nethermind").buildConfiguration(); expect(nethermindService.service).toBe("NethermindService"); expect(nethermindService.id).toMatch(/.{8}-.{4}-.{4}-.{4}-.{12}/); @@ -19,9 +15,7 @@ test("buildByUserInput", () => { expect(nethermindService.entrypoint).toContain("./nethermind"); expect(nethermindService.ports).toHaveLength(1); expect(nethermindService.ports).toContain("0.0.0.0:4040:4040/tcp"); - expect(nethermindService.volumes).toContain( - "/opt/stereum/nethermind-" + nethermindService.id + "/data:/opt/app/data" - ); + expect(nethermindService.volumes).toContain("/opt/stereum/nethermind-" + nethermindService.id + "/data:/opt/app/data"); expect(nethermindService.user).toBe("root"); expect(nethermindService.network).toBe("goerli"); }); @@ -54,14 +48,8 @@ test("buildExecutionClientMetricsEndpoint", () => { }); test("buildPrometheusJob", () => { - const nethermindPrometheusJob = NethermindService.buildByUserInput( - "goerli", - [], - "/opt/stereum/nethermind" - ).buildPrometheusJob(); - expect(nethermindPrometheusJob).toMatch( - /\n {2}- job_name: stereum-.{36}\n {4}static_configs:\n {6}- targets: \[stereum-.{36}:6060]/ - ); + const nethermindPrometheusJob = NethermindService.buildByUserInput("goerli", [], "/opt/stereum/nethermind").buildPrometheusJob(); + expect(nethermindPrometheusJob).toMatch(/\n {2}- job_name: stereum-.{36}\n {4}static_configs:\n {6}- targets: \[stereum-.{36}:6060]/); }); test("buildByConfiguration", () => { diff --git a/launcher/src/backend/tests/unit/NimbusBeaconService.test.js b/launcher/src/backend/tests/unit/NimbusBeaconService.test.js index dd6b06e7d..538a41359 100755 --- a/launcher/src/backend/tests/unit/NimbusBeaconService.test.js +++ b/launcher/src/backend/tests/unit/NimbusBeaconService.test.js @@ -23,10 +23,7 @@ test("buildConfiguration", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); @@ -82,10 +79,7 @@ test("buildConsensusClientWsEndpointUrl", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); @@ -115,10 +109,7 @@ test("getAvailablePorts", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); const nimbusServicePorts = NimbusBeaconService.buildByUserInput( @@ -147,10 +138,7 @@ test("network", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); const nimbusService = NimbusBeaconService.buildByUserInput( diff --git a/launcher/src/backend/tests/unit/PrometheusNodeExporterService.test.js b/launcher/src/backend/tests/unit/PrometheusNodeExporterService.test.js index c82ab22c2..7e7f334d2 100755 --- a/launcher/src/backend/tests/unit/PrometheusNodeExporterService.test.js +++ b/launcher/src/backend/tests/unit/PrometheusNodeExporterService.test.js @@ -7,8 +7,7 @@ test("buildConfiguration", () => { }); test("buildPrometheusNodeExporterClientHttpEndpointUrl", () => { - const pneService = - PrometheusNodeExporterService.buildByUserInput().buildPrometheusNodeExporterClientHttpEndpointUrl(); + const pneService = PrometheusNodeExporterService.buildByUserInput().buildPrometheusNodeExporterClientHttpEndpointUrl(); expect(pneService).toMatch(/http:\/\/stereum-.{36}:9100/); }); diff --git a/launcher/src/backend/tests/unit/PrometheusService.test.js b/launcher/src/backend/tests/unit/PrometheusService.test.js index 4fa1882b0..b0461df8d 100755 --- a/launcher/src/backend/tests/unit/PrometheusService.test.js +++ b/launcher/src/backend/tests/unit/PrometheusService.test.js @@ -46,13 +46,7 @@ test("buildConfiguration", () => { }); test("getAvailablePorts", () => { - const prometheus = PrometheusService.buildByUserInput( - "prater", - [], - "/opt/stereum/prometheus", - [], - [] - ).getAvailablePorts(); + const prometheus = PrometheusService.buildByUserInput("prater", [], "/opt/stereum/prometheus", [], []).getAvailablePorts(); expect(prometheus).toHaveLength(1); }); diff --git a/launcher/src/backend/tests/unit/PrysmBeaconService.test.js b/launcher/src/backend/tests/unit/PrysmBeaconService.test.js index dfa4cbd4d..0320b45e2 100755 --- a/launcher/src/backend/tests/unit/PrysmBeaconService.test.js +++ b/launcher/src/backend/tests/unit/PrysmBeaconService.test.js @@ -23,10 +23,7 @@ test("buildConfiguration", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); @@ -38,7 +35,7 @@ test("buildConfiguration", () => { [] ).buildConfiguration(); - expect(prysm.command).toContain('--execution-endpoint=http-endpoint-string,http-endpoint-string'); + expect(prysm.command).toContain("--execution-endpoint=http-endpoint-string,http-endpoint-string"); expect(prysm.volumes).toHaveLength(4); expect(prysm.volumes).toContain("/opt/stereum/prysm-" + prysm.id + "/beacon:/opt/app/beacon"); expect(prysm.volumes).toContain("/opt/stereum/prysm-" + prysm.id + "/genesis:/opt/app/genesis"); @@ -64,10 +61,7 @@ test("buildConsensusClientHttpEndpointUrl", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); const ports = [ @@ -102,10 +96,7 @@ test("buildConsensusClientGateway", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); const ports = [ @@ -140,10 +131,7 @@ test("buildConsensusClientEndpoint", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); const ports = [ @@ -189,10 +177,7 @@ test("getAvailablePorts", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); @@ -222,10 +207,7 @@ test("network", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); diff --git a/launcher/src/backend/tests/unit/PrysmValidatorService.test.js b/launcher/src/backend/tests/unit/PrysmValidatorService.test.js index 7a92e4d08..4f30c88d4 100755 --- a/launcher/src/backend/tests/unit/PrysmValidatorService.test.js +++ b/launcher/src/backend/tests/unit/PrysmValidatorService.test.js @@ -29,8 +29,8 @@ test("buildConfiguration", () => { new PrysmBeaconService.PrysmBeaconService(), ]).buildConfiguration(); - expect(prysm.command).toContain('--beacon-rpc-provider=buildConsensusClientEndpoint'); - expect(prysm.command).toContain('--beacon-rpc-gateway-provider=buildConsensusClientGateway'); + expect(prysm.command).toContain("--beacon-rpc-provider=buildConsensusClientEndpoint"); + expect(prysm.command).toContain("--beacon-rpc-gateway-provider=buildConsensusClientGateway"); expect(prysm.volumes).toHaveLength(4); expect(prysm.volumes).toContain("/opt/stereum/prysm-" + prysm.id + "/data/db:/opt/app/data/db"); expect(prysm.volumes).toContain("/opt/stereum/prysm-" + prysm.id + "/data/wallets:/opt/app/data/wallets"); diff --git a/launcher/src/backend/tests/unit/SSVNetworkService.test.js b/launcher/src/backend/tests/unit/SSVNetworkService.test.js index 7d1065831..5328ef368 100755 --- a/launcher/src/backend/tests/unit/SSVNetworkService.test.js +++ b/launcher/src/backend/tests/unit/SSVNetworkService.test.js @@ -3,10 +3,7 @@ import { ServicePort, servicePortProtocol } from "../../ethereum-services/Servic const log = require("electron-log"); test("buildConfiguration", () => { - const ports = [ - new ServicePort(null, 100, 200, servicePortProtocol.tcp), - new ServicePort(null, 101, 202, servicePortProtocol.udp), - ]; + const ports = [new ServicePort(null, 100, 200, servicePortProtocol.tcp), new ServicePort(null, 101, 202, servicePortProtocol.udp)]; jest.mock("../../ethereum-services/GethService"); const GethService = require("../../ethereum-services/GethService"); @@ -92,11 +89,7 @@ test("getServiceConfiguration", () => { "/opt/stereum/ssv", [new GethService.GethService()], [new LighthouseBeaconService.LighthouseBeaconService()] - ).getServiceConfiguration( - "prater", - [new GethService.GethService()], - [new LighthouseBeaconService.LighthouseBeaconService()] - ); + ).getServiceConfiguration("prater", [new GethService.GethService()], [new LighthouseBeaconService.LighthouseBeaconService()]); expect(ssvService).toBeDefined(); expect(ssvService).toMatch(/prater/); @@ -105,37 +98,19 @@ test("getServiceConfiguration", () => { }); test("getAvailablePorts", () => { - const service = SSVNetworkService.buildByUserInput( - "prater", - null, - "/opt/stereum/ssv", - [], - [] - ).getAvailablePorts(); + const service = SSVNetworkService.buildByUserInput("prater", null, "/opt/stereum/ssv", [], []).getAvailablePorts(); expect(service).toHaveLength(3); }); test("service name", () => { - const service = SSVNetworkService.buildByUserInput( - "prater", - null, - "/opt/stereum/ssv", - [], - [] - ).buildConfiguration(); + const service = SSVNetworkService.buildByUserInput("prater", null, "/opt/stereum/ssv", [], []).buildConfiguration(); expect(service.service).toMatch(/SSVNetworkService/); }); test("autoupdate", () => { - const service = SSVNetworkService.buildByUserInput( - "prater", - null, - "/opt/stereum/ssv", - [], - [] - ).buildConfiguration(); + const service = SSVNetworkService.buildByUserInput("prater", null, "/opt/stereum/ssv", [], []).buildConfiguration(); expect(service.autoupdate).toBe(true); }); diff --git a/launcher/src/backend/tests/unit/ServiceManager.test.js b/launcher/src/backend/tests/unit/ServiceManager.test.js index 87a574250..b83a00860 100755 --- a/launcher/src/backend/tests/unit/ServiceManager.test.js +++ b/launcher/src/backend/tests/unit/ServiceManager.test.js @@ -141,8 +141,8 @@ test("addDependencies LighthouseBeaconService", () => { const lhService = LighthouseBeaconService.buildByUserInput("prater", [], "/opt/stereum/lh", [], []); const result = sm.addDependencies(lhService, [geth1, geth2]); - expect(result.command.join(" ")).toMatch(/--execution-endpoint=http:\/\/stereum-.{36}:8551,http:\/\/stereum-.{36}:8551/) - expect(result.dependencies.executionClients).toHaveLength(2) + expect(result.command.join(" ")).toMatch(/--execution-endpoint=http:\/\/stereum-.{36}:8551,http:\/\/stereum-.{36}:8551/); + expect(result.dependencies.executionClients).toHaveLength(2); }); test("addDependencies FlashbotsMevBoost", () => { @@ -152,8 +152,8 @@ test("addDependencies FlashbotsMevBoost", () => { const mevboost = FlashbotsMevBoostService.buildByUserInput("goerli"); const result = sm.addDependencies(mevboost, [lhService1, lhService2]); - expect(result).toHaveLength(2) - expect(result[0].command.join(" ")).toMatch(/--builder=http:\/\/stereum-.{36}:18550/) + expect(result).toHaveLength(2); + expect(result[0].command.join(" ")).toMatch(/--builder=http:\/\/stereum-.{36}:18550/); }); test("addConnection String", () => { @@ -173,7 +173,7 @@ test("addConnection String", () => { test("addConnection array empty dependencies", () => { const geth1 = GethService.buildByUserInput("goerli", [], "/opt/stereum/geth"); const lhService = LighthouseBeaconService.buildByUserInput("prater", [], "/opt/stereum/prysm", [geth1], []); - const dependencies = [] + const dependencies = []; const endpointCommand = "--execution-endpoint="; const filter = (e) => e.buildExecutionClientEngineRPCHttpEndpointUrl(); @@ -201,14 +201,14 @@ test("addConnection array", () => { test("addConnection String empty dependencies", () => { const geth1 = GethService.buildByUserInput("goerli", [], "/opt/stereum/geth"); const prysm = PrysmBeaconService.buildByUserInput("prater", [], "/opt/stereum/prysm", [geth1], []); - const dependencies = [] + const dependencies = []; const endpointCommand = "--execution-endpoint="; const filter = (e) => e.buildExecutionClientEngineRPCHttpEndpointUrl(); const sm = new ServiceManager(); const result = sm.addCommandConnection(prysm, endpointCommand, dependencies, filter); - expect(result).not.toContain('--execution-endpoint='); + expect(result).not.toContain("--execution-endpoint="); }); test("removeConnection String", () => { @@ -251,12 +251,8 @@ test("removeConnection String multiple endpoints", () => { const sm = new ServiceManager(); const result = sm.removeCommandConnection(command, id); - expect(result).not.toMatch( - /--beacon-rpc-provider="stereum-42d9f0b4-257f-f71e-10fe-66c342dd4995:4000,stereum-foo:3000,stereum-bar:2000"/ - ); - expect(result).not.toMatch( - /--beacon-rpc-gateway-provider=stereum-foo:3000,stereum-42d9f0b4-257f-f71e-10fe-66c342dd4995:3500/ - ); + expect(result).not.toMatch(/--beacon-rpc-provider="stereum-42d9f0b4-257f-f71e-10fe-66c342dd4995:4000,stereum-foo:3000,stereum-bar:2000"/); + expect(result).not.toMatch(/--beacon-rpc-gateway-provider=stereum-foo:3000,stereum-42d9f0b4-257f-f71e-10fe-66c342dd4995:3500/); expect(result).toMatch(/--beacon-rpc-provider="stereum-foo:3000,stereum-bar:2000"/); expect(result).toMatch(/--beacon-rpc-gateway-provider=stereum-foo:3000/); }); @@ -313,9 +309,7 @@ test("removeConnection array multiple endpoints", () => { const sm = new ServiceManager(); const result = sm.removeCommandConnection(command, id); - expect(result).not.toContain( - '--ee-endpoint="http://stereum-9adfdb2e-9f5b-aba4-cfde-f3483d7aac8d:8551,foo:3000,bar:2000"' - ); + expect(result).not.toContain('--ee-endpoint="http://stereum-9adfdb2e-9f5b-aba4-cfde-f3483d7aac8d:8551,foo:3000,bar:2000"'); expect(result).toContain('--ee-endpoint="foo:3000,bar:2000"'); }); @@ -332,9 +326,7 @@ test("change network", () => { services.push(BesuService.buildByUserInput(oldNetwork, [], installDir + "/besu")); services.push(NethermindService.buildByUserInput(oldNetwork, [], installDir + "/nethermind")); services.push(FlashbotsMevBoostService.buildByUserInput(oldNetwork, relayURL)); - services.push( - LighthouseBeaconService.buildByUserInput(oldNetwork, [], installDir + "/lighthouse", [], [], checkpointURL) - ); + services.push(LighthouseBeaconService.buildByUserInput(oldNetwork, [], installDir + "/lighthouse", [], [], checkpointURL)); services.push(LighthouseValidatorService.buildByUserInput(oldNetwork, [], installDir + "/lighthouse", [])); services.push(PrysmBeaconService.buildByUserInput(oldNetwork, [], installDir + "/prysm", [], [], checkpointURL)); services.push(PrysmValidatorService.buildByUserInput(oldNetwork, [], installDir + "/prysm", [])); @@ -353,9 +345,9 @@ test("change network", () => { } expect(services.map((s) => s.network)).not.toContain("goerli"); expect(services.find((s) => s.service === "FlashbotsMevBoostService").entrypoint).toContain("-mainnet"); - expect(services.find((s) => s.service === "PrysmBeaconService").command).toContain('--mainnet'); + expect(services.find((s) => s.service === "PrysmBeaconService").command).toContain("--mainnet"); expect(services.find((s) => s.service === "PrysmBeaconService").command).not.toContain( - '--genesis-state=/opt/app/genesis/prysm-holesky-genesis.ssz' + "--genesis-state=/opt/app/genesis/prysm-holesky-genesis.ssz" ); expect(services.find((s) => s.service === "LighthouseBeaconService").command).toContain("--network=mainnet"); }); diff --git a/launcher/src/backend/tests/unit/ServicePort.test.js b/launcher/src/backend/tests/unit/ServicePort.test.js index 442d161a3..a2cd0e549 100755 --- a/launcher/src/backend/tests/unit/ServicePort.test.js +++ b/launcher/src/backend/tests/unit/ServicePort.test.js @@ -5,9 +5,7 @@ test("serviceport any destination ip", () => { }); test("serviceport specific destination ip", () => { - expect(new ServicePort("8.8.8.8", 1234, 5678, servicePortProtocol.udp).buildPortMapping()).toBe( - "8.8.8.8:1234:5678/udp" - ); + expect(new ServicePort("8.8.8.8", 1234, 5678, servicePortProtocol.udp).buildPortMapping()).toBe("8.8.8.8:1234:5678/udp"); }); test("buildByConfig", () => { diff --git a/launcher/src/backend/tests/unit/ServiceVolume.test.js b/launcher/src/backend/tests/unit/ServiceVolume.test.js index 03e7d17cc..c23d7b772 100755 --- a/launcher/src/backend/tests/unit/ServiceVolume.test.js +++ b/launcher/src/backend/tests/unit/ServiceVolume.test.js @@ -1,9 +1,7 @@ import { ServiceVolume } from "../../ethereum-services/ServiceVolume"; test("servicevolume", () => { - expect(new ServiceVolume("/opt/stereum/foo", "/opt/app/data").buildVolumeMapping()).toBe( - "/opt/stereum/foo:/opt/app/data" - ); + expect(new ServiceVolume("/opt/stereum/foo", "/opt/app/data").buildVolumeMapping()).toBe("/opt/stereum/foo:/opt/app/data"); }); test("buildByConfig", () => { diff --git a/launcher/src/backend/tests/unit/StringUtils.test.js b/launcher/src/backend/tests/unit/StringUtils.test.js index e410bd025..caca363c0 100755 --- a/launcher/src/backend/tests/unit/StringUtils.test.js +++ b/launcher/src/backend/tests/unit/StringUtils.test.js @@ -1,9 +1,7 @@ import { StringUtils } from "../../StringUtils"; test("escapeStringForShell small json", () => { - expect(StringUtils.escapeStringForShell(JSON.stringify({ foo: "bar", xyz: 123 }))).toEqual( - '"{\\"foo\\":\\"bar\\",\\"xyz\\":123}"' - ); + expect(StringUtils.escapeStringForShell(JSON.stringify({ foo: "bar", xyz: 123 }))).toEqual('"{\\"foo\\":\\"bar\\",\\"xyz\\":123}"'); }); test("escapeStringForShell simple String", () => { diff --git a/launcher/src/backend/tests/unit/TekuBeaconService.test.js b/launcher/src/backend/tests/unit/TekuBeaconService.test.js index 13efabc7e..a307ace05 100755 --- a/launcher/src/backend/tests/unit/TekuBeaconService.test.js +++ b/launcher/src/backend/tests/unit/TekuBeaconService.test.js @@ -25,10 +25,7 @@ test("buildConfiguration", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); @@ -72,10 +69,7 @@ test("buildConsensusClientHttpEndpointUrl", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); @@ -117,10 +111,7 @@ test("getAvailablePorts", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); const tekuServicePorts = TekuBeaconService.buildByUserInput( @@ -150,10 +141,7 @@ test("network", () => { service: "GethService", }; }), - volumes: [ - new ServiceVolume("some/path/data", "some/path/other/data"), - new ServiceVolume("some/path/engine.jwt", "/engine.jwt"), - ], + volumes: [new ServiceVolume("some/path/data", "some/path/other/data"), new ServiceVolume("some/path/engine.jwt", "/engine.jwt")], }; }); const tekuService = TekuBeaconService.buildByUserInput( diff --git a/launcher/src/background.js b/launcher/src/background.js index 8dcfcd53c..6c3dd06ee 100755 --- a/launcher/src/background.js +++ b/launcher/src/background.js @@ -506,12 +506,7 @@ ipcMain.handle("getCurrentEpochSlot", async (event, args) => { ipcMain.handle("beginAuthSetup", async (event, args) => { const current_window = event.sender; - return await authenticationService.beginAuthSetup( - args.timeBased, - args.increaseTimeLimit, - args.enableRateLimit, - current_window - ); + return await authenticationService.beginAuthSetup(args.timeBased, args.increaseTimeLimit, args.enableRateLimit, current_window); }); ipcMain.handle("finishAuthSetup", async () => { diff --git a/launcher/src/components/UI/base-header/components/menu/SingleMenu.vue b/launcher/src/components/UI/base-header/components/menu/SingleMenu.vue index 3ee2327d5..fa18dbf37 100644 --- a/launcher/src/components/UI/base-header/components/menu/SingleMenu.vue +++ b/launcher/src/components/UI/base-header/components/menu/SingleMenu.vue @@ -34,10 +34,7 @@ const handleClick = () => { const menuIcon = computed(() => { if (props.item.name !== "Available Update") { return props.item.icon; - } else if ( - props.item.name === "Available Update" && - (headerStore.isUpdateAvailable || headerStore.isOsUpdateAvailable) - ) { + } else if (props.item.name === "Available Update" && (headerStore.isUpdateAvailable || headerStore.isOsUpdateAvailable)) { return props.item.activeIcon; } else { return props.item.icon; diff --git a/launcher/src/components/UI/base-header/components/modals/LogoutModal.vue b/launcher/src/components/UI/base-header/components/modals/LogoutModal.vue index d793ac1b2..c698126d5 100755 --- a/launcher/src/components/UI/base-header/components/modals/LogoutModal.vue +++ b/launcher/src/components/UI/base-header/components/modals/LogoutModal.vue @@ -1,9 +1,6 @@