From 45baaff9da62719e1974f8d6e4fc1347ff1d9190 Mon Sep 17 00:00:00 2001 From: mytilene Date: Mon, 12 Dec 2022 09:51:13 +0800 Subject: [PATCH 001/108] Update mn.json --- web/src/config/lang/mn.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/src/config/lang/mn.json b/web/src/config/lang/mn.json index 5d3b669506..de1126f4e6 100644 --- a/web/src/config/lang/mn.json +++ b/web/src/config/lang/mn.json @@ -124,7 +124,7 @@ "FROZEN_ACCOUNT": "Таны бүртгэл түгжигдсэн байна", "INVALID_EMAIL": "И-мэйл хаяг буруу байна", "TYPE_EMAIL": "И-мэйл хаяг оруулна уу", - "REQUIRED": "Бөглөх шаардлагатай", + "REQUIRED": "Заавал бөглөнө", "INVALID_DATE": "Огноо буруу байна", "INVALID_PASSWORD": "Iууц үг буруу байна. Доод тал нь 8 тэмдэгттэй, тоо болон тусгай тэмдэгт орно.", "INVALID_PASSWORD_2": "Нууц үг буруу байна. Доод тал нь 8 тэмдэгттэй, тоо болон тусгай тэмдэгт орно.", @@ -135,7 +135,7 @@ "MIN_VALUE_NE": "Боломжит доод дүн {0}.", "MAX_VALUE_NE": "Боломжит дээд дүн {0}.", "INSUFFICIENT_BALANCE": "Үлдэгдэл хүрэлцэхгүй байна", - "PASSWORDS_DONT_MATCH": "Нууц үг буруу байна.", + "PASSWORDS_DONT_MATCH": "Нууц үг тохирохгүй байна.", "USER_EXIST": "И-мэйл хаяг бүртгэлтэй байна", "ACCEPT_TERMS": "Үйлчилгээний нөхцөл, нууцлалын бодлогыг зөвшөөрөөгүй байна", "STEP": "Буруу утга: {0}", @@ -306,7 +306,7 @@ "START_DOCUMENTATION_RESUBMISSION": "Бичиг баримт дахин илгээх", "SUBMISSION_PENDING_TXT": "*Энэ хэсгийг та өмнө нь илгээсэн байна. Өөрчлөлт хийж, дахин илгээх нь таны өмнөх мэдээллийг дарж бичих болно.", "CUSTOMER_SUPPORT_MESSAGE": "Операторын хариу", - "DOCUMENT_PENDING_NOTE": "Таны бичиг баримтыг илгээсэн бөгөөд шалгахаар хүлээгдэж байна.", + "DOCUMENT_PENDING_NOTE": "Таны бичиг баримтыг хүлээн авсан бөгөөд шалгахаар хүлээгдэж байна.", "DOCUMENT_VERIFIED_NOTE": "Таны бичиг баримт баталгаажсан байна.", "NOTE_FROM_VERIFICATION_DEPARTMENT": "Баталгаажуулалтын хариу", "CODE_EXPIRES_IN": "Код дуусах хугацаа", @@ -1170,7 +1170,7 @@ "TRANSACTION_STATUS": { "PENDING": "Хүлээгдэж буй", "REJECTED": "Татгалзсан", - "COMPLETED": "Дууссан" + "COMPLETED": "Баталгаажсан" }, "DEPOSIT_STATUS": { "NEW": "Шинэ", From b9766cecd7de7202281d667873d08e7a8379eab2 Mon Sep 17 00:00:00 2001 From: mytilene Date: Mon, 12 Dec 2022 11:41:28 +0800 Subject: [PATCH 002/108] Update mn.json --- web/src/config/lang/mn.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/src/config/lang/mn.json b/web/src/config/lang/mn.json index de1126f4e6..cb4a55fe86 100644 --- a/web/src/config/lang/mn.json +++ b/web/src/config/lang/mn.json @@ -105,7 +105,7 @@ }, "LOGIN": { "LOGIN_TO": "{0} нэвтрэх", - "CANT_LOGIN": "Нэвтэрч чадахгүй байна уу?", + "CANT_LOGIN": "Нууц үгээ мартсан уу?", "NO_ACCOUNT": "Бүртгэлгүй юу?", "CREATE_ACCOUNT": "Энд дарж бүртгүүлээрэй", "HELP": "Тусламж" @@ -226,7 +226,7 @@ "NO_EMAIL": "И-мэйл хүлээн аваагүй юу?", "REQUEST_EMAIL": "Энд дарж и-мэйл дахин авна уу", "HAVE_ACCOUNT": "Бүртгэлтэй юу?", - "GOTO_LOGIN": "Энд дарж нэвтрэх хэсэгт очно уу", + "GOTO_LOGIN": "Нэвтрэх хэсэгт очих", "AFFILIATION_CODE": "Найзын код (заавал биш)", "AFFILIATION_CODE_PLACEHOLDER": "Найзын кодоо оруулна уу", "TERMS": { @@ -319,7 +319,7 @@ "FULL_NAME_LABEL": "Таны нэр", "FULL_NAME_PLACEHOLDER": "Иргэний үнэмлэх дээрх өөрийн нэрээ бичнэ үү", "GENDER_LABEL": "Хүйс", - "GENDER_PLACEHOLDER": "Өөрийн хүйсээ оруулна уу", + "GENDER_PLACEHOLDER": "Хүйс оруулах", "GENDER_OPTIONS": { "MAN": "Эрэгтэй", "WOMAN": "Эмэгтэй" }, "NATIONALITY_LABEL": "Иргэншил", "NATIONALITY_PLACEHOLDER": "Та өөрийн иргэншилээ бичнэ үү", @@ -331,7 +331,7 @@ "ADDRESS_LABEL": "Хаяг", "ADDRESS_PLACEHOLDER": "Хаяг", "POSTAL_CODE_LABEL": "Зип код", - "POSTAL_CODE_PLACEHOLDER": "Зип кодоо оруулна уу", + "POSTAL_CODE_PLACEHOLDER": "Зип код оруулна уу", "PHONE_CODE_LABEL": "Улс", "PHONE_CODE_PLACEHOLDER": "Утасны дугаар байршиж буй улсаа бичнэ үү", "PHONE_CODE_DISPLAY": "({0}) {1}", @@ -340,7 +340,7 @@ "CONNECTING_LOADING": "Холбогдож байна", "SMS_SEND": "SМS илгээх", "SMS_CODE_LABEL": "SМS код", - "SMS_CODE_PLACEHOLDER": "SМS кодоо оруулна уу" + "SMS_CODE_PLACEHOLDER": "SМS код оруулна уу" }, "INFORMATION": { "TEXT": "АНХААРУУЛГА: Иргэний үнэмлэх дээрхтэй яг ижлээр нэрээ оруулна уу (овог нэр, өөрийн нэр). Та бизнес эрхэлдэг бол байгууллагын дансны хэрэглэгчийн дэмжлэгтэй холбогдоно уу.", @@ -535,7 +535,7 @@ "TITLE_TRADES": "Арилжааны түүх", "TITLE_DEPOSITS": "Орлогын түүх", "TITLE_WITHDRAWALS": "Зарлагын түүх", - "TEXT_DOWNLOAD": "ТҮҮХ ТАТАЖ АВАХ", + "TEXT_DOWNLOAD": "ТАТАЖ АВАХ", "TRADES": "Арилжаа", "DEPOSITS": "Орлого", "WITHDRAWALS": "Зарлага" From 21ae6853b87c0d1009ed0f77683aff3d7f1f371f Mon Sep 17 00:00:00 2001 From: mytilene Date: Mon, 18 Mar 2024 12:17:35 +0800 Subject: [PATCH 003/108] Update mn.json --- web/src/config/lang/mn.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/config/lang/mn.json b/web/src/config/lang/mn.json index cb4a55fe86..434d5a649b 100644 --- a/web/src/config/lang/mn.json +++ b/web/src/config/lang/mn.json @@ -1238,7 +1238,7 @@ "COMING_SOON": "тун удахгүй" }, "WALLET_BALANCE_LOADING": "Үлдэгдэл ачаалж байна...", - "LOADING": "Ачаалж байна...", + "LOADING": "Боловсруулж байна...", "CONNECT_VIA_DESKTOP": { "TITLE": "Суурин компьютерээр холбогдоно уу", "SUBTITLE": "Таны мобайл төхөөрөмжөөр дамжуулан DeFi stake хийхийг одоогоор дэмжихгүй байна.", From cb6cff88ba64c5fed092256a68222c251dd3d01c Mon Sep 17 00:00:00 2001 From: mytilene Date: Mon, 18 Mar 2024 12:19:22 +0800 Subject: [PATCH 004/108] Update mn.json --- web/src/config/lang/mn.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/config/lang/mn.json b/web/src/config/lang/mn.json index 434d5a649b..96128041e0 100644 --- a/web/src/config/lang/mn.json +++ b/web/src/config/lang/mn.json @@ -115,8 +115,8 @@ "EMAIL_PLACEHOLDER": "И-мэйл хаягаа энд оруулна", "PASSWORD_LABEL": "Нууц үг", "PASSWORD_PLACEHOLDER": "Нууц үгээ оруулна уу", - "PASSWORD_REPEAT_LABEL": "Retype your password", - "PASSWORD_REPEAT_PLACEHOLDER": "Retype your password" + "PASSWORD_REPEAT_LABEL": "Нууц үг давтах", + "PASSWORD_REPEAT_PLACEHOLDER": "Нууц үг давтах" }, "VALIDATIONS": { "OTP_LOGIN": "OTP код оруулна уу", From 81db6186c85af3931e6073d26ae73238d85ebf87 Mon Sep 17 00:00:00 2001 From: mytilene Date: Mon, 18 Mar 2024 12:19:58 +0800 Subject: [PATCH 005/108] Update mn.json --- web/src/config/lang/mn.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/config/lang/mn.json b/web/src/config/lang/mn.json index 96128041e0..e33680584a 100644 --- a/web/src/config/lang/mn.json +++ b/web/src/config/lang/mn.json @@ -126,7 +126,7 @@ "TYPE_EMAIL": "И-мэйл хаяг оруулна уу", "REQUIRED": "Заавал бөглөнө", "INVALID_DATE": "Огноо буруу байна", - "INVALID_PASSWORD": "Iууц үг буруу байна. Доод тал нь 8 тэмдэгттэй, тоо болон тусгай тэмдэгт орно.", + "INVALID_PASSWORD": "Нууц үг буруу байна. Доод тал нь 8 тэмдэгттэй, тоо болон тусгай тэмдэгт орно.", "INVALID_PASSWORD_2": "Нууц үг буруу байна. Доод тал нь 8 тэмдэгттэй, тоо болон тусгай тэмдэгт орно.", "INVALID_CURRENCY": "Дараах {0} хаяг буруу байна ({1})", "INVALID_BALANCE": "Таны баланс ({0}) хүрэлцэхгүй байна: ({1}).", From 3e216d704fd402d89c061a159467c6f7b20cf0c8 Mon Sep 17 00:00:00 2001 From: mytilene Date: Fri, 5 Apr 2024 10:21:01 +0800 Subject: [PATCH 006/108] Update mn.json Update Mongolian Language --- web/src/config/lang/mn.json | 208 ++++++++++++++++++------------------ 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/web/src/config/lang/mn.json b/web/src/config/lang/mn.json index a17289a7cf..eafbe6d0b1 100644 --- a/web/src/config/lang/mn.json +++ b/web/src/config/lang/mn.json @@ -5,7 +5,7 @@ "ADD_TRADING_PAIR": "Маркет сонгох", "CANCEL_BASE_WITHDRAWAL": "{0} зарлага цуцлах", "CANCEL_WITHDRAWAL": "Зарлага цуцлах", - "CANCEL_WITHDRAWAL_POPUP_CONFIRM": "Та дараах хүлээгдэж буй зарлагыг цуцлахдаа итгэлтэй байна уу:", + "CANCEL_WITHDRAWAL_POPUP_CONFIRM": "Та дараах зарлагыг цуцлахдаа итгэлтэй байна уу:", "TIMESTAMP_FORMAT": "YYYY/MM/DD HH:mm:ss", "NO_ACTIVE_ORDERS": "Захиалга байхгүй байна. Та арилжаа эсвэл хялбар арилжаа цэсээр захиалгаа өгөөрэй", "NO_ACTIVE_TRADES": "Арилжаа хийгдээгүй байна", @@ -42,13 +42,13 @@ "SECONDS": "хором", "VIEW_MARKET": "маркет харах", "GO_TRADE": "Арилжаанд оролцох", - "VIEW_INFO": "Мэдээллийн хуудас зочлох", + "VIEW_INFO": "Мэдээлэл харах", "APPLY_HERE": "Энд дарна уу", "CONVERT": "Хөрвүүлэх", - "TO": "Юунд", + "TO": "To", "HOME": { "MAIN_TITLE": "Крипто арилжааны бирж", - "MAIN_TEXT": "Та өөрийн и-мэйл хаягаар бүртгүүлээд 24 цагийн турш крипто хөрөнө хялбархан худалдан авах, арилжаалах боломжтой", + "MAIN_TEXT": "Та өөрийн и-мэйл хаягаар бүртгүүлээд 24 цагийн турш крипто хөрөнгө хялбархан худалдан авах, арилжаалах боломжтой", "TRADE_CRYPTO": "Арилжаанд оролцох", "VIEW_EXCHANGE": "Трэйдинг платформ" }, @@ -85,13 +85,13 @@ "OPTION_BUG": "Алдааг мэдээлэх", "OPTION_PERSONAL_INFO": "Хувийн мэдээлэл өөрчлөх", "OPTION_BANK_TRANSFER": "Банкны шилжүүлэг", - "OPTION_REQUEST": "HollaEx бирж дээр урилга илгээх" + "OPTION_REQUEST": "Урилга илгээх" }, "SUBJECT_LABEL": "Гарчиг", "SUBJECT_PLACEHOLDER": "Асуудлын тухай гарчиг оруулах", "DESCRIPTION_LABEL": "Тайлбар", "DESCRIPTION_PLACEHOLDER": "Асуудлын дэлгэрэнгүй тайлбар", - "ATTACHMENT_LABEL": "Хасвралт оруулах (хамгийн ихдээ 3)", + "ATTACHMENT_LABEL": "Хавсралт оруулах (хамгийн ихдээ 3)", "ATTACHMENT_PLACEHOLDER": "Асуудалд холбоотой файлууд. PDF, JPG, PNG ба GIF файл оруулах боломжтой", "SUCCESS_TITLE": "Зурвас илгээлээ", "SUCCESS_MESSAGE_1": "Таны асуудлыг хэрэглэгчийн тусламжийн төвд илгээлээ.", @@ -103,7 +103,7 @@ "DESTINATION_TAG": "Таны {0} хүлээн авах tag", "MEMO": "Таны {0} memo" }, - "QR_CODE": "Энэ QR кодыг танд мөнгө илгээхийг хүссэн хүн сканнердаж болно", + "QR_CODE": "Энэ QR кодыг уншуулан илгээх боломжтой", "NO_DATA": "Мэдээлэл байхгүй байна", "QR_CODE_TITLE": "{0} Хадгаламжийн мэдээлэл" }, @@ -113,8 +113,8 @@ "NO_ACCOUNT": "Бүртгэлгүй юу?", "CREATE_ACCOUNT": "Энд дарж бүртгүүлээрэй", "HELP": "Тусламж", - "LOOKING_PRICES": "Үнэ хайж байна уу?", - "VIEW_MARKETS": "Зах зээлүүдийг үзэх" + "LOOKING_PRICES": "Ханшийн мэдээл харах уу?", + "VIEW_MARKETS": "Арилжаанд оролцох" }, "FORM_FIELDS": { "EMAIL_LABEL": "И-мэйл", @@ -132,7 +132,7 @@ "TYPE_EMAIL": "И-мэйл хаяг оруулна уу", "REQUIRED": "Бөглөх шаардлагатай", "INVALID_DATE": "Огноо буруу байна", - "INVALID_PASSWORD": "Iууц үг буруу байна. Доод тал нь 8 тэмдэгттэй, тоо болон тусгай тэмдэгт орно.", + "INVALID_PASSWORD": "Нууц үг буруу байна. Доод тал нь 8 тэмдэгттэй, тоо болон тусгай тэмдэгт орно.", "INVALID_PASSWORD_2": "Нууц үг буруу байна. Доод тал нь 8 тэмдэгттэй, тоо болон тусгай тэмдэгт орно.", "INVALID_CURRENCY": "Дараах {0} хаяг буруу байна ({1})", "INVALID_BALANCE": "Таны баланс ({0}) хүрэлцэхгүй байна: ({1}).", @@ -155,7 +155,7 @@ "SUBTITLE_RECEIVED": "Та {0} орлого хүлээн авлаа", "SUBTITLE_INCOMING": "Танд {0} ирж байна", "INFORMATION_PENDING_1": "Таны {0} арилжаанд орохын тулд ядаж 1 баталгаажуулалт хэрэгтэй.", - "INFORMATION_PENDING_2": "Үүнд 10-30 минут зарцуулагдаж магадгүй. Таны {0} блокчлон дээр баталгаажсаны дараа бид имэйл илгээх болно." + "INFORMATION_PENDING_2": "Таны {0} блокчэйн дээр баталгаажсаны дараа бид имэйл илгээх болно." } }, "REFERRAL_SUCCESS": { "TITLE": "Хүсэлт илгээсэн", "BUTTON_TEXT": "Okay" }, @@ -467,7 +467,7 @@ "RISKY_WARNING_TEXT_3": " Та энэ арилжааг хийхийг үнэхээр хүсч байгаагаа шалгаж, баталгаажуулна уу.", "GO_TO_RISK_MANAGMENT": "ЭРСДЛИЙН УДИРДЛАГА", "CREATE_ORDER_WARING_TEXT": "Таны арилжааны захиалга таны багцын {0}-ээс илүү гарах үед сэрэмжлүүлэг гарна", - "ORDER_PORTFOLIO_LABEL": "Хэтэвчний хувь хэмжээ:", + "ORDER_PORTFOLIO_LABEL": "хэтэвчний хувь хэмжээ:", "NOTIFICATION_FORM": { "POPUP_ORDER_CONFIRMATION": "Захиалга өгөхөөс өмнө баталгаажуулах.", "POPUP_ORDER_COMPLETED": "Захиалга дууссан тухай цонх харуулах", @@ -681,7 +681,7 @@ "SLASHING_TEXT_2": "Бүх орлогыг хураана", "REVIEW_NOTE": "Блокчэйний блокуудын цагаар хэмжигддэг тул та стэйк хийх болон стэйк цуцлахдаа дээрх мэдээллийг сайн нягтална уу. Хугацаанаас өмнө стэйкинг цуцлавал хуримтлагдсан өгөөж цуцлагдах болно", "WAITING_TITLE": "Баталгаажуулахыг хүлээж байна", - "WAITING_TEXT": "Энэ гүйлгээг түрийвчэндээ баталгаажуулна уу", + "WAITING_TEXT": "Энэ гүйлгээг хэтэвчиндээ баталгаажуулна уу", "PENDING_TEXT": "Гүйлгээ хүлээгдэж байна...", "CHECKING_ALLOWANCE": "{0} тэтгэмжийг шалгаж байна...", "WAITING_PROMPT": "{0} {1} {2}", @@ -869,8 +869,8 @@ "TITLE": "XHT-г зөөх", "TEXT_1": "XHT-г бооцоо болгохын тулд та эхлээд өөрийн XHT-ээ өөрийн хэтэвч рүү шилжүүлэх ёстой.", "TEXT_2": "Таны одоо холбогдсон хэтэвчний хаяг байна:", - "LABEL": "Хэтэвчний хаяг", - "TEXT_3": "Хэтэвчний хаяг найдвартай эсэхийг шалгах нь чухал. XHT нь дээрх хэтэвчний хаяг руу шилжих болно." + "LABEL": "хэтэвчний хаяг", + "TEXT_3": "хэтэвчний хаяг найдвартай эсэхийг шалгах нь чухал. XHT нь дээрх хэтэвчний хаяг руу шилжих болно." }, "MOVE_AMOUNT": { "TITLE": "Оруулсан хэмжээ", @@ -943,7 +943,7 @@ "WITHDRAWALS_FORM_DESTINATION_TAG_WARNING": "Хүлээн авах хаяганд tag шаардлагатай эсэхийг шалгана уу. Tag -г зарим тохиолдолд Memo, digital ID, label, note гэж нэрлэдэг.", "WITHDRAWALS_FORM_NETWORK_PLACEHOLDER": "Сүлжээ сонгох", "WITHDRAWALS_FORM_ADDRESS_LABEL": "Хүлээн авах хаяг", - "WITHDRAWALS_FORM_ADDRESS_PLACEHOLDER": "Түрийвчний хаягийг оруулна уу", + "WITHDRAWALS_FORM_ADDRESS_PLACEHOLDER": "хэтэвчний хаягийг оруулна уу", "WITHDRAWALS_FORM_DESTINATION_TAG_LABEL": "Хүлээн авах tag оруулна уу", "WITHDRAWALS_FORM_MEMO_LABEL": "Memo (заавал биш)", "WITHDRAWALS_FORM_DESTINATION_TAG_PLACEHOLDER": "Хүлээн авах tag (заавал биш)", @@ -980,13 +980,13 @@ "WITHDRAWAL_CONFIRM_ADDRESS": "Хаяг", "WITHDRAWAL_CONFIRM_NETWORK": "Сүлжээ", "WITHDRAWAL_CANCEL_BUTTON": "ХААХ", - "WITHDRAWAL_CONFIRM_BUTTON": "ЗАРЛУУЛАХ БАТАЛГАА" + "WITHDRAWAL_CONFIRM_BUTTON": "ЗАРЛАГА БАТЛАХ" }, "WALLET_BUTTON_BASE_DEPOSIT": "орлого", "WALLET_BUTTON_BASE_WITHDRAW": "зарлага", "WALLET_BUTTON_CRYPTOCURRENCY_DEPOSIT": "хүлээн авах", "WALLET_BUTTON_CRYPTOCURRENCY_WITHDRAW": "илгээх", - "AVAILABLE_BALANCE_TEXT": "Боломжтой {0} үлдэгдэл: {1} {2} {3}", + "AVAILABLE_BALANCE_TEXT": "Боломжмт үлдэгдэл {0}: {1} {2} {3}", "BALANCE_TEXT": "Баланс", "CURRENCY_BALANCE_TEXT": "{0} Баланс", "WALLET_ALL_ASSETS": "Бүх хөрөнгө", @@ -1073,7 +1073,7 @@ "ACCESS": "Хандалт", "BASIC_ACCESS": "үндсэн хандалт", "BASIC_ACCESS_PROMPT": "үндсэн хандалт", - "READING_ACCESS": "Унших (Хэтэвчний үлдэгдэл гэх мэт)", + "READING_ACCESS": "Унших (хэтэвчний үлдэгдэл гэх мэт)", "TRADING_ACCESS": "Арилжаа", "IP_ACCESS": "IP хандалт", "IP_ACCESS_PROMPT": "Энэ API түлхүүрээр ямар IP хаяг ажиллахыг тохируулна уу.", @@ -1384,7 +1384,7 @@ "BANK_NAME": "банкны нэр", "VERIFY_BANK_WITHDRAW": "Зардага гаргахын тулд та өөрийн банкны дэлгэрэнгүй мэдээллийн баталгаажуулалтаа дуусгах шаардлагатай. Доорх үргэлжлүүлэх товчийг дарна уу.", "VERIFICATION_TITLE": "Баталгаажуулалт", - "WITHDRAW_NOTE": "Анхаарна уу: Та зөвхөн өөрийн нэр дээрх дансруу мөнгө татах боломжтой.", + "WITHDRAW_NOTE": "Анхаар: Та зөвхөн өөрийн нэр дээрх дансруу мөнгө татах боломжтой.", "USER_PAYMENT": { "TITLE": "Төлбөр" }, "QUOTE_CONFIRMATION_MSG_TEXT_1": "Доорх захиалгаа шалгаад баталгаажуулна уу.", "QUOTE_CONFIRMATION_MSG_TEXT_2": "Хүлээн авах дүн нь урьдчилсан тооцоо бөгөөд арилжааны хураамжийг оруулаагүй болно", @@ -1413,7 +1413,7 @@ "ASSETS": "Хөрөнгө", "CURRENCY_WALLET": { "BACK": "Буцах", - "WALLET_PAGE": "{0} түрийвчний хуудас руу", + "WALLET_PAGE": "{0} хэтэвчний хуудас руу", "LEARN_MORE": "Нэмэлт мэдээлэл авах {0}", "ABOUT": "тухай", "TOTAL_BALANCE": "Нийт үлдэгдэл: {0} {1}", @@ -1422,7 +1422,7 @@ "EARN_BY": "{0} {1} гэхэд олох", "STAKING": "бооцоо тавих", "TOOLTIP": "Үлдэгдэл хүлээгдэж буй төлөвт ороогүй эсвэл арилжаанд түгжигдсэн (нээлттэй захиалга)", - "WALLET_HAS_BALANCE_PERCENTAGE": "Таны түрийвч одоогоор ямар ч {0} агуулаагүй байна.", + "WALLET_HAS_BALANCE_PERCENTAGE": "Таны ХЭТЭВЧ одоогоор ямар ч {0} агуулаагүй байна.", "WALLET_DEPOSIT": "Та {0} байршуулах эсвэл {1} худалдаж авах боломжтой" }, "DEPOSIT_FORM_MIN_WARNING": "Зөвхөн {0} {1} ба түүнээс дээш хэмжээний хадгаламжийг хүлээн авна. Энэ хамгийн бага босго хэмжээнээс доогуур хадгаламж нь байнгын мөнгө алдахад хүргэдэг.", @@ -1453,18 +1453,18 @@ "UNDERSTAND_RISK_MSG": "Тийм ээ, би эрсдэлийг ойлгож байна" }, "DUST": { - "TITLE": "Түрийвч тоос сорогч", - "LINK": "Түрийвч тоос сорогч", - "TOOLTIP": "Жижиг түрийвчний үлдэгдлийг (тоос) крипто болгон хөрвүүлээрэй", + "TITLE": "Хэтэвч тоос сорогч", + "LINK": "Хэтэвч тоос сорогч", + "TOOLTIP": "Жижиг хэтэвчний үлдэгдлийг (тоос) крипто болгон хөрвүүлэх", "BACK_PLACEHOLDER": "{0} {1}", - "BACK_TO_WALLET": "миний түрийвч рүү", + "BACK_TO_WALLET": "миний хэтэвч рүү", "BACK": "Буцах", "ESTIMATED_TOTAL": "Тооцоолсон нийт тоосны үнэ цэнэ", "CONVERT_ALL": "хөрвүүлэх", - "NO_DUST": "Тоос шороо байхгүй!", + "NO_DUST": "Тоос байхгүй!", "SECTION": { - "TITLE": "Түрийвчний тоосыг хөрвүүлэх", - "TEXT_1": "{0} {1} буюу түүнээс бага утгатай түрийвчний бүх үлдэгдлийг хөрвүүлнэ.", + "TITLE": "хэтэвчний тоосыг хөрвүүлэх", + "TEXT_1": "{0} {1} буюу түүнээс бага утгатай хэтэвчний бүх үлдэгдлийг хөрвүүлнэ.", "TEXT_2": "Бүх харилцан яриаг {0} ({1}) дотор шийдвэрлэх болно." }, "CONFIRMATION": { @@ -1480,88 +1480,88 @@ "SUCCESSFUL": { "TITLE": "Тоосжилт амжилттай боллоо!", "TEXT": "Та хүлээн авлаа", - "VIEW_HISTORY": "түүхийг үзэх", + "VIEW_HISTORY": "түүх үзэх", "CLOSE": "хаах" } }, "PROFIT_LOSS": { "BACK": "Буцах", - "BACK_TO_WALLET": "түрийвч рүү", - "WALLET_PERFORMANCE_TITLE": "Гүйцэтгэлийг тэнцвэржүүлэх", - "WALLET_PERFORMANCE_DESCRIPTION": "Таны хэтэвчний үлдэгдлийн гүйцэтгэл болон хөрөнгийн задаргаа. Доорх огноонууд дээр дарж түрийвчнийхээ тухайн өдрийн гүйцэтгэлийг харна уу.", - "PL_7_DAY": "7 өдрийн P&L", - "EST_TOTAL_BALANCE": "Зүүн. Нийт үлдэгдэл", + "BACK_TO_WALLET": "Хэтэвч рүү буцах", + "WALLET_PERFORMANCE_TITLE": "Гүйцэтгэлийн баланс", + "WALLET_PERFORMANCE_DESCRIPTION": "Таны хэтэвчний үлдэгдлийн гүйцэтгэл болон хөрөнгийн задаргаа. Доорх огноонууд дээр дарж хэтэвчнийхээ тухайн өдрийн гүйцэтгэлийг харна уу.", + "PL_7_DAY": "7 хоногийн ашиг, алдагдал", + "EST_TOTAL_BALANCE": "Багцаа үлдэгдэл", "WEEK": "долоо хоног", "MONTH": "сар", "MONTHS": "сар", - "WALLET_BALANCE": "Түрийвчний үлдэгдлийн задаргаа", - "WALLET_BALANCE_DESCRIPTION_1": "Доорх нь түрийвчний задаргаа юм", + "WALLET_BALANCE": "хэтэвчний үлдэгдлийн задаргаа", + "WALLET_BALANCE_DESCRIPTION_1": "хэтэвчний задаргаа", "WALLET_BALANCE_DESCRIPTION_2": "Доорх хүснэгтийг шинэчлэхийн тулд дээрх график дээр дарна уу.", - "DATE_SELECT": "Огноог сонгоно уу", + "DATE_SELECT": "Огноо сонгох", "ASSET_NAME": "Хөрөнгийн нэр", "BALANCE_AMOUNT": "Үлдэгдэл дүн", "VALUE": "Үнэ цэнэ", - "PERFORMANCE_TREND": "7 өдрийн гүйцэтгэлийн чиг хандлага", - "CUSTOM_DATE_DESCRIPTION": "Түүхийн мэдээллээ авахын тулд тодорхой огноог сонгоно уу (огнооны зөрүү 3 сараас хэтрэхгүй)", - "SELECT_START_DATE": "Эхлэх огноог сонгоно уу", - "SELECT_END_DATE": "Дуусах огноог сонгоно уу", + "PERFORMANCE_TREND": "7 хоногийн чиг хандлага", + "CUSTOM_DATE_DESCRIPTION": "Хуулга авахын тулд тодорхой огноог сонгоно уу (3 сараас хэтрэхгүй)", + "SELECT_START_DATE": "Эхлэх огноо", + "SELECT_END_DATE": "Дуусах огноо", "CUSTOM": "Захиалгат", "BACK_CUSTOM": "БУЦАХ", - "PROOCED_CUSTOM": "НЭМЭГДСЭН" + "PROOCED_CUSTOM": "ҮРГЭЛЖЛҮҮЛЭХ" }, "ASSET_INFO": "Хөрөнгийн мэдээлэл", - "TAKER_FEES_APPLIED": "Хүлээн авагчийн хураамж авдаг", + "TAKER_FEES_APPLIED": "Авах шимтгэл хэрэглэнэ", "ASSET_INFO_PAGE": "Хөрөнгийн мэдээллийн хуудас", "DIGITAL_ASSETS": { "DIGITAL_ASSETS_TITLE": "Дижитал хөрөнгө", "GO_BACK": "Буцах", - "ASSETS_INFO": "Доорх платформ дээрх боломжтой хөрөнгийг доор харуулав.", - "ASSETS_INFO_DETAIL": "Дэлгэрэнгүй үзэхийн тулд та доорх жагсаалтын өмч дээр дарж болно.", - "QUICK_TRADE": "ШУУРХАЙ ХУДАЛДАА", + "ASSETS_INFO": "Биржийн хөрөнгүүдийг дор харуулав.", + "ASSETS_INFO_DETAIL": "Тухайн хөрөнгө дээр дарж дэлгэрэнгүй мэдээллийг авч болно.", + "QUICK_TRADE": "ХЯЛБАР АРИЛЖАА", "PRO_TRADE": "PRO TRADE", "MARKETS": "ЗАХ ЗЭЭЛ", - "WALLET": "ТҮРИЙВЧ", + "WALLET": "ХЭТЭВЧ", "PRICE_SOURCE": "Үнийн эх үүсвэр", "ORDERBOOK": "Захиалгын дэвтэр", "NETWORK": "Сүлжээний брокер OTC", - "BROKER": "Орон нутгийн брокер OTC", + "BROKER": "Дотоод брокер OTC", "BROKERAGE": "NA - (Зуучлах)" }, "HOLLAEX_TOKEN": { "REMOVE_FAVOURITES": "Дуртай зүйлсээс хасах", - "ADD_FAVOURITES": "Дуртай зүйлд нэмнэ үү", + "ADD_FAVOURITES": "Дуртай зүйлд нэмэх", "GO_BACK": " Буцах", "BALANCE": "Үлдэгдэл:", - "OPEN_WALLET": "(Нээлттэй хэтэвч)", + "OPEN_WALLET": "(Хэтэвч нээх)", "ABOUT": "тухай", - "VIEW": "Илүү ихийг үзэх", + "VIEW": "Дэлгэрэнгүй", "COMING_SOON": "Тун удахгүй...", - "NO_DESCRIPTION": "Энэ дижитал хөрөнгөд одоогоор тайлбар байхгүй байна.", - "STAKE": "Гадас", + "NO_DESCRIPTION": "Энэ виртуал хөрөнгөд одоогоор тайлбар байхгүй байна.", + "STAKE": "Стэйк", "MORE": "Илүү", "INFO": "мэдээлэл", - "TRADE": "ХУДАЛДАА", - "QUICK_TRADE": "ШУУРХАЙ ХУДАЛДАА {0}", + "TRADE": "АРИЛЖАА", + "QUICK_TRADE": "ХЯЛБАР АРИЛЖАА {0}", "PRICES": { "TITLE": "Үнэ", - "QUICK_TRADE": "Түргэн худалдаа", - "SUBTITLE": "{0}-н худалдах, худалдах үнийг харахын тулд {1}-д зочилно уу.", - "FOOTER": "Хурдан арилжаагаар хийгдсэн бүх арилжаанд зах зээлд оролцогчдын арилжааны хураамжийг хэрэглэнэ." + "QUICK_TRADE": "Хялбар арилжаа", + "SUBTITLE": "{0}-н худалдах, худалдах үнийг харахын тулд {1}-д очно уу.", + "FOOTER": "Хялбар арилжаагаар хийгдсэн бүх арилжаанд маркет шимтгэлийг хэрэглэнэ." }, - "LIST": "Та дижитал хөрөнгөө жагсаахыг хүсч байна уу?", + "LIST": "Та виртуал хөрөнгөө жагсаахыг хүсч байна уу?", "WEBSITE": "Вэб сайт", - "EXPLORER": "Судлаач" + "EXPLORER": "Explorer" }, "ACCORDIAN": { - "ACCORDIAN_ASSETS": "Бүх түрийвчний хөрөнгө", - "ACCORDIAN_INFO": "ХӨРӨНГИЙН МЭДЭЭЛЛИЙН ХУУДАС", + "ACCORDIAN_ASSETS": "Бүх хөрөнгө", + "ACCORDIAN_INFO": "ХӨРӨНГИЙН МЭДЭЭЛЭЛ", "ACCORDIAN_HISTORY": "ТҮҮХ" }, "ASYNC_LINK": { "TITLE": "Хуудас автоматаар нээгдэхгүй байна уу?", "TEXT": "Таны хөтөч хуудсыг хааж байж магадгүй. Оронд нь доорх холбоосыг хуулж буулгаад үзээрэй." }, - "TERMS_OF_SERVICES": { "TO_GET_ACCESS": "Хандалт авахын тулд холбогдоно уу" }, + "TERMS_OF_SERVICES": { "TO_GET_ACCESS": "To get access reach out to" }, "FEES_AND_LIMITS": { "LINK": "Миний хураамж, хязгаарлалтыг харах", "COIN_PAGE_LINK": "Арилжааны хураамж ба хязгаарлалт", @@ -1570,54 +1570,54 @@ "SEARCH_PLACEHOLDER": "Хайх...", "TABS": { "TRADING_FEES": { - "TITLE": "Худалдааны хураамж", + "TITLE": "Арилжааны шимтгэл", "TABLE": { - "TITLE": "Зах зээлийн арилжааны төлбөр", - "SUBTITLE": "Зах зээлийн хувь хүний арилжааны хураамжийн дүрмийг доор харуулав.", + "TITLE": "Арилжааны шимтгэл", + "SUBTITLE": "Арилжааны шимтгэлийг дор харуулав.", "HEADER": { "MARKET": "Зах зээл", - "MAKER": "Үйлдвэрлэгчийн арилжааны хураамж (захиалгыг хязгаарлах)", - "TAKER": "Такерын арилжааны хураамж (зах зээлийн захиалга)" + "MAKER": "Зарах шимтгэл (лимиттэй захиалга)", + "TAKER": "Авах шимтгэл (маркет захиалга)" } } }, "WITHDRAWAL_FEES": { - "TITLE": "Татан авалтын хураамж", + "TITLE": "Зарлагын шимтгэл", "TABLE": { - "TITLE": "Татгалзах үед хураамжийг хасна", - "SUBTITLE": "Хөрөнгийг эргүүлэн татахад төлөх бүх хураамжийг доор харуулав.", - "NOT_ALLOWED": "Зөвшөөрөгдөөгүй", + "TITLE": "Зарлага гарахын өмнө шимтгэл хасагдана", + "SUBTITLE": "Зарлагын шимтгэл, хураамжийн хэмжээг доор харуулав.", + "NOT_ALLOWED": "Not allowed", "HEADER": { "CURRENCY": "Валют/хөрөнгө", - "DEPOSIT": "Хадгаламжийн хураамж", - "WITHDRAWAL": "Татан авалтын хураамж" + "DEPOSIT": "Орлогын шимтгэл", + "WITHDRAWAL": "Зарлагын шимтгэл" } } }, "WITHDRAWAL_LIMITS": { - "TITLE": "Татан авалтын хязгаарлалт", + "TITLE": "Зарлагын хязгаарлалт", "TABLE_1": { - "TITLE": "Бие даасан мөнгө авах хязгаар", - "SUBTITLE": "Хамтын хязгаарлалтын дүрмээс тусгаарлагдсан, өөрийн бие даасан 24 цагийн мөнгө татах дүрмийг дагаж мөрддөг хөрөнгө:", + "TITLE": "Тусгайлсан хязгаарлалт", + "SUBTITLE": "Дундын хязгаарлалт ашигладаггүй виртуал хөрөнгүүд:", "HEADER": { "CURRENCY": "Валют/хөрөнгө", - "LIMIT": "Өдөр тутмын хязгаар", + "LIMIT": "Өдрийн хязгаар", "LIMIT_2": "Сарын хязгаар" }, - "LIMIT_TEXT": "(Бүх нийтээр татан авах хязгаарын хэмжээг хуваалцдаг хөрөнгө)", - "LIMIT_TEXT_2": "(Зөвхөн өөрийн мөнгөн тэмдэгт дээр суурилсан хязгаарлалт)", + "LIMIT_TEXT": "(Дундын лимиттэй виртуал хөрөнгүүд)", + "LIMIT_TEXT_2": "(Тусгайлсан лимиттэй виртуал хөрөнгүүд)", "VALUED": "(үнэлэгдсэн)", "NO_INDEPENDENT": "Энэ түвшний хувьд бие даасан хязгаарлалт байхгүй", - "LIMIT_TEXT_3": "(Бүгд {0}-д заасан өдөр тутмын мөнгө авах хязгаарын хэмжээг хуваалцдаг хөрөнгө)", - "LIMIT_TEXT_4": "(Бүгд нь {0}-д заасан сарын мөнгө авах хязгаарын хэмжээг хуваалцдаг хөрөнгө)" + "LIMIT_TEXT_3": "(Өдрийн лимит {0})", + "LIMIT_TEXT_4": "(Сарын лимит {0})" }, "TABLE_2": { - "TITLE": "Бие даасан хязгаар", - "SUBTITLE": "Өөрийн мөнгөн тэмдэгтээр өдөр бүр, сар бүр авах хязгаартай хөрөнгө:" + "TITLE": "Тусгайлсан лимит", + "SUBTITLE": "Тусгайлсан лимиттэй виртуал хөрөнгүүд:" }, "TABLE_3": { - "TITLE": "Хамтын хязгаарлалт", - "SUBTITLE": "Бүлэг зоосыг авах өдөр тутмын болон сарын хязгаарыг нэгтгэсэн" + "TITLE": "Дундын лимит", + "SUBTITLE": "Сар болон өдөр тутмын дундын лимит" } } } @@ -1626,20 +1626,20 @@ "INCOMPLETE": "бүрэн бус", "PENDING": "хүлээгдэж байна", "REJECTED": "татгалзсан", - "VERIFIED": "баталгаажуулсан" + "VERIFIED": "баталгаажсан" }, "LOGINS_HISTORY": { - "TAB": "Нэвтрэх түүх", + "TAB": "Нэвтрэлтийн түүх", "CONTENT": { "TITLE": "Нэвтрэх оролдлогын бүртгэл", - "SUBTITLE": "Таны дансанд нэвтэрч чадаагүй бүх оролдлого болон тэдгээрийн боломжит гарал үүслийн түүхэн тэмдэглэл.", + "SUBTITLE": "Таны дансанд нэвтэрч чадаагүй бүх оролдлого болон тэдгээрийн түүх.", "DOWNLOAD_HISTORY": "ТҮҮХ_ТАТАХ", - "FILTER": { "STATUS": "Статус", "ALL": "Бүгд", "FAILED": "Амжилтгүй", "SUCCESS": "Амжилт" }, + "FILTER": { "STATUS": "Статус", "ALL": "Бүгд", "FAILED": "Амжилтгүй", "SUCCESS": "Амжилттай" }, "TABLE": { "HEADER": { "LAST_SEEN": { "TITLE": "Хамгийн сүүлд харсан", - "DESCRIPTION": "(Хамгийн сүүлийн үеийн эхний)" + "DESCRIPTION": "(Шинэ нь эхэнд)" }, "FAILED_ATTEMPTS": "Амжилтгүй оролдлого", "COUNTRY": "Улс", @@ -1647,7 +1647,7 @@ }, "CELL": { "FAILED_LOGIN": "Амжилтгүй нэвтэрсэн: {0}x", - "SUCCESS": "Амжилт", + "SUCCESS": "Амжилттай", "DEVICE": "Төхөөрөмж" } } @@ -1658,34 +1658,34 @@ "CONTENT": { "TITLE": "Идэвхтэй сессүүд", "SUBTITLE": { - "TEXT": "Таны бүртгэлийн идэвхтэй сешнүүдийг доор харуулав. Идэвхтэй сессийг дуусгахын тулд {0} дээр товшвол тэр сессийг гаргана.", + "TEXT": "Таны бүртгэлийн идэвхтэй сешнүүдийг доор харуулав. Идэвхтэй сешнийг дуусгахын тулд {0} дээр дарна.", "LINK": "Хүчингүй болгох" }, "DOWNLOAD": "Татаж авах", "TABLE": { "HEADER": { "LAST_SEEN": { - "TITLE": "Хамгийн сүүлд харсан", - "DESCRIPTION": "(Хамгийн сүүлийн үеийн эхний)" + "TITLE": "Хамгийн сүүлд нэвтэрсэн", + "DESCRIPTION": "(Сүүл нь эхэндээ)" }, - "SESSION_STARTED": "Сессия эхэллээ", - "SESSION_EXPIRY": "Сеанс дуусах", - "STATUS": "Статус" + "SESSION_STARTED": "Сешн эхэлсэн", + "SESSION_EXPIRY": "Сешн дууссан", + "STATUS": "Төлөв" }, "CELL": { "ACTIVE": "Идэвхтэй", "COUNTRY": "Улс", "IP_ADDRESS": "IP хаяг", "DEVICE": "Төхөөрөмж", - "LOGIN_TIME": "Амжилттай нэвтрэх хугацаа" + "LOGIN_TIME": "Нэвтэрсэн хугацаа" } }, - "NOTIFICATION": "Сессийг цуцалсан/гарсан", + "NOTIFICATION": "Сешн цуцалсан/гарсан", "MODAL": { - "TITLE": "Сессийг хүчингүй болгох", - "PROMPT": "Та энэ сессийг хүчингүй болгож, гарахдаа итгэлтэй байна уу?", + "TITLE": "Сешн хүчингүй болгох", + "PROMPT": "Та энэ Сешн хүчингүй болгож, гарахдаа итгэлтэй байна уу?", "BACK": "БУЦАХ", - "CONFIRM": "БАТАЛГААХ" + "CONFIRM": "БАТЛАХ" } } } From 6aa462b596c485f4444370eb0bc176a8cb01065a Mon Sep 17 00:00:00 2001 From: fetok12 Date: Sun, 16 Jun 2024 05:55:41 +0300 Subject: [PATCH 007/108] broker-additional-null-checks --- server/utils/hollaex-tools-lib/tools/broker.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/server/utils/hollaex-tools-lib/tools/broker.js b/server/utils/hollaex-tools-lib/tools/broker.js index a00e73120e..eb0c0e8595 100644 --- a/server/utils/hollaex-tools-lib/tools/broker.js +++ b/server/utils/hollaex-tools-lib/tools/broker.js @@ -154,7 +154,7 @@ const calculateSize = (orderData, side, responseObject, symbol) => { if (incrementUnit < 1) { const decimalPoint = new BigNumber(incrementUnit).dp(); - const sourceAmount = new BigNumber(targetedAmount).decimalPlaces(decimalPoint).toNumber(); + const sourceAmount = new BigNumber(targetedAmount)?.decimalPlaces(decimalPoint)?.toNumber(); receiving_amount = sourceAmount; } else { receiving_amount = targetedAmount - (targetedAmount % incrementUnit); @@ -167,7 +167,7 @@ const calculateSize = (orderData, side, responseObject, symbol) => { if (incrementUnit < 1) { const decimalPoint = new BigNumber(incrementUnit).dp(); - const sourceAmount = new BigNumber(targetedAmount).decimalPlaces(decimalPoint).toNumber(); + const sourceAmount = new BigNumber(targetedAmount)?.decimalPlaces(decimalPoint)?.toNumber(); spending_amount = sourceAmount; } else { spending_amount = targetedAmount - (targetedAmount % incrementUnit); @@ -280,9 +280,9 @@ const calculatePrice = async (side, spread, formula, refresh_interval, brokerId, let convertedPrice = calculateFormula(formula); if (side === 'buy') { - convertedPrice = new BigNumber(convertedPrice).multipliedBy((1 + (spread / 100))).toNumber(); + convertedPrice = new BigNumber(convertedPrice)?.multipliedBy((1 + (spread / 100)))?.toNumber(); } else if (side === 'sell') { - convertedPrice = new BigNumber(convertedPrice).multipliedBy((1 - (spread / 100))).toNumber(); + convertedPrice = new BigNumber(convertedPrice)?.multipliedBy((1 - (spread / 100)))?.toNumber(); } return convertedPrice; @@ -368,8 +368,8 @@ const testBroker = async (data) => { const decimalPoint = new BigNumber(price).dp(); return { - buy_price: new BigNumber(price * (1 - (spread / 100))).decimalPlaces(decimalPoint).toNumber(), - sell_price: new BigNumber(price * (1 + (spread / 100))).decimalPlaces(decimalPoint).toNumber() + buy_price: new BigNumber(price * (1 - (spread / 100)))?.decimalPlaces(decimalPoint)?.toNumber(), + sell_price: new BigNumber(price * (1 + (spread / 100)))?.decimalPlaces(decimalPoint)?.toNumber() }; } catch (err) { throw new Error(err); From 4494764526a6af60ff72261142a73078143e80ca Mon Sep 17 00:00:00 2001 From: ram Date: Mon, 1 Jul 2024 22:14:08 +0530 Subject: [PATCH 008/108] Fixed the web refinements bugs and implemented the url based theme update --- .../Form/FormFields/_FieldWrapper.scss | 1 + web/src/config/lang/en.json | 4 +- web/src/containers/App/App.js | 33 ++++++++++++- web/src/containers/App/Socket.js | 22 +++++++++ .../DigitalAssets/components/AssetsWrapper.js | 46 ++++++++++--------- .../TradeTabs/components/_MarketList.scss | 1 + .../UserSettings/_UserSettings.scss | 12 ++++- web/src/containers/UserSettings/index.js | 14 ++---- web/src/containers/Wallet/CurrencyWallet.js | 40 ++++++++-------- web/src/index.css | 40 +++++++++------- 10 files changed, 143 insertions(+), 70 deletions(-) diff --git a/web/src/components/Form/FormFields/_FieldWrapper.scss b/web/src/components/Form/FormFields/_FieldWrapper.scss index 2cbae261ab..45f6ccd79c 100644 --- a/web/src/components/Form/FormFields/_FieldWrapper.scss +++ b/web/src/components/Form/FormFields/_FieldWrapper.scss @@ -73,6 +73,7 @@ $outline-height: 1.5px; position: relative; display: flex; flex-direction: column; + scrollbar-color: $colors-black $app-background-color; // margin-bottom: $underline-margin-bottom; } diff --git a/web/src/config/lang/en.json b/web/src/config/lang/en.json index 6f0563b874..b57aa69b87 100644 --- a/web/src/config/lang/en.json +++ b/web/src/config/lang/en.json @@ -483,8 +483,8 @@ "PAYMENT_VERIFICATION_HELP_TEXT": "In order for this section to be verified you must complete the {0} section." }, "USER_SETTINGS": { - "TITLE_TEXT_1": "Change the settings of your account. From interface, notifcations, username and other customizations.", - "TITLE_TEXT_2": "Saving your settings will apply the changes and save it.", + "TITLE_TEXT": "Revise your account settings by adjusting preferences such as interface layout, notification preferences, username, and other customizations.", + "TITLE_TEXT_1": "Once you've made your desired changes, saving your settings will apply them and ensure they are retained.", "TITLE_NOTIFICATION": "Notification", "TITLE_INTERFACE": "Interface", "TITLE_LANGUAGE": "Language", diff --git a/web/src/containers/App/App.js b/web/src/containers/App/App.js index 9ffc3f146c..8f81caa898 100644 --- a/web/src/containers/App/App.js +++ b/web/src/containers/App/App.js @@ -1,5 +1,6 @@ import React, { Component } from 'react'; import ReactDOM from 'react-dom'; +import { connect } from 'react-redux'; import classnames from 'classnames'; import EventListener from 'react-event-listener'; import { Helmet } from 'react-helmet'; @@ -212,7 +213,8 @@ class App extends Component { } componentDidUpdate(prevProps) { - const { tools } = this.props; + const { tools, activeTheme } = this.props; + const params = new URLSearchParams(window.location.search); if ( JSON.stringify(prevProps.location) !== JSON.stringify(this.props.location) ) { @@ -221,6 +223,29 @@ class App extends Component { if (JSON.stringify(prevProps.tools) !== JSON.stringify(tools)) { storeTools(tools); } + const themeOptions = [ + 'dark', + 'white', + 'Dark theme', + 'long black', + 'LONG FLAT BLACK', + 'yellow-piller', + ]; + const isValidTheme = themeOptions.includes( + this.props?.router?.location?.query?.theme + ); + this.props.getMe(); + if (!params.has('theme') && isValidTheme) { + params.set('theme', activeTheme); + const currentUrl = window.location.href.split('?')[0]; + const newUrl = `${currentUrl}?${params.toString()}`; + this.props.router.replace(newUrl); + } else if (!isValidTheme) { + params.set('theme', 'dark'); + const currentUrl = window.location.href.split('?')[0]; + const newUrl = `${currentUrl}?${params.toString()}`; + this.props.router.replace(newUrl); + } } componentWillUnmount() { @@ -991,4 +1016,8 @@ class App extends Component { } } -export default withEdit(withConfig(App)); +const mapStateToProps = (store) => ({ + activeTheme: store.app.theme, +}); + +export default connect(mapStateToProps)(withEdit(withConfig(App))); diff --git a/web/src/containers/App/Socket.js b/web/src/containers/App/Socket.js index 2724f2b3e7..6ab64b43e3 100644 --- a/web/src/containers/App/Socket.js +++ b/web/src/containers/App/Socket.js @@ -120,6 +120,17 @@ class Container extends Component { }; getUserDetails = () => { + const themeOptions = [ + 'dark', + 'white', + 'Dark theme', + 'long black', + 'LONG FLAT BLACK', + 'yellow-piller', + ]; + const isValidTheme = themeOptions.includes( + this.props?.router?.location?.query?.theme + ); return this.props .getMe() .then(({ value }) => { @@ -162,6 +173,17 @@ class Container extends Component { }, }, }; + } else if ( + this.props?.router?.location?.query?.theme && + isValidTheme + ) { + this.props.changeTheme( + this.props?.router?.location?.query?.theme + ); + localStorage.setItem( + 'theme', + this.props?.router?.location?.query?.theme + ); } else if ( data.settings.interface.theme !== this.props.activeTheme ) { diff --git a/web/src/containers/DigitalAssets/components/AssetsWrapper.js b/web/src/containers/DigitalAssets/components/AssetsWrapper.js index ca2147fa45..e304b1df4b 100644 --- a/web/src/containers/DigitalAssets/components/AssetsWrapper.js +++ b/web/src/containers/DigitalAssets/components/AssetsWrapper.js @@ -231,30 +231,32 @@ class AssetsWrapper extends Component { return (
-
-
- +
+
+ +
+
+ pageSize} />
-
- {data.length ? ( - pageSize} - /> ) : ( )} diff --git a/web/src/containers/TradeTabs/components/_MarketList.scss b/web/src/containers/TradeTabs/components/_MarketList.scss index 75fed8c8bf..1f361d19fc 100644 --- a/web/src/containers/TradeTabs/components/_MarketList.scss +++ b/web/src/containers/TradeTabs/components/_MarketList.scss @@ -236,6 +236,7 @@ } .custom-header-wrapper { + margin-top: 10%; color: $colors-black; font-family: 'Raleway'; font-weight: bold; diff --git a/web/src/containers/UserSettings/_UserSettings.scss b/web/src/containers/UserSettings/_UserSettings.scss index 427e67f77c..796b7e7652 100644 --- a/web/src/containers/UserSettings/_UserSettings.scss +++ b/web/src/containers/UserSettings/_UserSettings.scss @@ -38,7 +38,7 @@ } .header_title-wrapper { .action_notification-wrapper { - top: 30px; + top: 15px; } } .settings-form-wrapper { @@ -117,3 +117,13 @@ } } } + +@media screen and (min-width: 1920px) { + .settings_container { + .header_title-wrapper { + .action_notification-wrapper { + top: 30px; + } + } + } +} diff --git a/web/src/containers/UserSettings/index.js b/web/src/containers/UserSettings/index.js index 9d093bf307..9015bed9fd 100644 --- a/web/src/containers/UserSettings/index.js +++ b/web/src/containers/UserSettings/index.js @@ -156,11 +156,7 @@ class UserSettings extends Component { { activeLanguage = '', username = '', settings = {}, coins = {} }, activeTab ) => { - const { - constants = {}, - icons: ICONS, - themeOptions, - } = this.props; + const { constants = {}, icons: ICONS, themeOptions } = this.props; const formValues = generateFormValues({ options: themeOptions.map(({ value }) => ({ value, label: value })), }); @@ -451,13 +447,13 @@ class UserSettings extends Component { >
- - {STRINGS['USER_SETTINGS.TITLE_TEXT_1']} + + {STRINGS['USER_SETTINGS.TITLE_TEXT']}
- - {STRINGS['USER_SETTINGS.TITLE_TEXT_2']} + + {STRINGS['USER_SETTINGS.TITLE_TEXT_1']}
diff --git a/web/src/containers/Wallet/CurrencyWallet.js b/web/src/containers/Wallet/CurrencyWallet.js index 70ed489d42..4c87bf43a9 100644 --- a/web/src/containers/Wallet/CurrencyWallet.js +++ b/web/src/containers/Wallet/CurrencyWallet.js @@ -225,21 +225,22 @@ class Wallet extends Component { {!isMobile && - (currency !== BASE_CURRENCY && - parseFloat(balanceText || 0) > 0 ? ( -

- {`(≈ ${baseCoin.display_name} ${balanceText})`} -

- ) : ( - balanceText !== '0' && ( -
+ (currency !== BASE_CURRENCY ? ( + parseFloat(balanceText || 0) > 0 ? ( +

+ {`(≈ ${baseCoin.display_name} ${balanceText})`} +

+ ) : ( + balanceText !== '0' && ( +
+ ) ) - ))} + ) : null)}

{STRINGS.formatString( @@ -327,7 +328,8 @@ class Wallet extends Component { currency.toUpperCase() )} - {coins[currency].allow_deposit && coins[currency].allow_withdrawal ? ( + {coins[currency].allow_deposit && + coins[currency].allow_withdrawal ? ( {STRINGS.formatString( STRINGS['CURRENCY_WALLET.WALLET_DEPOSIT'], @@ -337,13 +339,15 @@ class Wallet extends Component { > {currency.toUpperCase()} , - + here )} - ) : null - } + ) : null} ) : chartData.length ? ( Date: Mon, 1 Jul 2024 22:38:31 +0530 Subject: [PATCH 009/108] Updated the index.css --- web/src/containers/App/App.js | 1 - web/src/index.css | 24 ++++++++++++------------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/web/src/containers/App/App.js b/web/src/containers/App/App.js index 8f81caa898..3fb9cc9383 100644 --- a/web/src/containers/App/App.js +++ b/web/src/containers/App/App.js @@ -234,7 +234,6 @@ class App extends Component { const isValidTheme = themeOptions.includes( this.props?.router?.location?.query?.theme ); - this.props.getMe(); if (!params.has('theme') && isValidTheme) { params.set('theme', activeTheme); const currentUrl = window.location.href.split('?')[0]; diff --git a/web/src/index.css b/web/src/index.css index dddba34459..0ab6951be4 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -377,8 +377,8 @@ table th { height: auto; flex: 1; } .app_container.layout-mobile .app_container-content { - min-height: calc( 100vh - 10rem); - max-height: calc( 100vh - 10rem); + min-height: calc( 100vh - 10rem); + max-height: calc( 100vh - 10rem); max-width: 100vw; overflow-y: scroll; } .app_container.layout-mobile .app_container-content.chart-embed { @@ -396,8 +396,8 @@ table th { .app_container.layout-mobile .app_container-content .app_container-main.no_bottom_navigation { height: 100%; } .app_container.layout-mobile .content-with-bar { - min-height: calc( 100vh - 17rem); - max-height: calc( 100vh - 17rem); + min-height: calc( 100vh - 17rem); + max-height: calc( 100vh - 17rem); max-width: 100vw; padding: 1rem; margin: 0; @@ -4324,8 +4324,8 @@ table th { .layout-mobile .quote-container { background-color: transparent; overflow-y: scroll; - min-height: calc( 100vh - 17rem); - max-height: calc( 100vh - 17rem); } + min-height: calc( 100vh - 17rem); + max-height: calc( 100vh - 17rem); } .layout-mobile .quote-container .quick_trade-wrapper { flex: 1 1; flex-direction: column; @@ -4498,7 +4498,7 @@ table th { .layout-mobile .presentation_container.verification_container { padding-top: 0 !important; - max-height: calc( 100vh - 10rem); } + max-height: calc( 100vh - 10rem); } .layout-mobile .presentation_container.verification_container .header-content { font-size: 13px !important; } @@ -8099,7 +8099,7 @@ table th { padding: 0.3rem 0; } .modal-market-menu .app-bar-add-tab-content .scroll-view { overflow-y: auto; - height: calc( 100vh - 19rem - 8rem); } + height: calc( 100vh - 19rem - 8rem); } .modal-market-menu .app-bar-tab-overflow-content { background-color: var(--base_background); color: var(--labels_secondary-inactive-label-text-graphics); @@ -10574,14 +10574,14 @@ table th { right: 0 !important; min-width: 100vw; max-width: 100vw; - min-height: calc( 100vh - 4rem); - max-height: calc( 100vh - 4rem); + min-height: calc( 100vh - 4rem); + max-height: calc( 100vh - 4rem); border-radius: 0 !important; padding: 0 !important; } .layout-mobile .ReactModal__Content .dialog-mobile-content { padding: 2.5rem !important; - min-height: calc( 100vh - 8rem); - max-height: calc( 100vh - 8rem); + min-height: calc( 100vh - 8rem); + max-height: calc( 100vh - 8rem); display: flex; } .layout-mobile.LogoutModal .ReactModal__Content { From d3de006d955b9acd16e92300ec5019e2dcfaa612 Mon Sep 17 00:00:00 2001 From: mytilene Date: Tue, 2 Jul 2024 12:17:45 +0800 Subject: [PATCH 010/108] Update mn.json --- web/src/config/lang/mn.json | 214 ++++++++++++++++++------------------ 1 file changed, 107 insertions(+), 107 deletions(-) diff --git a/web/src/config/lang/mn.json b/web/src/config/lang/mn.json index eafbe6d0b1..fb6fad6b46 100644 --- a/web/src/config/lang/mn.json +++ b/web/src/config/lang/mn.json @@ -5,12 +5,12 @@ "ADD_TRADING_PAIR": "Маркет сонгох", "CANCEL_BASE_WITHDRAWAL": "{0} зарлага цуцлах", "CANCEL_WITHDRAWAL": "Зарлага цуцлах", - "CANCEL_WITHDRAWAL_POPUP_CONFIRM": "Та дараах зарлагыг цуцлахдаа итгэлтэй байна уу:", + "CANCEL_WITHDRAWAL_POPUP_CONFIRM": "Та дараах хүлээгдэж буй зарлагыг цуцлахдаа итгэлтэй байна уу:", "TIMESTAMP_FORMAT": "YYYY/MM/DD HH:mm:ss", "NO_ACTIVE_ORDERS": "Захиалга байхгүй байна. Та арилжаа эсвэл хялбар арилжаа цэсээр захиалгаа өгөөрэй", - "NO_ACTIVE_TRADES": "Арилжаа хийгдээгүй байна", - "NO_ACTIVE_DEPOSITS": "Орлого байхгүй байна.", - "NO_ACTIVE_WITHDRAWALS": "Зарлага байхгүй байна", + "NO_ACTIVE_TRADES": "Арилжаа одоогоор хийгдээгүй байна", + "NO_ACTIVE_DEPOSITS": "Орлого одоогоор байхгүй байна.", + "NO_ACTIVE_WITHDRAWALS": "Зарлага одоогоор байхгүй байна", "HOUR_FORMAT": "HH:mm:ss", "LOGIN_TEXT": "Нэвтрэх хэсэг", "SIGN_IN": "Нэвтрэх", @@ -42,13 +42,13 @@ "SECONDS": "хором", "VIEW_MARKET": "маркет харах", "GO_TRADE": "Арилжаанд оролцох", - "VIEW_INFO": "Мэдээлэл харах", + "VIEW_INFO": "Мэдээллийн хуудас зочлох", "APPLY_HERE": "Энд дарна уу", "CONVERT": "Хөрвүүлэх", - "TO": "To", + "TO": "Юунд", "HOME": { "MAIN_TITLE": "Крипто арилжааны бирж", - "MAIN_TEXT": "Та өөрийн и-мэйл хаягаар бүртгүүлээд 24 цагийн турш крипто хөрөнгө хялбархан худалдан авах, арилжаалах боломжтой", + "MAIN_TEXT": "Та өөрийн и-мэйл хаягаар бүртгүүлээд 24 цагийн турш крипто хөрөнө хялбархан худалдан авах, арилжаалах боломжтой", "TRADE_CRYPTO": "Арилжаанд оролцох", "VIEW_EXCHANGE": "Трэйдинг платформ" }, @@ -85,13 +85,13 @@ "OPTION_BUG": "Алдааг мэдээлэх", "OPTION_PERSONAL_INFO": "Хувийн мэдээлэл өөрчлөх", "OPTION_BANK_TRANSFER": "Банкны шилжүүлэг", - "OPTION_REQUEST": "Урилга илгээх" + "OPTION_REQUEST": "HollaEx бирж дээр урилга илгээх" }, "SUBJECT_LABEL": "Гарчиг", "SUBJECT_PLACEHOLDER": "Асуудлын тухай гарчиг оруулах", "DESCRIPTION_LABEL": "Тайлбар", "DESCRIPTION_PLACEHOLDER": "Асуудлын дэлгэрэнгүй тайлбар", - "ATTACHMENT_LABEL": "Хавсралт оруулах (хамгийн ихдээ 3)", + "ATTACHMENT_LABEL": "Хасвралт оруулах (хамгийн ихдээ 3)", "ATTACHMENT_PLACEHOLDER": "Асуудалд холбоотой файлууд. PDF, JPG, PNG ба GIF файл оруулах боломжтой", "SUCCESS_TITLE": "Зурвас илгээлээ", "SUCCESS_MESSAGE_1": "Таны асуудлыг хэрэглэгчийн тусламжийн төвд илгээлээ.", @@ -103,7 +103,7 @@ "DESTINATION_TAG": "Таны {0} хүлээн авах tag", "MEMO": "Таны {0} memo" }, - "QR_CODE": "Энэ QR кодыг уншуулан илгээх боломжтой", + "QR_CODE": "Энэ QR кодыг танд мөнгө илгээхийг хүссэн хүн сканнердаж болно", "NO_DATA": "Мэдээлэл байхгүй байна", "QR_CODE_TITLE": "{0} Хадгаламжийн мэдээлэл" }, @@ -113,8 +113,8 @@ "NO_ACCOUNT": "Бүртгэлгүй юу?", "CREATE_ACCOUNT": "Энд дарж бүртгүүлээрэй", "HELP": "Тусламж", - "LOOKING_PRICES": "Ханшийн мэдээл харах уу?", - "VIEW_MARKETS": "Арилжаанд оролцох" + "LOOKING_PRICES": "Үнэ хайж байна уу?", + "VIEW_MARKETS": "Зах зээлүүдийг үзэх" }, "FORM_FIELDS": { "EMAIL_LABEL": "И-мэйл", @@ -132,7 +132,7 @@ "TYPE_EMAIL": "И-мэйл хаяг оруулна уу", "REQUIRED": "Бөглөх шаардлагатай", "INVALID_DATE": "Огноо буруу байна", - "INVALID_PASSWORD": "Нууц үг буруу байна. Доод тал нь 8 тэмдэгттэй, тоо болон тусгай тэмдэгт орно.", + "INVALID_PASSWORD": "Iууц үг буруу байна. Доод тал нь 8 тэмдэгттэй, тоо болон тусгай тэмдэгт орно.", "INVALID_PASSWORD_2": "Нууц үг буруу байна. Доод тал нь 8 тэмдэгттэй, тоо болон тусгай тэмдэгт орно.", "INVALID_CURRENCY": "Дараах {0} хаяг буруу байна ({1})", "INVALID_BALANCE": "Таны баланс ({0}) хүрэлцэхгүй байна: ({1}).", @@ -155,7 +155,7 @@ "SUBTITLE_RECEIVED": "Та {0} орлого хүлээн авлаа", "SUBTITLE_INCOMING": "Танд {0} ирж байна", "INFORMATION_PENDING_1": "Таны {0} арилжаанд орохын тулд ядаж 1 баталгаажуулалт хэрэгтэй.", - "INFORMATION_PENDING_2": "Таны {0} блокчэйн дээр баталгаажсаны дараа бид имэйл илгээх болно." + "INFORMATION_PENDING_2": "Үүнд 10-30 минут зарцуулагдаж магадгүй. Таны {0} блокчлон дээр баталгаажсаны дараа бид имэйл илгээх болно." } }, "REFERRAL_SUCCESS": { "TITLE": "Хүсэлт илгээсэн", "BUTTON_TEXT": "Okay" }, @@ -467,7 +467,7 @@ "RISKY_WARNING_TEXT_3": " Та энэ арилжааг хийхийг үнэхээр хүсч байгаагаа шалгаж, баталгаажуулна уу.", "GO_TO_RISK_MANAGMENT": "ЭРСДЛИЙН УДИРДЛАГА", "CREATE_ORDER_WARING_TEXT": "Таны арилжааны захиалга таны багцын {0}-ээс илүү гарах үед сэрэмжлүүлэг гарна", - "ORDER_PORTFOLIO_LABEL": "хэтэвчний хувь хэмжээ:", + "ORDER_PORTFOLIO_LABEL": "Хэтэвчний хувь хэмжээ:", "NOTIFICATION_FORM": { "POPUP_ORDER_CONFIRMATION": "Захиалга өгөхөөс өмнө баталгаажуулах.", "POPUP_ORDER_COMPLETED": "Захиалга дууссан тухай цонх харуулах", @@ -681,7 +681,7 @@ "SLASHING_TEXT_2": "Бүх орлогыг хураана", "REVIEW_NOTE": "Блокчэйний блокуудын цагаар хэмжигддэг тул та стэйк хийх болон стэйк цуцлахдаа дээрх мэдээллийг сайн нягтална уу. Хугацаанаас өмнө стэйкинг цуцлавал хуримтлагдсан өгөөж цуцлагдах болно", "WAITING_TITLE": "Баталгаажуулахыг хүлээж байна", - "WAITING_TEXT": "Энэ гүйлгээг хэтэвчиндээ баталгаажуулна уу", + "WAITING_TEXT": "Энэ гүйлгээг түрийвчэндээ баталгаажуулна уу", "PENDING_TEXT": "Гүйлгээ хүлээгдэж байна...", "CHECKING_ALLOWANCE": "{0} тэтгэмжийг шалгаж байна...", "WAITING_PROMPT": "{0} {1} {2}", @@ -869,8 +869,8 @@ "TITLE": "XHT-г зөөх", "TEXT_1": "XHT-г бооцоо болгохын тулд та эхлээд өөрийн XHT-ээ өөрийн хэтэвч рүү шилжүүлэх ёстой.", "TEXT_2": "Таны одоо холбогдсон хэтэвчний хаяг байна:", - "LABEL": "хэтэвчний хаяг", - "TEXT_3": "хэтэвчний хаяг найдвартай эсэхийг шалгах нь чухал. XHT нь дээрх хэтэвчний хаяг руу шилжих болно." + "LABEL": "Хэтэвчний хаяг", + "TEXT_3": "Хэтэвчний хаяг найдвартай эсэхийг шалгах нь чухал. XHT нь дээрх хэтэвчний хаяг руу шилжих болно." }, "MOVE_AMOUNT": { "TITLE": "Оруулсан хэмжээ", @@ -943,7 +943,7 @@ "WITHDRAWALS_FORM_DESTINATION_TAG_WARNING": "Хүлээн авах хаяганд tag шаардлагатай эсэхийг шалгана уу. Tag -г зарим тохиолдолд Memo, digital ID, label, note гэж нэрлэдэг.", "WITHDRAWALS_FORM_NETWORK_PLACEHOLDER": "Сүлжээ сонгох", "WITHDRAWALS_FORM_ADDRESS_LABEL": "Хүлээн авах хаяг", - "WITHDRAWALS_FORM_ADDRESS_PLACEHOLDER": "хэтэвчний хаягийг оруулна уу", + "WITHDRAWALS_FORM_ADDRESS_PLACEHOLDER": "Түрийвчний хаягийг оруулна уу", "WITHDRAWALS_FORM_DESTINATION_TAG_LABEL": "Хүлээн авах tag оруулна уу", "WITHDRAWALS_FORM_MEMO_LABEL": "Memo (заавал биш)", "WITHDRAWALS_FORM_DESTINATION_TAG_PLACEHOLDER": "Хүлээн авах tag (заавал биш)", @@ -980,13 +980,13 @@ "WITHDRAWAL_CONFIRM_ADDRESS": "Хаяг", "WITHDRAWAL_CONFIRM_NETWORK": "Сүлжээ", "WITHDRAWAL_CANCEL_BUTTON": "ХААХ", - "WITHDRAWAL_CONFIRM_BUTTON": "ЗАРЛАГА БАТЛАХ" + "WITHDRAWAL_CONFIRM_BUTTON": "ЗАРЛУУЛАХ БАТАЛГАА" }, "WALLET_BUTTON_BASE_DEPOSIT": "орлого", "WALLET_BUTTON_BASE_WITHDRAW": "зарлага", "WALLET_BUTTON_CRYPTOCURRENCY_DEPOSIT": "хүлээн авах", "WALLET_BUTTON_CRYPTOCURRENCY_WITHDRAW": "илгээх", - "AVAILABLE_BALANCE_TEXT": "Боломжмт үлдэгдэл {0}: {1} {2} {3}", + "AVAILABLE_BALANCE_TEXT": "Боломжтой {0} үлдэгдэл: {1} {2} {3}", "BALANCE_TEXT": "Баланс", "CURRENCY_BALANCE_TEXT": "{0} Баланс", "WALLET_ALL_ASSETS": "Бүх хөрөнгө", @@ -1073,7 +1073,7 @@ "ACCESS": "Хандалт", "BASIC_ACCESS": "үндсэн хандалт", "BASIC_ACCESS_PROMPT": "үндсэн хандалт", - "READING_ACCESS": "Унших (хэтэвчний үлдэгдэл гэх мэт)", + "READING_ACCESS": "Унших (Хэтэвчний үлдэгдэл гэх мэт)", "TRADING_ACCESS": "Арилжаа", "IP_ACCESS": "IP хандалт", "IP_ACCESS_PROMPT": "Энэ API түлхүүрээр ямар IP хаяг ажиллахыг тохируулна уу.", @@ -1384,7 +1384,7 @@ "BANK_NAME": "банкны нэр", "VERIFY_BANK_WITHDRAW": "Зардага гаргахын тулд та өөрийн банкны дэлгэрэнгүй мэдээллийн баталгаажуулалтаа дуусгах шаардлагатай. Доорх үргэлжлүүлэх товчийг дарна уу.", "VERIFICATION_TITLE": "Баталгаажуулалт", - "WITHDRAW_NOTE": "Анхаар: Та зөвхөн өөрийн нэр дээрх дансруу мөнгө татах боломжтой.", + "WITHDRAW_NOTE": "Анхаарна уу: Та зөвхөн өөрийн нэр дээрх дансруу мөнгө татах боломжтой.", "USER_PAYMENT": { "TITLE": "Төлбөр" }, "QUOTE_CONFIRMATION_MSG_TEXT_1": "Доорх захиалгаа шалгаад баталгаажуулна уу.", "QUOTE_CONFIRMATION_MSG_TEXT_2": "Хүлээн авах дүн нь урьдчилсан тооцоо бөгөөд арилжааны хураамжийг оруулаагүй болно", @@ -1413,7 +1413,7 @@ "ASSETS": "Хөрөнгө", "CURRENCY_WALLET": { "BACK": "Буцах", - "WALLET_PAGE": "{0} хэтэвчний хуудас руу", + "WALLET_PAGE": "{0} түрийвчний хуудас руу", "LEARN_MORE": "Нэмэлт мэдээлэл авах {0}", "ABOUT": "тухай", "TOTAL_BALANCE": "Нийт үлдэгдэл: {0} {1}", @@ -1422,7 +1422,7 @@ "EARN_BY": "{0} {1} гэхэд олох", "STAKING": "бооцоо тавих", "TOOLTIP": "Үлдэгдэл хүлээгдэж буй төлөвт ороогүй эсвэл арилжаанд түгжигдсэн (нээлттэй захиалга)", - "WALLET_HAS_BALANCE_PERCENTAGE": "Таны ХЭТЭВЧ одоогоор ямар ч {0} агуулаагүй байна.", + "WALLET_HAS_BALANCE_PERCENTAGE": "Таны түрийвч одоогоор ямар ч {0} агуулаагүй байна.", "WALLET_DEPOSIT": "Та {0} байршуулах эсвэл {1} худалдаж авах боломжтой" }, "DEPOSIT_FORM_MIN_WARNING": "Зөвхөн {0} {1} ба түүнээс дээш хэмжээний хадгаламжийг хүлээн авна. Энэ хамгийн бага босго хэмжээнээс доогуур хадгаламж нь байнгын мөнгө алдахад хүргэдэг.", @@ -1453,18 +1453,18 @@ "UNDERSTAND_RISK_MSG": "Тийм ээ, би эрсдэлийг ойлгож байна" }, "DUST": { - "TITLE": "Хэтэвч тоос сорогч", - "LINK": "Хэтэвч тоос сорогч", - "TOOLTIP": "Жижиг хэтэвчний үлдэгдлийг (тоос) крипто болгон хөрвүүлэх", + "TITLE": "Түрийвч тоос сорогч", + "LINK": "Түрийвч тоос сорогч", + "TOOLTIP": "Жижиг түрийвчний үлдэгдлийг (тоос) крипто болгон хөрвүүлээрэй", "BACK_PLACEHOLDER": "{0} {1}", - "BACK_TO_WALLET": "миний хэтэвч рүү", + "BACK_TO_WALLET": "миний түрийвч рүү", "BACK": "Буцах", "ESTIMATED_TOTAL": "Тооцоолсон нийт тоосны үнэ цэнэ", "CONVERT_ALL": "хөрвүүлэх", - "NO_DUST": "Тоос байхгүй!", + "NO_DUST": "Тоос шороо байхгүй!", "SECTION": { - "TITLE": "хэтэвчний тоосыг хөрвүүлэх", - "TEXT_1": "{0} {1} буюу түүнээс бага утгатай хэтэвчний бүх үлдэгдлийг хөрвүүлнэ.", + "TITLE": "Түрийвчний тоосыг хөрвүүлэх", + "TEXT_1": "{0} {1} буюу түүнээс бага утгатай түрийвчний бүх үлдэгдлийг хөрвүүлнэ.", "TEXT_2": "Бүх харилцан яриаг {0} ({1}) дотор шийдвэрлэх болно." }, "CONFIRMATION": { @@ -1480,88 +1480,88 @@ "SUCCESSFUL": { "TITLE": "Тоосжилт амжилттай боллоо!", "TEXT": "Та хүлээн авлаа", - "VIEW_HISTORY": "түүх үзэх", + "VIEW_HISTORY": "түүхийг үзэх", "CLOSE": "хаах" } }, "PROFIT_LOSS": { "BACK": "Буцах", - "BACK_TO_WALLET": "Хэтэвч рүү буцах", - "WALLET_PERFORMANCE_TITLE": "Гүйцэтгэлийн баланс", - "WALLET_PERFORMANCE_DESCRIPTION": "Таны хэтэвчний үлдэгдлийн гүйцэтгэл болон хөрөнгийн задаргаа. Доорх огноонууд дээр дарж хэтэвчнийхээ тухайн өдрийн гүйцэтгэлийг харна уу.", - "PL_7_DAY": "7 хоногийн ашиг, алдагдал", - "EST_TOTAL_BALANCE": "Багцаа үлдэгдэл", + "BACK_TO_WALLET": "түрийвч рүү", + "WALLET_PERFORMANCE_TITLE": "Гүйцэтгэлийг тэнцвэржүүлэх", + "WALLET_PERFORMANCE_DESCRIPTION": "Таны хэтэвчний үлдэгдлийн гүйцэтгэл болон хөрөнгийн задаргаа. Доорх огноонууд дээр дарж түрийвчнийхээ тухайн өдрийн гүйцэтгэлийг харна уу.", + "PL_7_DAY": "7 өдрийн P&L", + "EST_TOTAL_BALANCE": "Зүүн. Нийт үлдэгдэл", "WEEK": "долоо хоног", "MONTH": "сар", "MONTHS": "сар", - "WALLET_BALANCE": "хэтэвчний үлдэгдлийн задаргаа", - "WALLET_BALANCE_DESCRIPTION_1": "хэтэвчний задаргаа", + "WALLET_BALANCE": "Түрийвчний үлдэгдлийн задаргаа", + "WALLET_BALANCE_DESCRIPTION_1": "Доорх нь түрийвчний задаргаа юм", "WALLET_BALANCE_DESCRIPTION_2": "Доорх хүснэгтийг шинэчлэхийн тулд дээрх график дээр дарна уу.", - "DATE_SELECT": "Огноо сонгох", + "DATE_SELECT": "Огноог сонгоно уу", "ASSET_NAME": "Хөрөнгийн нэр", "BALANCE_AMOUNT": "Үлдэгдэл дүн", "VALUE": "Үнэ цэнэ", - "PERFORMANCE_TREND": "7 хоногийн чиг хандлага", - "CUSTOM_DATE_DESCRIPTION": "Хуулга авахын тулд тодорхой огноог сонгоно уу (3 сараас хэтрэхгүй)", - "SELECT_START_DATE": "Эхлэх огноо", - "SELECT_END_DATE": "Дуусах огноо", + "PERFORMANCE_TREND": "7 өдрийн гүйцэтгэлийн чиг хандлага", + "CUSTOM_DATE_DESCRIPTION": "Түүхийн мэдээллээ авахын тулд тодорхой огноог сонгоно уу (огнооны зөрүү 3 сараас хэтрэхгүй)", + "SELECT_START_DATE": "Эхлэх огноог сонгоно уу", + "SELECT_END_DATE": "Дуусах огноог сонгоно уу", "CUSTOM": "Захиалгат", "BACK_CUSTOM": "БУЦАХ", - "PROOCED_CUSTOM": "ҮРГЭЛЖЛҮҮЛЭХ" + "PROOCED_CUSTOM": "НЭМЭГДСЭН" }, "ASSET_INFO": "Хөрөнгийн мэдээлэл", - "TAKER_FEES_APPLIED": "Авах шимтгэл хэрэглэнэ", + "TAKER_FEES_APPLIED": "Хүлээн авагчийн хураамж авдаг", "ASSET_INFO_PAGE": "Хөрөнгийн мэдээллийн хуудас", "DIGITAL_ASSETS": { "DIGITAL_ASSETS_TITLE": "Дижитал хөрөнгө", "GO_BACK": "Буцах", - "ASSETS_INFO": "Биржийн хөрөнгүүдийг дор харуулав.", - "ASSETS_INFO_DETAIL": "Тухайн хөрөнгө дээр дарж дэлгэрэнгүй мэдээллийг авч болно.", - "QUICK_TRADE": "ХЯЛБАР АРИЛЖАА", + "ASSETS_INFO": "Доорх платформ дээрх боломжтой хөрөнгийг доор харуулав.", + "ASSETS_INFO_DETAIL": "Дэлгэрэнгүй үзэхийн тулд та доорх жагсаалтын өмч дээр дарж болно.", + "QUICK_TRADE": "ШУУРХАЙ ХУДАЛДАА", "PRO_TRADE": "PRO TRADE", "MARKETS": "ЗАХ ЗЭЭЛ", - "WALLET": "ХЭТЭВЧ", + "WALLET": "ТҮРИЙВЧ", "PRICE_SOURCE": "Үнийн эх үүсвэр", "ORDERBOOK": "Захиалгын дэвтэр", "NETWORK": "Сүлжээний брокер OTC", - "BROKER": "Дотоод брокер OTC", + "BROKER": "Орон нутгийн брокер OTC", "BROKERAGE": "NA - (Зуучлах)" }, "HOLLAEX_TOKEN": { "REMOVE_FAVOURITES": "Дуртай зүйлсээс хасах", - "ADD_FAVOURITES": "Дуртай зүйлд нэмэх", + "ADD_FAVOURITES": "Дуртай зүйлд нэмнэ үү", "GO_BACK": " Буцах", "BALANCE": "Үлдэгдэл:", - "OPEN_WALLET": "(Хэтэвч нээх)", + "OPEN_WALLET": "(Нээлттэй хэтэвч)", "ABOUT": "тухай", - "VIEW": "Дэлгэрэнгүй", + "VIEW": "Илүү ихийг үзэх", "COMING_SOON": "Тун удахгүй...", - "NO_DESCRIPTION": "Энэ виртуал хөрөнгөд одоогоор тайлбар байхгүй байна.", - "STAKE": "Стэйк", + "NO_DESCRIPTION": "Энэ дижитал хөрөнгөд одоогоор тайлбар байхгүй байна.", + "STAKE": "Гадас", "MORE": "Илүү", "INFO": "мэдээлэл", - "TRADE": "АРИЛЖАА", - "QUICK_TRADE": "ХЯЛБАР АРИЛЖАА {0}", + "TRADE": "ХУДАЛДАА", + "QUICK_TRADE": "ШУУРХАЙ ХУДАЛДАА {0}", "PRICES": { "TITLE": "Үнэ", - "QUICK_TRADE": "Хялбар арилжаа", - "SUBTITLE": "{0}-н худалдах, худалдах үнийг харахын тулд {1}-д очно уу.", - "FOOTER": "Хялбар арилжаагаар хийгдсэн бүх арилжаанд маркет шимтгэлийг хэрэглэнэ." + "QUICK_TRADE": "Түргэн худалдаа", + "SUBTITLE": "{0}-н худалдах, худалдах үнийг харахын тулд {1}-д зочилно уу.", + "FOOTER": "Хурдан арилжаагаар хийгдсэн бүх арилжаанд зах зээлд оролцогчдын арилжааны хураамжийг хэрэглэнэ." }, - "LIST": "Та виртуал хөрөнгөө жагсаахыг хүсч байна уу?", + "LIST": "Та дижитал хөрөнгөө жагсаахыг хүсч байна уу?", "WEBSITE": "Вэб сайт", - "EXPLORER": "Explorer" + "EXPLORER": "Судлаач" }, "ACCORDIAN": { - "ACCORDIAN_ASSETS": "Бүх хөрөнгө", - "ACCORDIAN_INFO": "ХӨРӨНГИЙН МЭДЭЭЛЭЛ", + "ACCORDIAN_ASSETS": "Бүх түрийвчний хөрөнгө", + "ACCORDIAN_INFO": "ХӨРӨНГИЙН МЭДЭЭЛЛИЙН ХУУДАС", "ACCORDIAN_HISTORY": "ТҮҮХ" }, "ASYNC_LINK": { "TITLE": "Хуудас автоматаар нээгдэхгүй байна уу?", "TEXT": "Таны хөтөч хуудсыг хааж байж магадгүй. Оронд нь доорх холбоосыг хуулж буулгаад үзээрэй." }, - "TERMS_OF_SERVICES": { "TO_GET_ACCESS": "To get access reach out to" }, + "TERMS_OF_SERVICES": { "TO_GET_ACCESS": "Хандалт авахын тулд холбогдоно уу" }, "FEES_AND_LIMITS": { "LINK": "Миний хураамж, хязгаарлалтыг харах", "COIN_PAGE_LINK": "Арилжааны хураамж ба хязгаарлалт", @@ -1570,54 +1570,54 @@ "SEARCH_PLACEHOLDER": "Хайх...", "TABS": { "TRADING_FEES": { - "TITLE": "Арилжааны шимтгэл", + "TITLE": "Худалдааны хураамж", "TABLE": { - "TITLE": "Арилжааны шимтгэл", - "SUBTITLE": "Арилжааны шимтгэлийг дор харуулав.", + "TITLE": "Зах зээлийн арилжааны төлбөр", + "SUBTITLE": "Зах зээлийн хувь хүний арилжааны хураамжийн дүрмийг доор харуулав.", "HEADER": { "MARKET": "Зах зээл", - "MAKER": "Зарах шимтгэл (лимиттэй захиалга)", - "TAKER": "Авах шимтгэл (маркет захиалга)" + "MAKER": "Үйлдвэрлэгчийн арилжааны хураамж (захиалгыг хязгаарлах)", + "TAKER": "Такерын арилжааны хураамж (зах зээлийн захиалга)" } } }, "WITHDRAWAL_FEES": { - "TITLE": "Зарлагын шимтгэл", + "TITLE": "Татан авалтын хураамж", "TABLE": { - "TITLE": "Зарлага гарахын өмнө шимтгэл хасагдана", - "SUBTITLE": "Зарлагын шимтгэл, хураамжийн хэмжээг доор харуулав.", - "NOT_ALLOWED": "Not allowed", + "TITLE": "Татгалзах үед хураамжийг хасна", + "SUBTITLE": "Хөрөнгийг эргүүлэн татахад төлөх бүх хураамжийг доор харуулав.", + "NOT_ALLOWED": "Зөвшөөрөгдөөгүй", "HEADER": { "CURRENCY": "Валют/хөрөнгө", - "DEPOSIT": "Орлогын шимтгэл", - "WITHDRAWAL": "Зарлагын шимтгэл" + "DEPOSIT": "Хадгаламжийн хураамж", + "WITHDRAWAL": "Татан авалтын хураамж" } } }, "WITHDRAWAL_LIMITS": { - "TITLE": "Зарлагын хязгаарлалт", + "TITLE": "Татан авалтын хязгаарлалт", "TABLE_1": { - "TITLE": "Тусгайлсан хязгаарлалт", - "SUBTITLE": "Дундын хязгаарлалт ашигладаггүй виртуал хөрөнгүүд:", + "TITLE": "Бие даасан мөнгө авах хязгаар", + "SUBTITLE": "Хамтын хязгаарлалтын дүрмээс тусгаарлагдсан, өөрийн бие даасан 24 цагийн мөнгө татах дүрмийг дагаж мөрддөг хөрөнгө:", "HEADER": { "CURRENCY": "Валют/хөрөнгө", - "LIMIT": "Өдрийн хязгаар", + "LIMIT": "Өдөр тутмын хязгаар", "LIMIT_2": "Сарын хязгаар" }, - "LIMIT_TEXT": "(Дундын лимиттэй виртуал хөрөнгүүд)", - "LIMIT_TEXT_2": "(Тусгайлсан лимиттэй виртуал хөрөнгүүд)", + "LIMIT_TEXT": "(Бүх нийтээр татан авах хязгаарын хэмжээг хуваалцдаг хөрөнгө)", + "LIMIT_TEXT_2": "(Зөвхөн өөрийн мөнгөн тэмдэгт дээр суурилсан хязгаарлалт)", "VALUED": "(үнэлэгдсэн)", "NO_INDEPENDENT": "Энэ түвшний хувьд бие даасан хязгаарлалт байхгүй", - "LIMIT_TEXT_3": "(Өдрийн лимит {0})", - "LIMIT_TEXT_4": "(Сарын лимит {0})" + "LIMIT_TEXT_3": "(Бүгд {0}-д заасан өдөр тутмын мөнгө авах хязгаарын хэмжээг хуваалцдаг хөрөнгө)", + "LIMIT_TEXT_4": "(Бүгд нь {0}-д заасан сарын мөнгө авах хязгаарын хэмжээг хуваалцдаг хөрөнгө)" }, "TABLE_2": { - "TITLE": "Тусгайлсан лимит", - "SUBTITLE": "Тусгайлсан лимиттэй виртуал хөрөнгүүд:" + "TITLE": "Бие даасан хязгаар", + "SUBTITLE": "Өөрийн мөнгөн тэмдэгтээр өдөр бүр, сар бүр авах хязгаартай хөрөнгө:" }, "TABLE_3": { - "TITLE": "Дундын лимит", - "SUBTITLE": "Сар болон өдөр тутмын дундын лимит" + "TITLE": "Хамтын хязгаарлалт", + "SUBTITLE": "Бүлэг зоосыг авах өдөр тутмын болон сарын хязгаарыг нэгтгэсэн" } } } @@ -1626,20 +1626,20 @@ "INCOMPLETE": "бүрэн бус", "PENDING": "хүлээгдэж байна", "REJECTED": "татгалзсан", - "VERIFIED": "баталгаажсан" + "VERIFIED": "баталгаажуулсан" }, "LOGINS_HISTORY": { - "TAB": "Нэвтрэлтийн түүх", + "TAB": "Нэвтрэх түүх", "CONTENT": { "TITLE": "Нэвтрэх оролдлогын бүртгэл", - "SUBTITLE": "Таны дансанд нэвтэрч чадаагүй бүх оролдлого болон тэдгээрийн түүх.", + "SUBTITLE": "Таны дансанд нэвтэрч чадаагүй бүх оролдлого болон тэдгээрийн боломжит гарал үүслийн түүхэн тэмдэглэл.", "DOWNLOAD_HISTORY": "ТҮҮХ_ТАТАХ", - "FILTER": { "STATUS": "Статус", "ALL": "Бүгд", "FAILED": "Амжилтгүй", "SUCCESS": "Амжилттай" }, + "FILTER": { "STATUS": "Статус", "ALL": "Бүгд", "FAILED": "Амжилтгүй", "SUCCESS": "Амжилт" }, "TABLE": { "HEADER": { "LAST_SEEN": { "TITLE": "Хамгийн сүүлд харсан", - "DESCRIPTION": "(Шинэ нь эхэнд)" + "DESCRIPTION": "(Хамгийн сүүлийн үеийн эхний)" }, "FAILED_ATTEMPTS": "Амжилтгүй оролдлого", "COUNTRY": "Улс", @@ -1647,7 +1647,7 @@ }, "CELL": { "FAILED_LOGIN": "Амжилтгүй нэвтэрсэн: {0}x", - "SUCCESS": "Амжилттай", + "SUCCESS": "Амжилт", "DEVICE": "Төхөөрөмж" } } @@ -1658,34 +1658,34 @@ "CONTENT": { "TITLE": "Идэвхтэй сессүүд", "SUBTITLE": { - "TEXT": "Таны бүртгэлийн идэвхтэй сешнүүдийг доор харуулав. Идэвхтэй сешнийг дуусгахын тулд {0} дээр дарна.", + "TEXT": "Таны бүртгэлийн идэвхтэй сешнүүдийг доор харуулав. Идэвхтэй сессийг дуусгахын тулд {0} дээр товшвол тэр сессийг гаргана.", "LINK": "Хүчингүй болгох" }, "DOWNLOAD": "Татаж авах", "TABLE": { "HEADER": { "LAST_SEEN": { - "TITLE": "Хамгийн сүүлд нэвтэрсэн", - "DESCRIPTION": "(Сүүл нь эхэндээ)" + "TITLE": "Хамгийн сүүлд харсан", + "DESCRIPTION": "(Хамгийн сүүлийн үеийн эхний)" }, - "SESSION_STARTED": "Сешн эхэлсэн", - "SESSION_EXPIRY": "Сешн дууссан", - "STATUS": "Төлөв" + "SESSION_STARTED": "Сессия эхэллээ", + "SESSION_EXPIRY": "Сеанс дуусах", + "STATUS": "Статус" }, "CELL": { "ACTIVE": "Идэвхтэй", "COUNTRY": "Улс", "IP_ADDRESS": "IP хаяг", "DEVICE": "Төхөөрөмж", - "LOGIN_TIME": "Нэвтэрсэн хугацаа" + "LOGIN_TIME": "Амжилттай нэвтрэх хугацаа" } }, - "NOTIFICATION": "Сешн цуцалсан/гарсан", + "NOTIFICATION": "Сессийг цуцалсан/гарсан", "MODAL": { - "TITLE": "Сешн хүчингүй болгох", - "PROMPT": "Та энэ Сешн хүчингүй болгож, гарахдаа итгэлтэй байна уу?", + "TITLE": "Сессийг хүчингүй болгох", + "PROMPT": "Та энэ сессийг хүчингүй болгож, гарахдаа итгэлтэй байна уу?", "BACK": "БУЦАХ", - "CONFIRM": "БАТЛАХ" + "CONFIRM": "БАТАЛГААХ" } } } From 8962e3d4cd67825883bb6551aadc01ac95940bff Mon Sep 17 00:00:00 2001 From: mytilene Date: Tue, 2 Jul 2024 12:27:03 +0800 Subject: [PATCH 011/108] Update mn.json --- web/src/config/lang/mn.json | 56 ++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/web/src/config/lang/mn.json b/web/src/config/lang/mn.json index fb6fad6b46..24081adbba 100644 --- a/web/src/config/lang/mn.json +++ b/web/src/config/lang/mn.json @@ -105,7 +105,7 @@ }, "QR_CODE": "Энэ QR кодыг танд мөнгө илгээхийг хүссэн хүн сканнердаж болно", "NO_DATA": "Мэдээлэл байхгүй байна", - "QR_CODE_TITLE": "{0} Хадгаламжийн мэдээлэл" + "QR_CODE_TITLE": "{0} Орлогын мэдээлэл" }, "LOGIN": { "LOGIN_TO": "{0} нэвтрэх", @@ -1178,7 +1178,7 @@ "ACTIVE_2FA_SECURITY": "2FA Хамгаалалт идэвхижүүлэх", "ACCOUNT_ASSETS_TXT_1": "Энэ хэсэгт таны бүх хөрөнгийн хураангуй байна.", "ACCOUNT_ASSETS_TXT_2": "Их хэмжээний хөрөнгөтэй байх нь танд өвөрмөц тэмдэг, арилжааны хураамж бага зэрэг дансны шинэчлэлт хийх эрх олгоно.", - "ACCOUNT_DETAILS_TXT_1": "Таны хэрэглэгчийн түвшин нь арилжааны хураамж, хадгаламж, мөнгө авах хязгаарыг тодорхойлдог.", + "ACCOUNT_DETAILS_TXT_1": "Таны хэрэглэгчийн түвшин нь арилжааны хураамж, орлого, зарлагын хязгаарыг тодорхойлдог.", "ACCOUNT_DETAILS_TXT_2": "Таны арилжаанд оролцсон хугацаа, үйл ажиллагааны түвшин болон дансны нийт хөрөнгийн хэмжээ таны дансыг шинэчлэх боломжтой эсэхийг тодорхойлно.", "ACCOUNT_DETAILS_TXT_3": "Та түвшингээ хадгалахын тулд тогтмол арилжаа хийх, тодорхой хэмжээний хөрөнгө хадгалах шаардлагатай.", "ACCOUNT_DETAILS_TXT_4": "Та тогтмол арилжаа болон хадгалалт хийгээгүй тохиолдолд таны түвшин буурна.", @@ -1345,8 +1345,8 @@ "UNVERIFIED": { "TITLE": "Бүрэн баталгаажуулалт", "TEXT": "{0}-г хийхийн тулд та өөрийн банкны дэлгэрэнгүй мэдээллийг баталгаажуулалтаа дуусгах шаардлагатай. Доорх үргэлжлүүлэх товчийг дарна уу.", - "DEPOSIT": "хадгаламж", - "WITHDRAWAL": "татах" + "DEPOSIT": "орлого", + "WITHDRAWAL": "зарлага" }, "REVIEW_DEPOSIT": { "TITLE": "Орлогын дэлгэрэнгүй мэдээллийг шалгаж баталгаажуулна уу", @@ -1367,7 +1367,7 @@ "AMOUNT_FORMAT": "{0} {1}", "PENDING_DEPOSIT_TITLE": "Орлого хүлээгдэж байна", "PENDING_DEPOSIT_TEXT_1": "Таны орлого хүсэлт баталгаажуулах хийхийг хүлээж байна.", - "PENDING_DEPOSIT_TEXT_2": "Орлого 24 цагийн дотор арилдаг боловч 48 цаг хүртэл хугацаа шаардагдах бөгөөд таны хадгаламжийн дүнг хассаны дараа шимтгэл таны үлдэгдэлд орно.", + "PENDING_DEPOSIT_TEXT_2": "Орлого 24 цагийн дотор баталгааждаг боловч зарим тохиолдолд 48 цаг хүртэл хугацаа шаардагдах бөгөөд таны орлогын дүнгээс шимтгэл хассаны дараа таны үлдэгдэлд орно.", "DEPOSIT_HOME_NOTE": "Орлогоо хийхдээ өөрийн данснаас мөнгө байршуулах мөнгөө оруулна уу. Саатал гарахаас зайлсхийхийн тулд доор оруулсан дүн таны данснаас илгээх эсвэл илгээсэн бодит дүнтэй тохирч байгаа эсэхийг шалгаарай.", "DEPOSIT_TXID_NOTE": "Орлогоо хойшлуулахаас зайлсхийхийн тулд гүйлгээний тэмдэглэл эсвэл мессежийн дотор банкны мөнгө хийхдээ дээр харуулсан өвөрмөц тэмдэглэлээ оруулна уу. Доорх дүн нь таны банкнаас байршуулсантай тохирч байгаа эсэх, мөн гүйлгээ хийсний дараа банкнаас өгсөн гүйлгээний ID-г оруулсан эсэхээ шалгаарай.", "DEPOSIT_BANK_TEXT": "Доорх банкны дэлгэрэнгүй мэдээллийг ашиглан мөнгө байршуулна уу.", @@ -1425,7 +1425,7 @@ "WALLET_HAS_BALANCE_PERCENTAGE": "Таны түрийвч одоогоор ямар ч {0} агуулаагүй байна.", "WALLET_DEPOSIT": "Та {0} байршуулах эсвэл {1} худалдаж авах боломжтой" }, - "DEPOSIT_FORM_MIN_WARNING": "Зөвхөн {0} {1} ба түүнээс дээш хэмжээний хадгаламжийг хүлээн авна. Энэ хамгийн бага босго хэмжээнээс доогуур хадгаламж нь байнгын мөнгө алдахад хүргэдэг.", + "DEPOSIT_FORM_MIN_WARNING": "Зөвхөн {0} {1} ба түүнээс дээш хэмжээний орлого хүлээн авна. Энэ хамгийн бага босго хэмжээнээс доогуур орлого нь байнгын мөнгө алдахад хүргэдэг.", "24H_MAX": "24 цагийн өндөр:", "24H_MIN": "24 цаг бага", "24H_VAL": "24H Vol", @@ -1434,12 +1434,12 @@ "QUICK_TRADE_QUOTE_EXPIRED_BUTTON": "ШААРДЛАГА", "ABOUT_LINK": "{0} тухай", "ZERO_ASSET_2": "илрүүлсэн. Хийх", - "ZERO_ASSET_3": "доор хадгаламж.", + "ZERO_ASSET_3": "доор орлого.", "SUMMARY_MARKETS": { "HOLLAEX": "Та дижитал хөрөнгөө жагсаахыг хүсч байна уу? HollaEx {0} {1} ашиглан өөрийн зах зээлээ эхлүүлээрэй", - "WHITE_LABEL": "цагаан шошго", + "WHITE_LABEL": "white label", "SOLUTION": "шийдэл", - "VISIT_COIN_INFO_PAGE": "Зоосны мэдээллийн хуудсанд зочилно уу {0}", + "VISIT_COIN_INFO_PAGE": "ВХөрөнгийн мэдээллийн хуудсанд зочилно уу {0}", "HERE": "энд" }, "RESET_LAYOUT": "Байршлыг дахин тохируулах", @@ -1497,14 +1497,14 @@ "WALLET_BALANCE": "Түрийвчний үлдэгдлийн задаргаа", "WALLET_BALANCE_DESCRIPTION_1": "Доорх нь түрийвчний задаргаа юм", "WALLET_BALANCE_DESCRIPTION_2": "Доорх хүснэгтийг шинэчлэхийн тулд дээрх график дээр дарна уу.", - "DATE_SELECT": "Огноог сонгоно уу", + "DATE_SELECT": "Огноо сонгоно уу", "ASSET_NAME": "Хөрөнгийн нэр", "BALANCE_AMOUNT": "Үлдэгдэл дүн", "VALUE": "Үнэ цэнэ", - "PERFORMANCE_TREND": "7 өдрийн гүйцэтгэлийн чиг хандлага", - "CUSTOM_DATE_DESCRIPTION": "Түүхийн мэдээллээ авахын тулд тодорхой огноог сонгоно уу (огнооны зөрүү 3 сараас хэтрэхгүй)", - "SELECT_START_DATE": "Эхлэх огноог сонгоно уу", - "SELECT_END_DATE": "Дуусах огноог сонгоно уу", + "PERFORMANCE_TREND": "7 хоногийн график", + "CUSTOM_DATE_DESCRIPTION": "Түүхийн мэдээллээ авах хугацааг сонгоно уу (3 сараас хэтрэхгүй)", + "SELECT_START_DATE": "Эхлэх огноо", + "SELECT_END_DATE": "Дуусах огноо", "CUSTOM": "Захиалгат", "BACK_CUSTOM": "БУЦАХ", "PROOCED_CUSTOM": "НЭМЭГДСЭН" @@ -1582,42 +1582,42 @@ } }, "WITHDRAWAL_FEES": { - "TITLE": "Татан авалтын хураамж", + "TITLE": "Зарлагын хураамж", "TABLE": { "TITLE": "Татгалзах үед хураамжийг хасна", "SUBTITLE": "Хөрөнгийг эргүүлэн татахад төлөх бүх хураамжийг доор харуулав.", "NOT_ALLOWED": "Зөвшөөрөгдөөгүй", "HEADER": { "CURRENCY": "Валют/хөрөнгө", - "DEPOSIT": "Хадгаламжийн хураамж", - "WITHDRAWAL": "Татан авалтын хураамж" + "DEPOSIT": "Орлогын хураамж", + "WITHDRAWAL": "Зарлагын хураамж" } } }, "WITHDRAWAL_LIMITS": { - "TITLE": "Татан авалтын хязгаарлалт", + "TITLE": "Зарлагын хязгаар", "TABLE_1": { - "TITLE": "Бие даасан мөнгө авах хязгаар", - "SUBTITLE": "Хамтын хязгаарлалтын дүрмээс тусгаарлагдсан, өөрийн бие даасан 24 цагийн мөнгө татах дүрмийг дагаж мөрддөг хөрөнгө:", + "TITLE": "Тусгайлсан зарлагын хязгаар", + "SUBTITLE": "Нийтлэг хязгаарлалтаас тусдаа, тусгай хэмжээг мөрддөг виртуал хөрөнгө", "HEADER": { "CURRENCY": "Валют/хөрөнгө", "LIMIT": "Өдөр тутмын хязгаар", "LIMIT_2": "Сарын хязгаар" }, - "LIMIT_TEXT": "(Бүх нийтээр татан авах хязгаарын хэмжээг хуваалцдаг хөрөнгө)", + "LIMIT_TEXT": "(Нийт зарлагын хэмжээг хуваалцдаг хөрөнгө)", "LIMIT_TEXT_2": "(Зөвхөн өөрийн мөнгөн тэмдэгт дээр суурилсан хязгаарлалт)", "VALUED": "(үнэлэгдсэн)", "NO_INDEPENDENT": "Энэ түвшний хувьд бие даасан хязгаарлалт байхгүй", - "LIMIT_TEXT_3": "(Бүгд {0}-д заасан өдөр тутмын мөнгө авах хязгаарын хэмжээг хуваалцдаг хөрөнгө)", - "LIMIT_TEXT_4": "(Бүгд нь {0}-д заасан сарын мөнгө авах хязгаарын хэмжээг хуваалцдаг хөрөнгө)" + "LIMIT_TEXT_3": "(Бүгд {0}-д заасан өдөр тутмын зарлагын хязгаарын хэмжээг хуваалцдаг хөрөнгө)", + "LIMIT_TEXT_4": "(Бүгд нь {0}-д заасан сарын зарлагын хязгаарын хэмжээг хуваалцдаг хөрөнгө)" }, "TABLE_2": { "TITLE": "Бие даасан хязгаар", - "SUBTITLE": "Өөрийн мөнгөн тэмдэгтээр өдөр бүр, сар бүр авах хязгаартай хөрөнгө:" + "SUBTITLE": "Тусгай хэмжээгээр өдөр бүр, сар бүр авах хязгаартай хөрөнгө:" }, "TABLE_3": { "TITLE": "Хамтын хязгаарлалт", - "SUBTITLE": "Бүлэг зоосыг авах өдөр тутмын болон сарын хязгаарыг нэгтгэсэн" + "SUBTITLE": "Дундын хязгаарлалттай хөрөнгө" } } } @@ -1632,9 +1632,9 @@ "TAB": "Нэвтрэх түүх", "CONTENT": { "TITLE": "Нэвтрэх оролдлогын бүртгэл", - "SUBTITLE": "Таны дансанд нэвтэрч чадаагүй бүх оролдлого болон тэдгээрийн боломжит гарал үүслийн түүхэн тэмдэглэл.", + "SUBTITLE": "Таны дансанд нэвтэрч чадаагүй бүх оролдлого болон тэдгээрийн түүх.", "DOWNLOAD_HISTORY": "ТҮҮХ_ТАТАХ", - "FILTER": { "STATUS": "Статус", "ALL": "Бүгд", "FAILED": "Амжилтгүй", "SUCCESS": "Амжилт" }, + "FILTER": { "STATUS": "Статус", "ALL": "Бүгд", "FAILED": "Амжилтгүй", "SUCCESS": "Амжилттай" }, "TABLE": { "HEADER": { "LAST_SEEN": { @@ -1647,7 +1647,7 @@ }, "CELL": { "FAILED_LOGIN": "Амжилтгүй нэвтэрсэн: {0}x", - "SUCCESS": "Амжилт", + "SUCCESS": "Амжилттай", "DEVICE": "Төхөөрөмж" } } From 781787148d6fd42c7b7809142bd0ea9f68a2ad71 Mon Sep 17 00:00:00 2001 From: mytilene Date: Tue, 2 Jul 2024 16:19:17 +0800 Subject: [PATCH 012/108] Update mn.json --- web/src/config/lang/mn.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/config/lang/mn.json b/web/src/config/lang/mn.json index 24081adbba..c6a510dc74 100644 --- a/web/src/config/lang/mn.json +++ b/web/src/config/lang/mn.json @@ -1293,7 +1293,7 @@ "CHART_24H": "График (24 цаг)", "VIEW_MARKETS": "Бүх хослол", "CHANGE_7D": "Өөрчлөлт (7 хоног)", - "CHANGE_1D": "Өөрчлөх (1 өдөр)", + "CHANGE_1D": "Өөрчлөлт (1 өдөр)", "CHART_7D": "График (7 хоног)", "TRADING_SYMBOL": "Худалдааны тэмдэг", "ASSET": "Хөрөнгө", From cf2638f61eaa9f603d33b8d9928f87a071cd0e53 Mon Sep 17 00:00:00 2001 From: ram Date: Thu, 4 Jul 2024 23:58:59 +0530 Subject: [PATCH 013/108] Restricted the chart endpoint and updated the balance percentage on the history page --- web/src/actions/appActions.js | 8 ++++ web/src/components/AppBar/PairTabs.js | 39 ++++++++++++------- web/src/containers/Home/index.js | 25 ++++++------ web/src/containers/Summary/MobileSummary.js | 8 +++- .../containers/Summary/components/Markets.js | 24 +++++++++--- web/src/containers/Summary/index.js | 4 ++ .../containers/Wallet/ProfitLossSection.js | 15 +++++-- web/src/reducers/appReducer.js | 7 ++++ 8 files changed, 94 insertions(+), 36 deletions(-) diff --git a/web/src/actions/appActions.js b/web/src/actions/appActions.js index 5ab988601a..7e1d8f94f9 100644 --- a/web/src/actions/appActions.js +++ b/web/src/actions/appActions.js @@ -112,6 +112,7 @@ export const SET_DEPOSIT_NETWORK_OPTIONS = 'SET_DEPOSIT_OPTIONS'; export const SET_SELECTED_METHOD = 'SET_SELECTED_METHOD'; export const SET_RECEIVER_EMAIL = 'SET_RECEIVER_EMAIL'; export const SET_WITHDRAW_OTIONAL_TAG = 'SET_WITHDRAW_OTIONAL_TAG'; +export const SET_CHART_DATA = 'SET_CHART_DATA'; export const SORT = { VOL: 'volume', @@ -375,6 +376,13 @@ export const changePair = (pair) => ({ }, }); +export const changeSparkLineChartData = (sparkLineChartData) => ({ + type: SET_CHART_DATA, + payload: { + sparkLineChartData, + }, +}); + export const setActiveOrdersMarket = (activeOrdersMarket) => ({ type: SET_ACTIVE_ORDERS_MARKET, payload: { diff --git a/web/src/components/AppBar/PairTabs.js b/web/src/components/AppBar/PairTabs.js index 7c7b92b436..ab898047ef 100644 --- a/web/src/components/AppBar/PairTabs.js +++ b/web/src/components/AppBar/PairTabs.js @@ -13,13 +13,12 @@ import { Slider, EditWrapper, PriceChange } from 'components'; import withConfig from 'components/ConfigProvider/withConfig'; import { formatToCurrency } from 'utils/currency'; import { MarketsSelector } from 'containers/Trade/utils'; -import { getSparklines } from 'actions/chartAction'; import SparkLine from 'containers/TradeTabs/components/SparkLine'; class PairTabs extends Component { state = { activePairTab: '', - sparkLine: [], + // sparkLine: [], }; componentDidMount() { @@ -30,9 +29,9 @@ class PairTabs extends Component { } this.setState({ activePairTab: active }); this.initTabs(pairs, active); - getSparklines(Object.keys(pairs)).then((sparkLine) => - this.setState({ sparkLine }) - ); + // getSparklines(Object.keys(pairs)).then((chartData) => + // this.props.changeSparkLineChartData(chartData) + // ); } UNSAFE_componentWillReceiveProps(nextProps) { @@ -90,10 +89,16 @@ class PairTabs extends Component { activePairTab, isMarketSelectorVisible, isToolsSelectorVisible, - sparkLine, + // sparkLine, } = this.state; - const { location, favourites, markets, quicktrade } = this.props; + const { + location, + favourites, + markets, + quicktrade, + sparkLineChartData, + } = this.props; const market = markets.find(({ key }) => key === activePairTab) || {}; const { key, @@ -163,12 +168,12 @@ class PairTabs extends Component { /> { const { - app: { language: activeLanguage, pairs, favourites, constants, quicktrade }, + app: { + language: activeLanguage, + pairs, + favourites, + constants, + quicktrade, + sparkLineChartData, + }, orderbook: { prices }, } = state; @@ -262,6 +274,7 @@ const mapStateToProps = (state) => { constants, markets: MarketsSelector(state), quicktrade, + sparkLineChartData, }; }; diff --git a/web/src/containers/Home/index.js b/web/src/containers/Home/index.js index f72795df4f..8eb90f1388 100644 --- a/web/src/containers/Home/index.js +++ b/web/src/containers/Home/index.js @@ -6,7 +6,6 @@ import { Spin } from 'antd'; import STRINGS from 'config/localizedStrings'; import { changePair, getExchangeInfo, getTickers } from 'actions/appActions'; -import { getSparklines } from 'actions/chartAction'; import Markets from 'containers/Summary/components/Markets'; import { Image, QuickTrade, EditWrapper } from 'components'; @@ -51,7 +50,7 @@ class Home extends Component { minHeight: MIN_HEIGHT, }, sectionData: {}, - chartData: {}, + // chartData: {}, isLoading: false, isHover: false, hoveredIndex: 0, @@ -67,12 +66,12 @@ class Home extends Component { } componentDidMount() { - const { sections, pairs, getExchangeInfo, getTickers } = this.props; + const { sections, getExchangeInfo, getTickers } = this.props; getExchangeInfo(); getTickers(); - getSparklines(Object.keys(pairs)).then((chartData) => - this.setState({ chartData }) - ); + // getSparklines(Object.keys(pairs)).then((chartData) => + // this.props.changeSparkLineData(chartData) + // ); this.generateSections(sections); setTimeout(() => { @@ -188,16 +187,14 @@ class Home extends Component { style={{ minHeight: this.calculateMinHeight(sectionsNumber), }} - onClickDemo={ - this.goTo('accounts') - } + onClickDemo={this.goTo('accounts')} onClickTrade={this.goTo('signup')} />

); } case 'market_list': { - const { router, coins, pairs } = this.props; + const { router, coins, pairs, sparkLineChartData } = this.props; return (
@@ -220,6 +217,7 @@ class Home extends Component { showMarkets={true} isHome={true} renderContent={this.renderContent} + chartData={sparkLineChartData} />
@@ -295,8 +293,8 @@ class Home extends Component { ); } case 'carousel_section': { - const { markets } = this.props; - const { chartData, carouselLoading } = this.state; + const { markets, sparkLineChartData } = this.props; + const { carouselLoading } = this.state; let testMarket = []; let loopCnt = 0; if (markets.length < 12) { @@ -347,7 +345,7 @@ class Home extends Component { market={sec} onDragStart={this.handleDragStart} role="presentation" - chartData={chartData} + chartData={sparkLineChartData} /> )}
@@ -403,6 +401,7 @@ const mapStateToProps = (store) => { fetchingAuth: store.auth.fetching, isReady: store.app.isReady, markets: MarketsSelector(store), + sparkLineChartData: store.app.sparkLineChartData, }; }; diff --git a/web/src/containers/Summary/MobileSummary.js b/web/src/containers/Summary/MobileSummary.js index 5c2f551ed2..d693075201 100644 --- a/web/src/containers/Summary/MobileSummary.js +++ b/web/src/containers/Summary/MobileSummary.js @@ -37,6 +37,7 @@ const MobileSummary = ({ affiliation, onDisplayReferralList, referral_history_config, + sparkLineChartData, }) => { const { fullname } = coins[BASE_CURRENCY] || DEFAULT_COIN_DATA; // const Title = STRINGS.formatString(STRINGS["SUMMARY.LEVEL_OF_ACCOUNT"],verification_level); @@ -99,7 +100,12 @@ const MobileSummary = ({ stringId="SUMMARY.MARKETS" title={STRINGS['SUMMARY.MARKETS']} > - +
{/*
diff --git a/web/src/containers/Summary/components/Markets.js b/web/src/containers/Summary/components/Markets.js index 4e1257a377..51d20214c6 100644 --- a/web/src/containers/Summary/components/Markets.js +++ b/web/src/containers/Summary/components/Markets.js @@ -3,6 +3,7 @@ import { connect } from 'react-redux'; import { Link } from 'react-router'; import { isMobile } from 'react-device-detect'; import { withRouter } from 'react-router'; +import { bindActionCreators } from 'redux'; import { SearchBox } from 'components'; import withConfig from 'components/ConfigProvider/withConfig'; @@ -12,13 +13,14 @@ import { getSparklines } from 'actions/chartAction'; import { EditWrapper } from 'components'; import { MarketsSelector } from 'containers/Trade/utils'; import MarketList from 'containers/TradeTabs/components/MarketList'; +import { changeSparkLineChartData } from 'actions/appActions'; class Markets extends Component { constructor(props) { super(props); this.state = { data: [], - chartData: {}, + // chartData: {}, pageSize: 10, page: 0, count: 0, @@ -32,7 +34,7 @@ class Markets extends Component { this.constructData(page, searchValue); getSparklines(Object.keys(pairs)).then((chartData) => - this.setState({ chartData }) + this.props.changeSparkLineChartData(chartData) ); } @@ -120,7 +122,7 @@ class Markets extends Component { }; render() { - const { data, chartData, page, pageSize, count } = this.state; + const { data, page, pageSize, count } = this.state; const { showSearch = true, showMarkets = false, @@ -128,6 +130,7 @@ class Markets extends Component { isHome = false, showContent = false, renderContent, + sparkLineChartData, } = this.props; if (isHome) { @@ -166,7 +169,7 @@ class Markets extends Component { @@ -216,6 +219,17 @@ const mapStateToProps = (state) => ({ tickers: state.app.tickers, constants: state.app.constants, markets: MarketsSelector(state), + sparkLineChartData: state.app.sparkLineChartData, }); -export default connect(mapStateToProps)(withRouter(withConfig(Markets))); +const mapDispatchToProps = (dispatch) => ({ + changeSparkLineChartData: bindActionCreators( + changeSparkLineChartData, + dispatch + ), +}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(withRouter(withConfig(Markets))); diff --git a/web/src/containers/Summary/index.js b/web/src/containers/Summary/index.js index 0e9742e0d5..89a8133fcd 100644 --- a/web/src/containers/Summary/index.js +++ b/web/src/containers/Summary/index.js @@ -158,6 +158,7 @@ class Summary extends Component { router, icons: ICONS, referral_history_config, + sparkLineChartData, } = this.props; const { selectedAccount, @@ -213,6 +214,7 @@ class Summary extends Component { logout={this.logoutConfirm} balance={balance} chartData={chartData} + sparkLineChartData={sparkLineChartData} totalAssets={totalAssets} lastMonthVolume={lastMonthVolume} traderAccTitle={traderAccTitle} @@ -305,6 +307,7 @@ class Summary extends Component { pairs={pairs} router={router} showContent={true} + chartData={sparkLineChartData} /> {/*
@@ -366,6 +369,7 @@ const mapStateToProps = (state) => ({ chartData: state.asset.chartData, totalAsset: state.asset.totalAsset, referral_history_config: state.app.constants.referral_history_config, + sparkLineChartData: state.app.sparkLineChartData, }); const mapDispatchToProps = (dispatch) => ({ diff --git a/web/src/containers/Wallet/ProfitLossSection.js b/web/src/containers/Wallet/ProfitLossSection.js index 89afc2ed28..424c7c66c2 100644 --- a/web/src/containers/Wallet/ProfitLossSection.js +++ b/web/src/containers/Wallet/ProfitLossSection.js @@ -311,9 +311,8 @@ const ProfitLossSection = ({ calculateOraclePrice(balance, oraclePrice), baseCoin.increment_unit ); - const getBalancePercentage = chartData.filter( - (coin) => coin.symbol === symbol - ); + const totalValue = currentBalance?.total; + const assetValue = sourceAmountNative; if (sourceAmount > 0) { return ( @@ -387,7 +386,10 @@ const ProfitLossSection = ({ }} className="td-fit" > -
{getBalancePercentage[0]?.balancePercentage}
+
{`${calculatePercentages( + totalValue, + assetValue + )}%`}
{isMobile && selectedCoin[0] !== BASE_CURRENCY && parseFloat(balanceText || 0) > 0 && ( @@ -610,6 +612,11 @@ const ProfitLossSection = ({ setActiveTab(activeKey); }; + function calculatePercentages(totalValue, value) { + const percentage = (value / totalValue) * 100; + return percentage.toFixed(1); + } + return (
diff --git a/web/src/reducers/appReducer.js b/web/src/reducers/appReducer.js index bfc9143c6c..296f7c110f 100644 --- a/web/src/reducers/appReducer.js +++ b/web/src/reducers/appReducer.js @@ -74,6 +74,7 @@ import { SET_SELECTED_METHOD, SET_RECEIVER_EMAIL, SET_WITHDRAW_OTIONAL_TAG, + SET_CHART_DATA, } from 'actions/appActions'; import { THEME_DEFAULT } from 'config/constants'; import { getLanguage } from 'utils/string'; @@ -140,6 +141,7 @@ const INITIAL_STATE = { snackNotification: EMPTY_SNACK_NOTIFICATION, theme: THEME_DEFAULT, language: getLanguage(), + sparkLineChartData: {}, pairs: {}, pair: '', activeOrdersMarket: '', @@ -222,6 +224,11 @@ const reducer = (state = INITIAL_STATE, { type, payload = {} }) => { activeOrdersMarket: payload.pair, recentTradesMarket: payload.pair, }; + case SET_CHART_DATA: + return { + ...state, + sparkLineChartData: payload.sparkLineChartData, + }; case SET_ACTIVE_ORDERS_MARKET: return { ...state, From 9fe8c3b08ecf8e755fec1b05980eca6ad5075217 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Thu, 4 Jul 2024 21:57:40 +0300 Subject: [PATCH 014/108] user-address-book --- server/api/controllers/user.js | 34 +++++++++- server/api/swagger/user.yaml | 60 ++++++++++++++++++ ...40624132614-create-user-addressbooks.js.js | 44 +++++++++++++ server/db/models/index.js | 2 + server/db/models/userAddressBook.js | 35 +++++++++++ server/messages.js | 4 +- server/utils/hollaex-tools-lib/tools/user.js | 63 ++++++++++++++++++- 7 files changed, 238 insertions(+), 4 deletions(-) create mode 100644 server/db/migrations/20240624132614-create-user-addressbooks.js.js create mode 100644 server/db/models/userAddressBook.js diff --git a/server/api/controllers/user.js b/server/api/controllers/user.js index 01054aa27c..fe43b817b7 100644 --- a/server/api/controllers/user.js +++ b/server/api/controllers/user.js @@ -1476,6 +1476,36 @@ const fetchUserReferrals = (req, res) => { }); }; +const fetchUserAddressBook = (req, res) => { + loggerUser.verbose(req.uuid, 'controllers/user/fetchUserAddressBook/auth', req.auth); + + toolsLib.user.fetchUserAddressBook(req.auth.sub.id) + .then((data) => { + return res.json(data); + }) + .catch((err) => { + loggerUser.error(req.uuid, 'controllers/user/fetchUserAddressBook', err.message); + return res.status(err.statusCode || 400).json({ message: errorMessageConverter(err) }); + }); +}; + +const updateUserAddresses = (req, res) => { + loggerUser.verbose(req.uuid, 'controllers/user/updateUserAddresses/auth', req.auth); + + const { addresses } = req.swagger.params.data.value; + + loggerUser.verbose(req.uuid, 'controllers/user/updateUserAddresses data', req.auth.sub.id, addresses); + + toolsLib.user.updateUserAddresses(req.auth.sub.id, { addresses }) + .then((data) => { + return res.json(data); + }) + .catch((err) => { + loggerUser.error(req.uuid, 'controllers/user/updateUserAddresses err', err.message); + return res.status(err.statusCode || 400).json({ message: errorMessageConverter(err) }); + }); +}; + module.exports = { signUpUser, @@ -1514,5 +1544,7 @@ module.exports = { fetchUserProfitLossInfo, fetchUserReferrals, createUserReferralCode, - getUserReferralCodes + getUserReferralCodes, + updateUserAddresses, + fetchUserAddressBook }; \ No newline at end of file diff --git a/server/api/swagger/user.yaml b/server/api/swagger/user.yaml index 6b6f93e699..9e61486b06 100644 --- a/server/api/swagger/user.yaml +++ b/server/api/swagger/user.yaml @@ -245,6 +245,66 @@ paths: - bearer x-security-scopes: - user + /user/addressbook: + x-swagger-router-controller: user + get: + description: Fetch address book for user + operationId: fetchUserAddressBook + tags: + - User + responses: + 200: + description: Success + schema: + $ref: "#/definitions/ObjectResponse" + default: + description: Error + schema: + $ref: "#/definitions/MessageResponse" + security: + - Token: [] + x-security-types: + - bearer + - hmac + x-security-scopes: + - user + post: + description: Update addresses for user address book + operationId: updateUserAddresses + tags: + - User + parameters: + - name: data + in: body + required: true + schema: + type: object + properties: + addresses: + type: array + items: + type: object + properties: + address: + type: string + network: + type: string + responses: + 200: + description: Success + schema: + $ref: "#/definitions/ObjectResponse" + default: + description: Error + schema: + $ref: "#/definitions/MessageResponse" + security: + - Token: [] + x-security-types: + - bearer + - hmac + x-security-scopes: + - user /user/affiliation: x-swagger-router-controller: user get: diff --git a/server/db/migrations/20240624132614-create-user-addressbooks.js.js b/server/db/migrations/20240624132614-create-user-addressbooks.js.js new file mode 100644 index 0000000000..b851ee030e --- /dev/null +++ b/server/db/migrations/20240624132614-create-user-addressbooks.js.js @@ -0,0 +1,44 @@ +'use strict'; + +const TABLE_NAME = 'UserAddressBooks'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable(TABLE_NAME, { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + user_id: { + type: Sequelize.INTEGER, + onDelete: 'CASCADE', + allowNull: false, + references: { + model: 'Users', + key: 'id' + } + }, + addresses: { + type: Sequelize.ARRAY(Sequelize.JSONB), + allowNull: false, + }, + created_at: { + allowNull: false, + type: Sequelize.DATE, + defaultValue: Sequelize.literal('NOW()') + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + defaultValue: Sequelize.literal('NOW()') + } + }, + { + timestamps: true, + underscored: true + }); + }, + down: (queryInterface) => queryInterface.dropTable(TABLE_NAME) +}; diff --git a/server/db/models/index.js b/server/db/models/index.js index e1f7f38c10..3fe31f321e 100644 --- a/server/db/models/index.js +++ b/server/db/models/index.js @@ -66,6 +66,8 @@ model = require(path.join(__dirname, './referralHistory'))(sequelize, Sequelize. db[model.name] = model; model = require(path.join(__dirname, './referralCode'))(sequelize, Sequelize.DataTypes); db[model.name] = model; +model = require(path.join(__dirname, './userAddressBook'))(sequelize, Sequelize.DataTypes); +db[model.name] = model; Object.keys(db).forEach(function (modelName) { if ('associate' in db[modelName]) { diff --git a/server/db/models/userAddressBook.js b/server/db/models/userAddressBook.js new file mode 100644 index 0000000000..2ec4955105 --- /dev/null +++ b/server/db/models/userAddressBook.js @@ -0,0 +1,35 @@ +'use strict'; + +module.exports = function (sequelize, DataTypes) { + const UserAddressBook = sequelize.define( + 'UserAddressBook', + { + id: { + type: DataTypes.INTEGER, + allowNull: false, + autoIncrement: true, + primaryKey: true, + }, + user_id: { + type: DataTypes.INTEGER, + onDelete: 'CASCADE', + allowNull: false, + references: { + model: 'Users', + key: 'id' + } + }, + addresses: { + type: DataTypes.ARRAY(DataTypes.JSONB), + allowNull: false, + } + }, + { + timestamps: true, + underscored: true, + tableName: 'UserAddressBooks' + } + ); + + return UserAddressBook; +}; \ No newline at end of file diff --git a/server/messages.js b/server/messages.js index 82c511af66..3135414579 100644 --- a/server/messages.js +++ b/server/messages.js @@ -261,4 +261,6 @@ exports.EMAIL_EXISTS = 'This email already exists'; exports.CANNOT_CHANGE_DELETED_EMAIL = 'Cannot change deleted email'; exports.FAILED_GET_QUOTE = 'Failed to get the quote'; exports.BALANCE_HISTORY_NOT_ACTIVE = 'This feature is not active on the exchange'; -exports.WITHDRAWAL_DISABLED = 'Withdrawal disabled for this user'; \ No newline at end of file +exports.WITHDRAWAL_DISABLED = 'Withdrawal disabled for this user'; +exports.ADDRESSBOOK_MISSING_FIELDS = 'Each address must contain both address and network fields'; +exports.ADDRESSBOOK_ALREADY_EXISTS = 'One or more addresses already exist in the address book'; \ No newline at end of file diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index 6ddb9b4f90..9365d6629e 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -61,7 +61,9 @@ const { REFERRAL_UNSUPPORTED_EXCHANGE_PLAN, CANNOT_CHANGE_DELETED_EMAIL, SERVICE_NOT_SUPPORTED, - BALANCE_HISTORY_NOT_ACTIVE + BALANCE_HISTORY_NOT_ACTIVE, + ADDRESSBOOK_MISSING_FIELDS, + ADDRESSBOOK_ALREADY_EXISTS } = require(`${SERVER_PATH}/messages`); const { publisher, client } = require('./database/redis'); const { @@ -3265,6 +3267,61 @@ const fetchUserProfitLossInfo = async (user_id, opts = { period: 7 }) => { return results; }; +const fetchUserAddressBook = async (user_id) => { + const user = await getUserByKitId(user_id); + + if (!user) { + throw new Error(USER_NOT_FOUND); + } + + const userAddressBook = await getModel('userAddressBook').findOne({ where: { user_id } }); + + if (!userAddressBook) { + throw new Error('User address book not found'); + } + + return userAddressBook; +}; + + +const updateUserAddresses = async (user_id, data) => { + const { addresses } = data; + + addresses.forEach((addressObj) => { + if (!addressObj.address || !addressObj.network) { + throw new Error(ADDRESSBOOK_MISSING_FIELDS); + } + }); + + const user = await getUserByKitId(user_id); + + if (!user) { + throw new Error(USER_NOT_FOUND); + } + + let userAddressBook = await getModel('userAddressBook').findOne({ where: { user_id } }); + if (!userAddressBook) { + userAddressBook = await getModel('userAddressBook').create({ + user_id, + addresses + }); + } else { + // Check if any address in the payload already exists + const existingAddresses = userAddressBook.addresses.map(a => a.address); + const duplicateAddresses = addresses.filter(a => existingAddresses.includes(a.address)); + if (duplicateAddresses.length > 0) { + throw new Error(ADDRESSBOOK_ALREADY_EXISTS); + } + + // Update the addresses + userAddressBook = await userAddressBook.update({ addresses }, { + fields: ['addresses'] + }); + } + + return userAddressBook; +}; + module.exports = { loginUser, @@ -3339,5 +3396,7 @@ module.exports = { fetchUserReferrals, createUnrealizedReferralFees, getUserReferralCodes, - createUserReferralCode + createUserReferralCode, + updateUserAddresses, + fetchUserAddressBook }; From ede0dfd0eb3eac81594c1748c5c9329bd047bfbb Mon Sep 17 00:00:00 2001 From: fetok12 Date: Thu, 4 Jul 2024 22:04:08 +0300 Subject: [PATCH 015/108] user-address-book --- server/messages.js | 3 ++- server/utils/hollaex-tools-lib/tools/user.js | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/server/messages.js b/server/messages.js index 3135414579..a584bfb3ba 100644 --- a/server/messages.js +++ b/server/messages.js @@ -263,4 +263,5 @@ exports.FAILED_GET_QUOTE = 'Failed to get the quote'; exports.BALANCE_HISTORY_NOT_ACTIVE = 'This feature is not active on the exchange'; exports.WITHDRAWAL_DISABLED = 'Withdrawal disabled for this user'; exports.ADDRESSBOOK_MISSING_FIELDS = 'Each address must contain both address and network fields'; -exports.ADDRESSBOOK_ALREADY_EXISTS = 'One or more addresses already exist in the address book'; \ No newline at end of file +exports.ADDRESSBOOK_ALREADY_EXISTS = 'One or more addresses already exist in the address book'; +exports.ADDRESSBOOK_NOT_FOUND = 'User address book not found'; \ No newline at end of file diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index 9365d6629e..fc49099af1 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -63,7 +63,8 @@ const { SERVICE_NOT_SUPPORTED, BALANCE_HISTORY_NOT_ACTIVE, ADDRESSBOOK_MISSING_FIELDS, - ADDRESSBOOK_ALREADY_EXISTS + ADDRESSBOOK_ALREADY_EXISTS, + ADDRESSBOOK_NOT_FOUND } = require(`${SERVER_PATH}/messages`); const { publisher, client } = require('./database/redis'); const { @@ -3277,7 +3278,7 @@ const fetchUserAddressBook = async (user_id) => { const userAddressBook = await getModel('userAddressBook').findOne({ where: { user_id } }); if (!userAddressBook) { - throw new Error('User address book not found'); + throw new Error(ADDRESSBOOK_NOT_FOUND); } return userAddressBook; From 1858b9be399858c54be13bcbedf66944b640c507 Mon Sep 17 00:00:00 2001 From: mytilene Date: Fri, 5 Jul 2024 10:11:13 +0800 Subject: [PATCH 016/108] Update mn.json --- web/src/config/lang/mn.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/src/config/lang/mn.json b/web/src/config/lang/mn.json index c6a510dc74..ad237d13f4 100644 --- a/web/src/config/lang/mn.json +++ b/web/src/config/lang/mn.json @@ -1486,11 +1486,11 @@ }, "PROFIT_LOSS": { "BACK": "Буцах", - "BACK_TO_WALLET": "түрийвч рүү", - "WALLET_PERFORMANCE_TITLE": "Гүйцэтгэлийг тэнцвэржүүлэх", - "WALLET_PERFORMANCE_DESCRIPTION": "Таны хэтэвчний үлдэгдлийн гүйцэтгэл болон хөрөнгийн задаргаа. Доорх огноонууд дээр дарж түрийвчнийхээ тухайн өдрийн гүйцэтгэлийг харна уу.", + "BACK_TO_WALLET": "буцах", + "WALLET_PERFORMANCE_TITLE": "Гүйцэтгэлийг графиъ", + "WALLET_PERFORMANCE_DESCRIPTION": "Таны хэтэвчний үлдэгдлийн гүйцэтгэл болон хөрөнгийн задаргаа. Доорх огноонууд дээр дарж тухайн өдрийн гүйцэтгэлийг харна уу.", "PL_7_DAY": "7 өдрийн P&L", - "EST_TOTAL_BALANCE": "Зүүн. Нийт үлдэгдэл", + "EST_TOTAL_BALANCE": "Барагцаа үлдэгдэл баланс", "WEEK": "долоо хоног", "MONTH": "сар", "MONTHS": "сар", From a34d804c1b5c1be2b958937b3b1307c3184e0230 Mon Sep 17 00:00:00 2001 From: mytilene Date: Fri, 5 Jul 2024 10:19:51 +0800 Subject: [PATCH 017/108] Update mn.json --- web/src/config/lang/mn.json | 68 ++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/web/src/config/lang/mn.json b/web/src/config/lang/mn.json index ad237d13f4..c78dadb768 100644 --- a/web/src/config/lang/mn.json +++ b/web/src/config/lang/mn.json @@ -71,9 +71,9 @@ "TAB_SIGNOUT": "Гарах", "TAB_STAKE": "Стэйкинг", "TAB_FIAT": "Бэлэн мөнгөний удирдлага", - "TAB_TRADE": "Худалдаа", + "TAB_TRADE": "Арилжаа", "PRO_TRADE": "Pro", - "QUICK_TRADE": "Хурдан" + "QUICK_TRADE": "Хялбар арилжаа" }, "CONTACT_FORM": { "CATEGORY_LABEL": "Ангилал", @@ -85,7 +85,7 @@ "OPTION_BUG": "Алдааг мэдээлэх", "OPTION_PERSONAL_INFO": "Хувийн мэдээлэл өөрчлөх", "OPTION_BANK_TRANSFER": "Банкны шилжүүлэг", - "OPTION_REQUEST": "HollaEx бирж дээр урилга илгээх" + "OPTION_REQUEST": "Найзаа урих" }, "SUBJECT_LABEL": "Гарчиг", "SUBJECT_PLACEHOLDER": "Асуудлын тухай гарчиг оруулах", @@ -1436,7 +1436,7 @@ "ZERO_ASSET_2": "илрүүлсэн. Хийх", "ZERO_ASSET_3": "доор орлого.", "SUMMARY_MARKETS": { - "HOLLAEX": "Та дижитал хөрөнгөө жагсаахыг хүсч байна уу? HollaEx {0} {1} ашиглан өөрийн зах зээлээ эхлүүлээрэй", + "HOLLAEX": "Та виртуал хөрөнгөө жагсаахыг хүсч байна уу? HollaEx {0} {1} ашиглан өөрийн зах зээлээ эхлүүлээрэй", "WHITE_LABEL": "white label", "SOLUTION": "шийдэл", "VISIT_COIN_INFO_PAGE": "ВХөрөнгийн мэдээллийн хуудсанд зочилно уу {0}", @@ -1513,7 +1513,7 @@ "TAKER_FEES_APPLIED": "Хүлээн авагчийн хураамж авдаг", "ASSET_INFO_PAGE": "Хөрөнгийн мэдээллийн хуудас", "DIGITAL_ASSETS": { - "DIGITAL_ASSETS_TITLE": "Дижитал хөрөнгө", + "DIGITAL_ASSETS_TITLE": "виртуал хөрөнгө", "GO_BACK": "Буцах", "ASSETS_INFO": "Доорх платформ дээрх боломжтой хөрөнгийг доор харуулав.", "ASSETS_INFO_DETAIL": "Дэлгэрэнгүй үзэхийн тулд та доорх жагсаалтын өмч дээр дарж болно.", @@ -1523,20 +1523,20 @@ "WALLET": "ТҮРИЙВЧ", "PRICE_SOURCE": "Үнийн эх үүсвэр", "ORDERBOOK": "Захиалгын дэвтэр", - "NETWORK": "Сүлжээний брокер OTC", - "BROKER": "Орон нутгийн брокер OTC", + "NETWORK": "Брокер OTC сүлжээ", + "BROKER": "Дотоод брокер OTC", "BROKERAGE": "NA - (Зуучлах)" }, "HOLLAEX_TOKEN": { "REMOVE_FAVOURITES": "Дуртай зүйлсээс хасах", - "ADD_FAVOURITES": "Дуртай зүйлд нэмнэ үү", + "ADD_FAVOURITES": "Дуртай зүйлд нэмэх", "GO_BACK": " Буцах", "BALANCE": "Үлдэгдэл:", "OPEN_WALLET": "(Нээлттэй хэтэвч)", "ABOUT": "тухай", - "VIEW": "Илүү ихийг үзэх", + "VIEW": "Харах", "COMING_SOON": "Тун удахгүй...", - "NO_DESCRIPTION": "Энэ дижитал хөрөнгөд одоогоор тайлбар байхгүй байна.", + "NO_DESCRIPTION": "Энэ виртуал хөрөнгөд одоогоор тайлбар байхгүй байна.", "STAKE": "Гадас", "MORE": "Илүү", "INFO": "мэдээлэл", @@ -1548,44 +1548,44 @@ "SUBTITLE": "{0}-н худалдах, худалдах үнийг харахын тулд {1}-д зочилно уу.", "FOOTER": "Хурдан арилжаагаар хийгдсэн бүх арилжаанд зах зээлд оролцогчдын арилжааны хураамжийг хэрэглэнэ." }, - "LIST": "Та дижитал хөрөнгөө жагсаахыг хүсч байна уу?", + "LIST": "Та виртуал хөрөнгөө жагсаахыг хүсч байна уу?", "WEBSITE": "Вэб сайт", - "EXPLORER": "Судлаач" + "EXPLORER": "Explorer" }, "ACCORDIAN": { - "ACCORDIAN_ASSETS": "Бүх түрийвчний хөрөнгө", + "ACCORDIAN_ASSETS": "Бүх хөрөнгө", "ACCORDIAN_INFO": "ХӨРӨНГИЙН МЭДЭЭЛЛИЙН ХУУДАС", "ACCORDIAN_HISTORY": "ТҮҮХ" }, "ASYNC_LINK": { "TITLE": "Хуудас автоматаар нээгдэхгүй байна уу?", - "TEXT": "Таны хөтөч хуудсыг хааж байж магадгүй. Оронд нь доорх холбоосыг хуулж буулгаад үзээрэй." + "TEXT": "Таны хөтөч хуудсыг хааж байж магадгүй. Доорх холбоосыг хуулж тавиад үзээрэй." }, "TERMS_OF_SERVICES": { "TO_GET_ACCESS": "Хандалт авахын тулд холбогдоно уу" }, "FEES_AND_LIMITS": { - "LINK": "Миний хураамж, хязгаарлалтыг харах", + "LINK": "Миний хураамж, хязгаарлалт", "COIN_PAGE_LINK": "Арилжааны хураамж ба хязгаарлалт", "BACK": { "PLACEHOLDER": "{0} {1}", "BACK": "Буцах", "TO": "хураангуйлах" }, "TITLE": "Төлбөр ба хязгаарлалт", "SEARCH_PLACEHOLDER": "Хайх...", "TABS": { "TRADING_FEES": { - "TITLE": "Худалдааны хураамж", + "TITLE": "Арилжааны шимтгэл", "TABLE": { - "TITLE": "Зах зээлийн арилжааны төлбөр", - "SUBTITLE": "Зах зээлийн хувь хүний арилжааны хураамжийн дүрмийг доор харуулав.", + "TITLE": "Маркет шимтгэл", + "SUBTITLE": "Арилжааны шимтгэлийн дүнг дор харуулав.", "HEADER": { - "MARKET": "Зах зээл", - "MAKER": "Үйлдвэрлэгчийн арилжааны хураамж (захиалгыг хязгаарлах)", - "TAKER": "Такерын арилжааны хураамж (зах зээлийн захиалга)" + "MARKET": "Маркет", + "MAKER": "Зарах (лимит захиалга)", + "TAKER": "Авах (лимит захиалга)" } } }, "WITHDRAWAL_FEES": { "TITLE": "Зарлагын хураамж", "TABLE": { - "TITLE": "Татгалзах үед хураамжийг хасна", - "SUBTITLE": "Хөрөнгийг эргүүлэн татахад төлөх бүх хураамжийг доор харуулав.", + "TITLE": "Зарлагаас шимтгэл хасагдаж бодогдоно", + "SUBTITLE": "Зарлагын шимтгэлийн хэмжээг дор харуулав.", "NOT_ALLOWED": "Зөвшөөрөгдөөгүй", "HEADER": { "CURRENCY": "Валют/хөрөнгө", @@ -1595,7 +1595,7 @@ } }, "WITHDRAWAL_LIMITS": { - "TITLE": "Зарлагын хязгаар", + "TITLE": "Зарлагын лимит", "TABLE_1": { "TITLE": "Тусгайлсан зарлагын хязгаар", "SUBTITLE": "Нийтлэг хязгаарлалтаас тусдаа, тусгай хэмжээг мөрддөг виртуал хөрөнгө", @@ -1632,14 +1632,14 @@ "TAB": "Нэвтрэх түүх", "CONTENT": { "TITLE": "Нэвтрэх оролдлогын бүртгэл", - "SUBTITLE": "Таны дансанд нэвтэрч чадаагүй бүх оролдлого болон тэдгээрийн түүх.", + "SUBTITLE": "Таны амжилтгүй нэвтрэлтийн түүх.", "DOWNLOAD_HISTORY": "ТҮҮХ_ТАТАХ", - "FILTER": { "STATUS": "Статус", "ALL": "Бүгд", "FAILED": "Амжилтгүй", "SUCCESS": "Амжилттай" }, + "FILTER": { "STATUS": "Төлөв", "ALL": "Бүгд", "FAILED": "Амжилтгүй", "SUCCESS": "Амжилттай" }, "TABLE": { "HEADER": { "LAST_SEEN": { "TITLE": "Хамгийн сүүлд харсан", - "DESCRIPTION": "(Хамгийн сүүлийн үеийн эхний)" + "DESCRIPTION": "(Шинэ нь эхэнд)" }, "FAILED_ATTEMPTS": "Амжилтгүй оролдлого", "COUNTRY": "Улс", @@ -1654,7 +1654,7 @@ } }, "SESSIONS": { - "TAB": "Хурал", + "TAB": "Session", "CONTENT": { "TITLE": "Идэвхтэй сессүүд", "SUBTITLE": { @@ -1666,18 +1666,18 @@ "HEADER": { "LAST_SEEN": { "TITLE": "Хамгийн сүүлд харсан", - "DESCRIPTION": "(Хамгийн сүүлийн үеийн эхний)" + "DESCRIPTION": "(Шинэ нь эхэнд)" }, - "SESSION_STARTED": "Сессия эхэллээ", - "SESSION_EXPIRY": "Сеанс дуусах", - "STATUS": "Статус" + "SESSION_STARTED": "Нэвтрэлт эхэлсэн", + "SESSION_EXPIRY": "Нэвтрэлт дууссан", + "STATUS": "Төлөв" }, "CELL": { "ACTIVE": "Идэвхтэй", "COUNTRY": "Улс", "IP_ADDRESS": "IP хаяг", "DEVICE": "Төхөөрөмж", - "LOGIN_TIME": "Амжилттай нэвтрэх хугацаа" + "LOGIN_TIME": "Огноо" } }, "NOTIFICATION": "Сессийг цуцалсан/гарсан", @@ -1685,7 +1685,7 @@ "TITLE": "Сессийг хүчингүй болгох", "PROMPT": "Та энэ сессийг хүчингүй болгож, гарахдаа итгэлтэй байна уу?", "BACK": "БУЦАХ", - "CONFIRM": "БАТАЛГААХ" + "CONFIRM": "БАТЛАХ" } } } From 455471e899979b786b39078b326b193af87d0ddb Mon Sep 17 00:00:00 2001 From: ram Date: Fri, 5 Jul 2024 17:18:55 +0530 Subject: [PATCH 018/108] Updated and fixed the bugs on the theme based URL update notion task --- web/src/components/AppBar/index.js | 16 ++++-- web/src/containers/App/App.js | 15 ++---- web/src/containers/App/Socket.js | 82 +++++++++++++++++++++--------- 3 files changed, 75 insertions(+), 38 deletions(-) diff --git a/web/src/components/AppBar/index.js b/web/src/components/AppBar/index.js index f730f32e21..b74ed6b1dd 100644 --- a/web/src/components/AppBar/index.js +++ b/web/src/components/AppBar/index.js @@ -110,6 +110,7 @@ class AppBar extends Component { handleTheme = (selected) => { const { isEditMode, themeOptions } = this.props; + const params = new URLSearchParams(window.location.search); if (!isLoggedIn() || isEditMode) { this.props.changeTheme(selected); localStorage.setItem('theme', selected); @@ -124,6 +125,10 @@ class AppBar extends Component { .then(({ data }) => { this.props.setUserData(data); if (data.settings && data.settings.interface) { + params.set('theme', data.settings.interface.theme); + const currentUrl = window.location.href.split('?')[0]; + const newUrl = `${currentUrl}?${params.toString()}`; + this.props.router.replace(newUrl); this.props.changeTheme(data.settings.interface.theme); localStorage.setItem('theme', data.settings.interface.theme); } @@ -241,11 +246,14 @@ class AppBar extends Component { activeLanguage, changeLanguage, icons, + themeOptions, } = this.props; - const { securityPending, verificationPending, walletPending } = this.state; - - const { selected } = this.state; - const { themeOptions } = this.props; + const { + securityPending, + verificationPending, + walletPending, + selected, + } = this.state; return isHome ? (
diff --git a/web/src/containers/App/App.js b/web/src/containers/App/App.js index 3fb9cc9383..e2f5f73687 100644 --- a/web/src/containers/App/App.js +++ b/web/src/containers/App/App.js @@ -223,18 +223,11 @@ class App extends Component { if (JSON.stringify(prevProps.tools) !== JSON.stringify(tools)) { storeTools(tools); } - const themeOptions = [ - 'dark', - 'white', - 'Dark theme', - 'long black', - 'LONG FLAT BLACK', - 'yellow-piller', - ]; - const isValidTheme = themeOptions.includes( - this.props?.router?.location?.query?.theme + const { themeOptions } = this.props; + const isValidTheme = themeOptions.some( + (option) => option.value === this.props?.router?.location?.query?.theme ); - if (!params.has('theme') && isValidTheme) { + if (!params.has('theme')) { params.set('theme', activeTheme); const currentUrl = window.location.href.split('?')[0]; const newUrl = `${currentUrl}?${params.toString()}`; diff --git a/web/src/containers/App/Socket.js b/web/src/containers/App/Socket.js index 6ab64b43e3..8568f7ea9f 100644 --- a/web/src/containers/App/Socket.js +++ b/web/src/containers/App/Socket.js @@ -6,7 +6,15 @@ import { WS_URL, SESSION_TIME, BASE_CURRENCY } from 'config/constants'; import { isMobile } from 'react-device-detect'; import { setWsHeartbeat } from 'ws-heartbeat/client'; -import { getMe, setMe, setBalance, updateUser } from 'actions/userAction'; +import withConfig from 'components/ConfigProvider/withConfig'; +import { + getMe, + setMe, + setBalance, + updateUser, + updateUserSettings, + setUserData, +} from 'actions/userAction'; import { addUserTrades } from 'actions/walletActions'; import { setUserOrders, @@ -120,16 +128,9 @@ class Container extends Component { }; getUserDetails = () => { - const themeOptions = [ - 'dark', - 'white', - 'Dark theme', - 'long black', - 'LONG FLAT BLACK', - 'yellow-piller', - ]; - const isValidTheme = themeOptions.includes( - this.props?.router?.location?.query?.theme + const { themeOptions } = this.props; + const isValidTheme = themeOptions.some( + (option) => option.value === this.props?.router?.location?.query?.theme ); return this.props .getMe() @@ -137,6 +138,7 @@ class Container extends Component { if (value && value.data && value.data.id) { const data = value.data; const { defaults = {} } = this.props.constants; + const params = new URLSearchParams(window.location.search); let userData = { ...data }; if (data.settings) { if ( @@ -173,22 +175,52 @@ class Container extends Component { }, }, }; - } else if ( + } + if ( + data.settings.interface.theme !== this.props.activeTheme && this.props?.router?.location?.query?.theme && isValidTheme ) { - this.props.changeTheme( - this.props?.router?.location?.query?.theme - ); - localStorage.setItem( - 'theme', - this.props?.router?.location?.query?.theme - ); - } else if ( - data.settings.interface.theme !== this.props.activeTheme - ) { + params.set('theme', data.settings.interface.theme); + const currentUrl = window.location.href.split('?')[0]; + const newUrl = `${currentUrl}?${params.toString()}`; + this.props.router.replace(newUrl); this.props.changeTheme(data.settings.interface.theme); localStorage.setItem('theme', data.settings.interface.theme); + } else if ( + this.props?.router?.location?.query?.theme !== + data.settings.interface.theme && + isValidTheme + ) { + const { settings = { interface: {} } } = this.props.user; + const settingsObj = { interface: { ...settings.interface } }; + const theme = ( + themeOptions.find( + ({ value }) => + value === this.props?.router?.location?.query?.theme + ) || themeOptions[0] + ).value; + settingsObj.interface.theme = theme; + return updateUserSettings(settingsObj) + .then(({ data }) => { + this.props.setUserData(data); + this.props.setMe(data); + if (data.settings && data.settings.interface) { + this.props.changeTheme( + this.props?.router?.location?.query?.theme + ); + localStorage.setItem( + 'theme', + this.props?.router?.location?.query?.theme + ); + } + }) + .catch((err) => { + const error = { _error: err.message }; + if (err.response && err.response.data) { + error._error = err.response.data.message; + } + }); } } } @@ -690,6 +722,10 @@ const mapDispatchToProps = (dispatch) => ({ getMe: bindActionCreators(getMe, dispatch), requestTiers: bindActionCreators(requestTiers, dispatch), setPairsTradesFetched: bindActionCreators(setPairsTradesFetched, dispatch), + setUserData: bindActionCreators(setUserData, dispatch), }); -export default connect(mapStateToProps, mapDispatchToProps)(Container); +export default connect( + mapStateToProps, + mapDispatchToProps +)(withConfig(Container)); From e9ce93410c2d4f942e07e388bd2977e19e6cf707 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Mon, 8 Jul 2024 01:52:01 +0300 Subject: [PATCH 019/108] add-label --- server/api/swagger/user.yaml | 2 ++ server/utils/hollaex-tools-lib/tools/user.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/server/api/swagger/user.yaml b/server/api/swagger/user.yaml index 9e61486b06..1e241de31b 100644 --- a/server/api/swagger/user.yaml +++ b/server/api/swagger/user.yaml @@ -287,6 +287,8 @@ paths: properties: address: type: string + label: + type: string network: type: string responses: diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index fc49099af1..fc706c83f0 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -3289,7 +3289,7 @@ const updateUserAddresses = async (user_id, data) => { const { addresses } = data; addresses.forEach((addressObj) => { - if (!addressObj.address || !addressObj.network) { + if (!addressObj.address || !addressObj.network || !addressObj.label) { throw new Error(ADDRESSBOOK_MISSING_FIELDS); } }); From 1e5e3a5c0a560c91606f5c08ee32ac38662f4ecc Mon Sep 17 00:00:00 2001 From: fetok12 Date: Mon, 8 Jul 2024 01:59:30 +0300 Subject: [PATCH 020/108] fix-withdrawal-block-ui --- web/src/containers/Admin/User/AboutData.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/src/containers/Admin/User/AboutData.js b/web/src/containers/Admin/User/AboutData.js index 1c25d6807c..d462b95268 100644 --- a/web/src/containers/Admin/User/AboutData.js +++ b/web/src/containers/Admin/User/AboutData.js @@ -851,7 +851,8 @@ const AboutData = ({
- {userData.withdrawal_blocked ? ( + {userData.withdrawal_blocked && + moment().isBefore(moment(userData?.withdrawal_blocked)) ? (
Date: Mon, 8 Jul 2024 11:28:01 +0900 Subject: [PATCH 021/108] addressbook refinements --- ...40624132614-create-user-addressbooks.js.js | 3 +- server/db/models/userAddressBook.js | 2 +- server/messages.js | 4 +-- server/utils/hollaex-tools-lib/tools/user.js | 31 ++++++++++--------- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/server/db/migrations/20240624132614-create-user-addressbooks.js.js b/server/db/migrations/20240624132614-create-user-addressbooks.js.js index b851ee030e..4463235752 100644 --- a/server/db/migrations/20240624132614-create-user-addressbooks.js.js +++ b/server/db/migrations/20240624132614-create-user-addressbooks.js.js @@ -21,8 +21,9 @@ module.exports = { } }, addresses: { - type: Sequelize.ARRAY(Sequelize.JSONB), + type: Sequelize.JSONB, allowNull: false, + defaultValue: [] }, created_at: { allowNull: false, diff --git a/server/db/models/userAddressBook.js b/server/db/models/userAddressBook.js index 2ec4955105..378d3e3740 100644 --- a/server/db/models/userAddressBook.js +++ b/server/db/models/userAddressBook.js @@ -20,7 +20,7 @@ module.exports = function (sequelize, DataTypes) { } }, addresses: { - type: DataTypes.ARRAY(DataTypes.JSONB), + type: DataTypes.JSONB, allowNull: false, } }, diff --git a/server/messages.js b/server/messages.js index a584bfb3ba..5e043d3d9b 100644 --- a/server/messages.js +++ b/server/messages.js @@ -262,6 +262,6 @@ exports.CANNOT_CHANGE_DELETED_EMAIL = 'Cannot change deleted email'; exports.FAILED_GET_QUOTE = 'Failed to get the quote'; exports.BALANCE_HISTORY_NOT_ACTIVE = 'This feature is not active on the exchange'; exports.WITHDRAWAL_DISABLED = 'Withdrawal disabled for this user'; -exports.ADDRESSBOOK_MISSING_FIELDS = 'Each address must contain both address and network fields'; -exports.ADDRESSBOOK_ALREADY_EXISTS = 'One or more addresses already exist in the address book'; +exports.ADDRESSBOOK_MISSING_FIELDS = 'Each address must contain both address, network and label fields'; +exports.ADDRESSBOOK_ALREADY_EXISTS = 'One or more addresses or labels already exist in the address book'; exports.ADDRESSBOOK_NOT_FOUND = 'User address book not found'; \ No newline at end of file diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index fc706c83f0..7fa601237a 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -1637,13 +1637,13 @@ const disableUserWithdrawal = async (user_id, opts = { expiry_date : null }) => if (!user) { throw new Error(USER_NOT_FOUND); - }; + } let withdrawal_blocked = null; if (expiry_date) { withdrawal_blocked = moment(expiry_date).toISOString(); - }; + } return user.update( { withdrawal_blocked }, @@ -2468,31 +2468,31 @@ const createUserReferralCode = async (data) => { if (discount < 0) { throw new Error('discount cannot be negative'); - }; + } if (discount > 100) { throw new Error('discount cannot be more than 100'); - }; + } if (discount % 10 !== 0) { throw new Error('discount must be in increments of 10'); - }; + } if (earning_rate < 1) { throw new Error('earning rate cannot be less than 1'); - }; + } if (earning_rate > 100) { throw new Error('earning rate cannot be more than 100'); - }; + } if (earning_rate % 10 !== 0) { throw new Error('earning rate must be in increments of 10'); - }; + } if (!is_admin && (earning_rate + discount > EARNING_RATE)) { throw new Error('discount and earning rate combined cannot exceed exchange earning rate'); - }; + } if (!is_admin && code.length !== 6) { throw new Error('invalid referral code'); @@ -2502,18 +2502,18 @@ const createUserReferralCode = async (data) => { if (!user) { throw new Error(USER_NOT_FOUND); - }; + } if (!is_admin) { const userReferralCodes = await getModel('referralCode').findAll({ where: { user_id } - }) + }); if (userReferralCodes.length > 3) { throw new Error('you cannot create more than 3 referral codes'); } - }; + } const referralCode = await getModel('referralCode').create(data, { fields: [ @@ -3278,7 +3278,10 @@ const fetchUserAddressBook = async (user_id) => { const userAddressBook = await getModel('userAddressBook').findOne({ where: { user_id } }); if (!userAddressBook) { - throw new Error(ADDRESSBOOK_NOT_FOUND); + return { + user_id: user.id, + addresses: [] + }; } return userAddressBook; @@ -3309,7 +3312,7 @@ const updateUserAddresses = async (user_id, data) => { } else { // Check if any address in the payload already exists const existingAddresses = userAddressBook.addresses.map(a => a.address); - const duplicateAddresses = addresses.filter(a => existingAddresses.includes(a.address)); + const duplicateAddresses = addresses.filter(a => existingAddresses.includes(a.address) || existingAddresses.includes(a.label)); if (duplicateAddresses.length > 0) { throw new Error(ADDRESSBOOK_ALREADY_EXISTS); } From c891e86494796adc160ed118b1ea8ed324b3a0f9 Mon Sep 17 00:00:00 2001 From: ram Date: Mon, 8 Jul 2024 17:59:03 +0530 Subject: [PATCH 022/108] Fixed the search issue on the withdraw/deposit pages --- web/src/containers/Deposit/Deposit.js | 56 +++++++++++++++++++++---- web/src/containers/Deposit/index.js | 7 ++++ web/src/containers/Withdraw/Withdraw.js | 55 ++++++++++++++++++++---- web/src/containers/Withdraw/form.js | 13 ++++-- web/src/containers/Withdraw/utils.js | 17 +++++++- web/src/utils/wallet.js | 27 ++++++++++++ 6 files changed, 157 insertions(+), 18 deletions(-) diff --git a/web/src/containers/Deposit/Deposit.js b/web/src/containers/Deposit/Deposit.js index 63672a57f2..b320ddfdcb 100644 --- a/web/src/containers/Deposit/Deposit.js +++ b/web/src/containers/Deposit/Deposit.js @@ -19,7 +19,12 @@ import { import { Coin, EditWrapper } from 'components'; import { STATIC_ICONS } from 'config/icons'; import { assetsSelector } from 'containers/Wallet/utils'; -import { renderLabel, renderNetworkWithLabel } from 'containers/Withdraw/utils'; +import { + networkList, + renderLabel, + renderNetworkField, + renderNetworkWithLabel, +} from 'containers/Withdraw/utils'; import STRINGS from 'config/localizedStrings'; import { onHandleSymbol } from './utils'; @@ -58,6 +63,7 @@ const DepositComponent = ({ const [optionalTag, setOptionalTag] = useState(''); const [isDisbaleDeposit, setIsDisbaleDeposit] = useState(false); const [isVisible, setIsVisible] = useState(false); + const [networkData, setNetworkData] = useState(null); const defaultCurrency = currency !== '' && currency; const address = depositAddress?.split(':'); @@ -215,8 +221,9 @@ const DepositComponent = ({ if (val) { setCurrStep((prev) => ({ ...prev, stepThree: true })); setDepositNetworkOptions(val); - updateAddress(val, true); + updateAddress(renderNetworkField(val), true); setDepositNetwork(val); + setNetworkData(val); } else if (!val) { setCurrStep((prev) => ({ ...prev, stepThree: false, stepFour: false })); } @@ -260,6 +267,7 @@ const DepositComponent = ({ } if (type === 'network') { setDepositNetworkOptions(null); + setNetworkData(null); } }; @@ -471,12 +479,16 @@ const DepositComponent = ({ coinLength?.length < 1 ? defaultNetwork : coinLength && coinLength.length <= 1 - ? renderNetworkWithLabel(networkIcon, network) + ? getDepositNetworkOptions && getDepositNetworkOptions + ? networkData + : renderNetworkWithLabel(networkIcon, network) : coinLength && coinLength.length > 1 - ? renderNetworkWithLabel( - networkOptionsIcon, - getDepositNetworkOptions - ) + ? getDepositNetworkOptions && getDepositNetworkOptions + ? networkData + : renderNetworkWithLabel( + networkOptionsIcon, + getDepositNetworkOptions + ) : coins[getDepositCurrency]?.symbol.toUpperCase() } disabled={ @@ -487,6 +499,7 @@ const DepositComponent = ({ onClear={() => onHandleClear('network')} > {coinLength && + coinLength?.length === 1 && coinLength.map((data, inx) => ( ))} + {coinLength && + coinLength?.length > 1 && + networkList.map((data, inx) => { + const coin = data.iconId.split('_'); + return coinLength.map((coinData, coinInx) => { + if (coinData === coin[0]?.toLowerCase()) { + return ( + + ); + } + return null; + }); + })} {(coinLength && coinLength.length === 1 && diff --git a/web/src/containers/Deposit/index.js b/web/src/containers/Deposit/index.js index 71001a2783..5c106bb2cc 100644 --- a/web/src/containers/Deposit/index.js +++ b/web/src/containers/Deposit/index.js @@ -26,6 +26,7 @@ import { getWallet } from 'utils/wallet'; import QRCode from './QRCode'; import withConfig from 'components/ConfigProvider/withConfig'; import strings from 'config/localizedStrings'; +import { networkList, renderNetworkField } from 'containers/Withdraw/utils'; class Deposit extends Component { state = { @@ -102,6 +103,12 @@ class Deposit extends Component { updateAddress = (selectedCurrency, hasNetwork = false) => { const { wallet, getDepositCurrency, getDepositNetworkOptions } = this.props; + const networkItems = networkList?.map((data) => { + return data.network; + }); + if (networkItems?.includes(selectedCurrency)) { + return renderNetworkField(selectedCurrency); + } const depositAddress = wallet.filter((val) => { if (hasNetwork) { return ( diff --git a/web/src/containers/Withdraw/Withdraw.js b/web/src/containers/Withdraw/Withdraw.js index 8481ae6ed7..b563a2a25f 100644 --- a/web/src/containers/Withdraw/Withdraw.js +++ b/web/src/containers/Withdraw/Withdraw.js @@ -30,9 +30,11 @@ import { getPrices } from 'actions/assetActions'; import { calculateFee, calculateFeeCoin, + networkList, onHandleSymbol, renderEstimatedValueAndFee, renderLabel, + renderNetworkField, renderNetworkWithLabel, } from './utils'; import { email, validAddress } from 'components/Form/validations'; @@ -69,6 +71,7 @@ const RenderWithdraw = ({ const [optionalTag, setOptionalTag] = useState(''); const [isValidEmail, setIsValidEmail] = useState(false); const [isDisbaleWithdraw, setIsDisbaleWithdraw] = useState(false); + const [networkData, setNetworkData] = useState(null); // const [isCheck, setIsCheck] = useState(false); // const [isVisible, setIsVisible] = useState(false); // const [isWarning, setIsWarning] = useState(false); @@ -344,7 +347,8 @@ const RenderWithdraw = ({ const onHandleChangeNetwork = (val) => { if (val) { setCurrStep((prev) => ({ ...prev, stepFour: true })); - setWithdrawNetworkOptions(val); + setWithdrawNetworkOptions(renderNetworkField(val)); + setNetworkData(val); } else if (!val) { setCurrStep((prev) => ({ ...prev, stepFour: false, stepFive: false })); } @@ -474,6 +478,7 @@ const RenderWithdraw = ({ if (type === 'network') { setWithdrawAddress(null); setWithdrawNetworkOptions(null); + setNetworkData(null); } setCurrStep({ ...currStep, @@ -789,12 +794,18 @@ const RenderWithdraw = ({ coinLength?.length < 1 ? defaultNetwork : coinLength && coinLength.length <= 1 - ? renderNetworkWithLabel(networkIcon, network) + ? getWithdrawNetworkOptions && + getWithdrawNetworkOptions + ? networkData + : renderNetworkWithLabel(networkIcon, network) : coinLength && coinLength.length > 1 - ? renderNetworkWithLabel( - networkOptionsIcon, - getWithdrawNetworkOptions - ) + ? getWithdrawNetworkOptions && + getWithdrawNetworkOptions + ? networkData + : renderNetworkWithLabel( + networkOptionsIcon, + getWithdrawNetworkOptions + ) : coins[getWithdrawCurrency]?.symbol.toUpperCase() } disabled={ @@ -803,7 +814,8 @@ const RenderWithdraw = ({ } onClear={() => onHandleClear('network')} > - {coinLength && + {coinLength?.length === 1 && + coinLength && coinLength.map((data, inx) => ( ))} + {coinLength && + coinLength?.length > 1 && + networkList.map((data, inx) => { + const coin = data.iconId.split('_'); + return coinLength.map((coinData, coinInx) => { + if (coinData === coin[0]?.toLowerCase()) { + return ( + + ); + } + return null; + }); + })} {selectedMethod !== strings['FORM_FIELDS.EMAIL_LABEL'] && isEmailAndAddress && diff --git a/web/src/containers/Withdraw/form.js b/web/src/containers/Withdraw/form.js index 003f8ac90f..fdd209fdd6 100644 --- a/web/src/containers/Withdraw/form.js +++ b/web/src/containers/Withdraw/form.js @@ -20,6 +20,7 @@ import { calculateFeeCoin, generateBaseInformation, renderLabel, + renderNetworkField, } from './utils'; import { setWithdrawOptionaltag, withdrawCurrency } from 'actions/appActions'; import { renderInformation } from 'containers/Wallet/components'; @@ -160,9 +161,15 @@ class Form extends Component { const currentCurrency = getWithdrawCurrency ? getWithdrawCurrency : currency; - const network = getWithdrawNetworkOptions - ? getWithdrawNetworkOptions - : getWithdrawNetwork; + const coinLength = + coins[getWithdrawCurrency]?.network && + coins[getWithdrawCurrency]?.network.split(','); + const network = + coinLength && coinLength === 1 + ? getWithdrawNetworkOptions + ? getWithdrawNetworkOptions + : getWithdrawNetwork + : renderNetworkField(getWithdrawNetworkOptions)?.toLowerCase(); const defaultNetwork = currentCurrency && coins[currentCurrency]?.network && diff --git a/web/src/containers/Withdraw/utils.js b/web/src/containers/Withdraw/utils.js index 94d1076396..c06bf74210 100644 --- a/web/src/containers/Withdraw/utils.js +++ b/web/src/containers/Withdraw/utils.js @@ -11,7 +11,7 @@ import { import STRINGS from 'config/localizedStrings'; import { renderBankInformation } from '../Wallet/components'; -import { getNetworkNameByKey } from 'utils/wallet'; +import { getNetworkName, getNetworkNameByKey } from 'utils/wallet'; export const generateBaseInformation = (currency, limits = {}) => { const { minAmount = 2, maxAmount = 10000 } = limits; @@ -157,3 +157,18 @@ export const renderNetworkWithLabel = (iconId, network) => {
) : null; }; + +export const renderNetworkField = (network) => { + return network ? getNetworkName(network) : null; +}; + +export const networkList = [ + { network: 'ERC20', iconId: 'ETH_ICON' }, + { network: 'BEP20', iconId: 'BNB_ICON' }, + { network: 'TRC20', iconId: 'TRX_ICON' }, + { network: 'klaytn', iconId: 'KLAY_ICON' }, + { network: 'Polygon', iconId: 'MATIC_ICON' }, + { network: 'Solana', iconId: 'SOL_ICON' }, + { network: 'Stellar', iconId: 'XLM_ICON' }, + { network: 'Fantom', iconId: 'FTM_ICON' }, +]; diff --git a/web/src/utils/wallet.js b/web/src/utils/wallet.js index 5276596e27..879be8e266 100644 --- a/web/src/utils/wallet.js +++ b/web/src/utils/wallet.js @@ -51,3 +51,30 @@ export const getNetworkNameByKey = (network) => { export const getNetworkLabelByKey = (network) => { return `${network.toUpperCase()} (${getNetworkNameByKey(network)})`; }; + +export const getNetworkName = (network) => { + if (network) { + switch (network) { + case 'ERC20': + return 'eth'; + case 'TRC20': + return 'trx'; + case 'BEP20': + return 'bnb'; + case 'klaytn': + return 'klay'; + case 'Polygon': + return 'matic'; + case 'Solana': + return 'sol'; + case 'Stellar': + return 'xlm'; + case 'Fantom': + return 'ftm'; + default: + return network.toUpperCase(); + } + } else { + return network; + } +}; From 08cb083ad07b8a5a53b24d49d231c638b5860e5d Mon Sep 17 00:00:00 2001 From: fetok12 Date: Tue, 9 Jul 2024 02:03:21 +0300 Subject: [PATCH 023/108] p2p-global-notifications --- server/ws/chat/index.js | 11 +++++++++ server/ws/sub.js | 2 ++ web/src/config/lang/en.json | 5 +++- web/src/containers/App/Socket.js | 37 +++++++++++++++++++++++++++++- web/src/containers/P2P/P2POrder.js | 4 ++++ 5 files changed, 57 insertions(+), 2 deletions(-) diff --git a/server/ws/chat/index.js b/server/ws/chat/index.js index a820bd5618..0fd7f6c652 100644 --- a/server/ws/chat/index.js +++ b/server/ws/chat/index.js @@ -85,6 +85,7 @@ const getP2PStatus = (user_id, p2pData) => { id: p2pData.id, user_id, status: p2pData.status, + ...p2pData, created_at }; publisher.publish(P2P_CHAT_MESSAGE_CHANNEL, JSON.stringify({ type: 'status', data })); @@ -124,6 +125,16 @@ const publishP2PChatMessage = (event, data) => { })); } }); + + each(getChannels()[WEBSOCKET_CHANNEL('p2pChat', data.receiver_id)], (ws) => { + if (ws.readyState === WebSocket.OPEN) { + ws.send(JSON.stringify({ + topic: `p2pChat`, + action: event, + data + })); + } + }); }; const maintenanceMessageList = debounce(() => { diff --git a/server/ws/sub.js b/server/ws/sub.js index a13867ffc9..89519f5379 100644 --- a/server/ws/sub.js +++ b/server/ws/sub.js @@ -104,6 +104,7 @@ const initializeTopic = (topic, ws, symbol) => { case 'p2pChat': addSubscriber(WEBSOCKET_CHANNEL(topic, symbol), ws); + addSubscriber(WEBSOCKET_CHANNEL(topic, ws.auth.sub.id), ws); break; case 'admin': // this channel can only be subscribed by the exchange admin @@ -176,6 +177,7 @@ const terminateTopic = (topic, ws, symbol) => { break; case 'p2pChat': removeSubscriber(WEBSOCKET_CHANNEL(topic, symbol), ws); + removeSubscriber(WEBSOCKET_CHANNEL(topic, ws.auth.sub.id), ws); ws.send(JSON.stringify({ message: `Unsubscribed from channel ${topic}:${ws.auth.sub.id}` })); break; case 'admin': diff --git a/web/src/config/lang/en.json b/web/src/config/lang/en.json index b57aa69b87..dfb812e2e3 100644 --- a/web/src/config/lang/en.json +++ b/web/src/config/lang/en.json @@ -2123,6 +2123,9 @@ "ALL_REGION": "All Region", "BUYER_NOT_MADE_THE_PAYMENT": "The buyer has not confirmed their payment yet.", "PRICE_TO_ADVERTISE": "Price you’ll advertise to sell", - "VIEW_PROFILE": "View vendor's profile" + "VIEW_PROFILE": "View vendor's profile", + "CLICK_TO_VIEW": "CLICK TO VIEW", + "NEW_MESSAGE:": "You have a new message for your order", + "STATUS_UPDATE": "You have an update on your order" } } diff --git a/web/src/containers/App/Socket.js b/web/src/containers/App/Socket.js index 8568f7ea9f..276abdae6f 100644 --- a/web/src/containers/App/Socket.js +++ b/web/src/containers/App/Socket.js @@ -46,6 +46,8 @@ import { playBackgroundAudioNotification } from 'utils/utils'; import { getToken, isLoggedIn } from 'utils/token'; import { NORMAL_CLOSURE_CODE, isIntentionalClosure } from 'utils/webSocket'; import { ERROR_TOKEN_EXPIRED } from 'components/Notification/Logout'; +import { notification } from 'antd'; +import STRINGS from 'config/localizedStrings'; class Container extends Component { constructor(props) { @@ -260,7 +262,14 @@ class Container extends Component { privateSocket.send( JSON.stringify({ op: 'subscribe', - args: ['trade', 'wallet', 'order', 'deposit', 'usertrade'], + args: [ + 'trade', + 'wallet', + 'order', + 'deposit', + 'usertrade', + `p2pChat:${this.props.user.id}`, + ], }) ); // this.wsInterval = setInterval(() => { @@ -421,6 +430,32 @@ class Container extends Component { this.props.setNotification(NOTIFICATIONS.DEPOSIT, data.data, show); } break; + case 'p2pChat': + notification.open({ + message: (data.action = 'getStatus' + ? STRINGS['P2P.STATUS_UPDATE'] + : STRINGS['P2P.NEW_MESSAGE']), + description: ( +
+
{ + window.location.href = `${window.location.origin}/p2p/order/${data.data.id}`; + }} + > + {STRINGS['P2P.CLICK_TO_VIEW']} +
+
+ ), + + placement: 'bottomRight', + type: 'info', + }); + break; default: break; } diff --git a/web/src/containers/P2P/P2POrder.js b/web/src/containers/P2P/P2POrder.js index 5e6bec4037..e1a5caf444 100644 --- a/web/src/containers/P2P/P2POrder.js +++ b/web/src/containers/P2P/P2POrder.js @@ -204,6 +204,10 @@ const P2POrder = ({ data: { id: selectedOrder.id, status, + receiver_id: + user.id === selectedOrder?.merchant_id + ? selectedOrder?.user_id + : selectedOrder?.merchant_id, }, }, ], From 26a655f9797866355f7178e1a483218e8db7ea06 Mon Sep 17 00:00:00 2001 From: ram Date: Tue, 9 Jul 2024 20:16:02 +0530 Subject: [PATCH 024/108] Fixed the QR code issue on the deposit page --- web/src/containers/Deposit/Deposit.js | 10 ++++++++-- web/src/containers/Deposit/_Deposit.scss | 6 ++++++ web/src/index.css | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/web/src/containers/Deposit/Deposit.js b/web/src/containers/Deposit/Deposit.js index b320ddfdcb..f7af83c512 100644 --- a/web/src/containers/Deposit/Deposit.js +++ b/web/src/containers/Deposit/Deposit.js @@ -637,8 +637,14 @@ const DepositComponent = ({
diff --git a/web/src/containers/Deposit/_Deposit.scss b/web/src/containers/Deposit/_Deposit.scss index 3ebfc7b14c..81883e26a6 100644 --- a/web/src/containers/Deposit/_Deposit.scss +++ b/web/src/containers/Deposit/_Deposit.scss @@ -165,6 +165,12 @@ $qr-code--size: 12rem; box-shadow: none; } + .tag-field { + .ant-input-suffix { + justify-content: end; + } + } + .ant-input-suffix { width: 15% !important; } diff --git a/web/src/index.css b/web/src/index.css index ea288242aa..ed9acdc4d0 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -2801,6 +2801,8 @@ table th { border-bottom: 1px solid var(--calculated_important-border) !important; } .deposit-address-wrapper .deposit-address-field .ant-input-affix-wrapper-focused { box-shadow: none; } + .deposit-address-wrapper .deposit-address-field .tag-field .ant-input-suffix { + justify-content: end; } .deposit-address-wrapper .deposit-address-field .ant-input-suffix { width: 15% !important; } .deposit-address-wrapper .deposit-address-field .divider { From c99d2a49e14365140b433cf9736c5c98715ad356 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Tue, 9 Jul 2024 23:19:33 +0300 Subject: [PATCH 025/108] p2p-expiration-state --- server/utils/hollaex-tools-lib/tools/p2p.js | 12 ++++++++++- web/src/containers/P2P/P2POrder.js | 23 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/server/utils/hollaex-tools-lib/tools/p2p.js b/server/utils/hollaex-tools-lib/tools/p2p.js index bb86e0e1ff..2f873e4c73 100644 --- a/server/utils/hollaex-tools-lib/tools/p2p.js +++ b/server/utils/hollaex-tools-lib/tools/p2p.js @@ -586,7 +586,7 @@ const updateP2pTransaction = async (data) => { throw new Error(`Transaction expired, ${transaction.transaction_duration} minutes passed without any action`); } - if (transaction.merchant_status !== 'pending' && moment() > moment(transaction.created_at).add(transaction.transaction_duration || 30 ,'minutes')) { + if (transaction.user_status === 'pending' && moment() > moment(transaction.created_at).add(transaction.transaction_duration || 30 ,'minutes')) { if (transaction.transaction_status !== 'expired') { @@ -610,6 +610,16 @@ const updateP2pTransaction = async (data) => { user.settings ); + sendEmail( + MAILTYPE.P2P_ORDER_EXPIRED, + merchant.email, + { + order_id: id, + ip + }, + merchant.settings + ); + newMessages.push(chatMessage); await transaction.update({ transaction_status: 'expired', messages: newMessages }, { diff --git a/web/src/containers/P2P/P2POrder.js b/web/src/containers/P2P/P2POrder.js index e1a5caf444..f47cdda1ed 100644 --- a/web/src/containers/P2P/P2POrder.js +++ b/web/src/containers/P2P/P2POrder.js @@ -167,6 +167,29 @@ const P2POrder = ({ } }) .catch((err) => err); + + if ( + selectedOrder.user_status === 'pending' && + moment() > + moment(selectedOrder.created_at).add( + selectedOrder.transaction_duration || 30, + 'minutes' + ) + ) { + if (selectedOrder.transaction_status !== 'expired') { + updateTransaction({ + id: selectedOrder.id, + transaction_status: 'expired', + }) + .then((res) => { + setSelectedOrder({ + ...selectedOrder, + transaction_status: 'expired', + }); + }) + .catch((err) => err); + } + } }, []); const getTransaction = async () => { From 05dcd7c2e8a5b613be9793d872f352b12ab28db2 Mon Sep 17 00:00:00 2001 From: ram Date: Wed, 10 Jul 2024 22:20:05 +0530 Subject: [PATCH 026/108] Fixed the bugs on the deposit/withdraw page and wallet mobile view --- .../components/ActionNotification/index.js | 35 ++++----- web/src/containers/Deposit/Deposit.js | 53 +++++++------ web/src/containers/Wallet/AssetsBlock.js | 76 ++++++++++++++----- web/src/containers/Wallet/_Wallet.scss | 21 +++-- .../Wallet/components/TradeInputGroup.js | 3 +- web/src/index.css | 50 +++++++----- 6 files changed, 151 insertions(+), 87 deletions(-) diff --git a/web/src/components/ActionNotification/index.js b/web/src/components/ActionNotification/index.js index 2eeb0854d6..1fae83f9d2 100644 --- a/web/src/components/ActionNotification/index.js +++ b/web/src/components/ActionNotification/index.js @@ -2,7 +2,6 @@ import React from 'react'; import classnames from 'classnames'; import Image from 'components/Image'; import { isMobile } from 'react-device-detect'; -import { MoreOutlined } from '@ant-design/icons'; const getClassNames = (status) => { switch (status) { @@ -79,28 +78,22 @@ const ActionNotification = ({ getClassNames(status) )} > - {text === 'mobile-trade' ? ( - - ) : ( - text - )} + {text}
)} - {text !== 'mobile-trade' && ( - {text} - )} + {text}
); }; diff --git a/web/src/containers/Deposit/Deposit.js b/web/src/containers/Deposit/Deposit.js index f7af83c512..d6cb04537e 100644 --- a/web/src/containers/Deposit/Deposit.js +++ b/web/src/containers/Deposit/Deposit.js @@ -116,12 +116,6 @@ const DepositComponent = ({ } else { setCurrStep({ ...currStep, stepTwo: true }); } - if ( - ['xrp', 'xlm', 'ton', 'pmn'].includes(defaultCurrency) || - ['xrp', 'xlm', 'ton', 'pmn'].includes(defaultNetwork) - ) { - setIsVisible(true); - } setDepositCurrency(defaultCurrency); setSelectedAsset(defaultCurrency); updateAddress(defaultCurrency); @@ -131,7 +125,7 @@ const DepositComponent = ({ setDepositNetworkOptions(null); }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }, [defaultCurrency]); useEffect(() => { if (isTag) { @@ -156,6 +150,18 @@ const DepositComponent = ({ } }, [getDepositCurrency, isDeposit]); + useEffect(() => { + if (selectedAsset) { + if ( + ['xrp', 'xlm', 'ton', 'pmn'].includes(defaultCurrency) || + ['xrp', 'xlm', 'ton', 'pmn'].includes(defaultNetwork) + ) { + setIsVisible(true); + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedAsset]); + const onHandleChangeSelect = (val, pinned_assets = false) => { if (pinned_assets) { setIsPinnedAssets(pinned_assets); @@ -229,7 +235,7 @@ const DepositComponent = ({ } }; - const renderScanIcon = (isTag = false) => { + const renderScanIcon = (isTag = false, type = 'address') => { return (
{!isTag && ( @@ -245,7 +251,9 @@ const DepositComponent = ({
)} - +
onCopy()}> {renderLabel('COPY_TEXT')}
@@ -273,7 +281,7 @@ const DepositComponent = ({ const onHandleSelect = (symbol) => { const curr = onHandleSymbol(symbol); - if (curr !== symbol) { + if (curr !== symbol && ['xrp', 'xlm', 'ton'].includes(curr)) { if ( ['xrp', 'xlm', 'ton'].includes(defaultCurrency) || ['xrp', 'xlm', 'ton'].includes(defaultNetwork) @@ -326,6 +334,16 @@ const DepositComponent = ({ : `deposit-wrapper-fields ${isMobile ? '' : 'mt-5'}` } > + setIsVisible(false)} + footer={false} + className="withdrawal-remove-tag-modal" + width={'420px'} + > + {renderDepositWarningPopup()} +
@@ -643,7 +661,8 @@ const DepositComponent = ({ : 'destination-input-field' }`} suffix={renderScanIcon( - ['xrp', 'xlm', 'ton'].includes(selectedAsset) + ['xrp', 'xlm', 'ton'].includes(selectedAsset), + 'address' )} value={address && address[0]} > @@ -724,7 +743,7 @@ const DepositComponent = ({ ? 'number' : 'text' } - suffix={renderScanIcon(true)} + suffix={renderScanIcon(true, 'optionalTag')} >
@@ -740,16 +759,6 @@ const DepositComponent = ({
- setIsVisible(false)} - footer={false} - className="withdrawal-remove-tag-modal" - width={'420px'} - > - {renderDepositWarningPopup()} -
)}
diff --git a/web/src/containers/Wallet/AssetsBlock.js b/web/src/containers/Wallet/AssetsBlock.js index b8fcac65fc..6c4dd28120 100644 --- a/web/src/containers/Wallet/AssetsBlock.js +++ b/web/src/containers/Wallet/AssetsBlock.js @@ -3,11 +3,13 @@ import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import { Link } from 'react-router'; import { isMobile } from 'react-device-detect'; -import { Checkbox, Switch } from 'antd'; +import { Checkbox, Dropdown, Menu, Switch } from 'antd'; import { CaretUpOutlined, CaretDownOutlined, SearchOutlined, + CloseCircleOutlined, + MoreOutlined, } from '@ant-design/icons'; import { fetchBalanceHistory, fetchPlHistory } from './actions'; import classnames from 'classnames'; @@ -324,8 +326,17 @@ const AssetsBlock = ({ placeHolder={`${STRINGS['WALLET_ASSETS_SEARCH_TXT']}...`} handleSearch={handleSearch} showCross + isFocus={true} /> +
setIsSearchActive(false)}> + + + {STRINGS['CLOSE_TEXT']} + + + +
)}
@@ -713,24 +724,53 @@ const AssetsBlock = ({ {assets && baseCoin && !loading && increment_unit ? (
-
-
{balance}
- {key !== BASE_CURRENCY && - parseFloat(balanceText || 0) > 0 && ( -
- {`(≈ $${balanceText})`} + goToTrade(key)}> + {markets.map((market) => { + const { display_name, icon_id } = + pairs[market] || + quicktrade.find( + ({ symbol }) => symbol === market + ) || + {}; + return ( + +
+ +
+ {display_name} +
+
+
+ ); + })} + + } + > +
+
+
+ {balance}
- )} -
-
- -
+ {key !== BASE_CURRENCY && + parseFloat(balanceText || 0) > 0 && ( +
+ {`(≈ $${balanceText})`} +
+ )} +
+ +
+
) : (
{ return ( Date: Wed, 10 Jul 2024 22:43:14 +0530 Subject: [PATCH 027/108] Fixed the search issue on the wallet mobile view --- web/src/containers/Wallet/AssetsBlock.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/web/src/containers/Wallet/AssetsBlock.js b/web/src/containers/Wallet/AssetsBlock.js index 6c4dd28120..1466d9617d 100644 --- a/web/src/containers/Wallet/AssetsBlock.js +++ b/web/src/containers/Wallet/AssetsBlock.js @@ -289,6 +289,11 @@ const AssetsBlock = ({ return unique([...quickTrade, ...trade]); }; + const onHandleClose = () => { + setIsSearchActive(false); + handleSearch(); + }; + return showDustSection ? ( ) : ( @@ -329,7 +334,7 @@ const AssetsBlock = ({ isFocus={true} /> -
setIsSearchActive(false)}> +
onHandleClose()}> {STRINGS['CLOSE_TEXT']} From bbf4b2d77199706427cd60396b23499a267d5405 Mon Sep 17 00:00:00 2001 From: mytilene Date: Tue, 16 Jul 2024 11:08:26 +0800 Subject: [PATCH 028/108] Update mn.json --- web/src/config/lang/mn.json | 94 ++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/web/src/config/lang/mn.json b/web/src/config/lang/mn.json index c514bb2f49..2c6471d4fd 100644 --- a/web/src/config/lang/mn.json +++ b/web/src/config/lang/mn.json @@ -1856,42 +1856,42 @@ } } }, - "CANCEL_WITHDRAWAL_ADDRESS": "Татгалзах хаяг", - "BALANCES": "Үлдэгдэл", + "CANCEL_WITHDRAWAL_ADDRESS": "Зарлагын хаяг", + "BALANCES": "Баланс", "P2P": { - "I_WANT_TO_BUY": "Би худалдаж авмаар байна", - "I_WANT_TO_SELL": "Би зармаар байна", - "SPEND_FIAT_CURRENCY": "Fiat валютыг сонгоно уу", + "I_WANT_TO_BUY": "Авна", + "I_WANT_TO_SELL": "Зарна", + "SPEND_FIAT_CURRENCY": "Fiat валют сонгох", "AMOUNT": "Дүн", - "PAYMENT_METHOD": "Төлбөрийн нөхцөл", - "AVAILABLE_REGIONS": "Боломжтой бүс нутаг", + "PAYMENT_METHOD": "Төлбөрийн хэлбэр", + "AVAILABLE_REGIONS": "Боломжтой бүс", "VENDOR": "Худалдагч", - "PRICE_LOWEST_FIRST": "Үнэ (эхлээд хамгийн бага)", - "LIMIT_AVAILABLE": "Хязгаар/боломжтой", + "PRICE_LOWEST_FIRST": "Үнэ (бага нь эхэнд)", + "LIMIT_AVAILABLE": "Лимит/боломжит", "PAYMENT": "Төлбөр", - "TRADE": "Худалдаа", - "SELECT_PAYMENT_METHOD": "Төлбөрийн аргыг сонгоно уу", - "SPEND_AMOUNT": "Зарцуулалтын хэмжээ", - "AMOUNT_TO_RECEIVE": "Хүлээн авах хэмжээ", + "TRADE": "Арилжаа", + "SELECT_PAYMENT_METHOD": "Төлбөрийн хэлбэр", + "SPEND_AMOUNT": "Зарцуулах дүн", + "AMOUNT_TO_RECEIVE": "Хүлээн авах дүн", "ORDER_CREATED": "Захиалга үүсгэсэн.", - "SELECT_PAYMENT_METHOD_AND_AMOUNT": "Төлбөрийн арга болон оруулах дүнг сонгоно уу", + "SELECT_PAYMENT_METHOD_AND_AMOUNT": "Төлбөрийн хэлбэр болон дүнг оруулна уу", "ERROR_MESSAGE": "Алдаа гарлаа.", "TRANSACTION_NOT_FOUND": "Гүйлгээ олдсонгүй", - "TITLE": "P2P хэлэлцээр", + "TITLE": "P2P арилжаа", "DESCRIPTION": "P2P нь Bitcoin, USDT болон бусад криптовалютыг худалдан авах, худалдах хэлцэл юм.", "TAB_P2P": "P2P", "TAB_ORDERS": "Захиалга", "TAB_PROFILE": "Профайл", - "TAB_POST_DEAL": "Гүйцэтгэлийн дараах", + "TAB_POST_DEAL": "Санал илгээх", "TAB_MY_DEALS": "Миний саналууд", - "NO_DEALS": "Ямар ч наймаа байхгүй", - "NUM_DEALS": "Хямдрал:", - "CHANGES_SAVED": "Өөрчлөлтүүдийг хадгалсан", + "NO_DEALS": "Санал байхгүй", + "NUM_DEALS": "Саналууд:", + "CHANGES_SAVED": "Өөрчлөлт хадгалсан", "ACTIVATE": "ИДЭВХЖҮҮЛЭХ", - "TAKE_OFFLINE": "ОФЛАЙН АВАХ", - "EDIT": "Засварлах", - "SIDE": "Хажуу тал", - "STATUS": "Статус", + "TAKE_OFFLINE": "ОФЛАЙН БОЛГОХ", + "EDIT": "Засах", + "SIDE": "Тал", + "STATUS": "Төлөв", "PRICE_DISPLAYED": "Үнийг харуулсан", "EDIT_DEAL": "Хэлэлцээрийг засах", "ACTIVE": "ИДЭВХТЭЙ", @@ -1983,42 +1983,42 @@ "ORDER_CLOSED": "Давж заалдах хүсэлтийн дагуу шийдвэр гарсны дараа захирамжийг хаасан.", "VENDOR_CANCELLED_ORDER": "Худалдагч энэ захиалгыг цуцалсан тул гүйлгээ хаагдсан.", "VENDOR_APPEALED_ORDER": "Худалдагч энэ захиалгыг давж заалдсан тул асуудлыг шийдвэрлэхийн тулд тусламж үйлчилгээтэй холбогдоно уу.", - "SET_TYPE_PRICE": "Төрөл, үнийг тохируулна уу", - "SET_AMOUNT_PAYMENT_METHODS": "Нийт дүн болон төлбөрийн аргыг тохируулна уу", - "SET_TERMS_RESPONSE": "Нөхцөл ба автомат хариуг тохируулах", - "UPDATE_DEAL": "Хэлэлцээрийг шинэчлэх", - "SELL_UPPER": "ЗАРНА", + "SET_TYPE_PRICE": "Үнэ, төрөл сонгох", + "SET_AMOUNT_PAYMENT_METHODS": "Нийт дүн, төлбөрийн хэлбэр", + "SET_TERMS_RESPONSE": "Нөхцөл тохируулах", + "UPDATE_DEAL": "Санал шинэчлэх", + "SELL_UPPER": "ЗАРАХ", "CRYPTO_WANT_TO_SELL": "Та зарахыг хүсч буй крипто", - "RECEIVE": "ХҮЛЭЭН АВАХ", - "FIAT_CURRENCY_WANT_TO_RECEIVE": "Таны авахыг хүссэн Fiat валют", + "RECEIVE": "АВАХ", + "FIAT_CURRENCY_WANT_TO_RECEIVE": "Хүлээн авах мөнгөн тэмдэгт", "PRICE_UPPER": "ҮНЭ", "STATIC": "СТАТИК", "FIXED_PRICE": "Тогтмол үнэ", "SPREAD_PERCENTAGE": "ТАРХАЛТ (%)", - "PRICE_PROFIT_SPREAD_SET": "Үнэ болон ашиг нь тогтоосон хэмжээнд тархсан", - "UNIT_PRICE": "НЭГЖИЙН ҮНЭ", - "PRICE_ADVERTISE_SELL": "Та зарахдаа зарах үнэ", + "PRICE_PROFIT_SPREAD_SET": "Үнэ, ашгийн өөрчлөгдөж болох хэмжээ", + "UNIT_PRICE": "НЭГЖ ҮНЭ", + "PRICE_ADVERTISE_SELL": "Та зарах үнэ", "TOTAL_ASSET_SELL_1": "Нийт", "TOTAL_ASSET_SELL_2": "та зарж болно", - "BUY_ORDER_LIMITS": "ХУДАЛДАН АВАХ ЗАХИАЛГЫН ХЯЗГААР", + "BUY_ORDER_LIMITS": "АВАХ ЗАХИАЛГЫН ЛИМИТ", "MIN_MAX_ORDER_VALUE_1": "Хамгийн бага ба хамгийн их", "MIN_MAX_ORDER_VALUE_2": "захиалгын үнийг худалдан авах", - "PAYMENT_METHODS_SEND_FIAT": "FIAT ИЛГЭЭХ ТӨЛБӨРИЙН АРГА", + "PAYMENT_METHODS_SEND_FIAT": "ТӨЛБӨР ТӨЛӨХ ХЭЛБЭР", "SELECT_PAYMENT_METHODS_1": "хүртэл сонгоно уу", "SELECT_PAYMENT_METHODS_2": "зориулсан аргууд", "REGION": "Бүс нутаг", - "SELECT_REGION": "Таны хэлцлийг жагсаах бүсээ сонгоно уу", + "SELECT_REGION": "Таны саналыг харах бүсээ сонгоно уу", "TERMS": "НӨХЦӨЛ", - "TERMS_CONDITIONS_DEAL": "Энэ гэрээний нөхцөл, нөхцөл", - "FIRST_RESPONSE": "АНХНЫ ХАРИУ", - "CHAT_RESPONSE": "P2P хэлэлцээрийн өрөөнд ороход таны хамтрагч харах чатын хариу", + "TERMS_CONDITIONS_DEAL": "Энэ гэрээний нөхцөл", + "FIRST_RESPONSE": "АВТОМАТ МСЖ", + "CHAT_RESPONSE": "P2P чатанд илгээх автомат зурвас", "BACK_UPPER": "БУЦАХ", - "PLEASE_FILL_INPUTS": "Бүх оролтыг бөглөнө үү", + "PLEASE_FILL_INPUTS": "Бүх нүдийг бөглөнө үү", "DEAL_EDITED": "Хэлэлцээрийг зассан", "DEAL_CREATED": "Хэлэлцээр хийгдсэн", - "NEXT": "ДАРААЧИЙН", - "ADD_PAYMENT_METHOD_DETAILS": "Төлбөрийн аргын дэлгэрэнгүй мэдээллийг нэмнэ үү", - "COMPLETE": "Бүрэн", + "NEXT": "ЦААШ НЬ", + "ADD_PAYMENT_METHOD_DETAILS": "Төлбөрийн дэлгэрэнгүй мэдээллийг оруулна уу", + "COMPLETE": "Болсон", "STEP_SET_TYPE_PRICE": "Төрөл, үнийг тохируулна уу", "STEP_SET_TOTAL_AMOUNT_PAYMENT_METHODS": "Нийт дүн болон төлбөрийн аргыг тохируулна уу", "STEP_SET_TERMS_AUTO_RESPONSE": "Нөхцөл ба автомат хариуг тохируулах", @@ -2028,16 +2028,16 @@ "RELEASE_WARNING": "Та энэ захиалгыг гаргахдаа итгэлтэй байна уу?", "ALL": "БҮГД", "ANONYMOUS": "Нэргүй", - "TERMS_CONDITIONS": "Нөхцөл, нөхцөл", - "PAYMENT_TIME_LIMIT": "Төлбөрийн хязгаар 30 минут", - "AMOUNT_SEND_RELEASE": "(Таны зарж, гаргах крипто мөнгөний хэмжээ)", + "TERMS_CONDITIONS": "Нөхцөл", + "PAYMENT_TIME_LIMIT": "Төлбөр төлөх лимит 30 минут", + "AMOUNT_SEND_RELEASE": "(Таны зарах крипто мөнгөний хэмжээ)", "MINUTES": "минут", "EDIT_UPPERCASE": "ЗАСАХ", "DATE": "Огноо", "DISPLAY_NAME": "Харагдах нэр", "TOTAL_ORDERS": "Нийт захиалга", "COMPLETION_RATE": "Гүйцэтгэлийн хувь", - "POSITIVE_FEEDBACK": "Эерэг санал", + "POSITIVE_FEEDBACK": "Үнэлгээ", "POSITIVE": "Эерэг", "NEGATIVE": "Сөрөг", "NO_FEEDBACK": "Санал хүсэлт олдсонгүй", From 4851891ef3b23bce512c2b7ddfebf418c54e9042 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Tue, 16 Jul 2024 11:05:28 +0300 Subject: [PATCH 029/108] fix-addressbook-duplicate-issue --- server/messages.js | 2 +- server/utils/hollaex-tools-lib/tools/user.js | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/server/messages.js b/server/messages.js index 5e043d3d9b..c18e540bd4 100644 --- a/server/messages.js +++ b/server/messages.js @@ -263,5 +263,5 @@ exports.FAILED_GET_QUOTE = 'Failed to get the quote'; exports.BALANCE_HISTORY_NOT_ACTIVE = 'This feature is not active on the exchange'; exports.WITHDRAWAL_DISABLED = 'Withdrawal disabled for this user'; exports.ADDRESSBOOK_MISSING_FIELDS = 'Each address must contain both address, network and label fields'; -exports.ADDRESSBOOK_ALREADY_EXISTS = 'One or more addresses or labels already exist in the address book'; +exports.ADDRESSBOOK_ALREADY_EXISTS = 'Address label already exists in the payload'; exports.ADDRESSBOOK_NOT_FOUND = 'User address book not found'; \ No newline at end of file diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index 7fa601237a..82f59dec20 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -3297,6 +3297,13 @@ const updateUserAddresses = async (user_id, data) => { } }); + // Check for duplicate labels in the payload + const labels = addresses.map(a => a.label); + const uniqueLabels = new Set(labels); + if (uniqueLabels.size !== labels.length) { + throw new Error(ADDRESSBOOK_ALREADY_EXISTS); + } + const user = await getUserByKitId(user_id); if (!user) { @@ -3310,13 +3317,6 @@ const updateUserAddresses = async (user_id, data) => { addresses }); } else { - // Check if any address in the payload already exists - const existingAddresses = userAddressBook.addresses.map(a => a.address); - const duplicateAddresses = addresses.filter(a => existingAddresses.includes(a.address) || existingAddresses.includes(a.label)); - if (duplicateAddresses.length > 0) { - throw new Error(ADDRESSBOOK_ALREADY_EXISTS); - } - // Update the addresses userAddressBook = await userAddressBook.update({ addresses }, { fields: ['addresses'] From 53c0ded71d737de9466fd3be8dea36fc056acfad Mon Sep 17 00:00:00 2001 From: ram Date: Tue, 16 Jul 2024 20:03:04 +0530 Subject: [PATCH 030/108] Changes for the address book implementation --- .../assets/images/global-address-book.svg | 15 + web/src/config/icons/dark.js | 2 + web/src/config/lang/en.json | 24 + web/src/containers/Wallet/AddressBook.js | 664 +++++++++++++++++ web/src/containers/Wallet/CurrencyWallet.js | 15 +- web/src/containers/Wallet/GenerateAddress.js | 336 +++++++++ web/src/containers/Wallet/HeaderSection.js | 7 + web/src/containers/Wallet/_AddressBook.scss | 421 +++++++++++ web/src/containers/Wallet/actions.js | 12 + web/src/containers/Wallet/utils.js | 25 +- web/src/containers/Withdraw/Withdraw.js | 107 +-- web/src/containers/Withdraw/_Withdraw.scss | 31 +- web/src/containers/Withdraw/utils.js | 12 + web/src/containers/_containers.scss | 1 + web/src/containers/index.js | 1 + web/src/index.css | 680 +++++++++++++++++- web/src/routes.js | 6 + 17 files changed, 2298 insertions(+), 61 deletions(-) create mode 100644 web/public/assets/images/global-address-book.svg create mode 100644 web/src/containers/Wallet/AddressBook.js create mode 100644 web/src/containers/Wallet/GenerateAddress.js create mode 100644 web/src/containers/Wallet/_AddressBook.scss diff --git a/web/public/assets/images/global-address-book.svg b/web/public/assets/images/global-address-book.svg new file mode 100644 index 0000000000..de714c6009 --- /dev/null +++ b/web/public/assets/images/global-address-book.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/web/src/config/icons/dark.js b/web/src/config/icons/dark.js index 3d39e35ca7..61b07a83d4 100644 --- a/web/src/config/icons/dark.js +++ b/web/src/config/icons/dark.js @@ -309,6 +309,8 @@ const nestedIcons = { WITHDRAW_TITLE: '/assets/images/withdraw-out-box.svg', DEPOSIT_TITLE: '/assets/images/deposit-box.svg', + + ADDRESS_BOOK: '/assets/images/global-address-book.svg', }; const icons = flatten(nestedIcons, options); diff --git a/web/src/config/lang/en.json b/web/src/config/lang/en.json index dfb812e2e3..1c00e4bbaa 100644 --- a/web/src/config/lang/en.json +++ b/web/src/config/lang/en.json @@ -1726,6 +1726,30 @@ "VIEW_WALLET_P&L": "VIEW WALLET P&L", "BALANCE_PERCENTAGE": "Balance Percentage" }, + "ADDRESS_BOOK": { + "ADDRESS_BOOK_LABEL": "Address book", + "ADDRESS_BOOK_DESC_1": "Add a white-listed withdrawal address to your personal address book", + "ADDRESS_BOOK_DESC_2": "You'll be able to easily use this addresses when withdrawing.", + "ADD_ADDRESS_LINK": "Add address", + "ADD_WITHDRAW_ADDRESS": "Add withdraw address", + "DATE_ADDED": "Date added", + "REMOVE": "Remove", + "NO_LINK": "No withdrawal address have been added yet.", + "ADD_WITHDRAW_ADDRESS_DESC_1": "Add a white-listed address that you can safely withdraw coins to.", + "ADD_WITHDRAW_ADDRESS_DESC_2": "This withdrawal address should be an address under your control.", + "NAME_YOUR_ADDRESS_TITLE": "Name your address", + "NAME_YOUR_ADDRESS_DESC": "Give this withdrawal address a name for your future reference.", + "USER_LABEL": "Name/label:", + "USER_FIELD_PLACEHOLDER": "Name this withdrawal address", + "CHECK_AND_CONFIRM": "Check and confirm", + "WARNING_ADDRESS": "Before adding this address to your address book please take the time to check and confirm that the details are correct:", + "ENSURE_DESC": "Ensure the Address is correct and under your control.", + "ADDRESSES": "Addresses", + "WITHDRAWAL_ADDRESS_BOOK": "Withdrawal address book", + "ADD_ADDRESS_DESC": "Add withdrawal address to {0}", + "ADDRESS_BOOK": "Address book", + "MANAGE_ADDRESS_BOOK": "Manage address book" + }, "ASSET_INFO": "Asset info", "TAKER_FEES_APPLIED": "Taker fees are applied", "ASSET_INFO_PAGE": "Asset info page", diff --git a/web/src/containers/Wallet/AddressBook.js b/web/src/containers/Wallet/AddressBook.js new file mode 100644 index 0000000000..ccb503c536 --- /dev/null +++ b/web/src/containers/Wallet/AddressBook.js @@ -0,0 +1,664 @@ +import React, { useEffect, useState } from 'react'; +import { bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; +import { isMobile } from 'react-device-detect'; +import { Input, Button } from 'antd'; +import { ExclamationCircleFilled } from '@ant-design/icons'; + +import GenerateAddress from './GenerateAddress'; +import withConfig from 'components/ConfigProvider/withConfig'; +import icons from 'config/icons/dark'; +import CopyToClipboard from 'react-copy-to-clipboard'; +import STRINGS from 'config/localizedStrings'; +import { Coin, Dialog, EditWrapper, IconTitle, Image, Table } from 'components'; +import { assetsSelector, RenderBtn } from './utils'; +import { + networkList, + renderNetworkField, + renderNetworkWithLabel, +} from 'containers/Withdraw/utils'; +import { renderBackToWallet } from 'containers/Deposit/utils'; +import { openContactForm, setSnackNotification } from 'actions/appActions'; +import { renderNeedHelpAction } from './components'; +import { getAddressBookDetails, setUserLabelAndAddress } from './actions'; +import { getNetworkNameByKey } from 'utils/wallet'; + +const AddressBook = ({ + coins, + router, + pinnedAssets, + assets, + icons: ICONS, + constants = { links: {} }, + setSnackNotification, + openContactForm, +}) => { + const [getUserData, setGetUserData] = useState([]); + const [renderPopUps, setRenderPopUps] = useState({ + step1: false, + step2: false, + step3: false, + }); + const [userLabel, setUserLabel] = useState(''); + const [topAssets, setTopAssets] = useState([]); + const [selectedAsset, setSelectedAsset] = useState(null); + const [networkOptions, setNetworkOptions] = useState(null); + const [isValidAddress, setIsValidAddress] = useState(false); + + const AddressBookTableData = [ + { + stringId: 'DEVELOPERS_TOKENS_TABLE.NAME', + label: STRINGS['DEVELOPERS_TOKENS_TABLE.NAME'], + key: 'name', + renderCell: (data, key) => ( + +
+ {data?.addresses?.map((data) => data?.label) || '-'} +
+ + ), + }, + { + stringId: 'ASSETS', + label: STRINGS['ASSETS'], + key: 'assets', + renderCell: (data, key) => ( + +
+ {data?.addresses?.map((data) => { + const asset = getNetworkNameByKey(data?.network); + const networkIcon = networkList.filter((item) => + asset === item?.network ? item?.iconId : null + ); + return ( +
+ + + {`${ + coins[data?.network]?.fullname + } (${data?.network?.toUpperCase()})`} + +
+ ); + }) || '-'} +
+ + ), + }, + { + stringId: 'WITHDRAWALS_FORM_NETWORK_LABEL', + label: STRINGS['WITHDRAWALS_FORM_NETWORK_LABEL'], + key: 'network', + renderCell: (data, key) => ( + +
+ {data?.addresses?.map((data) => { + const asset = getNetworkNameByKey(data?.network); + const networkIcon = networkList.filter((item) => + asset === item?.network ? item?.iconId : null + ); + return ( +
+ {asset ? asset : data?.network?.toUpperCase()} + +
+ ); + }) || '-'} +
+ + ), + }, + { + stringId: 'WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS', + label: STRINGS['WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS'], + key: 'address', + renderCell: (data, key) => ( + +
+ {data?.addresses?.map((data) => { + return ( +
+ {data?.address} + { + handleCopy(); + }} + > + + +
+ ); + }) || '-'} +
+ + ), + }, + { + stringId: 'ADDRESS_BOOK.DATE_ADDED', + label: STRINGS['ADDRESS_BOOK.DATE_ADDED'], + key: 'date added', + renderCell: (data, key) => { + let formatDate = ''; + if (data?.created_at) { + const date = new Date(data.created_at); + if (!isNaN(date)) { + formatDate = date.toISOString().slice(0, 10).replace(/-/g, '/'); + } + } + return ( + +
{formatDate}
+ + ); + }, + }, + { + stringId: 'ADDRESS_BOOK.REMOVE', + label: STRINGS['ADDRESS_BOOK.REMOVE'], + key: 'remove', + renderCell: (data, key) => ( + +
+
onHandleRemove()} + > + + {STRINGS['ADDRESS_BOOK.REMOVE']} + +
+
+ + ), + }, + ]; + + const coinLength = + coins[selectedAsset]?.network && coins[selectedAsset]?.network.split(','); + let network = + coins[selectedAsset]?.network && coins[selectedAsset]?.network !== 'other' + ? coins[selectedAsset]?.network + : coins[selectedAsset]?.symbol; + const networkIcon = coins[network]?.icon_id; + + useEffect(() => { + const getAddress = async () => { + const res = await getAddressBookDetails(); + setGetUserData(res); + }; + getAddress(); + }, []); + + const onGoBack = () => { + return router.push('/wallet'); + }; + + const handleCopy = () => { + setSnackNotification({ + icon: icons.COPY_NOTIFICATION, + content: STRINGS['COPY_SUCCESS_TEXT'], + timer: 2000, + }); + }; + + const onHandleRemove = () => {}; + + const onHandleClose = (currStep) => { + setRenderPopUps((prev) => ({ ...prev, [currStep]: false })); + setSelectedAsset(null); + setNetworkOptions(null); + setIsValidAddress(null); + setUserLabel(''); + }; + + const onHandlePopUpBtn = (previousStep, nextStep) => { + setRenderPopUps((prev) => ({ ...prev, [previousStep]: false })); + setRenderPopUps((prev) => ({ ...prev, [nextStep]: true })); + if (previousStep === 'step2' && nextStep === 'step1') { + setSelectedAsset(null); + setNetworkOptions(null); + setIsValidAddress(null); + } + if (previousStep === 'step3' && nextStep === 'step2') { + setUserLabel(''); + } + }; + + const onHandleConfirm = async () => { + try { + const selectedNetwork = networkOptions + ? renderNetworkField(networkOptions) + : network; + const currValue = { + addresses: [ + { + label: userLabel, + address: isValidAddress, + network: selectedNetwork, + }, + ], + }; + const userDetails = { addresses: [getUserData, currValue] }; + await setUserLabelAndAddress(userDetails); + } catch (error) { + console.error(error); + } + }; + + return ( +
+ {renderPopUps.step1 && ( + { + onHandleClose('step1'); + }} + > +
+
+
+
+ + {STRINGS['ADDRESS_BOOK.ADD_WITHDRAW_ADDRESS']} + +
+
+ + {STRINGS['ADDRESS_BOOK.ADD_WITHDRAW_ADDRESS_DESC_1']} + +
+
+ + {STRINGS['ADDRESS_BOOK.ADD_WITHDRAW_ADDRESS_DESC_2']} + +
+
+
+ +
+
+ onHandleClose('step1')} + /> + onHandlePopUpBtn('step1', 'step2')} + /> +
+
+
+
+ )} + {renderPopUps.step2 && ( + onHandleClose('step2')} + className="address_book_popup_wrapper" + > +
+
+
+
+ + {STRINGS['ADDRESS_BOOK.NAME_YOUR_ADDRESS_TITLE']} + +
+
+ + {STRINGS['ADDRESS_BOOK.NAME_YOUR_ADDRESS_DESC']} + +
+
+
+
+ + {STRINGS['ADDRESS_BOOK.USER_LABEL']} + +
+
+ setUserLabel(e.target.value)} + value={userLabel} + /> +
+
+
+
+
+
+ + {STRINGS['ASSETS']}: + +
+
+ + {`${ + coins[selectedAsset].fullname + } (${selectedAsset.toUpperCase()})`} +
+
+
+
+ + {STRINGS['WITHDRAWALS_FORM_NETWORK_LABEL']}: + +
+
+ + {' '} + {coinLength?.length === 1 ? ( + renderNetworkWithLabel(networkIcon, network) + ) : coinLength?.length > 1 ? ( +
+ {networkOptions} + {networkList.map((data) => + data.network === networkOptions ? ( + + ) : null + )} +
+ ) : coins[network]?.network ? ( + coins[network]?.network?.toUpperCase() + ) : ( + coins[network]?.symbol?.toUpperCase() + )} +
+
+
+
+
+ + {STRINGS['WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS']}: + +
+
+ {isValidAddress} +
+
+
+
+ onHandlePopUpBtn('step2', 'step1')} + /> + onHandlePopUpBtn('step2', 'step3')} + /> +
+
+
+
+ )} + {renderPopUps.step3 && ( + onHandleClose('step3')} + className="address_book_popup_wrapper" + > +
+
+
+ + {STRINGS['ADDRESS_BOOK.CHECK_AND_CONFIRM']} + +
+
+ + {STRINGS['ADDRESS_BOOK.WARNING_ADDRESS']} + +
+
+
+
+
+ + {STRINGS['DEVELOPERS_TOKENS_TABLE.NAME']}: + +
+
+ {userLabel} +
+
+
+
+
+ + {STRINGS['ASSETS']}: + +
+
+ + {`${ + coins[selectedAsset].fullname + } (${selectedAsset.toUpperCase()})`} +
+
+
+
+ + {STRINGS['WITHDRAWALS_FORM_NETWORK_LABEL']}: + +
+
+ + {' '} + {coinLength?.length === 1 ? ( + renderNetworkWithLabel(networkIcon, network) + ) : coinLength?.length > 1 ? ( +
+ {networkOptions} + {networkList.map((data) => + data.network === networkOptions ? ( + + ) : null + )} +
+ ) : coins[network]?.network ? ( + coins[network]?.network?.toUpperCase() + ) : ( + coins[network]?.symbol?.toUpperCase() + )} +
+
+
+
+
+
+ + {STRINGS['WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS']}: + +
+
+ {isValidAddress} +
+
+
+
+
+ +
+ + {STRINGS['ADDRESS_BOOK.ENSURE_DESC']} + +
+
+
+ onHandlePopUpBtn('step3', 'step2')} + /> + +
+
+
+ )} +
+
+
+
+ +
+
+
+
+ {renderBackToWallet(onGoBack)} + {openContactForm && + !isMobile && + renderNeedHelpAction( + openContactForm, + constants.links, + icons['BLUE_QUESTION'], + 'BLUE_QUESTION' + )} +
+
+
+
+ + {STRINGS['ADDRESS_BOOK.WITHDRAWAL_ADDRESS_BOOK']} + +
+
+ + {STRINGS['ADDRESS_BOOK.ADDRESS_BOOK_DESC_1']} + +
+
+ + {STRINGS['ADDRESS_BOOK.ADDRESS_BOOK_DESC_2']} + +
+ + + + setRenderPopUps((prev) => ({ ...prev, step1: true })) + } + > + {STRINGS['ADDRESS_BOOK.ADD_ADDRESS_LINK']} + + + +
+
+ {getUserData === 0 && ( +
+
+ {'text'} +
+
+ + {STRINGS['ADDRESS_BOOK.NO_LINK']} + +
+
+ setRenderPopUps((prev) => ({ ...prev, step1: true })) + } + > + + {STRINGS['ADDRESS_BOOK.ADD_WITHDRAW_ADDRESS']} + +
+
+ )} + + + + + + ); +}; + +const mapStateToProps = (store) => ({ + pinnedAssets: store.app.pinned_assets, + assets: assetsSelector(store), + coins: store.app.coins, + constants: store.app.constants, +}); + +const mapDispatchToProps = (dispatch) => ({ + setSnackNotification: bindActionCreators(setSnackNotification, dispatch), + openContactForm: bindActionCreators(openContactForm, dispatch), +}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(withConfig(AddressBook)); diff --git a/web/src/containers/Wallet/CurrencyWallet.js b/web/src/containers/Wallet/CurrencyWallet.js index 4c87bf43a9..940678927b 100644 --- a/web/src/containers/Wallet/CurrencyWallet.js +++ b/web/src/containers/Wallet/CurrencyWallet.js @@ -265,7 +265,7 @@ class Wallet extends Component { )} -
+
{STRINGS.formatString( STRINGS['CURRENCY_WALLET.LEARN_MORE'], @@ -278,6 +278,19 @@ class Wallet extends Component { )}
+
+ + {STRINGS.formatString( + STRINGS['ADDRESS_BOOK.ADD_ADDRESS_DESC'], + + {STRINGS['ADDRESS_BOOK.ADDRESS_BOOK']} + + )} + +
{coins[currency].allow_deposit ? ( diff --git a/web/src/containers/Wallet/GenerateAddress.js b/web/src/containers/Wallet/GenerateAddress.js new file mode 100644 index 0000000000..652e6005f7 --- /dev/null +++ b/web/src/containers/Wallet/GenerateAddress.js @@ -0,0 +1,336 @@ +import React, { useEffect, useState } from 'react'; +import { connect } from 'react-redux'; +import { change } from 'redux-form'; +import { Input, Select } from 'antd'; +import { + CaretDownOutlined, + CheckOutlined, + CloseOutlined, +} from '@ant-design/icons'; + +import QRScanner from 'containers/Withdraw/QRScanner'; +import STRINGS from 'config/localizedStrings'; +import { Coin, Dialog, EditWrapper } from 'components'; +import { + networkList, + renderNetworkField, + renderNetworkWithLabel, + renderScanIcon, +} from 'containers/Withdraw/utils'; +import { onHandleSymbol } from 'containers/Deposit/utils'; +import { validAddress } from 'components/Form/validations'; +import { FORM_NAME } from 'containers/Withdraw/form'; + +const GenerateAddress = ({ + topAssets, + selectedAsset, + networkoptions, + setTopAssets, + setSelectedAsset, + setNetworkOptions, + assets, + pinnedAssets, + coins, + coinLength, + network, + networkIcon, + setIsValidAddress, + isValidAddress, + dispatch, +}) => { + const [qrScannerOpen, setQrScannerOpen] = useState(false); + + const { Option } = Select; + + const displayAssets = + selectedAsset && + `${coins[selectedAsset].fullname} (${selectedAsset.toUpperCase()})`; + + const displayNetwork = + coinLength?.length === 1 + ? renderNetworkWithLabel(networkIcon, network) + : coinLength?.length > 1 + ? networkoptions + : network?.toUpperCase(); + + const currentNetwork = + coinLength?.length === 1 ? network : renderNetworkField(networkoptions); + + useEffect(() => { + const topWallet = assets + .filter((item, index) => { + return index <= 3; + }) + .map((data) => { + return data[0]; + }); + if (pinnedAssets.length) { + setTopAssets(pinnedAssets); + } else { + setTopAssets(topWallet); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const renderPinnedAsset = (data) => { + const icon_id = coins[data]?.icon_id; + return ( +
+ {data.toUpperCase()} + + + +
+ ); + }; + + const onHandleChangeSelect = (symbol) => { + setSelectedAsset(symbol); + setIsValidAddress(null); + }; + + const onHandleChangeNetwork = (symbol) => { + setNetworkOptions(symbol); + setIsValidAddress(null); + }; + + const onHandleScan = () => { + setQrScannerOpen(true); + }; + + const closeQRScanner = () => { + setQrScannerOpen(false); + }; + + const onHandleAddress = (val) => { + const isValid = validAddress( + selectedAsset, + STRINGS[`WITHDRAWALS_${selectedAsset?.toUpperCase()}_INVALID_ADDRESS`], + currentNetwork, + val + )(); + if (!isValid) { + setIsValidAddress(val); + } else { + setIsValidAddress(false); + } + }; + + const getQRData = (data) => { + dispatch(change(FORM_NAME, 'address', data)); + }; + + return ( +
+
+
+
+
1
+
+
+
+ + {STRINGS['ACCORDIAN.SELECT_ASSET']} + +
+
+
+
+ {topAssets.map((data, inx) => { + return ( + onHandleChangeSelect(data)} + > + {renderPinnedAsset(data)} + + ); + })} +
+
+ + {selectedAsset ? ( + + ) : ( + + )} +
+
+
+
+
+
+
2
+
+
+
+ + {STRINGS['ACCORDIAN.SELECT_NETWORK']} + +
+
+
+ {selectedAsset && ( +
+ + {displayNetwork ? ( + + ) : ( + + )} +
+ )} +
+
+
+
+
+
3
+
+
+
+ + { + STRINGS[ + 'USER_VERIFICATION.USER_DOCUMENTATION_FORM.FORM_FIELDS.ADDRESS_LABEL' + ] + } + : + +
+
+
+
+ {displayNetwork && ( +
+ onHandleAddress(e.target.value)} + suffix={renderScanIcon(onHandleScan)} + placeholder={STRINGS['WITHDRAWALS_FORM_ADDRESS_PLACEHOLDER']} + /> + {isValidAddress ? ( + + ) : ( + + )} +
+ )} + + {qrScannerOpen && ( + + )} + +
+
+
+ ); +}; + +const mapStateToProps = (state) => ({ + coins: state.app.coins, +}); + +const mapDispatchToProps = (dispatch) => ({ + dispatch, +}); +export default connect(mapStateToProps, mapDispatchToProps)(GenerateAddress); diff --git a/web/src/containers/Wallet/HeaderSection.js b/web/src/containers/Wallet/HeaderSection.js index c6a63c7ced..1e87608fcb 100644 --- a/web/src/containers/Wallet/HeaderSection.js +++ b/web/src/containers/Wallet/HeaderSection.js @@ -35,6 +35,13 @@ const HeaderSection = ({ icons: ICONS, setDepositAndWithdraw }) => {
+
+ + + {STRINGS['ADDRESS_BOOK.ADDRESSES']} + + +
diff --git a/web/src/containers/Wallet/_AddressBook.scss b/web/src/containers/Wallet/_AddressBook.scss new file mode 100644 index 0000000000..467782cf05 --- /dev/null +++ b/web/src/containers/Wallet/_AddressBook.scss @@ -0,0 +1,421 @@ +.address-book-form { + margin-top: 5%; + + .address-book-header-link { + position: relative; + } + + .address-book-tab-header-content { + width: 100%; + display: flex; + flex-direction: row; + align-items: flex-start; + justify-content: flex-start; + gap: 10px; + color: var(--labels_secondary-inactive-label-text-graphics); + font-size: 12px; + + .address-book-icon { + color: $colors-main-black; + margin-bottom: 2%; + + .icon_title-wrapper { + flex-direction: row; + align-items: center; + } + + .icon_title-wrapper .icon_title-text.title { + font-size: 3rem !important; + } + } + + .address-book-header-text { + .edit-wrapper__container { + font-size: 18px; + color: var(--labels_important-active-labels-text-graphics); + } + } + + .address-book-content { + width: 100%; + + .blue-link { + .edit-wrapper__container { + text-decoration: underline !important; + } + } + + .blue-link:hover { + cursor: pointer; + } + } + } + + .address-book-content-wrapper { + padding: 2%; + margin-top: 1%; + background-color: var(--base_wallet-sidebar-and-popup); + border-radius: 3px; + color: $colors-black; + + .address-book-title-text { + font-size: 18px; + color: $colors-main-black; + } + + .blue-link { + .edit-wrapper__container { + text-decoration: underline !important; + } + } + + .blue-link:hover { + cursor: pointer; + } + + .address-book-table-wrapper { + font-size: 12px; + + .table-content { + .table-wrapper { + td, + th { + padding: 1%; + width: 0%; + } + + th { + padding-bottom: 0; + } + + .table_header-wrapper { + border-bottom: 2px solid var(--calculated_secondary-border); + } + + .table_body-wrapper { + .table_body-row { + td div { + display: flex; + gap: 5px; + justify-content: flex-start !important; + } + + .remove-btn, + .copy-btn:hover { + cursor: pointer; + } + + .copy-btn { + background-color: var(--specials_buttons-links-and-highlights); + border-radius: 10px; + width: 10%; + height: 100%; + font-size: 10px; + color: var(--calculated_base_footer_text); + display: flex; + justify-content: center; + align-items: center; + border: none; + } + } + } + } + } + + .empty-content-display { + height: 15rem; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + } + } +} + +.address-book-wrapper { + width: 80%; + margin-left: auto; + margin-right: auto; +} + +.address_book_popup_wrapper { + .ReactModal__Content { + width: 40rem; + font-size: 13px; + } + + .address-book-popup-wrapper { + width: 45rem !important; + } + + .address-book-popup-wrapper, + .name-address-popup-wrapper, + .check-confirm-content-wrapper { + .address-book-header-content, + .name-address-header-content, + .confirm-header-wrapper { + .address-book-title { + font-size: 20px; + } + } + + .address-book-content { + width: 100% !important; + + .generate-address-form-wrapper { + width: 100%; + padding: 5%; + + .ant-select-clear { + user-select: none; + width: 1.5rem; + height: 1.5rem; + border-radius: 50%; + background-color: $colors-main-black; + + svg { + color: $app-sidebar-background; + font-size: 18px; + } + } + + .select-method-field, + .select-network-field, + .address-field { + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + gap: 15px; + + .input-label-field, + .input-label-field-disable { + width: 40%; + display: flex; + gap: 10%; + + .custom-field { + display: flex; + flex-direction: column; + align-items: center; + + .select-step { + width: 100%; + height: 2.4rem; + padding: 10px; + border: 1px solid $colors-main-black; + border-radius: 100%; + display: flex; + align-items: center; + } + + .custom-line { + height: 5.5rem; + width: 1%; + background-color: $colors-main-black; + } + } + + .label-content { + margin-top: 3%; + } + } + + .input-label-field-disable { + opacity: 0.5; + } + + .select-field, + .network-field { + width: 60%; + + .opacity-100 { + opacity: 1; + } + + .opacity-30 { + opacity: 0.5; + } + + .currency-label { + border: 1px solid $colors-black; + padding: 0.5%; + border-radius: 5px; + margin-right: 10px; + width: 4.5rem; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + } + + .destination-input-field { + border-radius: 2px; + border: 1px solid var(--calculated_important-border) !important; + background-color: var(--base_wallet-sidebar-and-popup); + color: $colors-main-black; + + .ant-input { + background-color: var(--base_wallet-sidebar-and-popup); + color: $colors-main-black; + text-overflow: ellipsis; + } + + .ant-input:focus { + box-shadow: unset; + } + + .render-scan-wrapper { + color: var(--specials_buttons-links-and-highlights); + cursor: pointer; + + .suffix-text { + padding-right: 0.5rem; + font-size: 15px; + + .edit-wrapper__container { + text-decoration: underline; + } + } + + .img-wrapper { + display: flex; + align-items: center; + + img { + height: 1rem; + } + } + } + } + + .destination-input-field:focus-within { + border: 1px solid $colors-main-border !important; + } + } + + .custom-select-input-style { + width: 100% !important; + } + + .custom-select-input-style .ant-select-selection-search-input { + height: 100% !important; + } + + .ant-select-single + .ant-select-selector + .ant-select-selection-placeholder { + margin-top: 1%; + pointer-events: unset !important; + } + + .custom-select-input-style .ant-select-selection-item { + line-height: 3rem !important; + } + + .custom-select-input-style .ant-select-selector { + height: 3rem !important; + } + } + } + } + + .address-book-detail-line { + width: 5%; + border-bottom: 2px solid + var(--labels_secondary-inactive-label-text-graphics); + } + + .address-book-field { + .address-book-input-field { + width: 65%; + + .ant-input { + background-color: var(--base_wallet-sidebar-and-popup); + color: $colors-main-black; + border: 1px solid $colors-main-black; + } + } + } + + .selected-assets-content { + color: var(--labels_secondary-inactive-label-text-graphics); + font-size: 12px; + + .assets-field { + display: flex; + align-items: flex-start; + gap: 5px; + + .selected-asset, + .selected-network { + display: flex; + align-items: flex-start; + gap: 5px; + } + } + } + + .confirm-title-text { + color: var(--labels_important-active-labels-text-graphics) !important; + } + + .address-book-popup-button-wrapper { + display: flex; + flex-direction: row; + justify-content: space-between; + margin-top: 5%; + + .back-btn, + .next-btn, + .okay-btn { + background-color: var(--specials_buttons-links-and-highlights); + width: 45%; + color: var(--labels_important-active-labels-text-graphics); + border: none; + } + + .okay-btn { + width: 100% !important; + } + } + } + + .check-confirm-content-wrapper { + .selected-assets-content { + border: 1px solid var(--labels_secondary-inactive-label-text-graphics); + + .confirm_name_detail { + padding: 3%; + border-bottom: 1px solid + var(--labels_secondary-inactive-label-text-graphics); + } + + .assets-content { + padding: 3%; + } + } + + .warning-message-wrapper { + margin: 3%; + font-size: 12px; + color: var(--specials_pending-waiting-caution) !important; + display: flex; + align-items: center; + gap: 2px; + } + } +} + +.add_withdrawal_address_wrapper { + .ReactModal__Content { + width: 50rem; + } +} + +.layout-mobile { + .address-book-popup-wrapper { + width: 100% !important; + } +} diff --git a/web/src/containers/Wallet/actions.js b/web/src/containers/Wallet/actions.js index 3a0b8bbce8..d8a23289a8 100644 --- a/web/src/containers/Wallet/actions.js +++ b/web/src/containers/Wallet/actions.js @@ -12,3 +12,15 @@ export const fetchPlHistory = (values) => { values && Object.keys(values).length ? querystring.stringify(values) : ''; return requestAuthenticated(`/user/balance-pl?${queryValues}`); }; + +export const getAddressBookDetails = () => { + return requestAuthenticated(`/user/addressbook`); +}; + +export const setUserLabelAndAddress = (values) => { + const options = { + method: 'POST', + body: JSON.stringify(values), + }; + return requestAuthenticated(`/user/addressbook`, options); +}; diff --git a/web/src/containers/Wallet/utils.js b/web/src/containers/Wallet/utils.js index a830bb4878..22d088f40e 100644 --- a/web/src/containers/Wallet/utils.js +++ b/web/src/containers/Wallet/utils.js @@ -1,5 +1,10 @@ -import math from 'mathjs'; +import React from 'react'; +import { Button } from 'antd'; import { createSelector } from 'reselect'; +import math from 'mathjs'; + +import STRINGS from 'config/localizedStrings'; +import { EditWrapper } from 'components'; import { calculateOraclePrice } from 'utils/currency'; import { WALLET_SORT } from 'actions/appActions'; @@ -108,3 +113,21 @@ export const searchAssets = (assets, searchValue = '', isZeroBalanceHidden) => { } }); }; + +export const RenderBtn = ({ + string, + buttonClassName, + onHandleClick, + disabled = false, +}) => { + return ( + + ); +}; diff --git a/web/src/containers/Withdraw/Withdraw.js b/web/src/containers/Withdraw/Withdraw.js index b563a2a25f..c6b4aa25f1 100644 --- a/web/src/containers/Withdraw/Withdraw.js +++ b/web/src/containers/Withdraw/Withdraw.js @@ -2,9 +2,10 @@ import React, { useEffect, useMemo, useState } from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { isMobile } from 'react-device-detect'; +import { Link } from 'react-router'; import { Button, Input, Select } from 'antd'; import BigNumber from 'bignumber.js'; -import { Coin } from 'components'; +import { Coin, EditWrapper } from 'components'; import STRINGS from 'config/localizedStrings'; import { CaretDownOutlined, @@ -36,6 +37,7 @@ import { renderLabel, renderNetworkField, renderNetworkWithLabel, + renderScanIcon, } from './utils'; import { email, validAddress } from 'components/Form/validations'; import strings from 'config/localizedStrings'; @@ -504,20 +506,6 @@ const RenderWithdraw = ({ // } // }; - const renderScanIcon = () => { - return ( -
onHandleScan()} - > - {renderLabel('ACCORDIAN.SCAN')} -
- scan-icon -
-
- ); - }; - const withdrawFeeFormat = selectedMethod === strings['FORM_FIELDS.EMAIL_LABEL'] ? 0 @@ -926,47 +914,60 @@ const RenderWithdraw = ({ : 'FORM_FIELDS.EMAIL_LABEL' )}
- {isEmailAndAddress && renderNetwork && ( -
- {selectedMethod === - strings['WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS'] || - selectedMethod === 'Address' ? ( - onHandleAddress(e.target.value, 'address')} - value={getWithdrawAddress} - placeholder={strings['WITHDRAW_PAGE.WITHDRAW_ADDRESS']} - suffix={renderScanIcon()} - > - ) : ( - onHandleAddress(e.target.value, 'email')} - value={receiverWithdrawalEmail} - placeholder={ - strings['WITHDRAW_PAGE.WITHDRAW_EMAIL_ADDRESS'] - } - > - )} - {selectedMethod === strings['FORM_FIELDS.EMAIL_LABEL'] ? ( - isValidEmail ? ( +
+ {isEmailAndAddress && renderNetwork && ( +
+ {selectedMethod === + strings['WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS'] || + selectedMethod === 'Address' ? ( +
+ + onHandleAddress(e.target.value, 'address') + } + value={getWithdrawAddress} + placeholder={strings['WITHDRAW_PAGE.WITHDRAW_ADDRESS']} + suffix={renderScanIcon(onHandleScan)} + > +
+ + + {STRINGS['ADDRESS_BOOK.MANAGE_ADDRESS_BOOK']} + + +
+
+ ) : ( + onHandleAddress(e.target.value, 'email')} + value={receiverWithdrawalEmail} + placeholder={ + strings['WITHDRAW_PAGE.WITHDRAW_EMAIL_ADDRESS'] + } + > + )} + {selectedMethod === strings['FORM_FIELDS.EMAIL_LABEL'] ? ( + isValidEmail ? ( + + ) : ( + + ) + ) : isValidAddress ? ( ) : ( - ) - ) : isValidAddress ? ( - - ) : ( - - )} -
- )} + )} +
+ )} +
diff --git a/web/src/containers/Withdraw/_Withdraw.scss b/web/src/containers/Withdraw/_Withdraw.scss index fb50f4bca0..bb07d26d5f 100644 --- a/web/src/containers/Withdraw/_Withdraw.scss +++ b/web/src/containers/Withdraw/_Withdraw.scss @@ -146,6 +146,9 @@ $content--margin: 2rem; padding: 1% 1%; } + .destination-input-address-field { + width: 100% !important; + } .destination-input-field { width: 80%; height: 38px; @@ -244,7 +247,25 @@ $content--margin: 2rem; .amount-field-icon { margin-top: 1%; } - + .destination-field-wrapper { + display: flex; + flex-direction: column; + width: 65%; + .select-wrapper { + width: 100%; + .destination-input-wrapper { + width: 80%; + display: flex; + flex-direction: column; + gap: 5px; + } + } + .address-link { + .edit-wrapper__container { + text-decoration: underline !important; + } + } + } .select-wrapper { display: flex; flex-direction: column; @@ -609,9 +630,11 @@ $content--margin: 2rem; .destination-field { height: 75px; } - + .destination-field-wrapper { + width: 100%; + } .destination-field-mobile { - height: 11rem; + height: 12rem; } .field-wrapper { @@ -649,7 +672,7 @@ $content--margin: 2rem; } .custom-line-selected-mobile { - height: 9rem; + height: 10rem; } } diff --git a/web/src/containers/Withdraw/utils.js b/web/src/containers/Withdraw/utils.js index c06bf74210..821d6baaa6 100644 --- a/web/src/containers/Withdraw/utils.js +++ b/web/src/containers/Withdraw/utils.js @@ -12,6 +12,7 @@ import STRINGS from 'config/localizedStrings'; import { renderBankInformation } from '../Wallet/components'; import { getNetworkName, getNetworkNameByKey } from 'utils/wallet'; +import { STATIC_ICONS } from 'config/icons'; export const generateBaseInformation = (currency, limits = {}) => { const { minAmount = 2, maxAmount = 10000 } = limits; @@ -172,3 +173,14 @@ export const networkList = [ { network: 'Stellar', iconId: 'XLM_ICON' }, { network: 'Fantom', iconId: 'FTM_ICON' }, ]; + +export const renderScanIcon = (onHandleScan) => { + return ( +
onHandleScan()}> + {renderLabel('ACCORDIAN.SCAN')} +
+ scan-icon +
+
+ ); +}; diff --git a/web/src/containers/_containers.scss b/web/src/containers/_containers.scss index 78716f7f91..463299e0ee 100644 --- a/web/src/containers/_containers.scss +++ b/web/src/containers/_containers.scss @@ -30,3 +30,4 @@ @import './Apps/Apps'; @import './CoinPage/CoinPage'; @import './Summary/components/ReferralList'; +@import './Wallet/AddressBook'; diff --git a/web/src/containers/index.js b/web/src/containers/index.js index b3af6a35ff..91fdfcadf3 100644 --- a/web/src/containers/index.js +++ b/web/src/containers/index.js @@ -39,6 +39,7 @@ export { default as WhiteLabel } from './WhiteLabel'; export { default as FeesAndLimits } from './FeesAndLimits'; export { default as ReferralList } from './Summary/components/ReferralList'; export { default as P2P } from './P2P'; +export { default as AddressBook } from './Wallet/AddressBook'; // ADMIN PAGE export { default as AdminDashboard } from './Admin/Dashboard'; diff --git a/web/src/index.css b/web/src/index.css index 46f0ff54d1..4303d1596b 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -2339,6 +2339,8 @@ table th { .withdrawal-container .withdraw-form-wrapper .withdraw-form .withdraw-deposit-content { font-size: 14px; padding: 1% 1%; } + .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-input-address-field { + width: 100% !important; } .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-input-field { width: 80%; height: 38px; @@ -2400,6 +2402,19 @@ table th { text-wrap: nowrap; } .withdrawal-container .withdraw-form-wrapper .withdraw-form .amount-field-icon { margin-top: 1%; } + .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-field-wrapper { + display: flex; + flex-direction: column; + width: 65%; } + .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-field-wrapper .select-wrapper { + width: 100%; } + .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-field-wrapper .select-wrapper .destination-input-wrapper { + width: 80%; + display: flex; + flex-direction: column; + gap: 5px; } + .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-field-wrapper .address-link .edit-wrapper__container { + text-decoration: underline !important; } .withdrawal-container .withdraw-form-wrapper .withdraw-form .select-wrapper { display: flex; flex-direction: column; @@ -2615,8 +2630,10 @@ table th { padding: 5%; } .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-field { height: 75px; } + .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-field-wrapper { + width: 100%; } .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-field-mobile { - height: 11rem; } + height: 12rem; } .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .field-wrapper .field-label-wrapper { flex-direction: column; } .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .withdraw-main-label-selected { @@ -2633,7 +2650,7 @@ table th { .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .custom-field .custom-line-network-selected { height: 15rem; } .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .custom-field .custom-line-selected-mobile { - height: 9rem; } + height: 10rem; } .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .mobile-view { margin-top: 5%; } .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .ant-select-clear svg { @@ -7908,6 +7925,665 @@ table th { .layout-mobile .summary-block_wrapper .referral-table-wrapper .table-wrapper th { font-size: 12px; } } +.address-book-form { + margin-top: 5%; } + .address-book-form .address-book-header-link { + position: relative; } + .address-book-form .address-book-tab-header-content { + width: 100%; + display: flex; + flex-direction: row; + align-items: flex-start; + justify-content: flex-start; + gap: 10px; + color: var(--labels_secondary-inactive-label-text-graphics); + font-size: 12px; } + .address-book-form .address-book-tab-header-content .address-book-icon { + color: var(--labels_important-active-labels-text-graphics); + margin-bottom: 2%; } + .address-book-form .address-book-tab-header-content .address-book-icon .icon_title-wrapper { + flex-direction: row; + align-items: center; } + .address-book-form .address-book-tab-header-content .address-book-icon .icon_title-wrapper .icon_title-text.title { + font-size: 3rem !important; } + .address-book-form .address-book-tab-header-content .address-book-header-text .edit-wrapper__container { + font-size: 18px; + color: var(--labels_important-active-labels-text-graphics); } + .address-book-form .address-book-tab-header-content .address-book-content { + width: 100%; } + .address-book-form .address-book-tab-header-content .address-book-content .blue-link .edit-wrapper__container { + text-decoration: underline !important; } + .address-book-form .address-book-tab-header-content .address-book-content .blue-link:hover { + cursor: pointer; } + .address-book-form .address-book-content-wrapper { + padding: 2%; + margin-top: 1%; + background-color: var(--base_wallet-sidebar-and-popup); + border-radius: 3px; + color: var(--labels_secondary-inactive-label-text-graphics); } + .address-book-form .address-book-content-wrapper .address-book-title-text { + font-size: 18px; + color: var(--labels_important-active-labels-text-graphics); } + .address-book-form .address-book-content-wrapper .blue-link .edit-wrapper__container { + text-decoration: underline !important; } + .address-book-form .address-book-content-wrapper .blue-link:hover { + cursor: pointer; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper { + font-size: 12px; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper td, + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper th { + padding: 1%; + width: 0%; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper th { + padding-bottom: 0; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_header-wrapper { + border-bottom: 2px solid var(--calculated_secondary-border); } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row td div { + display: flex; + gap: 5px; + justify-content: flex-start !important; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row .remove-btn, + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row .copy-btn:hover { + cursor: pointer; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row .copy-btn { + background-color: var(--specials_buttons-links-and-highlights); + border-radius: 10px; + width: 10%; + height: 100%; + font-size: 10px; + color: var(--calculated_base_footer_text); + display: flex; + justify-content: center; + align-items: center; + border: none; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .empty-content-display { + height: 15rem; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; } + +.address-book-wrapper { + width: 80%; + margin-left: auto; + margin-right: auto; } + +.address_book_popup_wrapper .ReactModal__Content { + width: 40rem; + font-size: 13px; } + +.address_book_popup_wrapper .address-book-popup-wrapper { + width: 45rem !important; } + +.address_book_popup_wrapper .address-book-popup-wrapper .address-book-header-content .address-book-title, +.address_book_popup_wrapper .address-book-popup-wrapper .name-address-header-content .address-book-title, +.address_book_popup_wrapper .address-book-popup-wrapper .confirm-header-wrapper .address-book-title, +.address_book_popup_wrapper .name-address-popup-wrapper .address-book-header-content .address-book-title, +.address_book_popup_wrapper .name-address-popup-wrapper .name-address-header-content .address-book-title, +.address_book_popup_wrapper .name-address-popup-wrapper .confirm-header-wrapper .address-book-title, +.address_book_popup_wrapper .check-confirm-content-wrapper .address-book-header-content .address-book-title, +.address_book_popup_wrapper .check-confirm-content-wrapper .name-address-header-content .address-book-title, +.address_book_popup_wrapper .check-confirm-content-wrapper .confirm-header-wrapper .address-book-title { + font-size: 20px; } + +.address_book_popup_wrapper .address-book-popup-wrapper .address-book-content, +.address_book_popup_wrapper .name-address-popup-wrapper .address-book-content, +.address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content { + width: 100% !important; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper { + width: 100%; + padding: 5%; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .ant-select-clear, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .ant-select-clear, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .ant-select-clear { + user-select: none; + width: 1.5rem; + height: 1.5rem; + border-radius: 50%; + background-color: var(--labels_important-active-labels-text-graphics); } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .ant-select-clear svg, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .ant-select-clear svg, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .ant-select-clear svg { + color: var(--base_wallet-sidebar-and-popup); + font-size: 18px; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field { + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + gap: 15px; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable { + width: 40%; + display: flex; + gap: 10%; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .custom-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .custom-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .custom-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .custom-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .custom-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .custom-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .custom-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .custom-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .custom-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .custom-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .custom-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .custom-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .custom-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .custom-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .custom-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .custom-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .custom-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .custom-field { + display: flex; + flex-direction: column; + align-items: center; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .custom-field .select-step, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .custom-field .select-step, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .custom-field .select-step, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .custom-field .select-step, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .custom-field .select-step, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .custom-field .select-step, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .custom-field .select-step, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .custom-field .select-step, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .custom-field .select-step, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .custom-field .select-step, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .custom-field .select-step, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .custom-field .select-step, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .custom-field .select-step, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .custom-field .select-step, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .custom-field .select-step, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .custom-field .select-step, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .custom-field .select-step, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .custom-field .select-step { + width: 100%; + height: 2.4rem; + padding: 10px; + border: 1px solid var(--labels_important-active-labels-text-graphics); + border-radius: 100%; + display: flex; + align-items: center; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .custom-field .custom-line, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .custom-field .custom-line, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .custom-field .custom-line, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .custom-field .custom-line, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .custom-field .custom-line, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .custom-field .custom-line, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .custom-field .custom-line, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .custom-field .custom-line, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .custom-field .custom-line, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .custom-field .custom-line, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .custom-field .custom-line, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .custom-field .custom-line, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .custom-field .custom-line, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .custom-field .custom-line, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .custom-field .custom-line, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .custom-field .custom-line, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .custom-field .custom-line, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .custom-field .custom-line { + height: 5.5rem; + width: 1%; + background-color: var(--labels_important-active-labels-text-graphics); } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .label-content, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .label-content, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .label-content, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .label-content, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .label-content, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .label-content, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .label-content, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .label-content, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .label-content, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .label-content, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .label-content, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .label-content, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .label-content, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .label-content, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .label-content, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .label-content, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .label-content, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .label-content { + margin-top: 3%; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable { + opacity: 0.5; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field { + width: 60%; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-100, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-100, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-100, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-100, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-100, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-100, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-100, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-100, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-100, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-100, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-100, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-100, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-100, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-100, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-100, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-100, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-100, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-100 { + opacity: 1; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-30, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-30, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-30, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-30, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-30, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-30, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-30, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-30, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-30, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-30, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-30, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-30, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-30, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-30, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-30, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-30, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-30, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-30 { + opacity: 0.5; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .currency-label, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .currency-label, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .currency-label, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .currency-label, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .currency-label, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .currency-label, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .currency-label, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .currency-label, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .currency-label, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .currency-label, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .currency-label, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .currency-label, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .currency-label, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .currency-label, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .currency-label, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .currency-label, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .currency-label, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .currency-label { + border: 1px solid var(--labels_secondary-inactive-label-text-graphics); + padding: 0.5%; + border-radius: 5px; + margin-right: 10px; + width: 4.5rem; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field { + border-radius: 2px; + border: 1px solid var(--calculated_important-border) !important; + background-color: var(--base_wallet-sidebar-and-popup); + color: var(--labels_important-active-labels-text-graphics); } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input { + background-color: var(--base_wallet-sidebar-and-popup); + color: var(--labels_important-active-labels-text-graphics); + text-overflow: ellipsis; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input:focus { + box-shadow: unset; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper { + color: var(--specials_buttons-links-and-highlights); + cursor: pointer; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text { + padding-right: 0.5rem; + font-size: 15px; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container { + text-decoration: underline; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper { + display: flex; + align-items: center; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img { + height: 1rem; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field:focus-within { + border: 1px solid var(--calculated_important-border) !important; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style { + width: 100% !important; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style .ant-select-selection-search-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style .ant-select-selection-search-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style .ant-select-selection-search-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style .ant-select-selection-search-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style .ant-select-selection-search-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style .ant-select-selection-search-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style .ant-select-selection-search-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style .ant-select-selection-search-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style .ant-select-selection-search-input { + height: 100% !important; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .ant-select-single .ant-select-selector .ant-select-selection-placeholder, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .ant-select-single .ant-select-selector .ant-select-selection-placeholder, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .ant-select-single .ant-select-selector .ant-select-selection-placeholder, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .ant-select-single .ant-select-selector .ant-select-selection-placeholder, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .ant-select-single .ant-select-selector .ant-select-selection-placeholder, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .ant-select-single .ant-select-selector .ant-select-selection-placeholder, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .ant-select-single .ant-select-selector .ant-select-selection-placeholder, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .ant-select-single .ant-select-selector .ant-select-selection-placeholder, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .ant-select-single .ant-select-selector .ant-select-selection-placeholder { + margin-top: 1%; + pointer-events: unset !important; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style .ant-select-selection-item, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style .ant-select-selection-item, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style .ant-select-selection-item, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style .ant-select-selection-item, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style .ant-select-selection-item, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style .ant-select-selection-item, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style .ant-select-selection-item, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style .ant-select-selection-item, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style .ant-select-selection-item { + line-height: 3rem !important; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style .ant-select-selector, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style .ant-select-selector, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style .ant-select-selector, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style .ant-select-selector, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style .ant-select-selector, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style .ant-select-selector, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style .ant-select-selector, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style .ant-select-selector, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style .ant-select-selector { + height: 3rem !important; } + +.address_book_popup_wrapper .address-book-popup-wrapper .address-book-detail-line, +.address_book_popup_wrapper .name-address-popup-wrapper .address-book-detail-line, +.address_book_popup_wrapper .check-confirm-content-wrapper .address-book-detail-line { + width: 5%; + border-bottom: 2px solid var(--labels_secondary-inactive-label-text-graphics); } + +.address_book_popup_wrapper .address-book-popup-wrapper .address-book-field .address-book-input-field, +.address_book_popup_wrapper .name-address-popup-wrapper .address-book-field .address-book-input-field, +.address_book_popup_wrapper .check-confirm-content-wrapper .address-book-field .address-book-input-field { + width: 65%; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-field .address-book-input-field .ant-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-field .address-book-input-field .ant-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-field .address-book-input-field .ant-input { + background-color: var(--base_wallet-sidebar-and-popup); + color: var(--labels_important-active-labels-text-graphics); + border: 1px solid var(--labels_important-active-labels-text-graphics); } + +.address_book_popup_wrapper .address-book-popup-wrapper .selected-assets-content, +.address_book_popup_wrapper .name-address-popup-wrapper .selected-assets-content, +.address_book_popup_wrapper .check-confirm-content-wrapper .selected-assets-content { + color: var(--labels_secondary-inactive-label-text-graphics); + font-size: 12px; } + .address_book_popup_wrapper .address-book-popup-wrapper .selected-assets-content .assets-field, + .address_book_popup_wrapper .name-address-popup-wrapper .selected-assets-content .assets-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .selected-assets-content .assets-field { + display: flex; + align-items: flex-start; + gap: 5px; } + .address_book_popup_wrapper .address-book-popup-wrapper .selected-assets-content .assets-field .selected-asset, + .address_book_popup_wrapper .address-book-popup-wrapper .selected-assets-content .assets-field .selected-network, + .address_book_popup_wrapper .name-address-popup-wrapper .selected-assets-content .assets-field .selected-asset, + .address_book_popup_wrapper .name-address-popup-wrapper .selected-assets-content .assets-field .selected-network, + .address_book_popup_wrapper .check-confirm-content-wrapper .selected-assets-content .assets-field .selected-asset, + .address_book_popup_wrapper .check-confirm-content-wrapper .selected-assets-content .assets-field .selected-network { + display: flex; + align-items: flex-start; + gap: 5px; } + +.address_book_popup_wrapper .address-book-popup-wrapper .confirm-title-text, +.address_book_popup_wrapper .name-address-popup-wrapper .confirm-title-text, +.address_book_popup_wrapper .check-confirm-content-wrapper .confirm-title-text { + color: var(--labels_important-active-labels-text-graphics) !important; } + +.address_book_popup_wrapper .address-book-popup-wrapper .address-book-popup-button-wrapper, +.address_book_popup_wrapper .name-address-popup-wrapper .address-book-popup-button-wrapper, +.address_book_popup_wrapper .check-confirm-content-wrapper .address-book-popup-button-wrapper { + display: flex; + flex-direction: row; + justify-content: space-between; + margin-top: 5%; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-popup-button-wrapper .back-btn, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-popup-button-wrapper .next-btn, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-popup-button-wrapper .okay-btn, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-popup-button-wrapper .back-btn, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-popup-button-wrapper .next-btn, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-popup-button-wrapper .okay-btn, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-popup-button-wrapper .back-btn, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-popup-button-wrapper .next-btn, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-popup-button-wrapper .okay-btn { + background-color: var(--specials_buttons-links-and-highlights); + width: 45%; + color: var(--labels_important-active-labels-text-graphics); + border: none; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-popup-button-wrapper .okay-btn, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-popup-button-wrapper .okay-btn, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-popup-button-wrapper .okay-btn { + width: 100% !important; } + +.address_book_popup_wrapper .check-confirm-content-wrapper .selected-assets-content { + border: 1px solid var(--labels_secondary-inactive-label-text-graphics); } + .address_book_popup_wrapper .check-confirm-content-wrapper .selected-assets-content .confirm_name_detail { + padding: 3%; + border-bottom: 1px solid var(--labels_secondary-inactive-label-text-graphics); } + .address_book_popup_wrapper .check-confirm-content-wrapper .selected-assets-content .assets-content { + padding: 3%; } + +.address_book_popup_wrapper .check-confirm-content-wrapper .warning-message-wrapper { + margin: 3%; + font-size: 12px; + color: var(--specials_pending-waiting-caution) !important; + display: flex; + align-items: center; + gap: 2px; } + +.add_withdrawal_address_wrapper .ReactModal__Content { + width: 50rem; } + +.layout-mobile .address-book-popup-wrapper { + width: 100% !important; } + .sidebar-row { min-height: 3rem; min-width: 10rem; } diff --git a/web/src/routes.js b/web/src/routes.js index 146431e9d5..23e2a3a743 100644 --- a/web/src/routes.js +++ b/web/src/routes.js @@ -69,6 +69,7 @@ import { WhiteLabel, FeesAndLimits, ReferralList, + AddressBook, } from './containers'; import chat from './containers/Admin/Chat'; import { Billing } from 'containers/Admin'; @@ -401,6 +402,11 @@ export const generateRoutes = (routes = []) => { + Date: Wed, 17 Jul 2024 04:23:16 +0900 Subject: [PATCH 031/108] contact addressbook support for currency --- server/api/swagger/user.yaml | 2 ++ server/constants.js | 3 ++- server/messages.js | 2 +- server/utils/hollaex-tools-lib/tools/user.js | 10 +++++++++- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/server/api/swagger/user.yaml b/server/api/swagger/user.yaml index 1e241de31b..8ddeb2fb7c 100644 --- a/server/api/swagger/user.yaml +++ b/server/api/swagger/user.yaml @@ -291,6 +291,8 @@ paths: type: string network: type: string + currency: + type: string responses: 200: description: Success diff --git a/server/constants.js b/server/constants.js index 46a67b53df..814dab3210 100644 --- a/server/constants.js +++ b/server/constants.js @@ -157,7 +157,7 @@ const overrideNetworkFields = () => { configuration.coins[coin.symbol] = { ...coin, ...configuration?.kit?.fiat_fees?.[coin.symbol] - } + }; } } }; @@ -632,6 +632,7 @@ exports.USER_FIELD_ADMIN_LOG = [ ]; exports.ADDRESS_FIELDS = ['city', 'address', 'country', 'postal_code']; +exports.CRYPTO_ADDRESS_FIELDS = ['address', 'network', 'label', 'currency']; exports.VERIFY_STATUS = { EMPTY: 0, diff --git a/server/messages.js b/server/messages.js index 5e043d3d9b..0b483e2976 100644 --- a/server/messages.js +++ b/server/messages.js @@ -262,6 +262,6 @@ exports.CANNOT_CHANGE_DELETED_EMAIL = 'Cannot change deleted email'; exports.FAILED_GET_QUOTE = 'Failed to get the quote'; exports.BALANCE_HISTORY_NOT_ACTIVE = 'This feature is not active on the exchange'; exports.WITHDRAWAL_DISABLED = 'Withdrawal disabled for this user'; -exports.ADDRESSBOOK_MISSING_FIELDS = 'Each address must contain both address, network and label fields'; +exports.ADDRESSBOOK_MISSING_FIELDS = 'Each address must contain both address, network, currency and label fields'; exports.ADDRESSBOOK_ALREADY_EXISTS = 'One or more addresses or labels already exist in the address book'; exports.ADDRESSBOOK_NOT_FOUND = 'User address book not found'; \ No newline at end of file diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index 7fa601237a..fe3e76bb08 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -72,6 +72,7 @@ const { AUDIT_KEYS, USER_FIELD_ADMIN_LOG, ADDRESS_FIELDS, + CRYPTO_ADDRESS_FIELDS, ID_FIELDS, SETTING_KEYS, OMITTED_USER_FIELDS, @@ -3288,13 +3289,20 @@ const fetchUserAddressBook = async (user_id) => { }; + + const updateUserAddresses = async (user_id, data) => { const { addresses } = data; addresses.forEach((addressObj) => { - if (!addressObj.address || !addressObj.network || !addressObj.label) { + if (!addressObj.address || !addressObj.network || !addressObj.label || !addressObj.currency) { throw new Error(ADDRESSBOOK_MISSING_FIELDS); } + Object.keys(addressObj).forEach((key) => { + if (!CRYPTO_ADDRESS_FIELDS.includes(key)) { + throw new Error(ADDRESSBOOK_MISSING_FIELDS); + } + }); }); const user = await getUserByKitId(user_id); From e7fd004aea1685ed975b021161f446b438194057 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Wed, 17 Jul 2024 15:50:05 +0300 Subject: [PATCH 032/108] addressbook-add-creation-date-field --- server/api/swagger/user.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/api/swagger/user.yaml b/server/api/swagger/user.yaml index 8ddeb2fb7c..5f9ac431cc 100644 --- a/server/api/swagger/user.yaml +++ b/server/api/swagger/user.yaml @@ -293,6 +293,9 @@ paths: type: string currency: type: string + created_at: + type: string + format: date-time responses: 200: description: Success From 0537e47de51981032cc66ac3486e4fca10f0ea93 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Wed, 17 Jul 2024 17:44:24 +0300 Subject: [PATCH 033/108] update object --- server/api/swagger/user.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/api/swagger/user.yaml b/server/api/swagger/user.yaml index 5f9ac431cc..9c6e100e78 100644 --- a/server/api/swagger/user.yaml +++ b/server/api/swagger/user.yaml @@ -285,6 +285,9 @@ paths: items: type: object properties: + id: + type: number + format: int32 address: type: string label: From d542536ee359c0b0dc721ffea46aa67a12770543 Mon Sep 17 00:00:00 2001 From: Ali Beikverdi Date: Thu, 18 Jul 2024 03:40:51 +0900 Subject: [PATCH 034/108] admin feature improved label --- web/package-lock.json | 2 +- web/src/containers/Admin/General/InterfaceForm.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/web/package-lock.json b/web/package-lock.json index 9a1cd35904..b6d23b79d3 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,6 +1,6 @@ { "name": "hollaex-kit", - "version": "2.11.0", + "version": "2.11.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/web/src/containers/Admin/General/InterfaceForm.js b/web/src/containers/Admin/General/InterfaceForm.js index 25bc082a54..ac0fbe3256 100644 --- a/web/src/containers/Admin/General/InterfaceForm.js +++ b/web/src/containers/Admin/General/InterfaceForm.js @@ -427,7 +427,7 @@ const InterfaceForm = ({ className="feature-icon mr-1" />
- Pro trade + Pro trade (Market)
(Chart, orderbook, limit orders with wallet)
@@ -449,7 +449,7 @@ const InterfaceForm = ({
- Quick trade + Quick trade (Convert)
(Simple buy/sell interface with wallet) From d72c1f14fbe8e13c290b1ab8f9d5a539d02fa95c Mon Sep 17 00:00:00 2001 From: fetok12 Date: Thu, 18 Jul 2024 11:03:26 +0300 Subject: [PATCH 035/108] update missing fields --- server/utils/hollaex-tools-lib/tools/user.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index d80ad9edbb..b0afb5b7c0 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -3295,9 +3295,7 @@ const updateUserAddresses = async (user_id, data) => { const { addresses } = data; addresses.forEach((addressObj) => { - if (!addressObj.address || !addressObj.network || !addressObj.label || !addressObj.currency) { - throw new Error(ADDRESSBOOK_MISSING_FIELDS); - } + Object.keys(addressObj).forEach((key) => { if (!CRYPTO_ADDRESS_FIELDS.includes(key)) { throw new Error(ADDRESSBOOK_MISSING_FIELDS); From 0e161861f7b3ca530271a475f47a5d375699280f Mon Sep 17 00:00:00 2001 From: fetok12 Date: Thu, 18 Jul 2024 11:07:49 +0300 Subject: [PATCH 036/108] add missing fields --- server/constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/constants.js b/server/constants.js index 814dab3210..dcad914c16 100644 --- a/server/constants.js +++ b/server/constants.js @@ -632,7 +632,7 @@ exports.USER_FIELD_ADMIN_LOG = [ ]; exports.ADDRESS_FIELDS = ['city', 'address', 'country', 'postal_code']; -exports.CRYPTO_ADDRESS_FIELDS = ['address', 'network', 'label', 'currency']; +exports.CRYPTO_ADDRESS_FIELDS = ['address', 'network', 'label', 'currency', 'created_at', 'id']; exports.VERIFY_STATUS = { EMPTY: 0, From 5707335d916cc1911bbb06c73411b4b78064c356 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Thu, 18 Jul 2024 16:53:49 +0300 Subject: [PATCH 037/108] stakepool-all-balance-update --- server/plugins/job.js | 54 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/server/plugins/job.js b/server/plugins/job.js index 26af538b97..086377a801 100644 --- a/server/plugins/job.js +++ b/server/plugins/job.js @@ -15,6 +15,24 @@ const getTimezone = () => { return isNumber(validTimezones[kitTimezone]) ? kitTimezone : 'Etc/UTC'; }; + +setTimeout(async () => { + const balances = await toolsLib.user.getAllBalancesAdmin({ format: 'all' }); + + const userBalances = balances?.data?.reduce((groups, item) => { + const group = (groups[item.user_id] || []); + group.push(item); + groups[item.user_id] = group; + return groups; + }, {}); + + + let symbols = {}; + (userBalances['1'] || []).forEach(balance => { symbols[balance.symbol] = balance.available }); + + + console.log(symbols) +}, 1000 * 10) const unstakingCheckRunner = () => { cron.schedule('0 0 0 * * *', async () => { loggerPlugin.verbose( @@ -25,20 +43,40 @@ const unstakingCheckRunner = () => { const stakePoolModel = toolsLib.database.getModel('stake'); const stakerData = await stakerModel.findAll({ where: { status: 'unstaking' } }); + const balances = await toolsLib.user.getAllBalancesAdmin({ format: 'all' }); + + const userBalances = balances?.data?.reduce((groups, item) => { + const group = (groups[item.user_id] || []); + group.push(item); + groups[item.user_id] = group; + return groups; + }, {}); + + for (const staker of stakerData) { const user = await toolsLib.user.getUserByKitId(staker.user_id); const stakePool = await stakePoolModel.findOne({ where: { id: staker.stake_id } }); - const balance = await toolsLib.wallet.getUserBalanceByKitId(stakePool.account_id); - let symbols = {}; - - for (const key of Object.keys(balance)) { - if (key.includes('available') && balance[key] != null) { - let symbol = key?.split('_')?.[0]; - symbols[symbol] = balance[key]; - } + // const balance = await toolsLib.wallet.getUserBalanceByKitId(stakePool.account_id); + const balance = userBalances[stakePool.account_id]; + if (!balance){ + sendEmail( + MAILTYPE.ALERT, + adminAccount.email, + { + type: 'Error! Source account balance not found during unstaking process', + data: `Source account balance not found for user id ${stakePool.account_id}. Please contact support ` + }, + adminAccount.settings + ); + + continue; } + let symbols = {}; + + (balance || []).forEach(balance => { symbols[balance.symbol] = balance.available }); + const amountAfterSlash = new BigNumber(staker.reward).minus(new BigNumber(staker.slashed)).toNumber(); let totalAmount = staker.amount; From c4054274da7436dc10e282b9a09722cd3766a050 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Thu, 18 Jul 2024 16:54:30 +0300 Subject: [PATCH 038/108] stakepool-all-balance-update --- server/plugins/job.js | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/server/plugins/job.js b/server/plugins/job.js index 086377a801..e36c149825 100644 --- a/server/plugins/job.js +++ b/server/plugins/job.js @@ -15,24 +15,6 @@ const getTimezone = () => { return isNumber(validTimezones[kitTimezone]) ? kitTimezone : 'Etc/UTC'; }; - -setTimeout(async () => { - const balances = await toolsLib.user.getAllBalancesAdmin({ format: 'all' }); - - const userBalances = balances?.data?.reduce((groups, item) => { - const group = (groups[item.user_id] || []); - group.push(item); - groups[item.user_id] = group; - return groups; - }, {}); - - - let symbols = {}; - (userBalances['1'] || []).forEach(balance => { symbols[balance.symbol] = balance.available }); - - - console.log(symbols) -}, 1000 * 10) const unstakingCheckRunner = () => { cron.schedule('0 0 0 * * *', async () => { loggerPlugin.verbose( From 688bdc1468515bdcb956b1ae4cc60d6cfa507895 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Fri, 19 Jul 2024 01:21:12 +0300 Subject: [PATCH 039/108] Revert "stakepool-all-balance-update" This reverts commit c4054274da7436dc10e282b9a09722cd3766a050. --- server/plugins/job.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/server/plugins/job.js b/server/plugins/job.js index e36c149825..086377a801 100644 --- a/server/plugins/job.js +++ b/server/plugins/job.js @@ -15,6 +15,24 @@ const getTimezone = () => { return isNumber(validTimezones[kitTimezone]) ? kitTimezone : 'Etc/UTC'; }; + +setTimeout(async () => { + const balances = await toolsLib.user.getAllBalancesAdmin({ format: 'all' }); + + const userBalances = balances?.data?.reduce((groups, item) => { + const group = (groups[item.user_id] || []); + group.push(item); + groups[item.user_id] = group; + return groups; + }, {}); + + + let symbols = {}; + (userBalances['1'] || []).forEach(balance => { symbols[balance.symbol] = balance.available }); + + + console.log(symbols) +}, 1000 * 10) const unstakingCheckRunner = () => { cron.schedule('0 0 0 * * *', async () => { loggerPlugin.verbose( From 4e12d1392948b707690695e808e1fedf6fddc80e Mon Sep 17 00:00:00 2001 From: fetok12 Date: Fri, 19 Jul 2024 01:21:20 +0300 Subject: [PATCH 040/108] Revert "stakepool-all-balance-update" This reverts commit 5707335d916cc1911bbb06c73411b4b78064c356. --- server/plugins/job.js | 54 +++++++------------------------------------ 1 file changed, 8 insertions(+), 46 deletions(-) diff --git a/server/plugins/job.js b/server/plugins/job.js index 086377a801..26af538b97 100644 --- a/server/plugins/job.js +++ b/server/plugins/job.js @@ -15,24 +15,6 @@ const getTimezone = () => { return isNumber(validTimezones[kitTimezone]) ? kitTimezone : 'Etc/UTC'; }; - -setTimeout(async () => { - const balances = await toolsLib.user.getAllBalancesAdmin({ format: 'all' }); - - const userBalances = balances?.data?.reduce((groups, item) => { - const group = (groups[item.user_id] || []); - group.push(item); - groups[item.user_id] = group; - return groups; - }, {}); - - - let symbols = {}; - (userBalances['1'] || []).forEach(balance => { symbols[balance.symbol] = balance.available }); - - - console.log(symbols) -}, 1000 * 10) const unstakingCheckRunner = () => { cron.schedule('0 0 0 * * *', async () => { loggerPlugin.verbose( @@ -43,40 +25,20 @@ const unstakingCheckRunner = () => { const stakePoolModel = toolsLib.database.getModel('stake'); const stakerData = await stakerModel.findAll({ where: { status: 'unstaking' } }); - const balances = await toolsLib.user.getAllBalancesAdmin({ format: 'all' }); - - const userBalances = balances?.data?.reduce((groups, item) => { - const group = (groups[item.user_id] || []); - group.push(item); - groups[item.user_id] = group; - return groups; - }, {}); - - for (const staker of stakerData) { const user = await toolsLib.user.getUserByKitId(staker.user_id); const stakePool = await stakePoolModel.findOne({ where: { id: staker.stake_id } }); - // const balance = await toolsLib.wallet.getUserBalanceByKitId(stakePool.account_id); - const balance = userBalances[stakePool.account_id]; - if (!balance){ - sendEmail( - MAILTYPE.ALERT, - adminAccount.email, - { - type: 'Error! Source account balance not found during unstaking process', - data: `Source account balance not found for user id ${stakePool.account_id}. Please contact support ` - }, - adminAccount.settings - ); - - continue; - } - + const balance = await toolsLib.wallet.getUserBalanceByKitId(stakePool.account_id); let symbols = {}; - - (balance || []).forEach(balance => { symbols[balance.symbol] = balance.available }); + for (const key of Object.keys(balance)) { + if (key.includes('available') && balance[key] != null) { + let symbol = key?.split('_')?.[0]; + symbols[symbol] = balance[key]; + } + } + const amountAfterSlash = new BigNumber(staker.reward).minus(new BigNumber(staker.slashed)).toNumber(); let totalAmount = staker.amount; From 94553a651c4e732671e44dd64d68c2f6ff650d1c Mon Sep 17 00:00:00 2001 From: fetok12 Date: Fri, 19 Jul 2024 01:23:50 +0300 Subject: [PATCH 041/108] add sleep --- server/plugins/job.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/plugins/job.js b/server/plugins/job.js index 26af538b97..9c7c341895 100644 --- a/server/plugins/job.js +++ b/server/plugins/job.js @@ -26,6 +26,7 @@ const unstakingCheckRunner = () => { const stakerData = await stakerModel.findAll({ where: { status: 'unstaking' } }); for (const staker of stakerData) { + await toolsLib.sleep(1000); const user = await toolsLib.user.getUserByKitId(staker.user_id); const stakePool = await stakePoolModel.findOne({ where: { id: staker.stake_id } }); From c016274a87f17b420380d40294714127fb7fa898 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Fri, 19 Jul 2024 01:30:45 +0300 Subject: [PATCH 042/108] field refinements --- server/api/swagger/user.yaml | 6 ------ server/constants.js | 2 +- server/utils/hollaex-tools-lib/tools/user.js | 9 ++++++++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/server/api/swagger/user.yaml b/server/api/swagger/user.yaml index 9c6e100e78..8ddeb2fb7c 100644 --- a/server/api/swagger/user.yaml +++ b/server/api/swagger/user.yaml @@ -285,9 +285,6 @@ paths: items: type: object properties: - id: - type: number - format: int32 address: type: string label: @@ -296,9 +293,6 @@ paths: type: string currency: type: string - created_at: - type: string - format: date-time responses: 200: description: Success diff --git a/server/constants.js b/server/constants.js index dcad914c16..814dab3210 100644 --- a/server/constants.js +++ b/server/constants.js @@ -632,7 +632,7 @@ exports.USER_FIELD_ADMIN_LOG = [ ]; exports.ADDRESS_FIELDS = ['city', 'address', 'country', 'postal_code']; -exports.CRYPTO_ADDRESS_FIELDS = ['address', 'network', 'label', 'currency', 'created_at', 'id']; +exports.CRYPTO_ADDRESS_FIELDS = ['address', 'network', 'label', 'currency']; exports.VERIFY_STATUS = { EMPTY: 0, diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index b0afb5b7c0..e0692d0534 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -3295,12 +3295,19 @@ const updateUserAddresses = async (user_id, data) => { const { addresses } = data; addresses.forEach((addressObj) => { - + if (!addressObj.address || !addressObj.network || !addressObj.label || !addressObj.currency) { + throw new Error(ADDRESSBOOK_MISSING_FIELDS); + } + Object.keys(addressObj).forEach((key) => { if (!CRYPTO_ADDRESS_FIELDS.includes(key)) { throw new Error(ADDRESSBOOK_MISSING_FIELDS); } }); + + if (!addressObj.created_at) { + addressObj.created_at = moment().toISOString(); + } }); // Check for duplicate labels in the payload From e22e262ddebd91854d7c12bf9bd264e9a7d06cd6 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Tue, 23 Jul 2024 01:22:21 +0300 Subject: [PATCH 043/108] p2p-sell-feature --- server/api/controllers/p2p.js | 21 +- server/api/controllers/user.js | 96 +- server/api/swagger/p2p.yaml | 9 + server/api/swagger/user.yaml | 196 ++++ .../20240722635282-create-payment-details.js | 70 ++ server/db/models/index.js | 2 + server/db/models/paymentDetail.js | 58 ++ server/utils/hollaex-tools-lib/tools/p2p.js | 53 +- server/utils/hollaex-tools-lib/tools/user.js | 84 +- web/src/config/lang/en.json | 11 + web/src/containers/P2P/P2PDash.js | 628 +++++++++---- web/src/containers/P2P/P2PMyDeals.js | 6 +- web/src/containers/P2P/P2POrder.js | 7 +- web/src/containers/P2P/P2PPostDeal.js | 393 +++++--- web/src/containers/P2P/P2PProfile.js | 836 ++++++++++++++++-- web/src/containers/P2P/_P2P.scss | 6 +- web/src/containers/P2P/actions/p2pActions.js | 34 +- web/src/containers/P2P/index.js | 2 + 18 files changed, 2079 insertions(+), 433 deletions(-) create mode 100644 server/db/migrations/20240722635282-create-payment-details.js create mode 100644 server/db/models/paymentDetail.js diff --git a/server/api/controllers/p2p.js b/server/api/controllers/p2p.js index 004b59974a..635cde5098 100644 --- a/server/api/controllers/p2p.js +++ b/server/api/controllers/p2p.js @@ -20,7 +20,8 @@ const createP2PDeal = (req, res) => { terms, auto_response, payment_methods, - region + region, + side } = req.swagger.params.data.value; loggerP2P.verbose( @@ -36,12 +37,13 @@ const createP2PDeal = (req, res) => { max_order_value, terms, auto_response, - region + region, + side ); toolsLib.p2p.createP2PDeal({ merchant_id: req.auth.sub.id, - side: 'sell', + side, price_type, buying_asset, spending_asset, @@ -87,6 +89,7 @@ const updateP2PDeal = (req, res) => { region, edited_ids, status, + side, id } = req.swagger.params.data.value; @@ -104,14 +107,15 @@ const updateP2PDeal = (req, res) => { terms, auto_response, region, - id + id, + side ); toolsLib.p2p.updateP2PDeal({ id, merchant_id: req.auth.sub.id, edited_ids, - side: 'sell', + side, price_type, buying_asset, spending_asset, @@ -283,7 +287,8 @@ const createP2PTransaction = (req, res) => { const { deal_id, amount_fiat, - payment_method_used + payment_method_used, + side } = req.swagger.params.data.value; loggerP2P.verbose( @@ -291,13 +296,15 @@ const createP2PTransaction = (req, res) => { 'controllers/p2p/createP2PTransaction data', deal_id, amount_fiat, - payment_method_used + payment_method_used, + side ); toolsLib.p2p.createP2PTransaction({ deal_id, user_id: req.auth.sub.id, amount_fiat, + side, payment_method_used, ip } diff --git a/server/api/controllers/user.js b/server/api/controllers/user.js index fe43b817b7..a8fdf8b3a6 100644 --- a/server/api/controllers/user.js +++ b/server/api/controllers/user.js @@ -1506,6 +1506,96 @@ const updateUserAddresses = (req, res) => { }); }; +const getPaymentDetails = (req, res) => { + loggerUser.verbose(req.uuid, 'controllers/user/getPaymentDetails/auth', req.auth); + + const { is_p2p, is_fiat_control, status, limit, page, order_by, order, start_date, end_date } = req.swagger.params; + + const user_id = req.auth.sub.id; + + toolsLib.user.getPaymentDetails(user_id, + { + limit: limit.value, + page: page.value, + order_by: order_by.value, + order: order.value, + start_date: start_date.value, + end_date: end_date.value, + is_p2p: is_p2p.value, + is_fiat_control: is_fiat_control.value, + status: status.value, + }) + .then((data) => { + return res.json(data); + }) + .catch((err) => { + loggerUser.error(req.uuid, 'controllers/user/getPaymentDetails', err.message); + return res.status(err.statusCode || 400).json({ message: errorMessageConverter(err) }); + }); +}; + +const createPaymentDetail = (req, res) => { + loggerUser.verbose(req.uuid, 'controllers/user/createPaymentDetail/auth', req.auth); + + const user_id = req.auth.sub.id; + const { name, label, details, is_p2p, is_fiat_control, status } = req.swagger.params.data.value; + + toolsLib.user.createPaymentDetail({ + user_id, + name, + label, + details, + is_p2p, + is_fiat_control, + status + }) + .then((data) => { + return res.json(data); + }) + .catch((err) => { + loggerUser.error(req.uuid, 'controllers/user/createPaymentDetail', err.message); + return res.status(err.statusCode || 400).json({ message: errorMessageConverter(err) }); + }); +}; + +const updatePaymentDetail = (req, res) => { + loggerUser.verbose(req.uuid, 'controllers/user/updatePaymentDetail/auth', req.auth); + + const { id, name, label, details, is_p2p, is_fiat_control } = req.swagger.params.data.value; + + toolsLib.user.updatePaymentDetail(id, { + name, + label, + details, + is_p2p, + is_fiat_control + }) + .then((data) => { + return res.json(data); + }) + .catch((err) => { + loggerUser.error(req.uuid, 'controllers/user/updatePaymentDetail', err.message); + return res.status(err.statusCode || 400).json({ message: errorMessageConverter(err) }); + }); +}; + +const deletePaymentDetail = (req, res) => { + loggerUser.verbose(req.uuid, 'controllers/user/deletePaymentDetail/auth', req.auth); + + const { id } = req.swagger.params.data.value; + + toolsLib.user.deletePaymentDetail(id) + .then(() => { + return res.json({ + message: "Success" + }); + }) + .catch((err) => { + loggerUser.error(req.uuid, 'controllers/user/deletePaymentDetail', err.message); + return res.status(err.statusCode || 400).json({ message: errorMessageConverter(err) }); + }); +}; + module.exports = { signUpUser, @@ -1546,5 +1636,9 @@ module.exports = { createUserReferralCode, getUserReferralCodes, updateUserAddresses, - fetchUserAddressBook + fetchUserAddressBook, + getPaymentDetails, + createPaymentDetail, + updatePaymentDetail, + deletePaymentDetail }; \ No newline at end of file diff --git a/server/api/swagger/p2p.yaml b/server/api/swagger/p2p.yaml index 90d3b6522b..678f3aa8e2 100644 --- a/server/api/swagger/p2p.yaml +++ b/server/api/swagger/p2p.yaml @@ -109,6 +109,9 @@ paths: type: string auto_response: type: string + side: + type: string + enum: ['sell', 'buy'] payment_methods: type: array items: @@ -168,6 +171,9 @@ paths: type: string auto_response: type: string + side: + type: string + enum: ['sell', 'buy'] payment_methods: type: array items: @@ -298,6 +304,9 @@ paths: deal_id: type: integer format: int32 + side: + type: string + enum: ['buy', 'sell'] amount_fiat: type: number format: double diff --git a/server/api/swagger/user.yaml b/server/api/swagger/user.yaml index 8ddeb2fb7c..f49510a44e 100644 --- a/server/api/swagger/user.yaml +++ b/server/api/swagger/user.yaml @@ -1813,6 +1813,202 @@ paths: - user x-token-permissions: - can_read + /user/payment-details: + x-swagger-router-controller: user + get: + description: Get payment details for user + operationId: getPaymentDetails + tags: + - PaymentDetails + parameters: + - in: query + name: id + description: Unique identifier + required: false + type: number + format: int32 + - in: query + name: is_p2p + description: is_p2p + required: false + type: boolean + - in: query + name: is_fiat_control + description: is_fiat_control + required: false + type: boolean + - in: query + name: status + description: status + required: false + type: boolean + - in: query + name: limit + description: "Number of elements to return. Default: 50. Maximun: 100" + required: false + type: number + format: int32 + - in: query + name: page + description: Page of data to retrieve + required: false + type: number + format: int32 + - in: query + name: order_by + description: Field to order data + required: false + type: string + - in: query + name: order + description: direction to order + required: false + type: string + enum: ['asc', 'desc'] + - in: query + name: start_date + description: Starting date of queried data + required: false + type: string + format: date-time + - in: query + name: end_date + description: Ending date of queried data + required: false + type: string + format: date-time + responses: + 200: + description: Success + schema: + $ref: "#/definitions/ObjectResponse" + default: + description: Error + schema: + $ref: "#/definitions/MessageResponse" + security: + - Token: [] + x-security-types: + - bearer + - hmac + x-security-scopes: + - user + post: + description: Create a new payment detail + operationId: createPaymentDetail + tags: + - PaymentDetails + parameters: + - name: data + in: body + required: true + schema: + type: object + properties: + name: + type: string + label: + type: string + details: + type: object + is_p2p: + type: boolean + is_fiat_control: + type: boolean + status: + type: integer + format: int32 + responses: + 200: + description: Success + schema: + $ref: "#/definitions/ObjectResponse" + default: + description: Error + schema: + $ref: "#/definitions/MessageResponse" + security: + - Token: [] + x-security-types: + - bearer + - hmac + x-security-scopes: + - user + put: + description: Update a payment detail + operationId: updatePaymentDetail + tags: + - PaymentDetails + parameters: + - name: data + in: body + required: true + schema: + type: object + properties: + id: + type: integer + format: int32 + name: + type: string + label: + type: string + details: + type: object + is_p2p: + type: boolean + is_fiat_control: + type: boolean + status: + type: integer + format: int32 + responses: + 200: + description: Success + schema: + $ref: "#/definitions/ObjectResponse" + default: + description: Error + schema: + $ref: "#/definitions/MessageResponse" + security: + - Token: [] + x-security-types: + - bearer + - hmac + x-security-scopes: + - user + delete: + description: Delete a payment detail + operationId: deletePaymentDetail + tags: + - PaymentDetails + parameters: + - name: data + in: body + required: true + schema: + type: object + properties: + id: + type: integer + format: int32 + responses: + 200: + description: Success + schema: + $ref: "#/definitions/ObjectResponse" + default: + description: Error + schema: + $ref: "#/definitions/MessageResponse" + security: + - Token: [] + x-security-types: + - bearer + - hmac + x-security-scopes: + - user /logout: x-swagger-router-controller: user get: diff --git a/server/db/migrations/20240722635282-create-payment-details.js b/server/db/migrations/20240722635282-create-payment-details.js new file mode 100644 index 0000000000..90ecbfe130 --- /dev/null +++ b/server/db/migrations/20240722635282-create-payment-details.js @@ -0,0 +1,70 @@ +'use strict'; + +const TABLE_NAME = 'PaymentDetails'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable( + TABLE_NAME, + { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + user_id: { + type: Sequelize.INTEGER, + onDelete: 'CASCADE', + allowNull: false, + references: { + model: 'Users', + key: 'id' + } + }, + name: { + type: Sequelize.STRING, + allowNull: false + }, + label: { + type: Sequelize.STRING, + allowNull: true + }, + details: { + type: Sequelize.JSONB, + allowNull: false, + }, + is_p2p: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false + }, + is_fiat_control: { + type: Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false + }, + status: { + type: Sequelize.INTEGER, + allowNull: false, + defaultValue: 0 + }, + created_at: { + allowNull: false, + type: Sequelize.DATE, + defaultValue: Sequelize.literal('NOW()') + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + defaultValue: Sequelize.literal('NOW()') + } + }, + { + timestamps: true, + underscored: true + } + ); + }, + down: (queryInterface) => queryInterface.dropTable(TABLE_NAME) +}; diff --git a/server/db/models/index.js b/server/db/models/index.js index 3fe31f321e..2d94bba38c 100644 --- a/server/db/models/index.js +++ b/server/db/models/index.js @@ -68,6 +68,8 @@ model = require(path.join(__dirname, './referralCode'))(sequelize, Sequelize.Dat db[model.name] = model; model = require(path.join(__dirname, './userAddressBook'))(sequelize, Sequelize.DataTypes); db[model.name] = model; +model = require(path.join(__dirname, './paymentDetail'))(sequelize, Sequelize.DataTypes); +db[model.name] = model; Object.keys(db).forEach(function (modelName) { if ('associate' in db[modelName]) { diff --git a/server/db/models/paymentDetail.js b/server/db/models/paymentDetail.js new file mode 100644 index 0000000000..e439e406f5 --- /dev/null +++ b/server/db/models/paymentDetail.js @@ -0,0 +1,58 @@ +'use strict'; + +module.exports = function (sequelize, DataTypes) { + const PaymentDetail = sequelize.define( + 'PaymentDetail', + { + id: { + type: DataTypes.INTEGER, + allowNull: false, + autoIncrement: true, + primaryKey: true, + }, + user_id: { + type: DataTypes.INTEGER, + onDelete: 'CASCADE', + allowNull: false, + references: { + model: 'Users', + key: 'id' + } + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + label: { + type: DataTypes.STRING, + allowNull: true + }, + details: { + type: DataTypes.JSONB, + allowNull: false + }, + is_p2p: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }, + is_fiat_control: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }, + status: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + } + }, + { + timestamps: true, + underscored: true, + tableName: 'PaymentDetails' + } + ); + + return PaymentDetail; +}; diff --git a/server/utils/hollaex-tools-lib/tools/p2p.js b/server/utils/hollaex-tools-lib/tools/p2p.js index 2f873e4c73..1759cced3b 100644 --- a/server/utils/hollaex-tools-lib/tools/p2p.js +++ b/server/utils/hollaex-tools-lib/tools/p2p.js @@ -199,7 +199,6 @@ const getP2PAccountBalance = async (account_id, coin) => { const createP2PDeal = async (data) => { let { merchant_id, - side, buying_asset, spending_asset, spread, @@ -258,10 +257,6 @@ const createP2PDeal = async (data) => { throw new Error('exchange rate cannot be less than 0'); }; - if (side !== 'sell') { - throw new Error('side can only be sell'); - }; - data.status = true; return getModel('p2pDeal').create(data, { @@ -290,7 +285,6 @@ const updateP2PDeal = async (data) => { id, edited_ids, merchant_id, - side, buying_asset, spending_asset, spread, @@ -368,9 +362,6 @@ const updateP2PDeal = async (data) => { throw new Error('exchange rate cannot be less than 0'); }; - if (side !== 'sell') { - throw new Error('side can only be sell'); - }; if (data.status == null) { data.status = true; @@ -402,6 +393,7 @@ const createP2PTransaction = async (data) => { deal_id, user_id, amount_fiat, + side, payment_method_used, ip } = data; @@ -445,7 +437,9 @@ const createP2PTransaction = async (data) => { } //Cant have more than 3 active transactions per user - const userTransactions = await getModel('p2pTransaction').findAll({ where: { user_id: buyer.id, transaction_status: "active" } }); + const userTransactions = await getModel('p2pTransaction').findAll({ where: { + ...(side === 'buy' ? { merchant_id: buyer.id } : { user_id: buyer.id }), + transaction_status: "active" } }); if (userTransactions.length > 3) { throw new Error('You have currently 3 active order, please complete them before creating another one'); @@ -453,7 +447,7 @@ const createP2PTransaction = async (data) => { const merchant = await getUserByKitId(p2pDeal.merchant_id); - const merchantBalance = await getP2PAccountBalance(merchant_id, p2pDeal.buying_asset); + const merchantBalance = await getP2PAccountBalance(side === 'buy' ? user_id : merchant_id, p2pDeal.buying_asset); const price = new BigNumber(exchange_rate).multipliedBy(1 + (spread / 100)); const amount_digital_currency = new BigNumber(amount_fiat).dividedBy(price).toNumber(); @@ -469,18 +463,18 @@ const createP2PTransaction = async (data) => { throw new Error('Transaction is not possible at the moment'); } - if (new BigNumber(amount_fiat).comparedTo(new BigNumber(max_order_value)) === 1) { + if (new BigNumber(side === 'sell' ? amount_fiat : amount_digital_currency).comparedTo(new BigNumber(max_order_value)) === 1) { throw new Error('input amount cannot be bigger than max allowable order amount'); } - if (new BigNumber(amount_fiat).comparedTo(new BigNumber(min_order_value)) === -1) { + if (new BigNumber(side === 'sell' ? amount_fiat : amount_digital_currency).comparedTo(new BigNumber(min_order_value)) === -1) { throw new Error('input amount cannot be lower than min allowable order amount'); } //Check the payment method const hasMethod = p2pDeal.payment_methods.find(method => method.system_name === payment_method_used.system_name); - if (!hasMethod) { + if (!hasMethod && side === 'sell') { throw new Error('invalid payment method'); } @@ -495,11 +489,11 @@ const createP2PTransaction = async (data) => { data.transaction_status = 'active'; data.transaction_duration = 30; data.transaction_id = uuid(); - data.merchant_id = merchant_id; - data.user_id = user_id; + data.merchant_id = side === 'buy' ? user_id : merchant_id; + data.user_id = side === 'buy' ? merchant_id : user_id; data.amount_digital_currency = amount; data.deal_id = deal_id; - const lock = await getNodeLib().lockBalance(merchant.network_id, p2pDeal.buying_asset, amount_digital_currency + merchantFeeAmount + buyerFeeAmount); + const lock = await getNodeLib().lockBalance(side === 'buy' ? buyer.network_id : merchant.network_id, p2pDeal.buying_asset, amount_digital_currency + merchantFeeAmount + buyerFeeAmount); data.locked_asset_id = lock.id; data.price = price.toNumber(); @@ -561,7 +555,7 @@ const updateP2pTransaction = async (data) => { const transaction = await getModel('p2pTransaction').findOne({ where: { id } }); const p2pDeal = await getModel('p2pDeal').findOne({ where: { id: transaction.deal_id } }); - const merchant = await getUserByKitId(p2pDeal.merchant_id); + const merchant = await getUserByKitId(transaction.merchant_id); const p2pConfig = getKitConfig()?.p2p_config; const user = await getUserByKitId(user_id); @@ -594,7 +588,7 @@ const updateP2pTransaction = async (data) => { const chatMessage = { sender_id: user_id, - receiver_id: merchant.id, + receiver_id: transaction.merchant_id, message: 'ORDER_EXPIRED', type: 'notification', created_at: new Date() @@ -655,12 +649,12 @@ const updateP2pTransaction = async (data) => { const buyerFeeAmount = (new BigNumber(transaction.amount_digital_currency).multipliedBy(p2pConfig.user_fee)) .dividedBy(100).toNumber(); const buyerTotalAmount = new BigNumber(transaction.amount_digital_currency).minus(new BigNumber(buyerFeeAmount)).toNumber(); - await transferAssetByKitIds(merchant.id, transaction.user_id, p2pDeal.buying_asset, buyerTotalAmount, 'P2P Transaction', false, { category: 'p2p' }); + await transferAssetByKitIds(transaction.merchant_id, transaction.user_id, p2pDeal.buying_asset, buyerTotalAmount, 'P2P Transaction', false, { category: 'p2p' }); //send the fees to the source account - if (p2pConfig.source_account !== merchant.id) { + if (p2pConfig.source_account !== transaction.merchant_id) { const totalFees = (new BigNumber(merchantFeeAmount).plus(buyerFeeAmount)).toNumber(); - await transferAssetByKitIds(merchant.id, p2pConfig.source_account, p2pDeal.buying_asset, totalFees, 'P2P Transaction', false, { category: 'p2p' }); + await transferAssetByKitIds(transaction.merchant_id, p2pConfig.source_account, p2pDeal.buying_asset, totalFees, 'P2P Transaction', false, { category: 'p2p' }); } data.transaction_status = 'complete'; @@ -677,7 +671,8 @@ const updateP2pTransaction = async (data) => { initiator_id = transaction.merchant_id; defendant_id = transaction.user_id; } - await getNodeLib().unlockBalance(merchant.network_id, transaction.locked_asset_id); + + await getNodeLib().unlockBalance( merchant.network_id, transaction.locked_asset_id); await createP2pDispute({ transaction_id: transaction.id, initiator_id, @@ -697,7 +692,7 @@ const updateP2pTransaction = async (data) => { if (user_status === 'confirmed') { const chatMessage = { sender_id: user_id, - receiver_id: merchant.id, + receiver_id: transaction.merchant_id, message: 'BUYER_PAID_ORDER', type: 'notification', created_at: new Date() @@ -719,7 +714,7 @@ const updateP2pTransaction = async (data) => { if (user_status === 'cancelled') { const chatMessage = { sender_id: user_id, - receiver_id: merchant.id, + receiver_id: transaction.merchant_id, message: 'BUYER_CANCELLED_ORDER', type: 'notification', created_at: new Date() @@ -741,7 +736,7 @@ const updateP2pTransaction = async (data) => { if (user_status === 'appeal') { const chatMessage = { sender_id: user_id, - receiver_id: merchant.id, + receiver_id: transaction.merchant_id, message: 'BUYER_APPEALED_ORDER', type: 'notification', created_at: new Date() @@ -763,7 +758,7 @@ const updateP2pTransaction = async (data) => { if (merchant_status === 'confirmed') { const chatMessage = { - sender_id: merchant.id, + sender_id: transaction.merchant_id, receiver_id: transaction.user_id, message: 'VENDOR_CONFIRMED_ORDER', type: 'notification', @@ -785,7 +780,7 @@ const updateP2pTransaction = async (data) => { if (merchant_status === 'cancelled') { const chatMessage = { - sender_id: merchant.id, + sender_id: transaction.merchant_id, receiver_id: transaction.user_id, message: 'VENDOR_CANCELLED_ORDER', type: 'notification', @@ -807,7 +802,7 @@ const updateP2pTransaction = async (data) => { if (merchant_status === 'appeal') { const chatMessage = { - sender_id: merchant.id, + sender_id: transaction.merchant_id, receiver_id: transaction.user_id, message: 'VENDOR_APPEALED_ORDER', type: 'notification', diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index e0692d0534..868c1c106d 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -3339,6 +3339,84 @@ const updateUserAddresses = async (user_id, data) => { return userAddressBook; }; +const getPaymentDetails = async (user_id, opts = { + limit: null, + page: null, + order_by: null, + order: null, + start_date: null, + end_date: null, + is_p2p: null, + is_fiat_control: null, + status: null, +}) => { + const pagination = paginationQuery(opts.limit, opts.page); + const ordering = orderingQuery(opts.order_by, opts.order); + const timeframe = timeframeQuery(opts.start_date, opts.end_date); + + const query = { + where: { + created_at: timeframe, + user_id, + ...(opts.is_p2p && { is_p2p: opts.is_p2p }), + ...(opts.is_fiat_control && { is_fiat_control: opts.is_fiat_control }), + ...(opts.status && { status: opts.status }) + }, + order: [ordering], + ...(!opts.format && pagination), + }; + + + return dbQuery.findAndCountAllWithRows('paymentDetail', query); +}; + +const createPaymentDetail = async (data) => { + const { user_id, name, label, details, is_p2p, is_fiat_control, status } = data; + + const user = await getUserByKitId(user_id); + + if (!user) { + throw new Error(USER_NOT_FOUND); + } + + const paymentDetail = await getModel('paymentDetail').create({ + user_id, + name, + label, + details, + is_p2p, + is_fiat_control, + status + }); + return paymentDetail; +}; + +const updatePaymentDetail = async (id, data) => { + const paymentDetail = await getModel('paymentDetail').findOne({ where: { id } }); + if (!paymentDetail) { + throw new Error('Payment detail not found'); + } + + await paymentDetail.update(data, { + fields: [ + 'name', + 'label', + 'details', + 'is_p2p', + 'is_fiat_control' + ] + }); + return paymentDetail; +}; + +const deletePaymentDetail = async (id) => { + const paymentDetail = await getModel('paymentDetail').findOne({ where: { id } }); + if (!paymentDetail) { + throw new Error('Payment detail not found'); + } + await paymentDetail.destroy(); +}; + module.exports = { loginUser, @@ -3415,5 +3493,9 @@ module.exports = { getUserReferralCodes, createUserReferralCode, updateUserAddresses, - fetchUserAddressBook + fetchUserAddressBook, + getPaymentDetails, + createPaymentDetail, + updatePaymentDetail, + deletePaymentDetail }; diff --git a/web/src/config/lang/en.json b/web/src/config/lang/en.json index dfb812e2e3..bc082d1631 100644 --- a/web/src/config/lang/en.json +++ b/web/src/config/lang/en.json @@ -1948,8 +1948,13 @@ "TRADE": "Trade", "SELECT_PAYMENT_METHOD": "Select payment Method", "SPEND_AMOUNT": "Spend Amount", + "P2P_METHODS": "P2P Payment Methods", + "PAYMENT_METHODS": "PAYMENT METHODS", + "PAYMENT_METHODS_DEC": "You can sell cryptocurrencies and receive fiat payments by adding your personal payment account details, such as bank information or other local payment methods. Ensure that the name associated with your payment account matches the name in your verified details before adding your payment information.", + "SELL_AMOUNT": "Sell Amount", "AMOUNT_TO_RECEIVE": "Amount to receive", "ORDER_CREATED": "Order Created.", + "ADD_PAYMENT_METHOD": "+ ADD PAYMENT METHOD", "SELECT_PAYMENT_METHOD_AND_AMOUNT": "please select payment method and input amount", "ERROR_MESSAGE": "An error occurred.", "TRANSACTION_NOT_FOUND": "Transaction not found", @@ -2064,6 +2069,7 @@ "SET_TERMS_RESPONSE": "Set terms and an automated response", "UPDATE_DEAL": "Update Deal", "SELL_UPPER": "SELL", + "BUY_UPPER": "BUY", "CRYPTO_WANT_TO_SELL": "Crypto you want to sell", "RECEIVE": "RECEIVE", "FIAT_CURRENCY_WANT_TO_RECEIVE": "Fiat currency you want to receive", @@ -2074,11 +2080,15 @@ "PRICE_PROFIT_SPREAD_SET": "Price and profit spread to set", "UNIT_PRICE": "UNIT PRICE", "PRICE_ADVERTISE_SELL": "Price you'll advertise to sell", + "PRICE_ADVERTISE_BUY": "Price you'll advertise to buy", "TOTAL_ASSET_SELL_1": "Total", "TOTAL_ASSET_SELL_2": "you can sell", + "TOTAL_ASSET_SEND_2": "you can send", "BUY_ORDER_LIMITS": "BUY ORDER LIMITS", + "SELL_ORDER_LIMITS": "SELL ORDER LIMITS", "MIN_MAX_ORDER_VALUE_1": "Minimum and max", "MIN_MAX_ORDER_VALUE_2": "buy order value in", + "MIN_MAX_ORDER_VALUE_3": "sell order value in", "PAYMENT_METHODS_SEND_FIAT": "PAYMENT METHODS TO SEND FIAT", "SELECT_PAYMENT_METHODS_1": "Select up to", "SELECT_PAYMENT_METHODS_2": "methods for", @@ -2109,6 +2119,7 @@ "AMOUNT_SEND_RELEASE": "(Amount of crypto you'll sell and release)", "MINUTES": "minutes", "EDIT_UPPERCASE": "EDIT", + "DELETE_UPPERCASE": "DELETE", "DATE": "Date", "DISPLAY_NAME": "Display Name", "TOTAL_ORDERS": "Total Orders", diff --git a/web/src/containers/P2P/P2PDash.js b/web/src/containers/P2P/P2PDash.js index f9738df305..f5bf577249 100644 --- a/web/src/containers/P2P/P2PDash.js +++ b/web/src/containers/P2P/P2PDash.js @@ -12,6 +12,7 @@ import { fetchDeals, createTransaction, fetchTransactions, + fetchP2PPaymentMethods, } from './actions/p2pActions'; import { COUNTRIES_OPTIONS } from 'utils/countries'; import { formatToCurrency } from 'utils/currency'; @@ -35,6 +36,7 @@ const P2PDash = ({ refresh, setSelectedTransaction, p2p_config, + setTab, changeProfileTab, }) => { const [expandRow, setExpandRow] = useState(false); @@ -54,6 +56,7 @@ const P2PDash = ({ const [userFeedback, setUserFeedback] = useState([]); const [userProfile, setUserProfile] = useState(); const [selectedProfile, setSelectedProfile] = useState(); + const [myMethods, setMyMethods] = useState([]); const inputRef = useRef(null); useEffect(() => { fetchDeals({ status: true }) @@ -72,6 +75,12 @@ const P2PDash = ({ setMethods(newMethods || []); }) .catch((err) => err); + + fetchP2PPaymentMethods({ is_p2p: true }) + .then((res) => { + setMyMethods(res.data); + }) + .catch((err) => err); }, [refresh]); const formatAmount = (currency, amount) => { @@ -576,20 +585,41 @@ const P2PDash = ({ setAmountFiat(); }} > -
- - {STRINGS['P2P.AVAILABLE']} - - : {deal.total_order_amount}{' '} - {deal.buying_asset.toUpperCase()} -
-
- - {STRINGS['P2P.LIMIT']} - - : {deal.min_order_value} - {deal.max_order_value}{' '} - {deal.spending_asset.toUpperCase()} -
+ {deal.side === 'sell' ? ( + <> +
+ + {STRINGS['P2P.AVAILABLE']} + + : {deal.total_order_amount}{' '} + {deal.buying_asset.toUpperCase()} +
+
+ + {STRINGS['P2P.LIMIT']} + + : {deal.min_order_value} - {deal.max_order_value}{' '} + {deal.spending_asset.toUpperCase()} +
+ + ) : ( + <> +
+ + {STRINGS['P2P.AVAILABLE']} + + : {deal.total_order_amount}{' '} + {deal.spending_asset.toUpperCase()} +
+
+ + {STRINGS['P2P.LIMIT']} + + : {deal.min_order_value} - {deal.max_order_value}{' '} + {deal.buying_asset.toUpperCase()} +
+ + )}
)} diff --git a/web/src/containers/P2P/P2PMyDeals.js b/web/src/containers/P2P/P2PMyDeals.js index 0a966eab59..608f0f1c16 100644 --- a/web/src/containers/P2P/P2PMyDeals.js +++ b/web/src/containers/P2P/P2PMyDeals.js @@ -202,7 +202,11 @@ const P2PMyDeals = ({ diff --git a/web/src/containers/P2P/P2POrder.js b/web/src/containers/P2P/P2POrder.js index f47cdda1ed..0ab28a218e 100644 --- a/web/src/containers/P2P/P2POrder.js +++ b/web/src/containers/P2P/P2POrder.js @@ -1716,7 +1716,12 @@ const P2POrder = ({ textAlign: 'center', }} > -
{selectedOrder?.merchant?.full_name}:
+
+ {message.sender_id === selectedOrder?.merchant_id + ? selectedOrder?.merchant?.full_name + : selectedOrder?.buyer?.full_name} + : +
{message.message}
{moment(message?.created_at || new Date()).format( diff --git a/web/src/containers/P2P/P2PPostDeal.js b/web/src/containers/P2P/P2PPostDeal.js index 9153efd474..120c8f9086 100644 --- a/web/src/containers/P2P/P2PPostDeal.js +++ b/web/src/containers/P2P/P2PPostDeal.js @@ -33,7 +33,7 @@ const P2PPostDeal = ({ setSelectedDealEdit, }) => { const [step, setStep] = useState(1); - + const [p2pSide, setP2pSide] = useState('sell'); const [priceType, setPriceType] = useState('static'); const [buyingAsset, setBuyingAsset] = useState(); const [spendingAsset, setSpendingAsset] = useState(); @@ -76,6 +76,7 @@ const P2PPostDeal = ({ setAutoResponse(selectedDealEdit?.auto_response); setPaymentMethods(selectedDealEdit?.payment_methods); setRegion(selectedDealEdit?.region); + setP2pSide(selectedDealEdit?.side); setStep(1); } else { setPriceType('static'); @@ -139,7 +140,16 @@ const P2PPostDeal = ({ - + { + if (checked) { + setP2pSide('sell'); + } else { + setP2pSide('buy'); + } + }} + /> @@ -176,9 +186,15 @@ const P2PPostDeal = ({
- - {STRINGS['P2P.SELL_UPPER']} - + {p2pSide === 'sell' ? ( + + {STRINGS['P2P.SELL_UPPER']} + + ) : ( + + {STRINGS['P2P.BUY_UPPER']} + + )}
- - {STRINGS['P2P.PRICE_ADVERTISE_SELL']} - {' '} + {p2pSide === 'sell' ? ( + + {STRINGS['P2P.PRICE_ADVERTISE_SELL']} + + ) : ( + + {STRINGS['P2P.PRICE_ADVERTISE_BUY']} + + )}{' '} {buyingAsset ? `${buyingAsset?.toUpperCase()}` : ''}
@@ -362,15 +390,28 @@ const P2PPostDeal = ({ >
-
- - {STRINGS['P2P.TOTAL_ASSET_SELL_1']} - {' '} - {buyingAsset?.toUpperCase()}{' '} - - {STRINGS['P2P.TOTAL_ASSET_SELL_2']} - -
+ {p2pSide === 'sell' ? ( +
+ + {STRINGS['P2P.TOTAL_ASSET_SELL_1']} + {' '} + {buyingAsset?.toUpperCase()}{' '} + + {STRINGS['P2P.TOTAL_ASSET_SELL_2']} + +
+ ) : ( +
+ + {STRINGS['P2P.TOTAL_ASSET_SELL_1']} + {' '} + {spendingAsset?.toUpperCase()}{' '} + + {STRINGS['P2P.TOTAL_ASSET_SEND_2']} + +
+ )} +
-
- - {STRINGS['P2P.BUY_ORDER_LIMITS']} - -
-
- - {STRINGS['P2P.MIN_MAX_ORDER_VALUE_1']} - {' '} - {spendingAsset?.toUpperCase()}{' '} - - {STRINGS['P2P.MIN_MAX_ORDER_VALUE_2']} - {' '} - {spendingAsset?.toUpperCase()} -
+ {p2pSide === 'sell' ? ( +
+ + {STRINGS['P2P.BUY_ORDER_LIMITS']} + +
+ ) : ( +
+ + {STRINGS['P2P.SELL_ORDER_LIMITS']} + +
+ )} + + {p2pSide === 'sell' ? ( +
+ + {STRINGS['P2P.MIN_MAX_ORDER_VALUE_1']} + {' '} + {spendingAsset?.toUpperCase()}{' '} + + {STRINGS['P2P.MIN_MAX_ORDER_VALUE_2']} + {' '} + {spendingAsset?.toUpperCase()} +
+ ) : ( +
+ + {STRINGS['P2P.MIN_MAX_ORDER_VALUE_1']} + {' '} + {buyingAsset?.toUpperCase()}{' '} + + {STRINGS['P2P.MIN_MAX_ORDER_VALUE_3']} + {' '} + {buyingAsset?.toUpperCase()} +
+ )} +
@@ -409,16 +473,18 @@ const P2PPostDeal = ({ }} />
-
- {minOrderValue - ? ( - minOrderValue / - formatRate(exchangeRate, spread, spendingAsset) - ).toFixed(4) + - ' ' + - buyingAsset?.toUpperCase() - : ''}{' '} -
+ {p2pSide === 'sell' && ( +
+ {minOrderValue + ? ( + minOrderValue / + formatRate(exchangeRate, spread, spendingAsset) + ).toFixed(4) + + ' ' + + buyingAsset?.toUpperCase() + : ''}{' '} +
+ )}
@@ -431,16 +497,18 @@ const P2PPostDeal = ({ }} />
-
- {maxOrderValue - ? ( - maxOrderValue / - formatRate(exchangeRate, spread, spendingAsset) - ).toFixed(4) + - ' ' + - buyingAsset?.toUpperCase() - : ''}{' '} -
+ {p2pSide === 'sell' && ( +
+ {maxOrderValue + ? ( + maxOrderValue / + formatRate(exchangeRate, spread, spendingAsset) + ).toFixed(4) + + ' ' + + buyingAsset?.toUpperCase() + : ''}{' '} +
+ )}
@@ -454,90 +522,157 @@ const P2PPostDeal = ({ gap: 25, }} > -
-
- - {STRINGS['P2P.PAYMENT_METHODS_SEND_FIAT']} - -
-
- - {STRINGS['P2P.SELECT_PAYMENT_METHODS_1']} - {' '} - {p2p_config?.bank_payment_methods?.length || 0}{' '} - - {STRINGS['P2P.SELECT_PAYMENT_METHODS_2']} - {' '} - {spendingAsset?.toUpperCase()} -
+ {p2pSide === 'sell' ? ( +
+
+ + {STRINGS['P2P.PAYMENT_METHODS_SEND_FIAT']} + +
+
+ + {STRINGS['P2P.SELECT_PAYMENT_METHODS_1']} + {' '} + {p2p_config?.bank_payment_methods?.length || 0}{' '} + + {STRINGS['P2P.SELECT_PAYMENT_METHODS_2']} + {' '} + {spendingAsset?.toUpperCase()} +
- {p2p_config?.bank_payment_methods?.map((method) => { - return ( -
-
x.system_name === method.system_name - ) - ? 'whiteTextP2P' - : 'greyTextP2P' - } - onClick={() => { - const newSelected = [...paymentMethods]; - - if ( - newSelected.find( + {p2p_config?.bank_payment_methods?.map((method) => { + return ( +
+
x.system_name === method.system_name ) - ) { - setPaymentMethods( - newSelected.filter( - (x) => x.system_name !== method.system_name - ) - ); - } else { - newSelected.push(method); - setPaymentMethods(newSelected); - setSelectedMethod(method); - setAddMethodDetails(true); + ? 'whiteTextP2P' + : 'greyTextP2P' } - }} - > -
{method.system_name}
+ onClick={() => { + const newSelected = [...paymentMethods]; + + if ( + newSelected.find( + (x) => x.system_name === method.system_name + ) + ) { + setPaymentMethods( + newSelected.filter( + (x) => x.system_name !== method.system_name + ) + ); + } else { + newSelected.push(method); + setPaymentMethods(newSelected); + setSelectedMethod(method); + setAddMethodDetails(true); + } + }} + > +
{method.system_name}
+ {paymentMethods?.find( + (x) => x.system_name === method.system_name + ) &&
} +
{paymentMethods?.find( (x) => x.system_name === method.system_name - ) &&
} + ) && ( +
{ + setSelectedMethod(method); + setAddMethodDetails(true); + }} + className="whiteTextP2P" + style={{ cursor: 'pointer' }} + > + + + {STRINGS['P2P.EDIT_UPPERCASE']} + + +
+ )}
- {paymentMethods?.find( - (x) => x.system_name === method.system_name - ) && ( + ); + })} +
+ ) : ( +
+
+ + {STRINGS['P2P.PAYMENT_METHODS_SEND_FIAT']} + +
+
+ + {STRINGS['P2P.SELECT_PAYMENT_METHODS_1']} + {' '} + {p2p_config?.bank_payment_methods?.length || 0}{' '} + + {STRINGS['P2P.SELECT_PAYMENT_METHODS_2']} + {' '} + {spendingAsset?.toUpperCase()} +
+ + {p2p_config?.bank_payment_methods?.map((method) => { + return ( +
x.system_name === method.system_name + ) + ? 'whiteTextP2P' + : 'greyTextP2P' + } onClick={() => { - setSelectedMethod(method); - setAddMethodDetails(true); + const newSelected = [...paymentMethods]; + + if ( + newSelected.find( + (x) => x.system_name === method.system_name + ) + ) { + setPaymentMethods( + newSelected.filter( + (x) => x.system_name !== method.system_name + ) + ); + } else { + newSelected.push(method); + setPaymentMethods(newSelected); + } }} - className="whiteTextP2P" - style={{ cursor: 'pointer' }} > - - - {STRINGS['P2P.EDIT_UPPERCASE']} - - +
{method.system_name}
+ {paymentMethods?.find( + (x) => x.system_name === method.system_name + ) &&
}
- )} -
- ); - })} -
+
+ ); + })} +
+ )}
@@ -710,7 +845,7 @@ const P2PPostDeal = ({ if (selectedDealEdit) { await editDeal({ id: selectedDealEdit.id, - side: 'sell', + side: p2pSide, price_type: priceType, buying_asset: buyingAsset, spending_asset: spendingAsset, @@ -727,7 +862,7 @@ const P2PPostDeal = ({ setSelectedDealEdit(); } else { await postDeal({ - side: 'sell', + side: p2pSide, price_type: priceType, buying_asset: buyingAsset, spending_asset: spendingAsset, diff --git a/web/src/containers/P2P/P2PProfile.js b/web/src/containers/P2P/P2PProfile.js index b37bdf72bb..57bdbba162 100644 --- a/web/src/containers/P2P/P2PProfile.js +++ b/web/src/containers/P2P/P2PProfile.js @@ -5,11 +5,28 @@ import { connect } from 'react-redux'; import { IconTitle, EditWrapper } from 'components'; import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; -import { Button, Checkbox, message, Rate } from 'antd'; -import { fetchFeedback, fetchP2PProfile } from './actions/p2pActions'; +import { + Button, + Checkbox, + message, + Rate, + Modal, + Input, + Radio, + Space, +} from 'antd'; +import { + fetchFeedback, + fetchP2PProfile, + fetchP2PPaymentMethods, + createP2PPaymentMethod, + updateP2PPaymentMethod, + deleteP2PPaymentMethod, +} from './actions/p2pActions'; import { isMobile } from 'react-device-detect'; import classnames from 'classnames'; import moment from 'moment'; +import { CloseOutlined } from '@ant-design/icons'; import './_P2P.scss'; const P2PProfile = ({ @@ -27,11 +44,40 @@ const P2PProfile = ({ setTab, selectedProfile, setSelectedProfile, + setRefresh, }) => { const [myDeals, setMyDeals] = useState([]); const [checks, setCheks] = useState([]); const [myProfile, setMyProfile] = useState(); const [selectedUser, setSelectedUser] = useState(user); + const [selectedTab, setSelectedTab] = useState('0'); + const [paymentMethods, setPaymentMethods] = useState([]); + const [selectedMethod, setSelectedMethod] = useState({ + name: null, + details: {}, + is_p2p: true, + }); + const [addMethodDetails, setAddMethodDetails] = useState(); + const [myMethods, setMyMethods] = useState([]); + const [displayPaymentAdd, setDisplayPaymentAdd] = useState(false); + const [displayNewPayment, setDisplayNewPayment] = useState(false); + const [paymentFieldAdd, setPaymentFieldAdd] = useState(false); + const [paymentMethod, setPaymentMethod] = useState({ + system_name: null, + fields: {}, + }); + const [customFields, setCustomFields] = useState([ + { + id: 1, + name: null, + required: true, + }, + ]); + const [customField, setCustomField] = useState({ + id: null, + name: null, + required: null, + }); useEffect(() => { fetchFeedback({ merchant_id: (selectedProfile || selectedUser).id }) @@ -45,6 +91,12 @@ const P2PProfile = ({ setMyProfile(res); }) .catch((err) => err); + + fetchP2PPaymentMethods({ is_p2p: true }) + .then((res) => { + setMyMethods(res.data); + }) + .catch((err) => err); }, [refresh, selectedProfile]); return ( @@ -165,108 +217,714 @@ const P2PProfile = ({
-
- Feedback({myDeals.length || 0}) -
- {myDeals.length == 0 ? ( +
{ + setSelectedTab('0'); }} > - - {STRINGS['P2P.NO_FEEDBACK']} + + {STRINGS['P2P.P2P_METHODS']}
- ) : ( -
+ + + + ) : (
- - - + + )} + {deal?.payment_methods?.filter((a) => + myMethods?.find( + (x) => + x.name.toLowerCase() === + a.system_name?.toLowerCase() + ) + ).length > 0 && ( + + + + )} +
- setSelectedTransaction(transData.data[0]); - setDisplayOrder(true); - setLoading(false); - } else { - message.error( - STRINGS[ - 'P2P.SELECT_PAYMENT_METHOD_AND_AMOUNT' - ] +
+ + + {STRINGS['P2P.SELL_AMOUNT']} + {' '} + ({deal.buying_asset.toUpperCase()}) + + + + { + setAmountFiat(e); + const currencyAmount = + Number(e) * + Number( + deal.exchange_rate * + (1 + Number(deal.spread / 100 || 0)) + ); + + const formatted = formatAmount( + deal.spending_asset, + currencyAmount ); - setLoading(false); - } - } catch (error) { - message.error(error.data.message); - setLoading(false); - } + + setAmountCurrency(formatted); + }} + placeholder={deal.buying_asset.toUpperCase()} + /> + +
+
+ + + {STRINGS['P2P.AMOUNT_TO_RECEIVE']} + {' '} + ({deal.spending_asset.toUpperCase()}) + + + + + +
+
- {deal.side === 'sell' ? 'BUY' : 'SELL'}{' '} - {deal.buying_asset.toUpperCase()} {'>'} - + + + +
- + )}
-
{ + setSelectedTab('1'); }} > - - - - - - - - - - {myDeals.map((deal) => { - return ( - + + {selectedTab === '0' && ( +
+
+
+
+
+ + {STRINGS['P2P.PAYMENT_METHODS']} + +
+
+ + {STRINGS['P2P.PAYMENT_METHODS_DEC']} + +
+
+
+
+
+
-
- - - + + {STRINGS['P2P.PAYMENT_METHODS_SEND_FIAT']} + + + +
+ +
+ + {myMethods + ?.map((x) => x.details) + .map((method) => { + return ( +
+
{ + const newSelected = [...paymentMethods]; + + if ( + newSelected.find( + (x) => x.system_name === method.system_name + ) + ) { + setPaymentMethods( + newSelected.filter( + (x) => x.system_name !== method.system_name + ) + ); + } else { + newSelected.push(method); + setPaymentMethods(newSelected); + setSelectedMethod(method); + setAddMethodDetails(true); + } + }} + > +
{method.system_name}
+
+
{ + setSelectedMethod(method); + setAddMethodDetails(true); + }} + className="whiteTextP2P" + style={{ + cursor: 'pointer', + position: 'relative', + top: 5, + }} + > + + + {STRINGS['P2P.EDIT_UPPERCASE']} + + +
+
{ + const found = myMethods.find( + (x) => + x?.details?.system_name === + method?.system_name + ); + await deleteP2PPaymentMethod({ id: found.id }); + message.success('Payment method deleted.'); + fetchP2PPaymentMethods({ is_p2p: true }) + .then((res) => { + setMyMethods(res.data); + }) + .catch((err) => err); + }} + className="whiteTextP2P" + style={{ + cursor: 'pointer', + position: 'relative', + top: 5, + }} + > + + + {STRINGS['P2P.DELETE_UPPERCASE']} + + +
+
+ ); + })} + + + + + )} + {selectedTab === '1' && ( +
+ {myDeals.length == 0 ? ( +
+ + {STRINGS['P2P.NO_FEEDBACK']} + +
+ ) : ( +
- - {STRINGS['P2P.DATE']} - - - - {STRINGS['P2P.USER']} - - - - {STRINGS['P2P.COMMENT']} - - - - {STRINGS['P2P.RATING']} - -
- {moment(deal.created_at).format('DD/MMM/YYYY, hh:mmA')} - - {deal.user.full_name || ( - - {STRINGS['P2P.ANONYMOUS']} - - )} - - {deal.comment} - - -
+ + + + + + + + + {myDeals.map((deal) => { + return ( + + + + + + + ); + })} + +
+ + {STRINGS['P2P.DATE']} + + + + {STRINGS['P2P.USER']} + + + + {STRINGS['P2P.COMMENT']} + + + + {STRINGS['P2P.RATING']} + +
+ {moment(deal.created_at).format( + 'DD/MMM/YYYY, hh:mmA' + )} + + {deal.user.full_name || ( + + {STRINGS['P2P.ANONYMOUS']} + + )} + + {deal.comment} + + +
+ )} +
+ )} + } + bodyStyle={{ + marginTop: 60, + }} + className="stake_theme" + visible={addMethodDetails} + footer={null} + onCancel={() => { + setAddMethodDetails(false); + }} + > +
+ + {STRINGS['P2P.ADD_PAYMENT_METHOD_DETAILS']} + +
+ + {selectedMethod?.fields?.map((x, index) => { + return ( +
+
{x?.name}:
+ { + if (!selectedMethod.fields[index].value) + selectedMethod.fields[index].value = ''; + + selectedMethod.fields[index].value = e.target.value; + + const newSelected = [ + ...(myMethods?.map((x) => x.details) || []), + ]; + + const Index = newSelected.findIndex( + (x) => x.system_name === selectedMethod.system_name + ); + + newSelected[Index].fields = selectedMethod.fields; + + setPaymentMethods(newSelected); + }} + /> +
+ ); + })} + +
+ + +
+
+ + {displayNewPayment && ( + } + bodyStyle={{ + marginTop: 60, + }} + className="stake_theme" + visible={displayNewPayment} + width={600} + footer={null} + onCancel={() => { + setDisplayNewPayment(false); + }} + > +

+ Create and add new payment methods +

+
+ To add a payment method to your P2P platform, you can do so + manually by entering the name of the payment method and the + required payment details. For example, PayPal uses email addresses + to send and receive funds.{' '} +
+ +
+ Once the payment method is added, your P2P merchants and users + will be able to select it and enter the necessary information when + making or receiving payments. The details they provide will be + shared with the other party in the P2P transaction. +
+ +
+ Name of method and main payment detail +
+ +
+
+ Create new payment methods +
+ { + setPaymentMethod({ + ...paymentMethod, + system_name: e.target.value, + }); + }} + /> +
+ + {customFields.map((field) => { + return ( +
+
+ FIELD {field.id}# +
+
Payment detail name
+ { + const newCustomFields = [...customFields]; + const found = newCustomFields.find( + (x) => x.id === field.id + ); + if (found) { + found.name = e?.target?.value; + } + + setCustomFields(newCustomFields); + }} + /> +
+ Payment detail value +
+ { + const newCustomFields = [...customFields]; + const found = newCustomFields.find( + (x) => x.id === field.id + ); + if (found) { + found.value = e?.target?.value; + } + + setCustomFields(newCustomFields); + }} + /> +
+ ); + })} + +
{ + setPaymentFieldAdd(true); + }} + > + Add new payment detail field +
+
+ + + +
+
+ )} + + {paymentFieldAdd && ( + } + bodyStyle={{ + marginTop: 60, + }} + className="stake_theme" + visible={paymentFieldAdd} + width={450} + footer={null} + onCancel={() => { + setPaymentFieldAdd(false); + }} + > +

+ Add an additional payment details +

+
+ This new payment field is additional and should assist P2P + participants in their fiat currency transfers. This should be + account details related to payment method. This may including + phone numbers, usernames, unique account numbers, and other + necessary information for transactions depending on the payment + methods system.{' '} +
+ +
+
Payment detail name
+ { + setCustomField({ + ...customField, + name: e.target.value, + }); + }} + /> +
+ +
+
Required or optional
+
+ + + + Required + +
+ (Important payment detail) +
+ + Optional + +
+ (Optional payment detail) +
+
+
+
+
+ +
+ + + +
+
)}
diff --git a/web/src/containers/P2P/_P2P.scss b/web/src/containers/P2P/_P2P.scss index 2839500d80..644e17e8c6 100644 --- a/web/src/containers/P2P/_P2P.scss +++ b/web/src/containers/P2P/_P2P.scss @@ -32,7 +32,11 @@ color: var(--calculated_base_top-bar-navigation_text) !important; border: none; } - +.redButtonP2P { + background-color: var(--trading_selling-related-elements) !important; + color: var(--calculated_base_top-bar-navigation_text) !important; + border: none; +} .greyButtonP2P { background-color: var(--labels_inactive-button) !important; color: var(--calculated_base_top-bar-navigation_text) !important; diff --git a/web/src/containers/P2P/actions/p2pActions.js b/web/src/containers/P2P/actions/p2pActions.js index f90708d834..890f6edc53 100644 --- a/web/src/containers/P2P/actions/p2pActions.js +++ b/web/src/containers/P2P/actions/p2pActions.js @@ -73,9 +73,41 @@ export const fetchFeedback = (values) => { return requestAuthenticated(`/p2p/feedback?${queryValues}`); }; - export const fetchP2PProfile = (values) => { const queryValues = values && Object.keys(values).length ? querystring.stringify(values) : ''; return requestAuthenticated(`/p2p/profile?${queryValues}`); }; + +export const fetchP2PPaymentMethods = (values) => { + const queryValues = + values && Object.keys(values).length ? querystring.stringify(values) : ''; + return requestAuthenticated(`/user/payment-details?${queryValues}`); +}; + +export const createP2PPaymentMethod = (values) => { + const options = { + method: 'POST', + body: JSON.stringify(values), + }; + + return requestAuthenticated('/user/payment-details', options); +}; + +export const deleteP2PPaymentMethod = (values) => { + const options = { + method: 'DELETE', + body: JSON.stringify(values), + }; + + return requestAuthenticated('/user/payment-details', options); +}; + +export const updateP2PPaymentMethod = (values) => { + const options = { + method: 'PUT', + body: JSON.stringify(values), + }; + + return requestAuthenticated('/user/payment-details', options); +}; diff --git a/web/src/containers/P2P/index.js b/web/src/containers/P2P/index.js index ad4750cade..6b7d2cc113 100644 --- a/web/src/containers/P2P/index.js +++ b/web/src/containers/P2P/index.js @@ -141,6 +141,7 @@ const P2P = ({ refresh={refresh} setSelectedTransaction={setSelectedTransaction} changeProfileTab={changeProfileTab} + setTab={setTab} /> @@ -163,6 +164,7 @@ const P2P = ({ )} From 01281308a408635446c803d0f897d57b7e3fd0ae Mon Sep 17 00:00:00 2001 From: fetok12 Date: Tue, 23 Jul 2024 01:45:43 +0300 Subject: [PATCH 044/108] p2p-lang-localization --- web/src/config/lang/en.json | 18 ++++- .../containers/Admin/Trades/p2pSettings.js | 2 + web/src/containers/P2P/P2PPostDeal.js | 7 +- web/src/containers/P2P/P2PProfile.js | 81 ++++++++++++------- 4 files changed, 79 insertions(+), 29 deletions(-) diff --git a/web/src/config/lang/en.json b/web/src/config/lang/en.json index bc082d1631..cb40118db1 100644 --- a/web/src/config/lang/en.json +++ b/web/src/config/lang/en.json @@ -2137,6 +2137,22 @@ "VIEW_PROFILE": "View vendor's profile", "CLICK_TO_VIEW": "CLICK TO VIEW", "NEW_MESSAGE:": "You have a new message for your order", - "STATUS_UPDATE": "You have an update on your order" + "STATUS_UPDATE": "You have an update on your order", + "ADDITIONAL_PAYMENT_DETAILS": "Add an additional payment details", + "PAYMENT_FIELD_INFO": "This new payment field is additional and should assist P2P participants in their fiat currency transfers. This should be account details related to payment method. This may including phone numbers, usernames, unique account numbers, and other necessary information for transactions depending on the payment methods system.", + "PAYMENT_DETAIL_NAME": "Payment detail name", + "REQUIRED_OR_OPTIONAL": "Required or optional", + "CREATE_NEW_PAYMENT_METHODS": "Create and add new payment methods", + "MANUAL_PAYMENT_METHOD_ENTRY": "To add a payment method to your P2P platform, you can do so manually by entering the name of the payment method and the required payment details. For example, PayPal uses email addresses to send and receive funds.", + "USERS_PAYMENT_SELECTION": "Once the payment method is added, your P2P merchants and users will be able to select it and enter the necessary information when making or receiving payments. The details they provide will be shared with the other party in the P2P transaction.", + "METHOD_NAME_AND_DETAIL": "Name of method and main payment detail", + "ADD_NEW_PAYMENT_METHODS": "Create new payment methods", + "DETAIL_NAME": "Payment detail name", + "DETAIL_VALUE": "Payment detail value", + "DETAIL_REQUIRED": "Required", + "IMPORTANT_DETAIL": "(Important payment detail)", + "DETAIL_OPTIONAL": "Optional", + "OPTIONAL_DETAIL": "(Optional payment detail)", + "ADD_NEW_PAYMENT_FIELD": "Add new payment detail field" } } diff --git a/web/src/containers/Admin/Trades/p2pSettings.js b/web/src/containers/Admin/Trades/p2pSettings.js index 672c456e29..d039dbb898 100644 --- a/web/src/containers/Admin/Trades/p2pSettings.js +++ b/web/src/containers/Admin/Trades/p2pSettings.js @@ -1392,6 +1392,8 @@ const P2PSettings = ({ coins, pairs, p2p_config, features, constants }) => { }} > Sell + Buy + All
diff --git a/web/src/containers/P2P/P2PPostDeal.js b/web/src/containers/P2P/P2PPostDeal.js index 120c8f9086..87ff3febdb 100644 --- a/web/src/containers/P2P/P2PPostDeal.js +++ b/web/src/containers/P2P/P2PPostDeal.js @@ -33,7 +33,9 @@ const P2PPostDeal = ({ setSelectedDealEdit, }) => { const [step, setStep] = useState(1); - const [p2pSide, setP2pSide] = useState('sell'); + const [p2pSide, setP2pSide] = useState( + p2p_config.side === 'all' || p2p_config.side === 'sell' ? 'sell' : 'buy' + ); const [priceType, setPriceType] = useState('static'); const [buyingAsset, setBuyingAsset] = useState(); const [spendingAsset, setSpendingAsset] = useState(); @@ -143,6 +145,9 @@ const P2PPostDeal = ({ { + if (p2p_config.side === 'sell' && !checked) return; + if (p2p_config.side === 'buy' && checked) return; + if (checked) { setP2pSide('sell'); } else { diff --git a/web/src/containers/P2P/P2PProfile.js b/web/src/containers/P2P/P2PProfile.js index 57bdbba162..14f1fcebda 100644 --- a/web/src/containers/P2P/P2PProfile.js +++ b/web/src/containers/P2P/P2PProfile.js @@ -640,29 +640,33 @@ const P2PProfile = ({ }} >

- Create and add new payment methods + + {STRINGS['P2P.CREATE_NEW_PAYMENT_METHODS']} +

- To add a payment method to your P2P platform, you can do so - manually by entering the name of the payment method and the - required payment details. For example, PayPal uses email addresses - to send and receive funds.{' '} + + {STRINGS['P2P.MANUAL_PAYMENT_METHOD_ENTRY']} + {' '}
- Once the payment method is added, your P2P merchants and users - will be able to select it and enter the necessary information when - making or receiving payments. The details they provide will be - shared with the other party in the P2P transaction. + + {STRINGS['P2P.USERS_PAYMENT_SELECTION']} +
- Name of method and main payment detail + + {STRINGS['P2P.METHOD_NAME_AND_DETAIL']} +
- Create new payment methods + + {STRINGS['P2P.ADD_NEW_PAYMENT_METHODS']} +
FIELD {field.id}#
-
Payment detail name
+
+ + {STRINGS['P2P.DETAIL_NAME']} + +
- Payment detail value + + {STRINGS['P2P.DETAIL_VALUE']} +
- Add new payment detail field + + {STRINGS['P2P.ADD_NEW_PAYMENT_FIELD']} +

- Add an additional payment details + + {STRINGS['P2P.ADDITIONAL_PAYMENT_DETAILS']} +

- This new payment field is additional and should assist P2P - participants in their fiat currency transfers. This should be - account details related to payment method. This may including - phone numbers, usernames, unique account numbers, and other - necessary information for transactions depending on the payment - methods system.{' '} + + {STRINGS['P2P.PAYMENT_FIELD_INFO']} + {' '}
-
Payment detail name
+
+ + {STRINGS['P2P.PAYMENT_DETAIL_NAME']} + +
-
Required or optional
+
+ + {STRINGS['P2P.REQUIRED_OR_OPTIONAL']} + +
- Required + + {STRINGS['P2P.DETAIL_REQUIRED']} +
- (Important payment detail) + + {STRINGS['P2P.IMPORTANT_DETAIL']} +
- Optional + + {STRINGS['P2P.DETAIL_OPTIONAL']} +
- (Optional payment detail) + + {STRINGS['P2P.OPTIONAL_DETAIL']} +
From cdda5301909f0bf07babd4d820428571756bf916 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Tue, 23 Jul 2024 01:47:09 +0300 Subject: [PATCH 045/108] remove log --- web/src/containers/P2P/P2PProfile.js | 1 - 1 file changed, 1 deletion(-) diff --git a/web/src/containers/P2P/P2PProfile.js b/web/src/containers/P2P/P2PProfile.js index 14f1fcebda..87abdfa35c 100644 --- a/web/src/containers/P2P/P2PProfile.js +++ b/web/src/containers/P2P/P2PProfile.js @@ -782,7 +782,6 @@ const P2PProfile = ({ let hasValidation = true; payload.fields?.forEach((field) => { - console.log(field.name); if (!field.name || !field.value) { message.error('Please input all method fields'); hasValidation = false; From da1345f131576ceab139645967e8187b2941256a Mon Sep 17 00:00:00 2001 From: fetok12 Date: Tue, 23 Jul 2024 01:51:10 +0300 Subject: [PATCH 046/108] logic refinements --- web/src/containers/P2P/P2PProfile.js | 39 +++------------------------- 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/web/src/containers/P2P/P2PProfile.js b/web/src/containers/P2P/P2PProfile.js index 87abdfa35c..5f080ea0f3 100644 --- a/web/src/containers/P2P/P2PProfile.js +++ b/web/src/containers/P2P/P2PProfile.js @@ -733,7 +733,6 @@ const P2PProfile = ({
{ @@ -741,7 +740,9 @@ const P2PProfile = ({ }} > - {STRINGS['P2P.ADD_NEW_PAYMENT_FIELD']} + + {STRINGS['P2P.ADD_NEW_PAYMENT_FIELD']} +
-
-
- - {STRINGS['P2P.REQUIRED_OR_OPTIONAL']} - -
-
- - - - - {STRINGS['P2P.DETAIL_REQUIRED']} - - -
- - {STRINGS['P2P.IMPORTANT_DETAIL']} - -
- - - {STRINGS['P2P.DETAIL_OPTIONAL']} - - -
- - {STRINGS['P2P.OPTIONAL_DETAIL']} - -
-
-
-
-
-
Date: Tue, 23 Jul 2024 20:08:58 +0530 Subject: [PATCH 047/108] Changes for the address book notion task --- web/src/config/lang/en.json | 8 +- web/src/containers/Wallet/AddressBook.js | 346 ++++++++++--------- web/src/containers/Wallet/GenerateAddress.js | 60 +++- web/src/containers/Wallet/_AddressBook.scss | 90 ++++- web/src/containers/Wallet/utils.js | 33 ++ web/src/containers/Withdraw/Withdraw.js | 339 +++++++++++++----- web/src/containers/Withdraw/_Withdraw.scss | 33 +- web/src/index.css | 59 +++- 8 files changed, 674 insertions(+), 294 deletions(-) diff --git a/web/src/config/lang/en.json b/web/src/config/lang/en.json index 1c00e4bbaa..58a32d7d9b 100644 --- a/web/src/config/lang/en.json +++ b/web/src/config/lang/en.json @@ -1134,7 +1134,8 @@ "ENTER_AMOUNT": "Enter Amount", "REMOVE_TITLE": "Remove Tag", "MAX_AMOUNT_WARNING_INFO": "This amount exceeds your maximum withdrawal limit.", - "ZERO_BALANCE": "You do not have enough available balance." + "ZERO_BALANCE": "You do not have enough available balance.", + "NEW_ADDRESS": "New Address" }, "WALLET_BUTTON_BASE_DEPOSIT": "deposit", "WALLET_BUTTON_BASE_WITHDRAW": "withdraw", @@ -1748,7 +1749,10 @@ "WITHDRAWAL_ADDRESS_BOOK": "Withdrawal address book", "ADD_ADDRESS_DESC": "Add withdrawal address to {0}", "ADDRESS_BOOK": "Address book", - "MANAGE_ADDRESS_BOOK": "Manage address book" + "MANAGE_ADDRESS_BOOK": "Manage address book", + "VIEW_ADDRESS_BOOK_LABEL": "View address book", + "ASSET_ALREADY_HAVE_ADDRESS": "This Asset has already Exists. Please try another.", + "ADD_WITHDRAWAL_ADDRESS_LINK": "Add withdrawal address" }, "ASSET_INFO": "Asset info", "TAKER_FEES_APPLIED": "Taker fees are applied", diff --git a/web/src/containers/Wallet/AddressBook.js b/web/src/containers/Wallet/AddressBook.js index ccb503c536..2a0afe9c53 100644 --- a/web/src/containers/Wallet/AddressBook.js +++ b/web/src/containers/Wallet/AddressBook.js @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import { isMobile } from 'react-device-detect'; -import { Input, Button } from 'antd'; +import { Input, Button, message, Spin } from 'antd'; import { ExclamationCircleFilled } from '@ant-design/icons'; import GenerateAddress from './GenerateAddress'; @@ -10,7 +10,8 @@ import withConfig from 'components/ConfigProvider/withConfig'; import icons from 'config/icons/dark'; import CopyToClipboard from 'react-copy-to-clipboard'; import STRINGS from 'config/localizedStrings'; -import { Coin, Dialog, EditWrapper, IconTitle, Image, Table } from 'components'; +import AddressBookEmptyTable from './utils'; +import { Coin, Dialog, EditWrapper, IconTitle, Table } from 'components'; import { assetsSelector, RenderBtn } from './utils'; import { networkList, @@ -41,9 +42,13 @@ const AddressBook = ({ }); const [userLabel, setUserLabel] = useState(''); const [topAssets, setTopAssets] = useState([]); - const [selectedAsset, setSelectedAsset] = useState(null); - const [networkOptions, setNetworkOptions] = useState(null); + const [selectedAsset, setSelectedAsset] = useState({ + selectedCurrency: null, + networkOptions: null, + address: null, + }); const [isValidAddress, setIsValidAddress] = useState(false); + const [isLoading, setIsLoading] = useState(false); const AddressBookTableData = [ { @@ -53,7 +58,7 @@ const AddressBook = ({ renderCell: (data, key) => (
- {data?.addresses?.map((data) => data?.label) || '-'} + {data?.label || '-'}
), @@ -65,29 +70,14 @@ const AddressBook = ({ renderCell: (data, key) => (
- {data?.addresses?.map((data) => { - const asset = getNetworkNameByKey(data?.network); - const networkIcon = networkList.filter((item) => - asset === item?.network ? item?.iconId : null - ); - return ( -
- - - {`${ - coins[data?.network]?.fullname - } (${data?.network?.toUpperCase()})`} - -
- ); - }) || '-'} +
+ + + {`${ + coins[data?.currency]?.fullname + } (${data?.currency?.toUpperCase()})`} + +
), @@ -96,60 +86,53 @@ const AddressBook = ({ stringId: 'WITHDRAWALS_FORM_NETWORK_LABEL', label: STRINGS['WITHDRAWALS_FORM_NETWORK_LABEL'], key: 'network', - renderCell: (data, key) => ( - -
- {data?.addresses?.map((data) => { - const asset = getNetworkNameByKey(data?.network); - const networkIcon = networkList.filter((item) => - asset === item?.network ? item?.iconId : null - ); - return ( -
- {asset ? asset : data?.network?.toUpperCase()} - -
- ); - }) || '-'} -
- - ), + renderCell: (data, key) => { + let network = + coins[data?.network]?.network && + coins[data?.network]?.network !== 'other' + ? getNetworkNameByKey(coins[data?.network]?.network) + : coins[data?.currency]?.symbol?.toUpperCase(); + return ( + +
+ {network} + +
+ + ); + }, }, { stringId: 'WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS', label: STRINGS['WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS'], key: 'address', renderCell: (data, key) => ( - +
- {data?.addresses?.map((data) => { - return ( -
- {data?.address} - { - handleCopy(); - }} - > - - -
- ); - }) || '-'} +
+ {data?.address} + { + handleCopy(); + }} + > + + +
), @@ -158,20 +141,18 @@ const AddressBook = ({ stringId: 'ADDRESS_BOOK.DATE_ADDED', label: STRINGS['ADDRESS_BOOK.DATE_ADDED'], key: 'date added', - renderCell: (data, key) => { - let formatDate = ''; - if (data?.created_at) { - const date = new Date(data.created_at); - if (!isNaN(date)) { - formatDate = date.toISOString().slice(0, 10).replace(/-/g, '/'); - } - } - return ( - -
{formatDate}
- - ); - }, + renderCell: (data, key) => ( + +
+ {data?.created_at + ? new Date(data.created_at) + .toISOString() + .slice(0, 10) + .replace(/-/g, '/') + : '-'} +
+ + ), }, { stringId: 'ADDRESS_BOOK.REMOVE', @@ -182,7 +163,7 @@ const AddressBook = ({
onHandleRemove()} + onClick={() => onHandleAddressBookDetails(data, 'revoke')} > {STRINGS['ADDRESS_BOOK.REMOVE']} @@ -195,17 +176,21 @@ const AddressBook = ({ ]; const coinLength = - coins[selectedAsset]?.network && coins[selectedAsset]?.network.split(','); + coins[selectedAsset?.selectedCurrency]?.network && + coins[selectedAsset?.selectedCurrency]?.network?.split(','); let network = - coins[selectedAsset]?.network && coins[selectedAsset]?.network !== 'other' - ? coins[selectedAsset]?.network - : coins[selectedAsset]?.symbol; + coins[selectedAsset?.selectedCurrency]?.network && + coins[selectedAsset?.selectedCurrency]?.network !== 'other' + ? coins[selectedAsset?.selectedCurrency]?.network + : coins[selectedAsset?.selectedCurrency]?.symbol; const networkIcon = coins[network]?.icon_id; useEffect(() => { const getAddress = async () => { + setIsLoading(false); const res = await getAddressBookDetails(); - setGetUserData(res); + setIsLoading(true); + setGetUserData(res?.addresses); }; getAddress(); }, []); @@ -222,12 +207,13 @@ const AddressBook = ({ }); }; - const onHandleRemove = () => {}; - const onHandleClose = (currStep) => { setRenderPopUps((prev) => ({ ...prev, [currStep]: false })); - setSelectedAsset(null); - setNetworkOptions(null); + setSelectedAsset((prev) => ({ + ...prev, + selectedCurrency: null, + networkOptions: null, + })); setIsValidAddress(null); setUserLabel(''); }; @@ -236,8 +222,11 @@ const AddressBook = ({ setRenderPopUps((prev) => ({ ...prev, [previousStep]: false })); setRenderPopUps((prev) => ({ ...prev, [nextStep]: true })); if (previousStep === 'step2' && nextStep === 'step1') { - setSelectedAsset(null); - setNetworkOptions(null); + setSelectedAsset((prev) => ({ + ...prev, + selectedCurrency: null, + networkOptions: null, + })); setIsValidAddress(null); } if (previousStep === 'step3' && nextStep === 'step2') { @@ -245,25 +234,63 @@ const AddressBook = ({ } }; - const onHandleConfirm = async () => { - try { - const selectedNetwork = networkOptions - ? renderNetworkField(networkOptions) - : network; + const onHandleAddressBookDetails = async (data, type) => { + const selectedNetwork = selectedAsset?.networkOptions + ? renderNetworkField(selectedAsset?.networkOptions) + : network; + const hasAsset = getUserData.some( + (val) => + val?.currency === selectedAsset?.selectedCurrency && + val?.network === selectedNetwork + ); + + const filterData = () => + getUserData.filter((val) => val.label !== data.label); + const removeCreatedAt = (arr) => arr.map(({ created_at, ...rest }) => rest); + + if (type === 'revoke') { + const filteredData = filterData(); + const restFilteredData = removeCreatedAt(filteredData); + setGetUserData(filteredData); + + try { + await setUserLabelAndAddress({ addresses: restFilteredData }); + } catch (error) { + console.error(error); + } + } else if (!hasAsset) { const currValue = { - addresses: [ - { - label: userLabel, - address: isValidAddress, - network: selectedNetwork, - }, - ], + label: userLabel, + address: selectedAsset?.address, + network: selectedNetwork, + currency: selectedAsset?.selectedCurrency, }; - const userDetails = { addresses: [getUserData, currValue] }; - await setUserLabelAndAddress(userDetails); - } catch (error) { - console.error(error); + const restGetUserData = removeCreatedAt(getUserData); + setGetUserData([ + ...getUserData, + { ...currValue, created_at: new Date().toISOString() }, + ]); + + try { + await setUserLabelAndAddress({ + addresses: [...restGetUserData, currValue], + }); + } catch (error) { + console.error(error); + } + } else { + message.error(STRINGS['ADDRESS_BOOK.ASSET_ALREADY_HAVE_ADDRESS']); } + + onHandleClose('step3'); + }; + + const onHandleUserLabel = () => { + const isValidLabel = getUserData.filter((data) => userLabel === data.label); + return ( + (isValidLabel && isValidLabel.length) || + !/^(?=.*[a-zA-Z])[a-zA-Z0-9]{3,15}$/.test(userLabel) + ); }; return ( @@ -301,8 +328,6 @@ const AddressBook = ({ setTopAssets={setTopAssets} selectedAsset={selectedAsset} setSelectedAsset={setSelectedAsset} - networkoptions={networkOptions} - setNetworkOptions={setNetworkOptions} assets={assets} pinnedAssets={pinnedAssets} coins={coins} @@ -373,10 +398,13 @@ const AddressBook = ({
- + {`${ - coins[selectedAsset].fullname - } (${selectedAsset.toUpperCase()})`} + coins[selectedAsset?.selectedCurrency]?.fullname + } (${selectedAsset?.selectedCurrency?.toUpperCase()})`}
@@ -392,9 +420,9 @@ const AddressBook = ({ renderNetworkWithLabel(networkIcon, network) ) : coinLength?.length > 1 ? (
- {networkOptions} + {selectedAsset?.networkOptions} {networkList.map((data) => - data.network === networkOptions ? ( + data.network === selectedAsset?.networkOptions ? ( ) : null )} @@ -414,7 +442,7 @@ const AddressBook = ({
- {isValidAddress} + {selectedAsset?.address}
@@ -427,9 +455,7 @@ const AddressBook = ({ onHandlePopUpBtn('step2', 'step3')} />
@@ -475,10 +501,13 @@ const AddressBook = ({
- + {`${ - coins[selectedAsset].fullname - } (${selectedAsset.toUpperCase()})`} + coins[selectedAsset?.selectedCurrency]?.fullname + } (${selectedAsset?.selectedCurrency?.toUpperCase()})`}
@@ -494,9 +523,9 @@ const AddressBook = ({ renderNetworkWithLabel(networkIcon, network) ) : coinLength?.length > 1 ? (
- {networkOptions} + {selectedAsset?.networkOptions} {networkList.map((data) => - data.network === networkOptions ? ( + data.network === selectedAsset?.networkOptions ? ( ) : null )} @@ -517,7 +546,7 @@ const AddressBook = ({
- {isValidAddress} + {selectedAsset?.address}
@@ -539,7 +568,7 @@ const AddressBook = ({
- {getUserData === 0 && ( -
-
- {'text'} -
-
- - {STRINGS['ADDRESS_BOOK.NO_LINK']} - -
-
- setRenderPopUps((prev) => ({ ...prev, step1: true })) - } - > - - {STRINGS['ADDRESS_BOOK.ADD_WITHDRAW_ADDRESS']} - -
+ {isLoading ? ( + + } + /> + ) : ( +
+
)} -
diff --git a/web/src/containers/Wallet/GenerateAddress.js b/web/src/containers/Wallet/GenerateAddress.js index 652e6005f7..5802eb4407 100644 --- a/web/src/containers/Wallet/GenerateAddress.js +++ b/web/src/containers/Wallet/GenerateAddress.js @@ -24,10 +24,8 @@ import { FORM_NAME } from 'containers/Withdraw/form'; const GenerateAddress = ({ topAssets, selectedAsset, - networkoptions, setTopAssets, setSelectedAsset, - setNetworkOptions, assets, pinnedAssets, coins, @@ -43,18 +41,22 @@ const GenerateAddress = ({ const { Option } = Select; const displayAssets = - selectedAsset && - `${coins[selectedAsset].fullname} (${selectedAsset.toUpperCase()})`; + selectedAsset?.selectedCurrency && + `${ + coins[selectedAsset?.selectedCurrency].fullname + } (${selectedAsset?.selectedCurrency.toUpperCase()})`; const displayNetwork = coinLength?.length === 1 ? renderNetworkWithLabel(networkIcon, network) : coinLength?.length > 1 - ? networkoptions + ? selectedAsset?.networkOptions : network?.toUpperCase(); const currentNetwork = - coinLength?.length === 1 ? network : renderNetworkField(networkoptions); + coinLength?.length === 1 + ? network + : renderNetworkField(selectedAsset?.networkOptions); useEffect(() => { const topWallet = assets @@ -85,13 +87,22 @@ const GenerateAddress = ({ }; const onHandleChangeSelect = (symbol) => { - setSelectedAsset(symbol); setIsValidAddress(null); + setSelectedAsset((prev) => ({ + ...prev, + selectedCurrency: symbol, + networkOptions: null, + address: null, + })); }; const onHandleChangeNetwork = (symbol) => { - setNetworkOptions(symbol); setIsValidAddress(null); + setSelectedAsset((prev) => ({ + ...prev, + networkOptions: symbol, + address: '', + })); }; const onHandleScan = () => { @@ -104,14 +115,18 @@ const GenerateAddress = ({ const onHandleAddress = (val) => { const isValid = validAddress( - selectedAsset, - STRINGS[`WITHDRAWALS_${selectedAsset?.toUpperCase()}_INVALID_ADDRESS`], + selectedAsset?.selectedCurrency, + STRINGS[ + `WITHDRAWALS_${selectedAsset?.selectedCurrency?.toUpperCase()}_INVALID_ADDRESS` + ], currentNetwork, val )(); + setSelectedAsset((prev) => ({ ...prev, address: val })); if (!isValid) { - setIsValidAddress(val); - } else { + setIsValidAddress(true); + } + if (isValid) { setIsValidAddress(false); } }; @@ -141,7 +156,9 @@ const GenerateAddress = ({ onHandleChangeSelect(data)} > @@ -173,7 +190,12 @@ const GenerateAddress = ({ } } }} - onClear={() => setSelectedAsset(null)} + onClear={() => + setSelectedAsset((prev) => ({ + ...prev, + selectedCurrency: null, + })) + } > {Object.entries(coins).map( ([_, { symbol, fullname, icon_id }]) => ( @@ -192,7 +214,7 @@ const GenerateAddress = ({ ) )} - {selectedAsset ? ( + {selectedAsset?.selectedCurrency ? ( ) : ( @@ -203,7 +225,9 @@ const GenerateAddress = ({
@@ -217,7 +241,7 @@ const GenerateAddress = ({
- {selectedAsset && ( + {selectedAsset?.selectedCurrency && (
{currStep.stepTwo && }
- {selectedMethod === strings['FORM_FIELDS.EMAIL_LABEL'] && ( + {selectedMethod === STRINGS['FORM_FIELDS.EMAIL_LABEL'] && (
{renderLabel('WITHDRAWALS_FORM_MAIL_INFO')}
@@ -644,7 +736,7 @@ const RenderWithdraw = ({ } - placeholder={strings['WITHDRAW_PAGE.SELECT']} + placeholder={STRINGS['WITHDRAW_PAGE.SELECT']} allowClear={true} value={ - selectedAsset && + selectedAsset?.selectedCurrency && `${ - coins[selectedAsset].fullname - } (${selectedAsset.toUpperCase()})` + coins[selectedAsset?.selectedCurrency].fullname + } (${selectedAsset?.selectedCurrency.toUpperCase()})` } onClear={() => onHandleClear('coin')} onKeyDown={(e) => { @@ -703,14 +795,14 @@ const RenderWithdraw = ({ ) )} - {selectedMethod === strings['FORM_FIELDS.EMAIL_LABEL'] ? ( + {selectedMethod === STRINGS['FORM_FIELDS.EMAIL_LABEL'] ? ( isEmailAndAddress && renderNetwork ? ( ) : ( ) ) : currStep.stepThree || - (selectedAsset && selectedMethod) ? ( + (selectedAsset?.selectedCurrency && selectedMethod) ? ( ) : ( @@ -722,20 +814,23 @@ const RenderWithdraw = ({
- {selectedMethod !== strings['FORM_FIELDS.EMAIL_LABEL'] && ( + {selectedMethod !== STRINGS['FORM_FIELDS.EMAIL_LABEL'] && (
3
{renderLabel('ACCORDIAN.SELECT_NETWORK')}
- {(currStep.stepThree || (selectedAsset && selectedMethod)) && ( + {(currStep.stepThree || + (selectedAsset?.selectedCurrency && selectedMethod)) && (
- {selectedMethod !== strings['FORM_FIELDS.EMAIL_LABEL'] && + {selectedMethod !== STRINGS['FORM_FIELDS.EMAIL_LABEL'] && isEmailAndAddress && renderNetwork ? ( @@ -870,7 +967,7 @@ const RenderWithdraw = ({ className={`${ ['xrp', 'xlm', 'ton', 'pmn'].includes(getWithdrawCurrency) && selectedMethod && - selectedMethod !== strings['FORM_FIELDS.EMAIL_LABEL'] && + selectedMethod !== STRINGS['FORM_FIELDS.EMAIL_LABEL'] && 'destination-field' } ${isMobile && isMobile && 'destination-field-mobile'}`} > @@ -879,14 +976,14 @@ const RenderWithdraw = ({ className={`custom-field d-flex flex-column align-items-center ${ ['xrp', 'xlm', 'ton', 'pmn'].includes(getWithdrawCurrency) && selectedMethod && - selectedMethod !== strings['FORM_FIELDS.EMAIL_LABEL'] && + selectedMethod !== STRINGS['FORM_FIELDS.EMAIL_LABEL'] && 'destination-field' } ${isMobile && isMobile && 'destination-field-mobile'}`} > - {selectedMethod === strings['FORM_FIELDS.EMAIL_LABEL'] ? 3 : 4} + {selectedMethod === STRINGS['FORM_FIELDS.EMAIL_LABEL'] ? 3 : 4} {renderLabel( selectedMethod === - strings['WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS'] || + STRINGS['WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS'] || selectedMethod === 'Address' ? 'ACCORDIAN.DESTINATION' : 'FORM_FIELDS.EMAIL_LABEL' @@ -924,25 +1021,75 @@ const RenderWithdraw = ({ } > {selectedMethod === - strings['WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS'] || + STRINGS['WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS'] || selectedMethod === 'Address' ? (
- - onHandleAddress(e.target.value, 'address') - } - value={getWithdrawAddress} - placeholder={strings['WITHDRAW_PAGE.WITHDRAW_ADDRESS']} - suffix={renderScanIcon(onHandleScan)} - > -
- - - {STRINGS['ADDRESS_BOOK.MANAGE_ADDRESS_BOOK']} - - -
+ {getAddress && getAddress?.length === 0 && ( + + onHandleAddress(e.target.value, 'address') + } + value={getWithdrawAddress} + placeholder={ + STRINGS['WITHDRAW_PAGE.WITHDRAW_ADDRESS'] + } + suffix={renderScanIcon(onHandleScan)} + > + )} + {getAddress && getAddress?.length > 0 && ( + + )} + {selectedAsset.addressField === 'New Address' && ( +
+ + onHandleAddress(e.target.value, 'address') + } + value={getWithdrawAddress} + placeholder={ + STRINGS['WITHDRAW_PAGE.WITHDRAW_ADDRESS'] + } + suffix={renderScanIcon(onHandleScan)} + > +
+ )} + {!selectedAsset.addressField && + !selectedAsset.addressField && ( +
+ + + {STRINGS['ADDRESS_BOOK.MANAGE_ADDRESS_BOOK']} + + +
+ )}
) : ( onHandleAddress(e.target.value, 'email')} value={receiverWithdrawalEmail} placeholder={ - strings['WITHDRAW_PAGE.WITHDRAW_EMAIL_ADDRESS'] + STRINGS['WITHDRAW_PAGE.WITHDRAW_EMAIL_ADDRESS'] } > )} - {selectedMethod === strings['FORM_FIELDS.EMAIL_LABEL'] ? ( - isValidEmail ? ( + {selectedMethod === STRINGS['FORM_FIELDS.EMAIL_LABEL'] ? ( + isValidField?.isValidEmail ? ( ) : ( @@ -1052,7 +1199,7 @@ const RenderWithdraw = ({
)} {/* setIsWarning(false)} footer={false} @@ -1062,7 +1209,7 @@ const RenderWithdraw = ({ {renderWithdrawWarningPopup()} setIsVisible(false)} footer={false} @@ -1078,7 +1225,7 @@ const RenderWithdraw = ({ > {isCondition ? 6 - : selectedMethod === strings['FORM_FIELDS.EMAIL_LABEL'] + : selectedMethod === STRINGS['FORM_FIELDS.EMAIL_LABEL'] ? 4 : 5}
@@ -1132,7 +1279,7 @@ const RenderWithdraw = ({ } suffix={renderAmountIcon()} type="number" - placeholder={strings['WITHDRAW_PAGE.ENTER_AMOUNT']} + placeholder={STRINGS['WITHDRAW_PAGE.ENTER_AMOUNT']} > {!isAmount ? ( diff --git a/web/src/containers/Withdraw/_Withdraw.scss b/web/src/containers/Withdraw/_Withdraw.scss index bb07d26d5f..126d94be7a 100644 --- a/web/src/containers/Withdraw/_Withdraw.scss +++ b/web/src/containers/Withdraw/_Withdraw.scss @@ -146,9 +146,11 @@ $content--margin: 2rem; padding: 1% 1%; } - .destination-input-address-field { + .destination-input-address-field, + .destination-select-field { width: 100% !important; } + .destination-input-field { width: 80%; height: 38px; @@ -247,25 +249,34 @@ $content--margin: 2rem; .amount-field-icon { margin-top: 1%; } + .destination-field-wrapper { display: flex; flex-direction: column; width: 65%; + .select-wrapper { width: 100%; + .destination-input-wrapper { width: 80%; display: flex; flex-direction: column; - gap: 5px; + gap: 10px; + + .custom-select-input-style .ant-select-selection-item { + text-transform: unset; + } } } + .address-link { .edit-wrapper__container { text-decoration: underline !important; } } } + .select-wrapper { display: flex; flex-direction: column; @@ -366,6 +377,7 @@ $content--margin: 2rem; width: 5rem; text-align: center; cursor: pointer; + .pinned-asset-icon { padding-top: 3%; } @@ -395,7 +407,7 @@ $content--margin: 2rem; } .destination-field { - height: 60px; + height: 80px; } .destination-field-mobile { @@ -515,6 +527,7 @@ $content--margin: 2rem; .warning-popup-wrapper { .button-wrapper { margin-top: 5%; + Button { width: 100%; } @@ -624,17 +637,21 @@ $content--margin: 2rem; .withdrawal-container { padding-top: 0px !important; + .withdraw-form-wrapper { .withdraw-form { margin: 0 0 30px; + .destination-field { height: 75px; } + .destination-field-wrapper { width: 100%; } + .destination-field-mobile { - height: 12rem; + height: 15rem; } .field-wrapper { @@ -672,7 +689,7 @@ $content--margin: 2rem; } .custom-line-selected-mobile { - height: 10rem; + height: 13rem; } } @@ -720,6 +737,7 @@ $content--margin: 2rem; .withdraw-icon { margin-top: 0px !important; } + .information_block { .information_block-text_wrapper { .title { @@ -738,6 +756,7 @@ $content--margin: 2rem; .withdraw-form-wrapper { .withdraw-form { margin: 0 0 20px; + .select-wrapper { margin-left: 7%; } @@ -818,3 +837,7 @@ $content--margin: 2rem; width: 25rem; margin: 2rem; } + +.withdraw-dropdown-address { + border-bottom: 1px solid $colors-black !important; +} diff --git a/web/src/index.css b/web/src/index.css index 4303d1596b..e8eadcf6f8 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -2339,7 +2339,8 @@ table th { .withdrawal-container .withdraw-form-wrapper .withdraw-form .withdraw-deposit-content { font-size: 14px; padding: 1% 1%; } - .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-input-address-field { + .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-input-address-field, + .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-select-field { width: 100% !important; } .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-input-field { width: 80%; @@ -2412,7 +2413,9 @@ table th { width: 80%; display: flex; flex-direction: column; - gap: 5px; } + gap: 10px; } + .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-field-wrapper .select-wrapper .destination-input-wrapper .custom-select-input-style .ant-select-selection-item { + text-transform: unset; } .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-field-wrapper .address-link .edit-wrapper__container { text-decoration: underline !important; } .withdrawal-container .withdraw-form-wrapper .withdraw-form .select-wrapper { @@ -2487,7 +2490,7 @@ table th { .withdrawal-container .withdraw-form-wrapper .withdraw-form .render-scan-wrapper .img-wrapper img { height: 1rem; } .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-field { - height: 60px; } + height: 80px; } .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-field-mobile { height: 6rem; } .withdrawal-container .withdraw-form-wrapper .bottom-content { @@ -2633,7 +2636,7 @@ table th { .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-field-wrapper { width: 100%; } .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .destination-field-mobile { - height: 12rem; } + height: 15rem; } .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .field-wrapper .field-label-wrapper { flex-direction: column; } .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .withdraw-main-label-selected { @@ -2650,7 +2653,7 @@ table th { .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .custom-field .custom-line-network-selected { height: 15rem; } .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .custom-field .custom-line-selected-mobile { - height: 10rem; } + height: 13rem; } .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .mobile-view { margin-top: 5%; } .layout-mobile .withdrawal-container .withdraw-form-wrapper .withdraw-form .ant-select-clear svg { @@ -2719,6 +2722,9 @@ table th { width: 25rem; margin: 2rem; } +.withdraw-dropdown-address { + border-bottom: 1px solid var(--labels_secondary-inactive-label-text-graphics) !important; } + .extra_information-wrapper { margin-top: 1rem; padding: 0.5rem; @@ -7974,14 +7980,37 @@ table th { .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper th { padding: 1%; width: 0%; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper td .edit-wrapper__container, + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper td .link-content, + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper td .edit-wrapper__container div, + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper th .edit-wrapper__container, + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper th .link-content, + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper th .edit-wrapper__container div { + width: 100%; } .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper th { padding-bottom: 0; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper th:last-child .edit-wrapper__container div, + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper td:last-child .edit-wrapper__container div { + text-align: end; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper th:not(:last-child) .edit-wrapper__container { + justify-content: flex-start !important; } .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_header-wrapper { border-bottom: 2px solid var(--calculated_secondary-border); } .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row td div { display: flex; gap: 5px; justify-content: flex-start !important; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row td:last-child div { + justify-content: flex-end !important; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row .network-field { + width: 40%; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row .address-field-wrapper .address-content { + width: 85%; + justify-content: space-between !important; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row .address-field-wrapper .address-content span { + width: 20rem; + overflow: hidden; + text-overflow: ellipsis; } .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row .remove-btn, .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row .copy-btn:hover { cursor: pointer; } @@ -8001,7 +8030,19 @@ table th { display: flex; flex-direction: column; align-items: center; - justify-content: center; } + justify-content: flex-start; + gap: 3px; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .empty-content-display .no-link-icon .form_currency-ball { + margin-bottom: 0; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .empty-content-display .no-link-icon .form_currency-ball div { + display: flex; + align-items: center; + justify-content: center; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .empty-content-display .no-link-icon .form_currency-ball div svg { + width: 12% !important; + height: 0% !important; + color: var(--labels_secondary-inactive-label-text-graphics) !important; + opacity: 0.1; } .address-book-wrapper { width: 80%; @@ -8584,6 +8625,12 @@ table th { .layout-mobile .address-book-popup-wrapper { width: 100% !important; } +@media screen and (min-width: 1920px) { + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row .network-field { + width: 30%; } + .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row .address-field-wrapper .address-content span { + width: 80%; } } + .sidebar-row { min-height: 3rem; min-width: 10rem; } From 858613980af0df66881a7d4cbb1feacf07c4441c Mon Sep 17 00:00:00 2001 From: fetok12 Date: Wed, 24 Jul 2024 01:00:18 +0300 Subject: [PATCH 048/108] logic refinements --- server/api/controllers/admin.js | 95 ++++++++- server/api/controllers/user.js | 5 +- server/api/swagger/admin.yaml | 210 ++++++++++++++++++- server/utils/hollaex-tools-lib/tools/user.js | 6 +- 4 files changed, 310 insertions(+), 6 deletions(-) diff --git a/server/api/controllers/admin.js b/server/api/controllers/admin.js index c19e14eb56..568fc1267a 100644 --- a/server/api/controllers/admin.js +++ b/server/api/controllers/admin.js @@ -3001,6 +3001,95 @@ const createUserReferralCodeByAdmin = (req, res) => { }); }; + +const getPaymentDetailsByAdmin = (req, res) => { + loggerAdmin.verbose(req.uuid, 'controllers/admin/getPaymentDetailsByAdmin/auth', req.auth); + + const { user_id, is_p2p, is_fiat_control, status, limit, page, order_by, order, start_date, end_date } = req.swagger.params; + + toolsLib.user.getPaymentDetails(user_id.value, + { + limit: limit.value, + page: page.value, + order_by: order_by.value, + order: order.value, + start_date: start_date.value, + end_date: end_date.value, + is_p2p: is_p2p.value, + is_fiat_control: is_fiat_control.value, + status: status.value, + }) + .then((data) => { + return res.json(data); + }) + .catch((err) => { + loggerAdmin.error(req.uuid, 'controllers/admin/getPaymentDetailsByAdmin', err.message); + return res.status(err.statusCode || 400).json({ message: errorMessageConverter(err) }); + }); +}; + +const createPaymentDetailByAdmin = (req, res) => { + loggerAdmin.verbose(req.uuid, 'controllers/admin/createPaymentDetailByAdmin/auth', req.auth); + + const { user_id, name, label, details, is_p2p, is_fiat_control, status } = req.swagger.params.data.value; + + toolsLib.user.createPaymentDetail({ + user_id, + name, + label, + details, + is_p2p, + is_fiat_control, + status + }) + .then((data) => { + return res.json(data); + }) + .catch((err) => { + loggerAdmin.error(req.uuid, 'controllers/admin/createPaymentDetailByAdmin', err.message); + return res.status(err.statusCode || 400).json({ message: errorMessageConverter(err) }); + }); +}; + +const updatePaymentDetailByAdmin = (req, res) => { + loggerAdmin.verbose(req.uuid, 'controllers/admin/updatePaymentDetailByAdmin/auth', req.auth); + + const { user_id, id, name, label, details, is_p2p, is_fiat_control } = req.swagger.params.data.value; + + toolsLib.user.updatePaymentDetail(id, { + user_id, + name, + label, + details, + is_p2p, + is_fiat_control + }) + .then((data) => { + return res.json(data); + }) + .catch((err) => { + loggerAdmin.error(req.uuid, 'controllers/admin/updatePaymentDetailByAdmin', err.message); + return res.status(err.statusCode || 400).json({ message: errorMessageConverter(err) }); + }); +}; + +const deletePaymentDetailByAdmin = (req, res) => { + loggerAdmin.verbose(req.uuid, 'controllers/admin/deletePaymentDetailByAdmin/auth', req.auth); + + const { id, user_id } = req.swagger.params.data.value; + + toolsLib.user.deletePaymentDetail(id, user_id) + .then(() => { + return res.json({ + message: "Success" + }); + }) + .catch((err) => { + loggerAdmin.error(req.uuid, 'controllers/admin/deletePaymentDetailByAdmin', err.message); + return res.status(err.statusCode || 400).json({ message: errorMessageConverter(err) }); + }); +}; + module.exports = { createInitialAdmin, getAdminKit, @@ -3074,5 +3163,9 @@ module.exports = { disableUserWithdrawal, performDirectWithdrawalByAdmin, getUserReferralCodesByAdmin, - createUserReferralCodeByAdmin + createUserReferralCodeByAdmin, + getPaymentDetailsByAdmin, + createPaymentDetailByAdmin, + updatePaymentDetailByAdmin, + deletePaymentDetailByAdmin }; diff --git a/server/api/controllers/user.js b/server/api/controllers/user.js index a8fdf8b3a6..c4fb4eb459 100644 --- a/server/api/controllers/user.js +++ b/server/api/controllers/user.js @@ -1561,9 +1561,11 @@ const createPaymentDetail = (req, res) => { const updatePaymentDetail = (req, res) => { loggerUser.verbose(req.uuid, 'controllers/user/updatePaymentDetail/auth', req.auth); + const user_id = req.auth.sub.id; const { id, name, label, details, is_p2p, is_fiat_control } = req.swagger.params.data.value; toolsLib.user.updatePaymentDetail(id, { + user_id, name, label, details, @@ -1582,9 +1584,10 @@ const updatePaymentDetail = (req, res) => { const deletePaymentDetail = (req, res) => { loggerUser.verbose(req.uuid, 'controllers/user/deletePaymentDetail/auth', req.auth); + const user_id = req.auth.sub.id; const { id } = req.swagger.params.data.value; - toolsLib.user.deletePaymentDetail(id) + toolsLib.user.deletePaymentDetail(id, user_id) .then(() => { return res.json({ message: "Success" diff --git a/server/api/swagger/admin.yaml b/server/api/swagger/admin.yaml index d4352cff84..fd46a66486 100644 --- a/server/api/swagger/admin.yaml +++ b/server/api/swagger/admin.yaml @@ -4219,4 +4219,212 @@ paths: x-security-scopes: - admin x-token-permissions: - - can_withdraw \ No newline at end of file + - can_withdraw + /admin/user/payment-details: + x-swagger-router-controller: admin + get: + description: Get payment details by admin + operationId: getPaymentDetailsByAdmin + tags: + - PaymentDetails + parameters: + - in: query + name: user_id + description: Unique identifier of user + required: false + type: number + format: int32 + - in: query + name: id + description: Unique identifier + required: false + type: number + format: int32 + - in: query + name: is_p2p + description: is_p2p + required: false + type: boolean + - in: query + name: is_fiat_control + description: is_fiat_control + required: false + type: boolean + - in: query + name: status + description: status + required: false + type: boolean + - in: query + name: limit + description: "Number of elements to return. Default: 50. Maximun: 100" + required: false + type: number + format: int32 + - in: query + name: page + description: Page of data to retrieve + required: false + type: number + format: int32 + - in: query + name: order_by + description: Field to order data + required: false + type: string + - in: query + name: order + description: direction to order + required: false + type: string + enum: ['asc', 'desc'] + - in: query + name: start_date + description: Starting date of queried data + required: false + type: string + format: date-time + - in: query + name: end_date + description: Ending date of queried data + required: false + type: string + format: date-time + responses: + 200: + description: Success + schema: + $ref: "#/definitions/ObjectResponse" + default: + description: Error + schema: + $ref: "#/definitions/MessageResponse" + security: + - Token: [] + x-security-types: + - bearer + - hmac + x-security-scopes: + - admin + post: + description: Create a new payment detail by admin + operationId: createPaymentDetailByAdmin + tags: + - PaymentDetails + parameters: + - name: data + in: body + required: true + schema: + type: object + properties: + user_id: + type: number + format: int32 + name: + type: string + label: + type: string + details: + type: object + is_p2p: + type: boolean + is_fiat_control: + type: boolean + status: + type: integer + format: int32 + responses: + 200: + description: Success + schema: + $ref: "#/definitions/ObjectResponse" + default: + description: Error + schema: + $ref: "#/definitions/MessageResponse" + security: + - Token: [] + x-security-types: + - bearer + - hmac + x-security-scopes: + - admin + put: + description: Update a payment detail by admin + operationId: updatePaymentDetailByAdmin + tags: + - PaymentDetails + parameters: + - name: data + in: body + required: true + schema: + type: object + properties: + user_id: + type: number + format: int32 + id: + type: integer + format: int32 + name: + type: string + label: + type: string + details: + type: object + is_p2p: + type: boolean + is_fiat_control: + type: boolean + status: + type: integer + format: int32 + responses: + 200: + description: Success + schema: + $ref: "#/definitions/ObjectResponse" + default: + description: Error + schema: + $ref: "#/definitions/MessageResponse" + security: + - Token: [] + x-security-types: + - bearer + - hmac + x-security-scopes: + - admin + delete: + description: Delete a payment detail + operationId: deletePaymentDetail + tags: + - PaymentDetails + parameters: + - name: data + in: body + required: true + schema: + type: object + properties: + id: + type: integer + format: int32 + responses: + 200: + description: Success + schema: + $ref: "#/definitions/ObjectResponse" + default: + description: Error + schema: + $ref: "#/definitions/MessageResponse" + security: + - Token: [] + x-security-types: + - bearer + - hmac + x-security-scopes: + - admin \ No newline at end of file diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index 868c1c106d..15142cce0e 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -3392,7 +3392,7 @@ const createPaymentDetail = async (data) => { }; const updatePaymentDetail = async (id, data) => { - const paymentDetail = await getModel('paymentDetail').findOne({ where: { id } }); + const paymentDetail = await getModel('paymentDetail').findOne({ where: { id, user_id: data.user_id } }); if (!paymentDetail) { throw new Error('Payment detail not found'); } @@ -3409,8 +3409,8 @@ const updatePaymentDetail = async (id, data) => { return paymentDetail; }; -const deletePaymentDetail = async (id) => { - const paymentDetail = await getModel('paymentDetail').findOne({ where: { id } }); +const deletePaymentDetail = async (id, user_id) => { + const paymentDetail = await getModel('paymentDetail').findOne({ where: { id, user_id } }); if (!paymentDetail) { throw new Error('Payment detail not found'); } From 7a55072c7dec1fa5b56b92b0ed49a9150ddac20b Mon Sep 17 00:00:00 2001 From: fetok12 Date: Wed, 24 Jul 2024 02:10:34 +0300 Subject: [PATCH 049/108] admin-flow --- server/api/controllers/admin.js | 7 +- server/api/swagger/admin.yaml | 5 +- server/api/swagger/user.yaml | 6 +- server/utils/hollaex-tools-lib/tools/user.js | 7 +- web/src/config/lang/en.json | 5 +- .../containers/Admin/User/PaymentMethods.js | 497 ++++++++++++++++++ web/src/containers/Admin/User/UserContent.js | 6 + web/src/containers/Admin/User/actions.js | 33 ++ web/src/containers/P2P/P2PDash.js | 2 +- web/src/containers/P2P/P2PProfile.js | 35 +- 10 files changed, 588 insertions(+), 15 deletions(-) create mode 100644 web/src/containers/Admin/User/PaymentMethods.js diff --git a/server/api/controllers/admin.js b/server/api/controllers/admin.js index 568fc1267a..264dd57d43 100644 --- a/server/api/controllers/admin.js +++ b/server/api/controllers/admin.js @@ -3054,7 +3054,7 @@ const createPaymentDetailByAdmin = (req, res) => { const updatePaymentDetailByAdmin = (req, res) => { loggerAdmin.verbose(req.uuid, 'controllers/admin/updatePaymentDetailByAdmin/auth', req.auth); - const { user_id, id, name, label, details, is_p2p, is_fiat_control } = req.swagger.params.data.value; + const { user_id, id, name, label, details, is_p2p, is_fiat_control, status } = req.swagger.params.data.value; toolsLib.user.updatePaymentDetail(id, { user_id, @@ -3062,8 +3062,9 @@ const updatePaymentDetailByAdmin = (req, res) => { label, details, is_p2p, - is_fiat_control - }) + is_fiat_control, + status + }, true) .then((data) => { return res.json(data); }) diff --git a/server/api/swagger/admin.yaml b/server/api/swagger/admin.yaml index fd46a66486..6366b730c9 100644 --- a/server/api/swagger/admin.yaml +++ b/server/api/swagger/admin.yaml @@ -4399,7 +4399,7 @@ paths: - admin delete: description: Delete a payment detail - operationId: deletePaymentDetail + operationId: deletePaymentDetailByAdmin tags: - PaymentDetails parameters: @@ -4409,6 +4409,9 @@ paths: schema: type: object properties: + user_id: + type: integer + format: int32 id: type: integer format: int32 diff --git a/server/api/swagger/user.yaml b/server/api/swagger/user.yaml index f49510a44e..2e2d83b8fb 100644 --- a/server/api/swagger/user.yaml +++ b/server/api/swagger/user.yaml @@ -1841,7 +1841,8 @@ paths: name: status description: status required: false - type: boolean + type: number + format: int32 - in: query name: limit description: "Number of elements to return. Default: 50. Maximun: 100" @@ -1959,9 +1960,6 @@ paths: type: boolean is_fiat_control: type: boolean - status: - type: integer - format: int32 responses: 200: description: Success diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index 15142cce0e..3b7049f891 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -3391,19 +3391,22 @@ const createPaymentDetail = async (data) => { return paymentDetail; }; -const updatePaymentDetail = async (id, data) => { +const updatePaymentDetail = async (id, data, isAdmin = false) => { const paymentDetail = await getModel('paymentDetail').findOne({ where: { id, user_id: data.user_id } }); if (!paymentDetail) { throw new Error('Payment detail not found'); } + if (!isAdmin) { delete data.status }; + await paymentDetail.update(data, { fields: [ 'name', 'label', 'details', 'is_p2p', - 'is_fiat_control' + 'is_fiat_control', + 'status' ] }); return paymentDetail; diff --git a/web/src/config/lang/en.json b/web/src/config/lang/en.json index cb40118db1..d8d7fe5b48 100644 --- a/web/src/config/lang/en.json +++ b/web/src/config/lang/en.json @@ -2153,6 +2153,9 @@ "IMPORTANT_DETAIL": "(Important payment detail)", "DETAIL_OPTIONAL": "Optional", "OPTIONAL_DETAIL": "(Optional payment detail)", - "ADD_NEW_PAYMENT_FIELD": "Add new payment detail field" + "ADD_NEW_PAYMENT_FIELD": "Add new payment detail field", + "PAYMENT_METHOD_CREATED": "Payment method created! Waiting for verification by admin", + "PAYMENT_METHOD_DELETED": "Payment method deleted.", + "PAYMENT_METHOD_UPDATED": "Payment method updated." } } diff --git a/web/src/containers/Admin/User/PaymentMethods.js b/web/src/containers/Admin/User/PaymentMethods.js new file mode 100644 index 0000000000..11b5e2ad49 --- /dev/null +++ b/web/src/containers/Admin/User/PaymentMethods.js @@ -0,0 +1,497 @@ +import React, { useState, useEffect } from 'react'; +import { message, Table, Button, Spin, Modal, Select, Checkbox } from 'antd'; +import { + fetchP2PPaymentMethods, + deleteP2PPaymentMethod, + updateP2PPaymentMethod, +} from './actions'; +import { CloseOutlined } from '@ant-design/icons'; +import withConfig from 'components/ConfigProvider/withConfig'; +import { connect } from 'react-redux'; + +const PaymentMethods = ({ user }) => { + const [coinData, setCoinData] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [queryValues] = useState({ user_id: user.id }); + // eslint-disable-next-line + const [editMode, setEditMode] = useState(false); + const [selectedData, setSelectedData] = useState({}); + const [queryFilters, setQueryFilters] = useState({ + total: 0, + page: 1, + pageSize: 10, + limit: 50, + currentTablePage: 1, + isRemaining: true, + }); + + const [displayCostumizationModal, setDisplayCostumizationModal] = useState( + false + ); + + const [displayDeleteModal, setDisplayDeleteModal] = useState(false); + + const columns = [ + // { + // title: 'ID', + // dataIndex: 'id', + // key: 'id', + // render: (user_id, data) => { + // return ( + //
+ // + // {/*
{data.User.email}
*/} + //
+ // ); + // }, + // }, + { + title: 'User ID', + dataIndex: 'user_id', + key: 'user_id', + render: (user_id, data) => { + return ( +
+ +
+ ); + }, + }, + { + title: 'Name', + dataIndex: 'name', + key: 'name', + render: (user_id, data) => { + return
{data?.name}
; + }, + }, + { + title: 'Details', + dataIndex: 'details', + key: 'details', + render: (user_id, data) => { + return ( +
+
    + {data?.details?.fields.map((field) => ( +
  • + {field.name}: {field.value} +
  • + ))} +
+
+ ); + }, + }, + { + title: 'P2P', + dataIndex: 'is_p2p', + key: 'is_p2p', + render: (user_id, data) => { + return
{data?.is_p2p ? 'Yes' : 'No'}
; + }, + }, + { + title: 'Fiat Controls', + dataIndex: 'is_fiat_control', + key: 'is_fiat_control', + render: (user_id, data) => { + return ( +
{data?.is_fiat_control ? 'Yes' : 'No'}
+ ); + }, + }, + { + title: 'Status', + dataIndex: 'status', + key: 'status', + render: (user_id, data) => { + return ( +
+ {data?.status === 0 && 'Unverified'} + {data?.status === 3 && 'Verified'} +
+ ); + }, + }, + { + title: 'Edit', + dataIndex: 'edit', + key: 'edit', + render: (user_id, data) => { + return ( +
+ +
+ ); + }, + }, + { + title: 'Delete', + dataIndex: 'delete', + key: 'delete', + render: (user_id, data) => { + return ( +
+ +
+ ); + }, + }, + ]; + + useEffect(() => { + setIsLoading(true); + requesPaymentMethods(queryFilters.page, queryFilters.limit); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + requesPaymentMethods(queryFilters.page, queryFilters.limit); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [queryValues]); + + const requesPaymentMethods = (page = 1, limit = 50) => { + setIsLoading(true); + fetchP2PPaymentMethods({ page, limit, ...queryValues }) + .then((response) => { + setCoinData( + page === 1 ? response.data : [...coinData, ...response.data] + ); + + setQueryFilters({ + total: response.count, + fetched: true, + page, + currentTablePage: page === 1 ? 1 : queryFilters.currentTablePage, + isRemaining: response.count > page * limit, + }); + setIsLoading(false); + }) + .catch((error) => { + // const message = error.message; + setIsLoading(false); + }); + }; + + const pageChange = (count, pageSize) => { + const { page, limit, isRemaining } = queryFilters; + const pageCount = count % 5 === 0 ? 5 : count % 5; + const apiPageTemp = Math.floor(count / 5); + if (limit === pageSize * pageCount && apiPageTemp >= page && isRemaining) { + requesPaymentMethods(page + 1, limit); + } + setQueryFilters({ ...queryFilters, currentTablePage: count }); + }; + + const handleCostumizationModal = () => { + setDisplayCostumizationModal(false); + setSelectedData({}); + setEditMode(false); + }; + + return ( +
+
+ Below are details of payment methods belonging to this user +
+
+
+
+
+ +
+
+
+ Payment methods of the user +
+
+ {/*
+ + + +
*/} +
+
{ + return data.id; + }} + pagination={{ + current: queryFilters.currentTablePage, + onChange: pageChange, + }} + /> + + + + + {displayCostumizationModal && ( + } + bodyStyle={{ + backgroundColor: '#27339D', + }} + visible={displayCostumizationModal} + footer={null} + onCancel={() => { + handleCostumizationModal(); + }} + > +
+ Update User's payment method +
+
+
Features
+ +
+ { + setSelectedData({ + ...selectedData, + is_p2p: e.target.checked, + }); + }} + checked={selectedData?.is_p2p} + > + P2P Enabled + +
+
+ { + setSelectedData({ + ...selectedData, + is_fiat_control: e.target.checked, + }); + }} + checked={selectedData?.is_fiat_control} + > + Fiat Control Enabled + +
+
+
Status
+ +
+ +
+ + +
+
+ )} + + {displayDeleteModal && ( + } + bodyStyle={{ + backgroundColor: '#27339D', + }} + visible={displayDeleteModal} + footer={null} + onCancel={() => { + setDisplayDeleteModal(false); + }} + > +
+ Delete Payment Method +
+
+ Are you sure you want to delete this payment method? +
+ +
+ + +
+
+ )} + + + ); +}; + +const mapStateToProps = (state) => ({}); + +const mapDispatchToProps = (dispatch) => ({}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(withConfig(PaymentMethods)); diff --git a/web/src/containers/Admin/User/UserContent.js b/web/src/containers/Admin/User/UserContent.js index bb63495678..3db46b0b4b 100644 --- a/web/src/containers/Admin/User/UserContent.js +++ b/web/src/containers/Admin/User/UserContent.js @@ -33,6 +33,7 @@ import { requestTiers, } from './actions'; import UserMetaForm from './UserMetaForm'; +import PaymentMethods from './PaymentMethods'; // import Flagger from '../Flaguser'; // import Notes from './Notes'; @@ -376,6 +377,11 @@ class UserContent extends Component { /> + +
+ +
+
{!isSupportUser && !isKYC() && ( diff --git a/web/src/containers/Admin/User/actions.js b/web/src/containers/Admin/User/actions.js index 0a8dcacea2..3dee3d6e04 100644 --- a/web/src/containers/Admin/User/actions.js +++ b/web/src/containers/Admin/User/actions.js @@ -354,3 +354,36 @@ export const changeUserEmail = (values) => { return error; } }; + +export const fetchP2PPaymentMethods = (values) => { + const queryValues = + values && Object.keys(values).length ? querystring.stringify(values) : ''; + return requestAuthenticated(`/admin/user/payment-details?${queryValues}`); +}; + +export const createP2PPaymentMethod = (values) => { + const options = { + method: 'POST', + body: JSON.stringify(values), + }; + + return requestAuthenticated('/admin/user/payment-details', options); +}; + +export const deleteP2PPaymentMethod = (values) => { + const options = { + method: 'DELETE', + body: JSON.stringify(values), + }; + + return requestAuthenticated('/admin/user/payment-details', options); +}; + +export const updateP2PPaymentMethod = (values) => { + const options = { + method: 'PUT', + body: JSON.stringify(values), + }; + + return requestAuthenticated('/admin/user/payment-details', options); +}; diff --git a/web/src/containers/P2P/P2PDash.js b/web/src/containers/P2P/P2PDash.js index f5bf577249..6d69d82476 100644 --- a/web/src/containers/P2P/P2PDash.js +++ b/web/src/containers/P2P/P2PDash.js @@ -76,7 +76,7 @@ const P2PDash = ({ }) .catch((err) => err); - fetchP2PPaymentMethods({ is_p2p: true }) + fetchP2PPaymentMethods({ is_p2p: true, status: 3 }) .then((res) => { setMyMethods(res.data); }) diff --git a/web/src/containers/P2P/P2PProfile.js b/web/src/containers/P2P/P2PProfile.js index 5f080ea0f3..d177bb7a9a 100644 --- a/web/src/containers/P2P/P2PProfile.js +++ b/web/src/containers/P2P/P2PProfile.js @@ -311,6 +311,9 @@ const P2PProfile = ({ {myMethods ?.map((x) => x.details) .map((method) => { + const info = myMethods.find( + (x) => x?.details?.system_name === method?.system_name + ); return (
{ setMyMethods(res.data); @@ -392,6 +397,30 @@ const P2PProfile = ({
+
+ {info?.status === 0 && ( + + (Unverified) + + )} + {info?.status === 3 && ( + + (Verified) + + )} +
); })} @@ -606,7 +635,7 @@ const P2PProfile = ({ }) .catch((err) => err); - message.success('Payment method updated.'); + message.success(STRINGS['P2P.PAYMENT_METHOD_UPDATED']); setRefresh(!refresh); setAddMethodDetails(false); }} @@ -795,7 +824,7 @@ const P2PProfile = ({ is_p2p: true, }); - message.success('Payment method created!'); + message.success(STRINGS['P2P.PAYMENT_METHOD_CREATED']); fetchP2PPaymentMethods({ is_p2p: true }) .then((res) => { From 5c4e628e7040be8a907646294b76d49aedabadc9 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Wed, 24 Jul 2024 22:49:33 +0300 Subject: [PATCH 050/108] user-addressbook-created-at-fix --- server/utils/hollaex-tools-lib/tools/user.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index e0692d0534..8a0d1d8972 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -3294,6 +3294,8 @@ const fetchUserAddressBook = async (user_id) => { const updateUserAddresses = async (user_id, data) => { const { addresses } = data; + let userAddressBook = await getModel('userAddressBook').findOne({ where: { user_id } }); + addresses.forEach((addressObj) => { if (!addressObj.address || !addressObj.network || !addressObj.label || !addressObj.currency) { throw new Error(ADDRESSBOOK_MISSING_FIELDS); @@ -3305,8 +3307,11 @@ const updateUserAddresses = async (user_id, data) => { } }); - if (!addressObj.created_at) { + const hasCreatedAt = userAddressBook?.addresses?.find?.(address => address.label === addressObj.label)?.created_at; + if (!hasCreatedAt) { addressObj.created_at = moment().toISOString(); + } else { + addressObj.created_at = hasCreatedAt; } }); @@ -3323,7 +3328,6 @@ const updateUserAddresses = async (user_id, data) => { throw new Error(USER_NOT_FOUND); } - let userAddressBook = await getModel('userAddressBook').findOne({ where: { user_id } }); if (!userAddressBook) { userAddressBook = await getModel('userAddressBook').create({ user_id, From cb276e030f45da638171fb0c3189e9377b4cd6ee Mon Sep 17 00:00:00 2001 From: ram Date: Thu, 25 Jul 2024 18:52:57 +0530 Subject: [PATCH 051/108] Updated the Amount field rounding logic --- web/src/config/lang/en.json | 1 + web/src/containers/Withdraw/Withdraw.js | 92 +++++++++++++++++-------- 2 files changed, 64 insertions(+), 29 deletions(-) diff --git a/web/src/config/lang/en.json b/web/src/config/lang/en.json index 58a32d7d9b..19b788e6ae 100644 --- a/web/src/config/lang/en.json +++ b/web/src/config/lang/en.json @@ -1134,6 +1134,7 @@ "ENTER_AMOUNT": "Enter Amount", "REMOVE_TITLE": "Remove Tag", "MAX_AMOUNT_WARNING_INFO": "This amount exceeds your maximum withdrawal limit.", + "MIN_AMOUNT_WARNING_INFO": "The minimum withdrawal amount is {0}", "ZERO_BALANCE": "You do not have enough available balance.", "NEW_ADDRESS": "New Address" }, diff --git a/web/src/containers/Withdraw/Withdraw.js b/web/src/containers/Withdraw/Withdraw.js index a45d1c963b..f66a2fb874 100644 --- a/web/src/containers/Withdraw/Withdraw.js +++ b/web/src/containers/Withdraw/Withdraw.js @@ -5,6 +5,8 @@ import { isMobile } from 'react-device-detect'; import { Link } from 'react-router'; import { Button, Input, Select } from 'antd'; import BigNumber from 'bignumber.js'; +import math from 'mathjs'; + import { Coin, EditWrapper } from 'components'; import STRINGS from 'config/localizedStrings'; import { @@ -41,6 +43,8 @@ import { } from './utils'; import { email, validAddress } from 'components/Form/validations'; import { getAddressBookDetails } from 'containers/Wallet/actions'; +import { getDecimals } from 'utils/utils'; +import { roundNumber, toFixed } from 'utils/currency'; const RenderWithdraw = ({ coins, @@ -184,6 +188,15 @@ const RenderWithdraw = ({ }, [getWithdrawCurrency, UpdateCurrency, fee, setFee]); useEffect(() => { + const getAddress = async () => { + try { + const res = await getAddressBookDetails(); + setSelectedAddress([res]); + } catch (err) { + console.error(err); + } + }; + getAddress(); if (defaultCurrency) { setSelectedAsset((prev) => ({ ...prev, @@ -230,14 +243,6 @@ const RenderWithdraw = ({ } }, [getWithdrawCurrency, isWithdrawal]); - useEffect(() => { - const getAddress = async () => { - const res = await getAddressBookDetails(); - setSelectedAddress([res]); - }; - getAddress(); - }, []); - const isAmount = useMemo(() => { const isCondition = selectedMethod === STRINGS['FORM_FIELDS.EMAIL_LABEL'] @@ -355,6 +360,7 @@ const RenderWithdraw = ({ ...prev, selectedCurrency: val && coins[val] && coins[val].allow_withdrawal ? val : '', + addressField: null, })); setWithdrawAddress(''); setReceiverEmail(''); @@ -416,7 +422,24 @@ const RenderWithdraw = ({ const onHandleAmount = (val) => { if (val >= 0) { - setWithdrawAmount(val); + const curr = defaultCurrency + ? defaultCurrency + : selectedAsset?.selectedCurrency; + const { increment_unit, min } = coins[curr]; + let decimal = getDecimals(increment_unit); + let decValue = toFixed(val); + let valueDecimal = getDecimals(decValue); + let result = val; + if (decimal < valueDecimal) { + const newValue = decValue + .toString() + .substring(0, decValue.toString().length - (valueDecimal - decimal)); + result = roundNumber(val, 8); + if (math.larger(newValue, min)) { + result = parseFloat(newValue); + } + } + setWithdrawAmount(result); } }; @@ -595,7 +618,12 @@ const RenderWithdraw = ({ ((selectedMethod === STRINGS['WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS'] || (selectedMethod && selectedMethod === 'Address')) && isValidAddress); - const isErrorAmountField = getWithdrawAmount > maxAmount && maxAmount > 0; + const isErrorMaxAmountField = getWithdrawAmount > maxAmount && maxAmount > 0; + const minAmount = defaultCurrency + ? coins[defaultCurrency]?.min + : coins[selectedAsset && selectedAsset?.selectedCurrency]?.min; + const isErrorMinAmountField = + getWithdrawAmount && getWithdrawAmount < minAmount && minAmount > 0; const networkIcon = selectedNetwork ? coins[selectedNetwork]?.icon_id : coins[defaultNetwork]?.icon_id; @@ -762,21 +790,10 @@ const RenderWithdraw = ({ } (${selectedAsset?.selectedCurrency.toUpperCase()})` } onClear={() => onHandleClear('coin')} - onKeyDown={(e) => { - if (e.key === 'Enter') { - const highlightedOption = document.querySelector( - '.ant-select-item-option-active' - ); - if (highlightedOption) { - const value = highlightedOption - .querySelector('div') - .textContent.trim(); - const curr = onHandleSymbol(value); - onHandleChangeSelect(curr); - } - } + onSelect={(e) => { + const curr = onHandleSymbol(e); + onHandleChangeSelect(curr); }} - // onSelect={(e) => onHandleSelect(e)} > {Object.entries(coins).map( ([_, { symbol, fullname, icon_id }]) => ( @@ -1044,7 +1061,7 @@ const RenderWithdraw = ({ dropdownClassName="custom-select-style" suffixIcon={} allowClear={true} - value={selectedAsset.addressField} + value={selectedAsset?.addressField} onChange={onchangeAddressField} onClear={() => onHandleClear('address')} > @@ -1273,7 +1290,11 @@ const RenderWithdraw = ({ onChange={(e) => onHandleAmount(e.target.value)} value={getWithdrawAmount} className={ - isErrorAmountField + (isErrorMaxAmountField && isErrorMinAmountField) || + (maxAmount && + maxAmount && + isErrorMinAmountField && + isErrorMinAmountField) ? `destination-input-field field-error` : `destination-input-field` } @@ -1281,18 +1302,28 @@ const RenderWithdraw = ({ type="number" placeholder={STRINGS['WITHDRAW_PAGE.ENTER_AMOUNT']} > - {!isAmount ? ( + {!isAmount && !isErrorMinAmountField ? ( ) : ( )} - {isErrorAmountField && ( + {isErrorMaxAmountField && (
{renderLabel('WITHDRAW_PAGE.MAX_AMOUNT_WARNING_INFO')}
)} + {maxAmount && maxAmount && isErrorMinAmountField ? ( +
+ + {STRINGS.formatString( + STRINGS['WITHDRAW_PAGE.MIN_AMOUNT_WARNING_INFO'], + minAmount, + selectedAsset + )} +
+ ) : null} {!maxAmount && maxAmount === 0 && (
@@ -1345,7 +1376,10 @@ const RenderWithdraw = ({ )}
-
+
{selectedAsset?.address}
@@ -545,7 +549,7 @@ const AddressBook = ({ {STRINGS['WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS']}:
-
+
{selectedAsset?.address}
@@ -604,7 +608,13 @@ const AddressBook = ({ 'BLUE_QUESTION' )} -
+
diff --git a/web/src/containers/Wallet/GenerateAddress.js b/web/src/containers/Wallet/GenerateAddress.js index 5802eb4407..132fb70025 100644 --- a/web/src/containers/Wallet/GenerateAddress.js +++ b/web/src/containers/Wallet/GenerateAddress.js @@ -1,6 +1,7 @@ import React, { useEffect, useState } from 'react'; import { connect } from 'react-redux'; import { change } from 'redux-form'; +import { isMobile } from 'react-device-detect'; import { Input, Select } from 'antd'; import { CaretDownOutlined, @@ -79,7 +80,11 @@ const GenerateAddress = ({ return (
{data.toUpperCase()} - +
@@ -143,82 +148,84 @@ const GenerateAddress = ({
1
+
+
{STRINGS['ACCORDIAN.SELECT_ASSET']}
-
-
-
- {topAssets.map((data, inx) => { - return ( - onHandleChangeSelect(data)} - > - {renderPinnedAsset(data)} - - ); - })} -
-
- } + onKeyDown={(e) => { + if (e.key === 'Enter') { + const highlightedOption = document.querySelector( + '.ant-select-item-option-active' + ); + if (highlightedOption) { + const value = highlightedOption + .querySelector('div') + .textContent.trim(); + const curr = onHandleSymbol(value); + onHandleChangeSelect(curr); + } } + }} + onClear={() => + setSelectedAsset((prev) => ({ + ...prev, + selectedCurrency: null, + })) } - }} - onClear={() => - setSelectedAsset((prev) => ({ - ...prev, - selectedCurrency: null, - })) - } - > - {Object.entries(coins).map( - ([_, { symbol, fullname, icon_id }]) => ( - - ) +
onHandleChangeSelect(symbol)} + > + +
{`${fullname} (${symbol.toUpperCase()})`}
+
+ + ) + )} + + {selectedAsset?.selectedCurrency ? ( + + ) : ( + )} - - {selectedAsset?.selectedCurrency ? ( - - ) : ( - - )} +
@@ -234,15 +241,27 @@ const GenerateAddress = ({
2
-
+
+
+
{STRINGS['ACCORDIAN.SELECT_NETWORK']}
-
-
{selectedAsset?.selectedCurrency && ( -
+
onHandleAddress(e.target.value)} diff --git a/web/src/containers/Wallet/_AddressBook.scss b/web/src/containers/Wallet/_AddressBook.scss index 4e0dd44565..1481050dec 100644 --- a/web/src/containers/Wallet/_AddressBook.scss +++ b/web/src/containers/Wallet/_AddressBook.scss @@ -82,6 +82,7 @@ th { padding: 1%; width: 0%; + // font-size: 10px; .edit-wrapper__container, .link-content, @@ -124,7 +125,7 @@ } .network-field { - width: 40%; + width: 100%; } .address-field-wrapper { @@ -240,6 +241,18 @@ } } + .select-network-field { + .network-field { + .ant-select-arrow { + top: 20%; + } + + .ant-select-clear { + top: 17%; + } + } + } + .select-method-field, .select-network-field, .address-field { @@ -249,9 +262,17 @@ justify-content: space-between; gap: 15px; + .label-disable { + opacity: 0.5; + } + + .label-active { + opacity: 1; + } + .input-label-field, .input-label-field-disable { - width: 40%; + width: 10%; display: flex; gap: 10%; @@ -276,19 +297,33 @@ background-color: $colors-main-black; } } - - .label-content { - margin-top: 3%; - } } .input-label-field-disable { opacity: 0.5; } + .select-field { + width: 90%; + display: flex; + justify-content: space-between; + + .asset-input { + .selected-asset-btn { + width: 95%; + } + } + + .label-content { + margin-top: 1%; + } + } + .select-field, .network-field { - width: 60%; + .network-input { + width: 60%; + } .opacity-100 { opacity: 1; @@ -408,6 +443,11 @@ align-items: flex-start; gap: 5px; + .selected-asset-address { + overflow: hidden; + text-overflow: ellipsis; + } + .selected-asset, .selected-network { display: flex; @@ -415,6 +455,16 @@ gap: 5px; } } + + .confirm_name_detail { + padding: 3%; + border-bottom: 1px solid + var(--labels_secondary-inactive-label-text-graphics); + } + + .assets-content { + padding: 3%; + } } .confirm-title-text { @@ -440,22 +490,6 @@ width: 100% !important; } } - } - - .check-confirm-content-wrapper { - .selected-assets-content { - border: 1px solid var(--labels_secondary-inactive-label-text-graphics); - - .confirm_name_detail { - padding: 3%; - border-bottom: 1px solid - var(--labels_secondary-inactive-label-text-graphics); - } - - .assets-content { - padding: 3%; - } - } .warning-message-wrapper { margin: 3%; @@ -466,6 +500,12 @@ gap: 2px; } } + + .check-confirm-content-wrapper { + .selected-assets-content { + border: 1px solid var(--labels_secondary-inactive-label-text-graphics); + } + } } .add_withdrawal_address_wrapper { @@ -477,6 +517,174 @@ .layout-mobile { .address-book-popup-wrapper { width: 100% !important; + + .address-book-popup-wrapper, + .address-book-content { + .generate-address-form-wrapper { + .ant-select-clear { + width: 18px; + height: 18px; + } + + .select-network-field { + .network-field { + .ant-select-arrow { + top: 57%; + } + + .ant-select-clear { + top: 50%; + } + } + } + + .select-method-field, + .select-network-field, + .address-field { + display: flex; + + .input-label-field, + .input-label-field-disable { + .custom-field { + .select-step { + height: 3.4rem; + } + + .custom-line { + height: 12rem; + } + } + } + + .custom-select-input-style { + .ant-select-selector { + font-size: 10px !important; + height: 4.4rem !important; + } + + .ant-select-selection-item { + line-height: 3.5rem !important; + } + } + + .destination-input-field { + background-color: var(--base_background) !important; + color: $colors-main-black; + + .ant-input { + background-color: var(--base_background) !important; + } + + .destination-input-field:focus-within { + background-color: var(--base_background) !important; + } + } + + .select-field { + display: flex; + flex-direction: column; + justify-content: unset; + margin-bottom: 1%; + + .currency-label { + width: 22%; + } + + .network-input { + width: 100%; + } + } + + .input-label-field { + display: flex; + } + } + } + } + } + + .check-confirm-content-wrapper { + .warning-message-wrapper { + margin: unset; + margin-top: 3%; + } + } + + .address-book-form { + .address-book-content-wrapper { + .address-book-table-wrapper { + .table-content { + overflow-x: scroll; + + .table-wrapper { + th { + min-width: 8rem; + text-wrap: nowrap; + } + + th, + td, + .remove-btn { + font-size: 10px; + } + } + } + } + } + } + + @media only screen and (min-width: 768px) { + .address-book-popup-wrapper { + font-size: 20px; + + .address-book-popup-wrapper, + .address-book-content { + .generate-address-form-wrapper { + .select-method-field { + .select-field { + .currency-label { + width: 25%; + height: 3rem; + } + } + } + + .select-method-field, + .select-network-field, + .address-field { + .input-label-field { + .custom-field { + .select-step { + width: 3rem !important; + } + } + } + + .ant-select-single { + .ant-select-selector { + .ant-select-selection-placeholder { + margin-top: 2% !important; + font-size: 14px !important; + } + } + } + + .select-field { + .destination-input-field { + height: 4rem; + } + } + + .custom-select-input-style { + .ant-select-selection-item { + margin-top: 1%; + font-size: 14px; + } + } + } + } + } + } } } @@ -489,7 +697,7 @@ .table_body-wrapper { .table_body-row { .network-field { - width: 30%; + width: 50%; } .address-field-wrapper { diff --git a/web/src/index.css b/web/src/index.css index e8eadcf6f8..fcb03cdf47 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -8003,7 +8003,7 @@ table th { .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row td:last-child div { justify-content: flex-end !important; } .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row .network-field { - width: 40%; } + width: 100%; } .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row .address-field-wrapper .address-content { width: 85%; justify-content: space-between !important; } @@ -8089,6 +8089,14 @@ table th { .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .ant-select-clear svg { color: var(--base_wallet-sidebar-and-popup); font-size: 18px; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .ant-select-arrow, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .ant-select-arrow, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .ant-select-arrow { + top: 20%; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .ant-select-clear, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .ant-select-clear, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .ant-select-clear { + top: 17%; } .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field, .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field, .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field, @@ -8103,6 +8111,26 @@ table th { flex-direction: row; justify-content: space-between; gap: 15px; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .label-disable, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .label-disable, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .label-disable, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .label-disable, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .label-disable, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .label-disable, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .label-disable, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .label-disable, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .label-disable { + opacity: 0.5; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .label-active, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .label-active, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .label-active, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .label-active, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .label-active, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .label-active, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .label-active, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .label-active, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .label-active { + opacity: 1; } .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field, .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable, .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field, @@ -8121,7 +8149,7 @@ table th { .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable, .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field, .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable { - width: 40%; + width: 10%; display: flex; gap: 10%; } .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .custom-field, @@ -8191,25 +8219,6 @@ table th { height: 5.5rem; width: 1%; background-color: var(--labels_important-active-labels-text-graphics); } - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .label-content, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .label-content, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .label-content, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .label-content, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .label-content, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .label-content, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .label-content, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .label-content, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .label-content, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .label-content, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .label-content, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .label-content, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .label-content, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .label-content, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .label-content, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .label-content, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .label-content, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .label-content { - margin-top: 3%; } .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable, .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable, .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable, @@ -8221,268 +8230,300 @@ table th { .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable { opacity: 0.5; } .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field, .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field, .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field, .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field, .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field, .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field, .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field, .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field { + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field { + width: 90%; + display: flex; + justify-content: space-between; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .asset-input .selected-asset-btn, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .asset-input .selected-asset-btn, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .asset-input .selected-asset-btn, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .asset-input .selected-asset-btn, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .asset-input .selected-asset-btn, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .asset-input .selected-asset-btn, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .asset-input .selected-asset-btn, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .asset-input .selected-asset-btn, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .asset-input .selected-asset-btn { + width: 95%; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .label-content, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .label-content, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .label-content, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .label-content, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .label-content, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .label-content, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .label-content, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .label-content, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .label-content { + margin-top: 1%; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .network-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .network-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .network-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .network-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .network-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .network-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .network-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .network-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .network-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .network-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .network-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .network-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .network-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .network-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .network-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .network-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .network-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .network-input { width: 60%; } - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-100, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-100, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-100, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-100, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-100, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-100, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-100, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-100, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-100, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-100, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-100, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-100, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-100, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-100, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-100, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-100, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-100, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-100 { - opacity: 1; } - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-30, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-30, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-30, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-30, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-30, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-30, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-30, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-30, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-30, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-30, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-30, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-30, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-30, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-30, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-30, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-30, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-30, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-30 { - opacity: 0.5; } - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .currency-label, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .currency-label, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .currency-label, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .currency-label, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .currency-label, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .currency-label, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .currency-label, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .currency-label, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .currency-label, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .currency-label, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .currency-label, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .currency-label, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .currency-label, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .currency-label, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .currency-label, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .currency-label, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .currency-label, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .currency-label { - border: 1px solid var(--labels_secondary-inactive-label-text-graphics); - padding: 0.5%; - border-radius: 5px; - margin-right: 10px; - width: 4.5rem; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; } - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field { - border-radius: 2px; - border: 1px solid var(--calculated_important-border) !important; + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-100, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-100, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-100, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-100, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-100, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-100, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-100, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-100, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-100, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-100, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-100, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-100, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-100, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-100, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-100, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-100, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-100, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-100 { + opacity: 1; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-30, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-30, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-30, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-30, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-30, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-30, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-30, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-30, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-30, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-30, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-30, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-30, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .opacity-30, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .opacity-30, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .opacity-30, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .opacity-30, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .opacity-30, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .opacity-30 { + opacity: 0.5; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .currency-label, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .currency-label, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .currency-label, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .currency-label, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .currency-label, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .currency-label, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .currency-label, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .currency-label, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .currency-label, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .currency-label, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .currency-label, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .currency-label, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .currency-label, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .currency-label, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .currency-label, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .currency-label, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .currency-label, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .currency-label { + border: 1px solid var(--labels_secondary-inactive-label-text-graphics); + padding: 0.5%; + border-radius: 5px; + margin-right: 10px; + width: 4.5rem; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field { + border-radius: 2px; + border: 1px solid var(--calculated_important-border) !important; + background-color: var(--base_wallet-sidebar-and-popup); + color: var(--labels_important-active-labels-text-graphics); } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input { background-color: var(--base_wallet-sidebar-and-popup); - color: var(--labels_important-active-labels-text-graphics); } - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input { - background-color: var(--base_wallet-sidebar-and-popup); - color: var(--labels_important-active-labels-text-graphics); - text-overflow: ellipsis; } - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input:focus, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input:focus { - box-shadow: unset; } - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper { - color: var(--specials_buttons-links-and-highlights); - cursor: pointer; } - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text { - padding-right: 0.5rem; - font-size: 15px; } - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container { - text-decoration: underline; } - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper { - display: flex; - align-items: center; } - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img { - height: 1rem; } - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field:focus-within, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field:focus-within, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field:focus-within, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field:focus-within, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field:focus-within, - .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field:focus-within, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field:focus-within, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field:focus-within, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field:focus-within, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field:focus-within, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field:focus-within, - .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field:focus-within, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field:focus-within, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field:focus-within, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field:focus-within, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field:focus-within, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field:focus-within, - .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field:focus-within { - border: 1px solid var(--calculated_important-border) !important; } + color: var(--labels_important-active-labels-text-graphics); + text-overflow: ellipsis; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .ant-input:focus, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .ant-input:focus { + box-shadow: unset; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper { + color: var(--specials_buttons-links-and-highlights); + cursor: pointer; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text { + padding-right: 0.5rem; + font-size: 15px; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .suffix-text .edit-wrapper__container { + text-decoration: underline; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper { + display: flex; + align-items: center; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field .render-scan-wrapper .img-wrapper img, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field .render-scan-wrapper .img-wrapper img { + height: 1rem; } + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .name-address-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .destination-input-field:focus-within, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field:focus-within, + .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-content .generate-address-form-wrapper .address-field .network-field .destination-input-field:focus-within { + border: 1px solid var(--calculated_important-border) !important; } .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style, .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style, .address_book_popup_wrapper .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style, @@ -8563,6 +8604,11 @@ table th { display: flex; align-items: flex-start; gap: 5px; } + .address_book_popup_wrapper .address-book-popup-wrapper .selected-assets-content .assets-field .selected-asset-address, + .address_book_popup_wrapper .name-address-popup-wrapper .selected-assets-content .assets-field .selected-asset-address, + .address_book_popup_wrapper .check-confirm-content-wrapper .selected-assets-content .assets-field .selected-asset-address { + overflow: hidden; + text-overflow: ellipsis; } .address_book_popup_wrapper .address-book-popup-wrapper .selected-assets-content .assets-field .selected-asset, .address_book_popup_wrapper .address-book-popup-wrapper .selected-assets-content .assets-field .selected-network, .address_book_popup_wrapper .name-address-popup-wrapper .selected-assets-content .assets-field .selected-asset, @@ -8572,6 +8618,15 @@ table th { display: flex; align-items: flex-start; gap: 5px; } + .address_book_popup_wrapper .address-book-popup-wrapper .selected-assets-content .confirm_name_detail, + .address_book_popup_wrapper .name-address-popup-wrapper .selected-assets-content .confirm_name_detail, + .address_book_popup_wrapper .check-confirm-content-wrapper .selected-assets-content .confirm_name_detail { + padding: 3%; + border-bottom: 1px solid var(--labels_secondary-inactive-label-text-graphics); } + .address_book_popup_wrapper .address-book-popup-wrapper .selected-assets-content .assets-content, + .address_book_popup_wrapper .name-address-popup-wrapper .selected-assets-content .assets-content, + .address_book_popup_wrapper .check-confirm-content-wrapper .selected-assets-content .assets-content { + padding: 3%; } .address_book_popup_wrapper .address-book-popup-wrapper .confirm-title-text, .address_book_popup_wrapper .name-address-popup-wrapper .confirm-title-text, @@ -8603,14 +8658,8 @@ table th { .address_book_popup_wrapper .check-confirm-content-wrapper .address-book-popup-button-wrapper .okay-btn { width: 100% !important; } -.address_book_popup_wrapper .check-confirm-content-wrapper .selected-assets-content { - border: 1px solid var(--labels_secondary-inactive-label-text-graphics); } - .address_book_popup_wrapper .check-confirm-content-wrapper .selected-assets-content .confirm_name_detail { - padding: 3%; - border-bottom: 1px solid var(--labels_secondary-inactive-label-text-graphics); } - .address_book_popup_wrapper .check-confirm-content-wrapper .selected-assets-content .assets-content { - padding: 3%; } - +.address_book_popup_wrapper .address-book-popup-wrapper .warning-message-wrapper, +.address_book_popup_wrapper .name-address-popup-wrapper .warning-message-wrapper, .address_book_popup_wrapper .check-confirm-content-wrapper .warning-message-wrapper { margin: 3%; font-size: 12px; @@ -8619,15 +8668,181 @@ table th { align-items: center; gap: 2px; } +.address_book_popup_wrapper .check-confirm-content-wrapper .selected-assets-content { + border: 1px solid var(--labels_secondary-inactive-label-text-graphics); } + .add_withdrawal_address_wrapper .ReactModal__Content { width: 50rem; } .layout-mobile .address-book-popup-wrapper { width: 100% !important; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .ant-select-clear, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .ant-select-clear { + width: 18px; + height: 18px; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .network-field .ant-select-arrow, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .ant-select-arrow { + top: 57%; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .network-field .ant-select-clear, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .network-field .ant-select-clear { + top: 50%; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field { + display: flex; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .input-label-field .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .input-label-field-disable .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .input-label-field .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .input-label-field-disable .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .input-label-field .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .input-label-field-disable .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .custom-field .select-step { + height: 3.4rem; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .input-label-field .custom-field .custom-line, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .input-label-field-disable .custom-field .custom-line, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .input-label-field .custom-field .custom-line, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .input-label-field-disable .custom-field .custom-line, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .input-label-field .custom-field .custom-line, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .input-label-field-disable .custom-field .custom-line, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .custom-field .custom-line, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field-disable .custom-field .custom-line, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .custom-field .custom-line, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field-disable .custom-field .custom-line, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .custom-field .custom-line, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field-disable .custom-field .custom-line { + height: 12rem; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .custom-select-input-style .ant-select-selector, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .custom-select-input-style .ant-select-selector, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .custom-select-input-style .ant-select-selector, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style .ant-select-selector, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style .ant-select-selector, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style .ant-select-selector { + font-size: 10px !important; + height: 4.4rem !important; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .custom-select-input-style .ant-select-selection-item, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .custom-select-input-style .ant-select-selection-item, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .custom-select-input-style .ant-select-selection-item, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style .ant-select-selection-item, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style .ant-select-selection-item, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style .ant-select-selection-item { + line-height: 3.5rem !important; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .destination-input-field, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .destination-input-field, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .destination-input-field, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .destination-input-field, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .destination-input-field, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .destination-input-field { + background-color: var(--base_background) !important; + color: var(--labels_important-active-labels-text-graphics); } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .destination-input-field .ant-input, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .destination-input-field .ant-input, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .destination-input-field .ant-input, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .destination-input-field .ant-input, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .destination-input-field .ant-input, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .destination-input-field .ant-input { + background-color: var(--base_background) !important; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .destination-input-field .destination-input-field:focus-within, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .destination-input-field .destination-input-field:focus-within, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .destination-input-field .destination-input-field:focus-within, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .destination-input-field .destination-input-field:focus-within, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .destination-input-field .destination-input-field:focus-within, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .destination-input-field .destination-input-field:focus-within { + background-color: var(--base_background) !important; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .select-field, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .select-field, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .select-field, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field { + display: flex; + flex-direction: column; + justify-content: unset; + margin-bottom: 1%; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .select-field .currency-label, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .select-field .currency-label, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .select-field .currency-label, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .currency-label, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .currency-label, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .currency-label { + width: 22%; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .select-field .network-input, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .select-field .network-input, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .select-field .network-input, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .network-input, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .network-input, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .network-input { + width: 100%; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .input-label-field, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .input-label-field, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .input-label-field, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field { + display: flex; } + +.layout-mobile .check-confirm-content-wrapper .warning-message-wrapper { + margin: unset; + margin-top: 3%; } + +.layout-mobile .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content { + overflow-x: scroll; } + .layout-mobile .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper th { + min-width: 8rem; + text-wrap: nowrap; } + .layout-mobile .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper th, + .layout-mobile .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper td, + .layout-mobile .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .remove-btn { + font-size: 10px; } + +@media only screen and (min-width: 768px) { + .layout-mobile .address-book-popup-wrapper { + font-size: 20px; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .select-field .currency-label, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .currency-label { + width: 25%; + height: 3rem; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .input-label-field .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .input-label-field .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .input-label-field .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .input-label-field .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .input-label-field .custom-field .select-step, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .input-label-field .custom-field .select-step { + width: 3rem !important; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .ant-select-single .ant-select-selector .ant-select-selection-placeholder, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .ant-select-single .ant-select-selector .ant-select-selection-placeholder, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .ant-select-single .ant-select-selector .ant-select-selection-placeholder, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .ant-select-single .ant-select-selector .ant-select-selection-placeholder, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .ant-select-single .ant-select-selector .ant-select-selection-placeholder, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .ant-select-single .ant-select-selector .ant-select-selection-placeholder { + margin-top: 2% !important; + font-size: 14px !important; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .select-field .destination-input-field, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .select-field .destination-input-field, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .select-field .destination-input-field, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .select-field .destination-input-field, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .select-field .destination-input-field, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .select-field .destination-input-field { + height: 4rem; } + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-method-field .custom-select-input-style .ant-select-selection-item, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .select-network-field .custom-select-input-style .ant-select-selection-item, + .layout-mobile .address-book-popup-wrapper .address-book-popup-wrapper .generate-address-form-wrapper .address-field .custom-select-input-style .ant-select-selection-item, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-method-field .custom-select-input-style .ant-select-selection-item, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .select-network-field .custom-select-input-style .ant-select-selection-item, + .layout-mobile .address-book-popup-wrapper .address-book-content .generate-address-form-wrapper .address-field .custom-select-input-style .ant-select-selection-item { + margin-top: 1%; + font-size: 14px; } } @media screen and (min-width: 1920px) { .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row .network-field { - width: 30%; } + width: 50%; } .address-book-form .address-book-content-wrapper .address-book-table-wrapper .table-content .table-wrapper .table_body-wrapper .table_body-row .address-field-wrapper .address-content span { width: 80%; } } From 23ffe1760e2c39c8b0ab0674af1b07b9245e277a Mon Sep 17 00:00:00 2001 From: ram Date: Fri, 26 Jul 2024 19:12:33 +0530 Subject: [PATCH 053/108] Fixed minor issues in addressbook page and updated the transaction history deposit tab mobile UI --- web/src/components/ActionNotification/index.js | 14 ++++++++++++-- web/src/components/Table/index.js | 7 +++++++ .../TransactionsHistory/HistoryDisplay.js | 4 ++-- web/src/containers/Wallet/AddressBook.js | 8 ++++---- web/src/containers/Wallet/_AddressBook.scss | 13 +++++++++++++ web/src/index.css | 15 +++++++++++++++ 6 files changed, 53 insertions(+), 8 deletions(-) diff --git a/web/src/components/ActionNotification/index.js b/web/src/components/ActionNotification/index.js index 1fae83f9d2..905311c14b 100644 --- a/web/src/components/ActionNotification/index.js +++ b/web/src/components/ActionNotification/index.js @@ -41,7 +41,7 @@ const ActionNotification = ({ disable = false, isFromWallet = false, }) => { - const isVisibale = isFromWallet ? isFromWallet : !isMobile; + const isVisible = isFromWallet ? isFromWallet : !isMobile; // This is to prevent action when edit string or upload icons are clicked const onActionClick = ({ target: { dataset = {} } }) => { const { stringId, iconId } = dataset; @@ -71,7 +71,17 @@ const ActionNotification = ({ )} onClick={onActionClick} > - {!hideActionText && (showActionText || isVisibale) && ( + {!hideActionText && (showActionText || isVisible) && ( +
+ {text} +
+ )} + {isMobile && text === 'Check deposit status' && (
totalPages) { + this.goToPreviousPage(); + } + } if (count === 0) { if (!showHeaderNoData) { diff --git a/web/src/containers/TransactionsHistory/HistoryDisplay.js b/web/src/containers/TransactionsHistory/HistoryDisplay.js index b79897e7b7..2ed0cc6528 100644 --- a/web/src/containers/TransactionsHistory/HistoryDisplay.js +++ b/web/src/containers/TransactionsHistory/HistoryDisplay.js @@ -116,7 +116,7 @@ const HistoryDisplay = (props) => { onClick={handleDownload} /> )} - {!isMobile && activeTab === 2 && !isDepositFromWallet && ( + {activeTab === 2 && !isDepositFromWallet && ( { onClick={openDialog} /> )} - {!isMobile && !isFromWallet && ( + {!isFromWallet && (!isMobile || activeTab === 2) && ( (
-
+
{`${ @@ -271,13 +271,13 @@ const AddressBook = ({ }; const restGetUserData = removeCreatedAt(getUserData); setGetUserData([ - ...getUserData, { ...currValue, created_at: new Date().toISOString() }, + ...getUserData, ]); try { await setUserLabelAndAddress({ - addresses: [...restGetUserData, currValue], + addresses: [currValue, ...restGetUserData], }); } catch (error) { console.error(error); @@ -646,8 +646,8 @@ const AddressBook = ({
{isLoading ? ( Date: Mon, 29 Jul 2024 00:26:56 +0300 Subject: [PATCH 054/108] payment-method-statuses --- .../containers/Admin/User/PaymentMethods.js | 4 ++++ web/src/containers/P2P/P2PProfile.js | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/web/src/containers/Admin/User/PaymentMethods.js b/web/src/containers/Admin/User/PaymentMethods.js index 11b5e2ad49..3853b66c19 100644 --- a/web/src/containers/Admin/User/PaymentMethods.js +++ b/web/src/containers/Admin/User/PaymentMethods.js @@ -113,6 +113,8 @@ const PaymentMethods = ({ user }) => { return (
{data?.status === 0 && 'Unverified'} + {data?.status === 1 && 'Pending'} + {data?.status === 2 && 'Rejected'} {data?.status === 3 && 'Verified'}
); @@ -343,6 +345,8 @@ const PaymentMethods = ({ user }) => { }} > Unverified + Pending + RejectedVerified diff --git a/web/src/containers/P2P/P2PProfile.js b/web/src/containers/P2P/P2PProfile.js index d177bb7a9a..502f53b6ab 100644 --- a/web/src/containers/P2P/P2PProfile.js +++ b/web/src/containers/P2P/P2PProfile.js @@ -409,6 +409,28 @@ const P2PProfile = ({ (Unverified) )} + {info?.status === 1 && ( + + (Pending) + + )} + {info?.status === 2 && ( + + (Rejected) + + )} {info?.status === 3 && ( Date: Mon, 29 Jul 2024 23:40:51 +0300 Subject: [PATCH 055/108] p2p-sell-verify-email --- server/messages.js | 3 ++- server/utils/hollaex-tools-lib/tools/user.js | 22 ++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/server/messages.js b/server/messages.js index 705c21519d..85d24e7fcd 100644 --- a/server/messages.js +++ b/server/messages.js @@ -264,4 +264,5 @@ exports.BALANCE_HISTORY_NOT_ACTIVE = 'This feature is not active on the exchange exports.WITHDRAWAL_DISABLED = 'Withdrawal disabled for this user'; exports.ADDRESSBOOK_MISSING_FIELDS = 'Each address must contain both address, network, currency and label fields'; exports.ADDRESSBOOK_ALREADY_EXISTS = 'Address label already exists in the payload'; -exports.ADDRESSBOOK_NOT_FOUND = 'User address book not found'; \ No newline at end of file +exports.ADDRESSBOOK_NOT_FOUND = 'User address book not found'; +exports.PAYMENT_DETAIL_NOT_FOUND = 'Payment detail not found'; \ No newline at end of file diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index 3b7049f891..5ddd1171ec 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -63,6 +63,7 @@ const { SERVICE_NOT_SUPPORTED, BALANCE_HISTORY_NOT_ACTIVE, ADDRESSBOOK_MISSING_FIELDS, + PAYMENT_DETAIL_NOT_FOUND, ADDRESSBOOK_ALREADY_EXISTS, ADDRESSBOOK_NOT_FOUND } = require(`${SERVER_PATH}/messages`); @@ -3379,6 +3380,18 @@ const createPaymentDetail = async (data) => { throw new Error(USER_NOT_FOUND); } + const adminAccount = await getUserByKitId(1); + + sendEmail( + MAILTYPE.ALERT, + adminAccount.email, + { + type: 'An exchange user added a new payment method, Awaiting your approval', + data: `User ID: ${user_id} added a new payment method. Account details:
    ${details.fields.map(field => (`
  • ${field.name}: ${field.value}
  • `))}
` + }, + adminAccount.settings + ); + const paymentDetail = await getModel('paymentDetail').create({ user_id, name, @@ -3394,11 +3407,16 @@ const createPaymentDetail = async (data) => { const updatePaymentDetail = async (id, data, isAdmin = false) => { const paymentDetail = await getModel('paymentDetail').findOne({ where: { id, user_id: data.user_id } }); if (!paymentDetail) { - throw new Error('Payment detail not found'); + throw new Error(PAYMENT_DETAIL_NOT_FOUND); } if (!isAdmin) { delete data.status }; + if (data.status === 3) { + const user = await getUserByKitId(data.user_id); + sendEmail(MAILTYPE.BANK_VERIFIED, user.email, { bankAccounts: paymentDetail?.details?.fields }, user.settings); + } + await paymentDetail.update(data, { fields: [ 'name', @@ -3415,7 +3433,7 @@ const updatePaymentDetail = async (id, data, isAdmin = false) => { const deletePaymentDetail = async (id, user_id) => { const paymentDetail = await getModel('paymentDetail').findOne({ where: { id, user_id } }); if (!paymentDetail) { - throw new Error('Payment detail not found'); + throw new Error(PAYMENT_DETAIL_NOT_FOUND); } await paymentDetail.destroy(); }; From 2e7400e3b4ff57133dcb424a88e79c6beb063ef6 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Tue, 30 Jul 2024 01:24:38 +0300 Subject: [PATCH 056/108] remove get transaction call --- web/src/containers/P2P/P2POrder.js | 1 - 1 file changed, 1 deletion(-) diff --git a/web/src/containers/P2P/P2POrder.js b/web/src/containers/P2P/P2POrder.js index 0ab28a218e..3df85d1a78 100644 --- a/web/src/containers/P2P/P2POrder.js +++ b/web/src/containers/P2P/P2POrder.js @@ -159,7 +159,6 @@ const P2POrder = ({ }, []); useEffect(() => { - getTransaction(); fetchFeedback({ transaction_id: selectedOrder.id }) .then((res) => { if (res?.data?.length > 0) { From c5ea21fb3fe90e5d863307972cdeeeaefee2da94 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Tue, 30 Jul 2024 18:04:31 +0300 Subject: [PATCH 057/108] staker-email-error-message --- server/utils/hollaex-tools-lib/tools/stake.js | 42 +++++++++++++------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/server/utils/hollaex-tools-lib/tools/stake.js b/server/utils/hollaex-tools-lib/tools/stake.js index 585cd64d93..7a2ae7e16d 100644 --- a/server/utils/hollaex-tools-lib/tools/stake.js +++ b/server/utils/hollaex-tools-lib/tools/stake.js @@ -561,20 +561,36 @@ const createExchangeStaker = async (stake_id, amount, user_id) => { await transferAssetByKitIds(user_id, stakePool.account_id, stakePool.currency, amount, 'User transfer stake', false, { category: 'stake' }); - const stakerData = await getModel('staker').create(staker, { - fields: [ - 'user_id', - 'stake_id', - 'amount', - 'currency', - 'reward_currency', - 'status', - 'closing', - 'unstaked_date' - ] - }); + try { + const stakerData = await getModel('staker').create(staker, { + fields: [ + 'user_id', + 'stake_id', + 'amount', + 'currency', + 'reward_currency', + 'status', + 'closing', + 'unstaked_date' + ] + }); + + return stakerData; + } catch (error) { + const adminAccount = await getUserByKitId(1); + sendEmail( + MAILTYPE.ALERT, + adminAccount.email, + { + type: 'Urgent! Staker Creation Failed!', + data: `User id ${user.id} failed to stake in the pool id ${stake_id} after funds were transferred. Please check with the exchange user. Error message :${error.message}` + }, + adminAccount.settings + ); - return stakerData; + throw new Error(error.message); + } + }; const deleteExchangeStaker = async (staker_id, user_id) => { From a7ad5afa1fb67f2d4ad885e22cb78de69067caf5 Mon Sep 17 00:00:00 2001 From: ram Date: Wed, 31 Jul 2024 15:58:15 +0530 Subject: [PATCH 058/108] Fixed the loading issue in blue admin page and updated the address book workflow --- web/src/config/lang/en.json | 5 +- .../containers/Admin/CreatePair/Preview.js | 4 + web/src/containers/Wallet/AddressBook.js | 216 ++++- web/src/containers/Wallet/GenerateAddress.js | 91 +- web/src/containers/Wallet/_AddressBook.scss | 84 +- web/src/containers/Withdraw/Withdraw.js | 101 ++- web/src/containers/Withdraw/_Withdraw.scss | 23 +- web/src/containers/Withdraw/form.js | 8 +- web/src/containers/Withdraw/utils.js | 5 +- web/src/index.css | 829 ++++++++++++++---- 10 files changed, 1092 insertions(+), 274 deletions(-) diff --git a/web/src/config/lang/en.json b/web/src/config/lang/en.json index caae6abf2c..72be64d6f1 100644 --- a/web/src/config/lang/en.json +++ b/web/src/config/lang/en.json @@ -1753,7 +1753,10 @@ "MANAGE_ADDRESS_BOOK": "Manage address book", "VIEW_ADDRESS_BOOK_LABEL": "View address book", "ASSET_ALREADY_HAVE_ADDRESS": "This Asset has already Exists. Please try another.", - "ADD_WITHDRAWAL_ADDRESS_LINK": "Add withdrawal address" + "ADD_WITHDRAWAL_ADDRESS_LINK": "Add withdrawal address", + "REVOKE_ADDRESS": "Your Address is Removed", + "REMOVE_ADDRESS": "Remove Address", + "REMOVE_CONTENT": "Do you want to remove this withdrawal address from your address book?" }, "ASSET_INFO": "Asset info", "TAKER_FEES_APPLIED": "Taker fees are applied", diff --git a/web/src/containers/Admin/CreatePair/Preview.js b/web/src/containers/Admin/CreatePair/Preview.js index 212c24ca37..bd5d713be4 100644 --- a/web/src/containers/Admin/CreatePair/Preview.js +++ b/web/src/containers/Admin/CreatePair/Preview.js @@ -28,6 +28,7 @@ const Preview = ({ buttonSubmitting = false, }) => { const [isVisible, setIsVisible] = useState(false); + const [isLoading, setIsLoading] = useState(false); const pair_base_data = allCoins.filter((data) => data.symbol === formData.pair_base)[0] || {}; @@ -41,9 +42,11 @@ const Preview = ({ id: exchange.id, pairs: [...pairs, `${formData.pair_base}-${formData.pair_2}`], }; + setIsLoading(true); await updateExchange(formProps); await getMyExchange(); onClose(); + setIsLoading(false); message.success('Pairs added successfully'); } catch (error) { let errMsg = @@ -243,6 +246,7 @@ const Preview = ({ onHandleRemoveMarket={onDelete} removePair={formData} removeContent={'Markets'} + isLoading={isLoading} /> ) : null} diff --git a/web/src/containers/Wallet/AddressBook.js b/web/src/containers/Wallet/AddressBook.js index 1fc7137b44..6b58d040d7 100644 --- a/web/src/containers/Wallet/AddressBook.js +++ b/web/src/containers/Wallet/AddressBook.js @@ -46,6 +46,8 @@ const AddressBook = ({ selectedCurrency: null, networkOptions: null, address: null, + optionalTag: null, + selectedData: null, }); const [isValidAddress, setIsValidAddress] = useState(false); const [isLoading, setIsLoading] = useState(false); @@ -113,29 +115,32 @@ const AddressBook = ({ stringId: 'WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS', label: STRINGS['WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS'], key: 'address', - renderCell: (data, key) => ( -
- ), + + ); + }, }, { stringId: 'ADDRESS_BOOK.DATE_ADDED', @@ -163,7 +168,7 @@ const AddressBook = ({
onHandleAddressBookDetails(data, 'revoke')} + onClick={() => onHandleRemove(data)} > {STRINGS['ADDRESS_BOOK.REMOVE']} @@ -184,6 +189,9 @@ const AddressBook = ({ ? coins[selectedAsset?.selectedCurrency]?.network : coins[selectedAsset?.selectedCurrency]?.symbol; const networkIcon = coins[network]?.icon_id; + const hasOptionalTag = + ['xrp', 'xlm'].includes(selectedAsset?.selectedCurrency) || + ['xlm', 'ton'].includes(network); useEffect(() => { const getAddress = async () => { @@ -222,6 +230,11 @@ const AddressBook = ({ setUserLabel(''); }; + const onHandleRemove = (data) => { + setRenderPopUps((prev) => ({ ...prev, remove: true })); + setSelectedAsset((prev) => ({ ...prev, selectedData: data })); + }; + const onHandlePopUpBtn = (previousStep, nextStep) => { setRenderPopUps((prev) => ({ ...prev, [previousStep]: false })); setRenderPopUps((prev) => ({ ...prev, [nextStep]: true })); @@ -230,8 +243,10 @@ const AddressBook = ({ ...prev, selectedCurrency: null, networkOptions: null, + optionalTag: null, })); setIsValidAddress(null); + setUserLabel(''); } if (previousStep === 'step3' && nextStep === 'step2') { setUserLabel(''); @@ -259,13 +274,18 @@ const AddressBook = ({ try { await setUserLabelAndAddress({ addresses: restFilteredData }); + message.success(STRINGS['ADDRESS_BOOK.REVOKE_ADDRESS']); } catch (error) { console.error(error); } } else if (!hasAsset) { + const address = + hasOptionalTag && selectedAsset?.optionalTag + ? `${selectedAsset?.address}:${selectedAsset?.optionalTag}` + : selectedAsset?.address; const currValue = { label: userLabel, - address: selectedAsset?.address, + address, network: selectedNetwork, currency: selectedAsset?.selectedCurrency, }; @@ -340,6 +360,7 @@ const AddressBook = ({ networkIcon={networkIcon} isValidAddress={isValidAddress} setIsValidAddress={setIsValidAddress} + hasOptionalTag={hasOptionalTag} />
@@ -350,7 +371,7 @@ const AddressBook = ({ /> onHandlePopUpBtn('step1', 'step2')} /> @@ -449,6 +470,18 @@ const AddressBook = ({ {selectedAsset?.address}
+ {hasOptionalTag && selectedAsset?.optionalTag && ( +
+
+ + {STRINGS['ACCORDIAN.TAG']} + +
+
+ {selectedAsset?.optionalTag} +
+
+ )}
onHandlePopUpBtn('step2', 'step3')} /> @@ -473,7 +508,7 @@ const AddressBook = ({ onCloseDialog={() => onHandleClose('step3')} className="address_book_popup_wrapper" > -
+
@@ -553,6 +588,18 @@ const AddressBook = ({ {selectedAsset?.address}
+ {hasOptionalTag && selectedAsset?.optionalTag && ( +
+
+ + {STRINGS['ACCORDIAN.TAG']} + +
+
+ {selectedAsset?.optionalTag} +
+
+ )}
@@ -573,7 +620,6 @@ const AddressBook = ({ className="text-uppercase next-btn" type="default" onClick={() => onHandleAddressBookDetails(null, 'confirm')} - disabled={false} > {STRINGS['DUST.CONFIRMATION.CONFIRM']} @@ -662,6 +708,120 @@ const AddressBook = ({
)}
+ + setRenderPopUps((prev) => ({ ...prev, remove: false })) + } + className="address_book_popup_wrapper" + > +
+
+
+ + {STRINGS['ADDRESS_BOOK.REMOVE_ADDRESS']} + +
+
+
+
+
+ + {STRINGS['DEVELOPERS_TOKENS_TABLE.NAME']}: + +
+
+ {selectedAsset?.selectedData?.label} +
+
+
+
+
+ + {STRINGS['ASSETS']}: + +
+
+ + {`${ + coins[selectedAsset?.selectedData?.currency]?.fullname + } (${selectedAsset?.selectedData?.currency?.toUpperCase()})`} +
+
+
+
+ + {STRINGS['WITHDRAWALS_FORM_NETWORK_LABEL']}: + +
+
+ {renderNetworkWithLabel( + coins[selectedAsset?.selectedData?.network]?.icon_id, + selectedAsset?.selectedData?.network + )} +
+
+
+
+
+ + {STRINGS['WITHDRAW_PAGE.WITHDRAWAL_CONFIRM_ADDRESS']}: + +
+
+ {selectedAsset?.selectedData?.address} +
+
+ {selectedAsset?.selectedData?.address?.split(':')[1] && ( +
+
+ + {STRINGS['ACCORDIAN.TAG']} + +
+
+ + {selectedAsset?.selectedData?.address?.split(':')[1]} + +
+
+ )} +
+
+
+
+ + {STRINGS['ADDRESS_BOOK.REMOVE_CONTENT']} + +
+
+
+ + setRenderPopUps((prev) => ({ ...prev, remove: false })) + } + /> + { + onHandleAddressBookDetails( + selectedAsset?.selectedData, + 'revoke' + ); + setRenderPopUps((prev) => ({ ...prev, remove: false })); + }} + /> +
+
+
diff --git a/web/src/containers/Wallet/GenerateAddress.js b/web/src/containers/Wallet/GenerateAddress.js index 132fb70025..bda75ef7de 100644 --- a/web/src/containers/Wallet/GenerateAddress.js +++ b/web/src/containers/Wallet/GenerateAddress.js @@ -36,6 +36,7 @@ const GenerateAddress = ({ setIsValidAddress, isValidAddress, dispatch, + hasOptionalTag, }) => { const [qrScannerOpen, setQrScannerOpen] = useState(false); @@ -140,6 +141,12 @@ const GenerateAddress = ({ dispatch(change(FORM_NAME, 'address', data)); }; + const onHandleOptionalTag = (value) => { + if (hasOptionalTag) { + setSelectedAsset((prev) => ({ ...prev, optionalTag: value })); + } + }; + return (
@@ -204,20 +211,21 @@ const GenerateAddress = ({ } > {Object.entries(coins).map( - ([_, { symbol, fullname, icon_id }]) => ( - - ) +
onHandleChangeSelect(symbol)} + > + +
{`${fullname} (${symbol.toUpperCase()})`}
+
+ + ) )} {selectedAsset?.selectedCurrency ? ( @@ -320,6 +328,7 @@ const GenerateAddress = ({ >
3
+ {hasOptionalTag &&
}
@@ -377,6 +386,62 @@ const GenerateAddress = ({
+ {hasOptionalTag && ( +
+
+
+
4
+
+
+
+
+
+ + {STRINGS['DEPOSIT_STATUS.DESTINATION_TAG_LABEL']}: + +
+
+ {displayNetwork && ( +
+ onHandleOptionalTag(e.target.value)} + value={selectedAsset?.optionalTag} + type={ + selectedAsset?.selectedCurrency === 'xrp' || + selectedAsset?.selectedCurrency === 'xlm' + ? 'number' + : 'text' + } + /> + {selectedAsset?.optionalTag ? ( + + ) : ( + + )} +
+ )} +
+
+ )} ); }; diff --git a/web/src/containers/Wallet/_AddressBook.scss b/web/src/containers/Wallet/_AddressBook.scss index 6818a12dfd..eb8d599e39 100644 --- a/web/src/containers/Wallet/_AddressBook.scss +++ b/web/src/containers/Wallet/_AddressBook.scss @@ -212,7 +212,8 @@ .address-book-popup-wrapper, .name-address-popup-wrapper, - .check-confirm-content-wrapper { + .confirm-popup-wrapper, + .remove-popup-wrapper { .address-book-header-content, .name-address-header-content, .confirm-header-wrapper { @@ -244,18 +245,20 @@ .select-network-field { .network-field { .ant-select-arrow { - top: 20%; + margin-top: 1%; + top: 85%; } .ant-select-clear { - top: 17%; + top: 100%; } } } .select-method-field, .select-network-field, - .address-field { + .address-field, + .optional-tag-field { width: 100%; display: flex; flex-direction: row; @@ -305,6 +308,7 @@ .select-field { width: 90%; + height: 35%; display: flex; justify-content: space-between; @@ -465,6 +469,20 @@ .assets-content { padding: 3%; } + + .remove_name_detail, + .remove-assets-content { + padding: 0 3% 0 0; + } + .remove_name_detail { + padding: 2%; + border: 1px solid var(--labels_important-active-labels-text-graphics); + border-bottom: unset; + } + .remove-assets-content { + padding: 2%; + border: 1px solid var(--labels_important-active-labels-text-graphics); + } } .confirm-title-text { @@ -486,6 +504,12 @@ border: none; } + .disable-btn { + background-color: var(--labels_inactive-button) !important; + width: 45%; + border: none; + } + .okay-btn { width: 100% !important; } @@ -499,9 +523,16 @@ align-items: center; gap: 2px; } + + .remove-message-wrapper { + margin: unset !important; + margin-top: 2% !important; + gap: 5px; + align-items: baseline; + } } - .check-confirm-content-wrapper { + .confirm-popup-wrapper { .selected-assets-content { border: 1px solid var(--labels_secondary-inactive-label-text-graphics); } @@ -517,6 +548,8 @@ .layout-mobile { .address-book-popup-wrapper { width: 100% !important; + height: max-content; + overflow: scroll; .address-book-popup-wrapper, .address-book-content { @@ -529,18 +562,19 @@ .select-network-field { .network-field { .ant-select-arrow { - top: 57%; + top: 25%; } .ant-select-clear { - top: 50%; + top: 40%; } } } .select-method-field, .select-network-field, - .address-field { + .address-field, + .optional-tag-field { display: flex; .input-label-field, @@ -608,9 +642,12 @@ } } } + .address-book-popup-button-wrapper { + margin: 5% 0 20% 0; + } } - .check-confirm-content-wrapper { + .confirm-popup-wrapper { .warning-message-wrapper { margin: unset; margin-top: 3%; @@ -629,15 +666,33 @@ text-wrap: nowrap; } + th:nth-child(2) { + min-width: 20rem; + } + th, td, .remove-btn { font-size: 10px; } - .asset-label { - span { - min-width: 13rem; + .table_body-wrapper { + .table_body-row { + .asset-label { + span { + min-width: 13rem; + } + } + + td:nth-child(2) { + .asset-label { + width: 85%; + } + } + + .network-field { + width: 8rem; + } } } } @@ -664,7 +719,8 @@ .select-method-field, .select-network-field, - .address-field { + .address-field, + .optional-tag-field { .input-label-field { .custom-field { .select-step { @@ -690,7 +746,7 @@ .custom-select-input-style { .ant-select-selection-item { - margin-top: 1%; + margin-top: unset; font-size: 14px; } } diff --git a/web/src/containers/Withdraw/Withdraw.js b/web/src/containers/Withdraw/Withdraw.js index f66a2fb874..45195ecd9a 100644 --- a/web/src/containers/Withdraw/Withdraw.js +++ b/web/src/containers/Withdraw/Withdraw.js @@ -55,6 +55,7 @@ const RenderWithdraw = ({ router, onHandleScan, selectedNetwork, + optionalTag, ...rest }) => { const { Option } = Select; @@ -73,7 +74,6 @@ const RenderWithdraw = ({ const [topAssets, setTopAssets] = useState([]); const [selectedAddress, setSelectedAddress] = useState([]); const [prices, setPrices] = useState({}); - const [optionalTag, setOptionalTag] = useState(''); const [selectedAsset, setSelectedAsset] = useState({ selectedCurrency: null, networkData: null, @@ -83,6 +83,9 @@ const RenderWithdraw = ({ isPinnedAssets: false, isValidEmail: false, isDisbaleWithdraw: false, + isSelected: false, + dropdownOpen: false, + isOptionalTag: false, }); // const [isCheck, setIsCheck] = useState(false); // const [isVisible, setIsVisible] = useState(false); @@ -208,6 +211,7 @@ const RenderWithdraw = ({ } setCurrStep({ ...currStep, stepTwo: true, stepThree: true }); getWithdrawMAx(defaultCurrency); + setWithdrawOptionaltag(null); } else { setSelectedAsset((prev) => ({ ...prev, selectedCurrency: null })); } @@ -300,10 +304,16 @@ const RenderWithdraw = ({ setWithdrawAddress(''); setWithdrawAmount(''); setReceiverEmail(''); + setWithdrawOptionaltag(null); setSelectedMethod(method); setCurrStep((prev) => ({ ...prev, stepTwo: true })); setIsValidAdress(false); - setIsValidField((prev) => ({ ...prev, isValidEmail: false })); + setIsValidField((prev) => ({ + ...prev, + isValidEmail: false, + isOptionalTag: false, + })); + setSelectedAsset((prev) => ({ ...prev, addressField: null })); if (!method) { setCurrStep((prev) => ({ ...prev, @@ -364,6 +374,8 @@ const RenderWithdraw = ({ })); setWithdrawAddress(''); setReceiverEmail(''); + setWithdrawOptionaltag(null); + setIsValidField((prev) => ({ ...prev, isOptionalTag: false })); }; const renderPinnedAsset = (data) => { @@ -386,9 +398,11 @@ const RenderWithdraw = ({ } else if (!val) { setCurrStep((prev) => ({ ...prev, stepFour: false, stepFive: false })); } - setSelectedAsset((prev) => ({ ...prev, addressField: null })); setWithdrawAddress(null); setIsValidAdress(false); + setWithdrawOptionaltag(null); + setSelectedAsset((prev) => ({ ...prev, addressField: null })); + setIsValidField((prev) => ({ ...prev, isOptionalTag: false })); }; const onHandleAddress = (val, method) => { @@ -418,6 +432,7 @@ const RenderWithdraw = ({ setReceiverEmail(val); setIsValidAdress({ isValid: !isValid }); setWithdrawAmount(''); + setWithdrawOptionaltag(null); }; const onHandleAmount = (val) => { @@ -523,7 +538,9 @@ const RenderWithdraw = ({ // }; const onHandleOptionalTag = (value) => { - setOptionalTag(value); + if (value === '') { + setIsValidField((prev) => ({ ...prev, isOptionalTag: true })); + } setWithdrawOptionaltag(value); }; @@ -554,8 +571,13 @@ const RenderWithdraw = ({ stepFour: false, stepFive: false, }); + setWithdrawOptionaltag(null); setIsValidAdress(false); - setIsValidField((prev) => ({ ...prev, isValidEmail: false })); + setIsValidField((prev) => ({ + ...prev, + isValidEmail: false, + isOptionalTag: false, + })); }; // const onHandleSelect = (symbol) => { @@ -572,18 +594,35 @@ const RenderWithdraw = ({ // } // }; + const handleDropdownVisibleChange = (open) => { + setIsValidField((prev) => ({ ...prev, dropdownOpen: open })); + }; + const onchangeAddressField = (val) => { - setSelectedAsset((prev) => ({ ...prev, addressField: val })); - if (val === STRINGS['WITHDRAW_PAGE.NEW_ADDRESS']) { - setWithdrawAddress(null); - setIsValidAdress(false); - } - if (val !== STRINGS['WITHDRAW_PAGE.NEW_ADDRESS']) { - onHandleAddress(val, 'address'); - } - if (val === STRINGS['ADDRESS_BOOK.VIEW_ADDRESS_BOOK_LABEL']) { - return router.push('/wallet/address-book'); + if (val) { + if (val === STRINGS['WITHDRAW_PAGE.NEW_ADDRESS']) { + setWithdrawOptionaltag(null); + setWithdrawAddress(null); + setIsValidAdress(false); + } + if (val !== STRINGS['WITHDRAW_PAGE.NEW_ADDRESS']) { + setIsValidField((prev) => ({ ...prev, isSelected: true })); + onHandleAddress(val, 'address'); + if (isCondition && address?.length > 1) { + setWithdrawOptionaltag(address[1]); + } + } + if (val === STRINGS['ADDRESS_BOOK.VIEW_ADDRESS_BOOK_LABEL']) { + setWithdrawOptionaltag(null); + return router.push('/wallet/address-book'); + } } + setSelectedAsset((prev) => ({ ...prev, addressField: val })); + setIsValidField((prev) => ({ + ...prev, + isOptionalTag: false, + dropdownOpen: false, + })); }; const withdrawFeeFormat = @@ -643,14 +682,37 @@ const RenderWithdraw = ({ ) ); })(); + + const address = getAddress[0]?.address?.split(':'); + const selectAddressField = [ { value: STRINGS['WITHDRAW_PAGE.NEW_ADDRESS'], label: STRINGS['WITHDRAW_PAGE.NEW_ADDRESS'], }, { - value: getAddress[0]?.address, - label: `${getAddress[0]?.label}: ${getAddress[0]?.address}`, + value: address && address[0], + label: ( +
+ {getAddress[0]?.label} +
+ : {address && address[0]} + {address && + address.length > 1 && + isCondition && + (!isValidField?.isSelected || isValidField?.dropdownOpen) && ( +
+
+ + {STRINGS['ACCORDIAN.TAG']} + + {address && address[1]} +
+
+ )} +
+
+ ), }, { value: STRINGS['ADDRESS_BOOK.VIEW_ADDRESS_BOOK_LABEL'], @@ -1063,6 +1125,7 @@ const RenderWithdraw = ({ allowClear={true} value={selectedAsset?.addressField} onChange={onchangeAddressField} + onDropdownVisibleChange={handleDropdownVisibleChange} onClear={() => onHandleClear('address')} > {selectAddressField.map((data) => { @@ -1070,8 +1133,7 @@ const RenderWithdraw = ({ + ); + }, + }, { stringId: 'CURRENCY', label: STRINGS['CURRENCY'], @@ -813,7 +833,7 @@ export const generateWithdrawalsHeaders = ( ); }, }, - { + type === 'withdraw' && { stringId: 'MORE,CANCEL,VIEW', label: STRINGS['MORE'], key: 'transaction_id', diff --git a/web/src/containers/Wallet/_Wallet.scss b/web/src/containers/Wallet/_Wallet.scss index 2b46bc9554..bae99b3f98 100644 --- a/web/src/containers/Wallet/_Wallet.scss +++ b/web/src/containers/Wallet/_Wallet.scss @@ -817,12 +817,11 @@ $header-margin: 2rem; } .layout-mobile { - .footer-button { - margin-top: 4%; - margin-bottom: 2%; - } .bottom-bar-button { padding: 3%; + position: sticky; + bottom: 0%; + background: $app-background-color; display: flex; justify-content: space-around; diff --git a/web/src/containers/Withdraw/Withdraw.js b/web/src/containers/Withdraw/Withdraw.js index 45195ecd9a..593eceab12 100644 --- a/web/src/containers/Withdraw/Withdraw.js +++ b/web/src/containers/Withdraw/Withdraw.js @@ -210,7 +210,6 @@ const RenderWithdraw = ({ setCurrStep({ ...currStep, stepTwo: true }); } setCurrStep({ ...currStep, stepTwo: true, stepThree: true }); - getWithdrawMAx(defaultCurrency); setWithdrawOptionaltag(null); } else { setSelectedAsset((prev) => ({ ...prev, selectedCurrency: null })); @@ -247,6 +246,20 @@ const RenderWithdraw = ({ } }, [getWithdrawCurrency, isWithdrawal]); + useEffect(() => { + const networkOption = defaultNetwork?.split(',')?.length; + if (defaultCurrency) { + if ( + selectedMethod === 'Email' || + networkOption <= 1 || + selectedAsset?.networkData + ) { + getWithdrawMAx(defaultCurrency); + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [getWithdrawNetworkOptions, selectedMethod]); + const isAmount = useMemo(() => { const isCondition = selectedMethod === STRINGS['FORM_FIELDS.EMAIL_LABEL'] @@ -351,7 +364,6 @@ const RenderWithdraw = ({ } setWithdrawCurrency(val); network = val ? val : coins[getWithdrawCurrency]?.symbol; - getWithdrawMAx(val); setWithdrawNetworkOptions(''); setIsValidAdress(false); setIsValidField((prev) => ({ ...prev, isValidEmail: false })); diff --git a/web/src/index.css b/web/src/index.css index 6de62eb6f4..eb2d3ba96e 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -2222,12 +2222,11 @@ table th { display: flex; justify-content: center; } -.layout-mobile .footer-button { - margin-top: 4%; - margin-bottom: 2%; } - .layout-mobile .bottom-bar-button { padding: 3%; + position: sticky; + bottom: 0%; + background: var(--base_background); display: flex; justify-content: space-around; } .layout-mobile .bottom-bar-button .bottom-bar-deposit-button, @@ -3217,6 +3216,14 @@ table th { .history_block-wrapper .loader_wrapper { top: 0; left: 0; } + .history_block-wrapper .transactions-history-table .table_body-wrapper .expandable-container .custom-row-line { + width: 5px; + height: 1px; + background-color: var(--labels_important-active-labels-text-graphics); } + .history_block-wrapper .transactions-history-table .table_body-wrapper .expandable-container .blue-link .edit-wrapper__container { + text-decoration: underline !important; } + .history_block-wrapper .transactions-history-table .table_body-wrapper .expandable-container .blue-link:hover { + cursor: pointer; } .history_block-wrapper .table-wrapper .table_body-wrapper.with_icon tr td:first-child { border-top: 1px solid var(--calculated_secondary-border) !important; border-bottom: 1px solid var(--calculated_secondary-border) !important; } From c3da74b9ef8ecedf63fd32dcc818322faca12f45 Mon Sep 17 00:00:00 2001 From: ram Date: Wed, 14 Aug 2024 19:11:57 +0530 Subject: [PATCH 076/108] Updated the deposit withdraw tab in history page and max amount issue in withdraw page --- web/src/containers/TransactionsHistory/index.js | 8 ++++---- web/src/containers/TransactionsHistory/utils.js | 7 +++---- web/src/containers/Withdraw/Withdraw.js | 10 ++++++---- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/web/src/containers/TransactionsHistory/index.js b/web/src/containers/TransactionsHistory/index.js index f3fd8539f7..ff04c71dda 100644 --- a/web/src/containers/TransactionsHistory/index.js +++ b/web/src/containers/TransactionsHistory/index.js @@ -295,15 +295,13 @@ class TransactionsHistory extends Component { symbol, coins, withdrawalPopup, - ICONS, - 'deposit' + ICONS ), withdrawals: generateWithdrawalsHeaders( symbol, coins, withdrawalPopup, - ICONS, - 'withdraw' + ICONS ), }, }); @@ -698,6 +696,8 @@ class TransactionsHistory extends Component { props.noData = prepareNoData('NO_ACTIVE_WITHDRAWALS'); props.refetchData = () => this.requestData(activeTab); props.onHandleView = () => this.onHandleView(); + props.expandableRow = true; + props.expandableContent = this.getExpandableRowContentForDeposit; break; default: return
; diff --git a/web/src/containers/TransactionsHistory/utils.js b/web/src/containers/TransactionsHistory/utils.js index 2ee5397850..5de92c2b66 100644 --- a/web/src/containers/TransactionsHistory/utils.js +++ b/web/src/containers/TransactionsHistory/utils.js @@ -665,8 +665,7 @@ export const generateWithdrawalsHeaders = ( symbol, coins = {}, withdrawalPopup, - ICONS, - type + ICONS ) => { return [ // { @@ -685,7 +684,7 @@ export const generateWithdrawalsHeaders = ( // ); // }, // }, - type === 'deposit' && { + { key: 'icon', className: 'sticky-col', renderCell: ( @@ -833,7 +832,7 @@ export const generateWithdrawalsHeaders = ( ); }, }, - type === 'withdraw' && { + { stringId: 'MORE,CANCEL,VIEW', label: STRINGS['MORE'], key: 'transaction_id', diff --git a/web/src/containers/Withdraw/Withdraw.js b/web/src/containers/Withdraw/Withdraw.js index 593eceab12..3bbcebf516 100644 --- a/web/src/containers/Withdraw/Withdraw.js +++ b/web/src/containers/Withdraw/Withdraw.js @@ -167,6 +167,7 @@ const RenderWithdraw = ({ : coins[defaultCurrency]?.symbol; const isWithdrawal = coins[getWithdrawCurrency]?.allow_withdrawal; const isValidUserEmail = isValidField?.isValidEmail; + const { selectedCurrency } = selectedAsset; useEffect(() => { const topWallet = assets @@ -250,15 +251,16 @@ const RenderWithdraw = ({ const networkOption = defaultNetwork?.split(',')?.length; if (defaultCurrency) { if ( - selectedMethod === 'Email' || - networkOption <= 1 || - selectedAsset?.networkData + selectedCurrency && + (selectedMethod === 'Email' || + networkOption <= 1 || + selectedAsset?.networkData) ) { getWithdrawMAx(defaultCurrency); } } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [getWithdrawNetworkOptions, selectedMethod]); + }, [getWithdrawNetworkOptions, selectedMethod, selectedCurrency]); const isAmount = useMemo(() => { const isCondition = From 9602543b931023ad8a23bbcab6f42b71ce2ce05f Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Thu, 15 Aug 2024 00:27:23 +0900 Subject: [PATCH 077/108] docs: update server/README.md langauge -> language --- server/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/README.md b/server/README.md index ae1b784b80..82701b8256 100644 --- a/server/README.md +++ b/server/README.md @@ -47,7 +47,7 @@ This folder holds the `swagger.yaml` file that contains all the endpoints for th - Database used is `postgreSQL` - mail - This directory holds everything relevant to emails. - - The `strings` directory holds all the strings that contain email messages. They are separated by langauge e.g. `en.js`, `fa.js`, etc. + - The `strings` directory holds all the strings that contain email messages. They are separated by language e.g. `en.js`, `fa.js`, etc. - The `templates` directory holds all the email templates. They are separated by the emails being send e.g. `welcome.js`, `deposit.js`, etc. - The library used for emails is `Nodemailer`. - config From 69b2a8201dadd217c56225d74285deb08c823068 Mon Sep 17 00:00:00 2001 From: Ali Beikverdi Date: Fri, 16 Aug 2024 03:15:36 +0900 Subject: [PATCH 078/108] admin tag fix --- server/api/swagger/admin.yaml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/server/api/swagger/admin.yaml b/server/api/swagger/admin.yaml index 6366b730c9..d0339f95a2 100644 --- a/server/api/swagger/admin.yaml +++ b/server/api/swagger/admin.yaml @@ -3073,8 +3073,7 @@ paths: operationId: createUserWalletByAdmin description: Create a crypto address for the user by admin tags: - - User - - Wallet + - Admin parameters: - name: data in: body @@ -3402,7 +3401,7 @@ paths: description: Get user referral codes for admin operationId: getUserReferralCodesByAdmin tags: - - User + - Admin parameters: - name: user_id in: query @@ -3468,7 +3467,7 @@ paths: operationId: createUserReferralCodeByAdmin description: create referral code config for user by admin tags: - - User + - Admin parameters: - name: data in: body @@ -3994,7 +3993,7 @@ paths: description: Get p2p disputes operationId: fetchP2PDisputes tags: - - User + - Admin parameters: - in: query name: user_id @@ -4169,7 +4168,7 @@ paths: operationId: performDirectWithdrawalByAdmin description: Make a withdrawal without email confirmation for admin tags: - - User + - Admin parameters: - name: data in: body From 5ba627f63b71e14ae830dc530f91687bbf653787 Mon Sep 17 00:00:00 2001 From: Yechan Kim Date: Sat, 17 Aug 2024 00:13:19 +0900 Subject: [PATCH 079/108] Remove dev nginx logs placeholder --- server/tools/nginx-dev/logs/error.log | 0 server/tools/nginx-dev/logs/hollaex.access.log | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 server/tools/nginx-dev/logs/error.log delete mode 100644 server/tools/nginx-dev/logs/hollaex.access.log diff --git a/server/tools/nginx-dev/logs/error.log b/server/tools/nginx-dev/logs/error.log deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/server/tools/nginx-dev/logs/hollaex.access.log b/server/tools/nginx-dev/logs/hollaex.access.log deleted file mode 100644 index e69de29bb2..0000000000 From 3ea569c53295f191d829e7630838ce5a719e2d2e Mon Sep 17 00:00:00 2001 From: fetok12 Date: Fri, 16 Aug 2024 19:16:59 +0300 Subject: [PATCH 080/108] add-size-price-check-broker-token-creation --- server/utils/hollaex-tools-lib/tools/broker.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/server/utils/hollaex-tools-lib/tools/broker.js b/server/utils/hollaex-tools-lib/tools/broker.js index 089a51babb..412d559829 100644 --- a/server/utils/hollaex-tools-lib/tools/broker.js +++ b/server/utils/hollaex-tools-lib/tools/broker.js @@ -37,7 +37,9 @@ const { REBALANCE_SYMBOL_MISSING, PRICE_NOT_FOUND, QUOTE_EXPIRY_TIME_ERROR, - FAILED_GET_QUOTE + FAILED_GET_QUOTE, + INVALID_SIZE, + INVALID_PRICE } = require(`${SERVER_PATH}/messages`); const validateBrokerPair = (brokerPair) => { @@ -289,6 +291,14 @@ const calculatePrice = async (side, spread, formula, refresh_interval, brokerId, }; const generateRandomToken = (user_id, symbol, side, expiryTime = 30, price, size, type) => { + if (!size) { + throw new Error(INVALID_SIZE); + }; + + if (!price) { + throw new Error(INVALID_PRICE); + }; + // Generate random token const randomToken = randomString({ length: 32, From 0744fee2f3dfc85a90789d2206a759c9a0f5d239 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Sat, 17 Aug 2024 21:45:32 +0300 Subject: [PATCH 081/108] dynamic rate --- server/api/controllers/p2p.js | 6 + server/api/swagger/p2p.yaml | 4 + .../20240801746328-add-p2p-dynamic-type.js | 14 ++ server/db/models/p2pDeal.js | 4 + server/utils/hollaex-tools-lib/tools/p2p.js | 48 +++++- web/src/containers/P2P/P2PPostDeal.js | 138 ++++++++++++++++-- web/src/containers/P2P/_P2P.scss | 3 + 7 files changed, 201 insertions(+), 16 deletions(-) create mode 100644 server/db/migrations/20240801746328-add-p2p-dynamic-type.js diff --git a/server/api/controllers/p2p.js b/server/api/controllers/p2p.js index 635cde5098..b80d8e448e 100644 --- a/server/api/controllers/p2p.js +++ b/server/api/controllers/p2p.js @@ -10,6 +10,7 @@ const createP2PDeal = (req, res) => { const { price_type, + dynamic_pair, buying_asset, spending_asset, exchange_rate, @@ -28,6 +29,7 @@ const createP2PDeal = (req, res) => { req.uuid, 'controllers/p2p/createP2PDeal data', price_type, + dynamic_pair, buying_asset, spending_asset, exchange_rate, @@ -45,6 +47,7 @@ const createP2PDeal = (req, res) => { merchant_id: req.auth.sub.id, side, price_type, + dynamic_pair, buying_asset, spending_asset, exchange_rate, @@ -76,6 +79,7 @@ const updateP2PDeal = (req, res) => { const { price_type, + dynamic_pair, buying_asset, spending_asset, exchange_rate, @@ -97,6 +101,7 @@ const updateP2PDeal = (req, res) => { req.uuid, 'controllers/p2p/updateP2PDeal data', price_type, + dynamic_pair, buying_asset, spending_asset, exchange_rate, @@ -117,6 +122,7 @@ const updateP2PDeal = (req, res) => { edited_ids, side, price_type, + dynamic_pair, buying_asset, spending_asset, exchange_rate, diff --git a/server/api/swagger/p2p.yaml b/server/api/swagger/p2p.yaml index 678f3aa8e2..9c081ec3ab 100644 --- a/server/api/swagger/p2p.yaml +++ b/server/api/swagger/p2p.yaml @@ -86,6 +86,8 @@ paths: properties: price_type: type: string + dynamic_pair: + type: string buying_asset: type: string spending_asset: @@ -148,6 +150,8 @@ paths: properties: price_type: type: string + dynamic_pair: + type: string buying_asset: type: string spending_asset: diff --git a/server/db/migrations/20240801746328-add-p2p-dynamic-type.js b/server/db/migrations/20240801746328-add-p2p-dynamic-type.js new file mode 100644 index 0000000000..9526b8c1b8 --- /dev/null +++ b/server/db/migrations/20240801746328-add-p2p-dynamic-type.js @@ -0,0 +1,14 @@ +'use strict'; + +const TABLE = 'P2pDeals'; +const COLUMN = 'dynamic_pair'; + +module.exports = { + up: (queryInterface, Sequelize) => + queryInterface.addColumn(TABLE, COLUMN, { + type: Sequelize.STRING, + allowNull: true + }), + down: (queryInterface) => + queryInterface.removeColumn(TABLE, COLUMN) +}; \ No newline at end of file diff --git a/server/db/models/p2pDeal.js b/server/db/models/p2pDeal.js index 69e6b3faf8..2107855108 100644 --- a/server/db/models/p2pDeal.js +++ b/server/db/models/p2pDeal.js @@ -39,6 +39,10 @@ module.exports = function (sequelize, DataTypes) { type: DataTypes.DOUBLE, allowNull: true, }, + dynamic_pair: { + type: DataTypes.STRING, + allowNull: true, + }, spread: { type: DataTypes.DOUBLE, allowNull: true, diff --git a/server/utils/hollaex-tools-lib/tools/p2p.js b/server/utils/hollaex-tools-lib/tools/p2p.js index 76c2dcfdc8..0595070fbc 100644 --- a/server/utils/hollaex-tools-lib/tools/p2p.js +++ b/server/utils/hollaex-tools-lib/tools/p2p.js @@ -5,8 +5,9 @@ const { SERVER_PATH } = require('../constants'); const { getNodeLib } = require(`${SERVER_PATH}/init`); const { P2P_SUPPORTED_PLANS } = require(`${SERVER_PATH}/constants`); const { getUserByKitId } = require('./user'); -const { subscribedToCoin, getKitConfig } = require('./common'); +const { subscribedToCoin, getKitConfig, subscribedToPair } = require('./common'); const { transferAssetByKitIds, getUserBalanceByKitId } = require('./wallet'); +const { testBroker } = require('./broker'); const { Op } = require('sequelize'); const BigNumber = require('bignumber.js'); const { getKitCoin } = require('./common'); @@ -15,6 +16,7 @@ const dbQuery = require('./database/query'); const uuid = require('uuid/v4'); const { parse } = require('json2csv'); const moment = require('moment'); +const { client } = require('./database/redis'); const { sendEmail } = require('../../../mail'); const { MAILTYPE } = require('../../../mail/strings'); @@ -114,7 +116,30 @@ const fetchP2PDeals = async (opts = { } }); } else { - return dbQuery.findAndCountAllWithRows('p2pDeal', query); + const p2pDeals = await client.getAsync(`p2p-deals`); + + if (p2pDeals) return JSON.parse(p2pDeals); + else { + const deals = await dbQuery.findAndCountAllWithRows('p2pDeal', query); + const brokers = await getModel('broker').findAll({ type: 'dynamic' }); + for (let deal of (deals?.data || [])) { + if (deal.dynamic_pair) { + const broker = brokers.find(broker => broker.symbol === deal.dynamic_pair); + const { formula, increment_size } = broker; + + const result = await testBroker({ + formula, + increment_size, + spread: 1 + }); + + deal.exchange_rate = result.buy_price; + } + } + + await client.setexAsync(`p2p-deals`, 30, JSON.stringify(deals)); + return deals; + } } }; @@ -206,6 +231,8 @@ const createP2PDeal = async (data) => { total_order_amount, min_order_value, max_order_value, + price_type, + dynamic_pair, } = data; const exchangeInfo = getKitConfig().info; @@ -231,6 +258,10 @@ const createP2PDeal = async (data) => { throw new Error('Invalid coin ' + buying_asset); }; + if (price_type === 'dynamic' && !subscribedToPair(dynamic_pair)) { + throw new Error('Invalid pair ' + dynamic_pair); + }; + const balance = await getP2PAccountBalance(merchant_id, buying_asset); if (new BigNumber(balance).comparedTo(new BigNumber(total_order_amount)) !== 1) { @@ -253,12 +284,13 @@ const createP2PDeal = async (data) => { throw new Error('spread cannot be less than 0'); }; - if (exchange_rate < 0) { + if (price_type === 'static' && exchange_rate < 0) { throw new Error('exchange rate cannot be less than 0'); }; data.status = true; + return getModel('p2pDeal').create(data, { fields: [ 'merchant_id', @@ -267,6 +299,7 @@ const createP2PDeal = async (data) => { 'buying_asset', 'spending_asset', 'exchange_rate', + 'dynamic_pair', 'spread', 'total_order_amount', 'min_order_value', @@ -292,6 +325,8 @@ const updateP2PDeal = async (data) => { total_order_amount, min_order_value, max_order_value, + price_type, + dynamic_pair, payment_method_used, status, } = data; @@ -337,6 +372,10 @@ const updateP2PDeal = async (data) => { throw new Error('Invalid coin ' + buying_asset); }; + if (price_type === 'dynamic' && !subscribedToPair(dynamic_pair)) { + throw new Error('Invalid pair ' + dynamic_pair); + }; + const balance = await getP2PAccountBalance(merchant_id, buying_asset); if (new BigNumber(balance).comparedTo(new BigNumber(total_order_amount)) !== 1) { @@ -358,7 +397,7 @@ const updateP2PDeal = async (data) => { throw new Error('spread cannot be less than 0'); }; - if (exchange_rate < 0) { + if (price_type === 'static' && exchange_rate < 0) { throw new Error('exchange rate cannot be less than 0'); }; @@ -375,6 +414,7 @@ const updateP2PDeal = async (data) => { 'buying_asset', 'spending_asset', 'exchange_rate', + 'dynamic_pair', 'spread', 'total_order_amount', 'min_order_value', diff --git a/web/src/containers/P2P/P2PPostDeal.js b/web/src/containers/P2P/P2PPostDeal.js index 803e1707e7..7540b51fd3 100644 --- a/web/src/containers/P2P/P2PPostDeal.js +++ b/web/src/containers/P2P/P2PPostDeal.js @@ -4,6 +4,8 @@ import { connect } from 'react-redux'; import { ReactSVG } from 'react-svg'; import { Button, Steps, message, Modal } from 'antd'; import { IconTitle, EditWrapper } from 'components'; +import { getBroker } from 'containers/Admin/Trades/actions'; +import { createTestBroker } from 'containers/Admin/Trades/actions'; import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; import { Switch, Select, Input, InputNumber } from 'antd'; @@ -50,6 +52,9 @@ const P2PPostDeal = ({ const [selectedMethod, setSelectedMethod] = useState({}); const [addMethodDetails, setAddMethodDetails] = useState(); const [region, setRegion] = useState(); + const [brokerData, setBrokerData] = useState([]); + const [dynamicPair, setDynamicPair] = useState(); + const [dynamicRate, setDynamicRate] = useState(); const dataSte = [ { @@ -95,8 +100,38 @@ const P2PPostDeal = ({ setRegion(); setStep(1); } + + getBrokerData(); }, [selectedDealEdit]); + const getBrokerData = async () => { + try { + const res = await getBroker(); + setBrokerData(res); + } catch (error) { + if (error) { + message.error(error.message); + } + } + }; + + const getDynamicRate = async (pair) => { + try { + const broker = brokerData.find((broker) => broker.symbol === pair); + const { formula, increment_size } = broker; + const result = await createTestBroker({ + formula, + increment_size, + spread: 1, + }); + + setDynamicRate(result.data.buy_price); + } catch (error) { + if (error) { + message.error(error.message); + } + } + }; const formatAmount = (currency, amount) => { const formattedAmount = new BigNumber(amount).decimalPlaces(4).toNumber(); return formattedAmount; @@ -139,7 +174,10 @@ const P2PPostDeal = ({ justifyContent: 'center', }} > - + {STRINGS['P2P.I_WANT_TO_BUY']} @@ -278,12 +316,13 @@ const P2PPostDeal = ({
- {/*
- +
+ {/* {STRINGS['P2P.PRICE_UPPER']} - -
*/} - {/*
+ */} + TYPE: +
+
-
*/} +
{priceType === 'static' && ( <> @@ -324,6 +364,41 @@ const P2PPostDeal = ({
)} + + {priceType === 'dynamic' && ( + <> +
+ + {STRINGS['P2P.PRICE_UPPER']} + {' '} + {spendingAsset + ? `(${spendingAsset?.toUpperCase()})` + : ''} +
+
+ +
+
Rate: {formatAmount('', dynamicRate) || '-'}
+ + )} +
{STRINGS['P2P.SPREAD_PERCENTAGE']} @@ -382,6 +457,31 @@ const P2PPostDeal = ({
)} + + {dynamicRate && ( +
+
+ + {STRINGS['P2P.UNIT_PRICE']} + +
+
+ {formatRate(dynamicRate, spread, spendingAsset)} +
+
+ {p2pSide === 'sell' ? ( + + {STRINGS['P2P.PRICE_ADVERTISE_SELL']} + + ) : ( + + {STRINGS['P2P.PRICE_ADVERTISE_BUY']} + + )}{' '} + {buyingAsset ? `${buyingAsset?.toUpperCase()}` : ''} +
+
+ )}
)} @@ -486,7 +586,11 @@ const P2PPostDeal = ({ {minOrderValue ? ( minOrderValue / - formatRate(exchangeRate, spread, spendingAsset) + formatRate( + exchangeRate || dynamicRate, + spread, + spendingAsset + ) ).toFixed(4) + ' ' + buyingAsset?.toUpperCase() @@ -510,7 +614,11 @@ const P2PPostDeal = ({ {maxOrderValue ? ( maxOrderValue / - formatRate(exchangeRate, spread, spendingAsset) + formatRate( + exchangeRate || dynamicRate, + spread, + spendingAsset + ) ).toFixed(4) + ' ' + buyingAsset?.toUpperCase() @@ -818,7 +926,11 @@ const P2PPostDeal = ({ onClick={async () => { if ( step === 1 && - (!priceType || !buyingAsset || !spendingAsset || !exchangeRate) + (!priceType || + !buyingAsset || + !spendingAsset || + (priceType === 'static' && !exchangeRate) || + (priceType === 'dynamic' && !dynamicRate)) ) { message.error(STRINGS['P2P.PLEASE_FILL_INPUTS']); return; @@ -855,9 +967,10 @@ const P2PPostDeal = ({ id: selectedDealEdit.id, side: p2pSide, price_type: priceType, + dynamic_pair: dynamicPair, buying_asset: buyingAsset, spending_asset: spendingAsset, - exchange_rate: Number(exchangeRate), + exchange_rate: Number(exchangeRate || 0), spread: Number(spread), region, total_order_amount: Number(totalOrderAmount), @@ -872,9 +985,10 @@ const P2PPostDeal = ({ await postDeal({ side: p2pSide, price_type: priceType, + dynamic_pair: dynamicPair, buying_asset: buyingAsset, spending_asset: spendingAsset, - exchange_rate: Number(exchangeRate), + exchange_rate: Number(exchangeRate || 0), spread: Number(spread), region, total_order_amount: Number(totalOrderAmount), diff --git a/web/src/containers/P2P/_P2P.scss b/web/src/containers/P2P/_P2P.scss index 644e17e8c6..a0352ddb6f 100644 --- a/web/src/containers/P2P/_P2P.scss +++ b/web/src/containers/P2P/_P2P.scss @@ -37,6 +37,9 @@ color: var(--calculated_base_top-bar-navigation_text) !important; border: none; } +.redTextP2P { + color: var(--calculated_base_top-bar-navigation_text) !important; +} .greyButtonP2P { background-color: var(--labels_inactive-button) !important; color: var(--calculated_base_top-bar-navigation_text) !important; From eabf73d8f210df909c382c36a07b9a988f3b5d87 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Mon, 19 Aug 2024 03:20:24 +0300 Subject: [PATCH 082/108] p2p-feedback --- server/api/controllers/p2p.js | 27 ++++++++ server/api/swagger/p2p.yaml | 33 ++++++++++ server/messages.js | 3 +- server/utils/hollaex-tools-lib/tools/p2p.js | 24 +++++++ web/src/config/lang/en.json | 1 + web/src/containers/Admin/Trades/p2pDeals.js | 30 +++++++++ .../containers/Admin/Trades/p2pSettings.js | 60 +++++++++-------- web/src/containers/P2P/P2PDash.js | 65 ++++++++----------- web/src/containers/P2P/P2PMyDeals.js | 25 ++++++- web/src/containers/P2P/P2PPostDeal.js | 22 ++++--- web/src/containers/P2P/_P2P.scss | 5 +- web/src/containers/P2P/actions/p2pActions.js | 9 +++ 12 files changed, 223 insertions(+), 81 deletions(-) diff --git a/server/api/controllers/p2p.js b/server/api/controllers/p2p.js index b80d8e448e..78079832bf 100644 --- a/server/api/controllers/p2p.js +++ b/server/api/controllers/p2p.js @@ -149,6 +149,32 @@ const updateP2PDeal = (req, res) => { return res.status(err.statusCode || 400).json({ message: errorMessageConverter(err) }); }); }; +const deleteP2PDeal = (req, res) => { + loggerP2P.verbose(req.uuid, 'controllers/p2p/deleteP2PDeal/auth', req.auth); + + const { + removed_ids + } = req.swagger.params.data.value; + + loggerP2P.verbose( + req.uuid, + 'controllers/p2p/deleteP2PDeal data', + removed_ids + ); + + toolsLib.p2p.deleteP2PDeal(removed_ids, req.auth.sub.id) + .then(() => { + return res.json({ message: 'Success' }); + }) + .catch((err) => { + loggerP2P.error( + req.uuid, + 'controllers/p2p/deleteP2PDeal err', + err.message + ); + return res.status(err.statusCode || 400).json({ message: errorMessageConverter(err) }); + }); +}; const fetchP2PDeals = (req, res) => { loggerP2P.verbose(req.uuid, 'controllers/p2p/fetchP2PDeals/auth', req.auth); @@ -551,6 +577,7 @@ module.exports = { updateP2PTransaction, fetchP2PDisputes, updateP2PDeal, + deleteP2PDeal, updateP2PDispute, createP2PFeedback, fetchP2PFeedbacks, diff --git a/server/api/swagger/p2p.yaml b/server/api/swagger/p2p.yaml index 9c081ec3ab..8a13e40582 100644 --- a/server/api/swagger/p2p.yaml +++ b/server/api/swagger/p2p.yaml @@ -210,6 +210,39 @@ paths: - hmac x-security-scopes: - user + delete: + description: Delete deal for p2p + operationId: deleteP2PDeal + tags: + - P2P + parameters: + - name: data + in: body + required: true + schema: + type: object + properties: + removed_ids: + type: array + items: + type: integer + format: int32 + responses: + 200: + description: Success + schema: + $ref: "#/definitions/ObjectResponse" + default: + description: Error + schema: + $ref: "#/definitions/MessageResponse" + security: + - Token: [] + x-security-types: + - bearer + - hmac + x-security-scopes: + - user /p2p/order: x-swagger-router-controller: p2p get: diff --git a/server/messages.js b/server/messages.js index 85d24e7fcd..557975aeaf 100644 --- a/server/messages.js +++ b/server/messages.js @@ -265,4 +265,5 @@ exports.WITHDRAWAL_DISABLED = 'Withdrawal disabled for this user'; exports.ADDRESSBOOK_MISSING_FIELDS = 'Each address must contain both address, network, currency and label fields'; exports.ADDRESSBOOK_ALREADY_EXISTS = 'Address label already exists in the payload'; exports.ADDRESSBOOK_NOT_FOUND = 'User address book not found'; -exports.PAYMENT_DETAIL_NOT_FOUND = 'Payment detail not found'; \ No newline at end of file +exports.PAYMENT_DETAIL_NOT_FOUND = 'Payment detail not found'; +exports.P2P_DEAL_NOT_FOUND = 'P2P Deal not found!'; \ No newline at end of file diff --git a/server/utils/hollaex-tools-lib/tools/p2p.js b/server/utils/hollaex-tools-lib/tools/p2p.js index 0595070fbc..5d7a5d6f95 100644 --- a/server/utils/hollaex-tools-lib/tools/p2p.js +++ b/server/utils/hollaex-tools-lib/tools/p2p.js @@ -24,6 +24,7 @@ const { NO_DATA_FOR_CSV, FUNDING_ACCOUNT_INSUFFICIENT_BALANCE, USER_NOT_FOUND, + P2P_DEAL_NOT_FOUND } = require(`${SERVER_PATH}/messages`); @@ -428,6 +429,28 @@ const updateP2PDeal = async (data) => { }); }; +const deleteP2PDeal = async (removed_ids, user_id) => { + const deals = await getModel('p2pDeal').findAll({ + where: { + id: removed_ids, + merchant_id: user_id + } + }); + + if (deals?.length === 0) { + throw new Error(P2P_DEAL_NOT_FOUND); + }; + + + const promises = deals.map(async (deal) => { + return await deal.destroy(); + }); + + const results = await Promise.all(promises); + return results; +}; + + const createP2PTransaction = async (data) => { let { deal_id, @@ -1167,6 +1190,7 @@ module.exports = { fetchP2PTransactions, fetchP2PDisputes, updateP2PDeal, + deleteP2PDeal, fetchP2PFeedbacks, fetchP2PProfile }; \ No newline at end of file diff --git a/web/src/config/lang/en.json b/web/src/config/lang/en.json index a9a082dbcb..9a483ebe02 100644 --- a/web/src/config/lang/en.json +++ b/web/src/config/lang/en.json @@ -2004,6 +2004,7 @@ "CHANGES_SAVED": "Changes saved", "ACTIVATE": "ACTIVATE", "TAKE_OFFLINE": "TAKE OFFLINE", + "REMOVE": "REMOVE", "EDIT": "Edit", "SIDE": "Side", "STATUS": "Status", diff --git a/web/src/containers/Admin/Trades/p2pDeals.js b/web/src/containers/Admin/Trades/p2pDeals.js index 4fa64484e1..395aa6c00c 100644 --- a/web/src/containers/Admin/Trades/p2pDeals.js +++ b/web/src/containers/Admin/Trades/p2pDeals.js @@ -43,6 +43,14 @@ const P2PDeals = ({ coins }) => { ); }, }, + { + title: 'Side', + dataIndex: 'side', + key: 'side', + render: (user_id, data) => { + return
{data?.side?.toUpperCase()}
; + }, + }, { title: 'Price', dataIndex: 'price', @@ -108,6 +116,28 @@ const P2PDeals = ({ coins }) => { return
{formatDate(data?.created_at)}
; }, }, + { + title: 'Edit', + dataIndex: 'edit', + key: 'edit', + render: (user_id, data) => { + return ( +
+ +
+ ); + }, + }, // { // title: 'Action', diff --git a/web/src/containers/Admin/Trades/p2pSettings.js b/web/src/containers/Admin/Trades/p2pSettings.js index e01baf9b7c..59d5843240 100644 --- a/web/src/containers/Admin/Trades/p2pSettings.js +++ b/web/src/containers/Admin/Trades/p2pSettings.js @@ -422,38 +422,36 @@ const P2PSettings = ({ coins, pairs, p2p_config, features, constants }) => { >
Crypto assets
Select the crypto assets that vendors can transact with
- {Object.values(coins || {}) - .filter((coin) => coin.symbol === 'usdt') - .map((coin) => { - return ( -
- { - if (e.target.checked) { - if (!digitalCurrencies.includes(coin.symbol)) { - setDigitalCurrencies([ - ...digitalCurrencies, - coin.symbol, - ]); - } - } else { - if (digitalCurrencies.includes(coin.symbol)) { - setDigitalCurrencies( - [...digitalCurrencies].filter( - (symbol) => symbol !== coin.symbol - ) - ); - } + {Object.values(coins || {}).map((coin) => { + return ( +
+ { + if (e.target.checked) { + if (!digitalCurrencies.includes(coin.symbol)) { + setDigitalCurrencies([ + ...digitalCurrencies, + coin.symbol, + ]); } - }} - > - {coin.fullname} ({coin?.symbol?.toUpperCase()}) - -
- ); - })} + } else { + if (digitalCurrencies.includes(coin.symbol)) { + setDigitalCurrencies( + [...digitalCurrencies].filter( + (symbol) => symbol !== coin.symbol + ) + ); + } + } + }} + > + {coin.fullname} ({coin?.symbol?.toUpperCase()}) +
+
+ ); + })} )} diff --git a/web/src/containers/P2P/P2PDash.js b/web/src/containers/P2P/P2PDash.js index 404fd21a9e..4699bc8489 100644 --- a/web/src/containers/P2P/P2PDash.js +++ b/web/src/containers/P2P/P2PDash.js @@ -18,7 +18,11 @@ import { COUNTRIES_OPTIONS } from 'utils/countries'; import { formatToCurrency } from 'utils/currency'; import { isMobile } from 'react-device-detect'; import classnames from 'classnames'; -import { CloseOutlined } from '@ant-design/icons'; +import { + CloseOutlined, + PlusSquareOutlined, + MinusSquareOutlined, +} from '@ant-design/icons'; import { fetchFeedback, fetchP2PProfile } from './actions/p2pActions'; import './_P2P.scss'; @@ -550,7 +554,13 @@ const P2PDash = ({ }} className="td-fit" > - +{' '} + + {expandRow ? ( + + ) : ( + + )} + {' '} {deal.merchant.full_name || ( @@ -589,41 +599,22 @@ const P2PDash = ({ setAmountFiat(); }} > - {deal.side === 'sell' ? ( - <> -
- - {STRINGS['P2P.AVAILABLE']} - - : {deal.total_order_amount}{' '} - {deal.buying_asset.toUpperCase()} -
-
- - {STRINGS['P2P.LIMIT']} - - : {deal.min_order_value} - {deal.max_order_value}{' '} - {deal.spending_asset.toUpperCase()} -
- - ) : ( - <> -
- - {STRINGS['P2P.AVAILABLE']} - - : {deal.total_order_amount}{' '} - {deal.spending_asset.toUpperCase()} -
-
- - {STRINGS['P2P.LIMIT']} - - : {deal.min_order_value} - {deal.max_order_value}{' '} - {deal.buying_asset.toUpperCase()} -
- - )} + <> +
+ + {STRINGS['P2P.AVAILABLE']} + + : {deal.total_order_amount}{' '} + {deal.buying_asset.toUpperCase()} +
+
+ + {STRINGS['P2P.LIMIT']} + + : {deal.min_order_value} - {deal.max_order_value}{' '} + {deal.spending_asset.toUpperCase()} +
+
-
-
- {data?.address} - { - handleCopy(); - }} - > - - + renderCell: (data, key) => { + const hasOptionalTag = data?.address?.split(':')[0]; + return ( +
+
+
+ {hasOptionalTag ? hasOptionalTag : data?.address} + { + handleCopy(); + }} + > + + +
- -
+
+ {isExpanded ? : } +
+
+ + +
diff --git a/web/src/containers/P2P/P2PPostDeal.js b/web/src/containers/P2P/P2PPostDeal.js index 7540b51fd3..9d631dd075 100644 --- a/web/src/containers/P2P/P2PPostDeal.js +++ b/web/src/containers/P2P/P2PPostDeal.js @@ -175,8 +175,8 @@ const P2PPostDeal = ({ }} > {STRINGS['P2P.I_WANT_TO_BUY']} @@ -186,6 +186,7 @@ const P2PPostDeal = ({ { + if (step !== 1) return; if (p2p_config.side === 'sell' && !checked) return; if (p2p_config.side === 'buy' && checked) return; @@ -197,7 +198,10 @@ const P2PPostDeal = ({ }} /> - + {STRINGS['P2P.I_WANT_TO_SELL']} @@ -252,13 +256,11 @@ const P2PPostDeal = ({ setBuyingAsset(e); }} > - {p2p_config?.digital_currencies - .filter((coin) => coin === 'usdt') - .map((coin) => ( - - {coin?.toUpperCase()} - - ))} + {p2p_config?.digital_currencies.map((coin) => ( + + {coin?.toUpperCase()} + + ))}
diff --git a/web/src/containers/P2P/_P2P.scss b/web/src/containers/P2P/_P2P.scss index a0352ddb6f..b80b6e693a 100644 --- a/web/src/containers/P2P/_P2P.scss +++ b/web/src/containers/P2P/_P2P.scss @@ -38,7 +38,10 @@ border: none; } .redTextP2P { - color: var(--calculated_base_top-bar-navigation_text) !important; + color: var(--trading_selling-related-elements) !important; +} +.greenTextP2P { + color: var(--specials_checks-okay-done) !important; } .greyButtonP2P { background-color: var(--labels_inactive-button) !important; diff --git a/web/src/containers/P2P/actions/p2pActions.js b/web/src/containers/P2P/actions/p2pActions.js index 890f6edc53..1c749e7b11 100644 --- a/web/src/containers/P2P/actions/p2pActions.js +++ b/web/src/containers/P2P/actions/p2pActions.js @@ -31,6 +31,15 @@ export const editDeal = (values) => { return requestAuthenticated('/p2p/deal', options); }; +export const removeDeal = (values) => { + const options = { + method: 'DELETE', + body: JSON.stringify(values), + }; + + return requestAuthenticated('/p2p/deal', options); +}; + export const createTransaction = (values) => { const options = { method: 'POST', From 4bbccee376130e47c3fad0d5b49131d9e30debe2 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Mon, 19 Aug 2024 05:39:35 +0300 Subject: [PATCH 083/108] p2p-feedback --- server/utils/hollaex-tools-lib/tools/p2p.js | 16 +++++++++++++++- web/src/containers/P2P/P2POrder.js | 10 +++++++++- web/src/containers/P2P/P2POrders.js | 5 ++++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/server/utils/hollaex-tools-lib/tools/p2p.js b/server/utils/hollaex-tools-lib/tools/p2p.js index 5d7a5d6f95..ad04c5225f 100644 --- a/server/utils/hollaex-tools-lib/tools/p2p.js +++ b/server/utils/hollaex-tools-lib/tools/p2p.js @@ -472,7 +472,8 @@ const createP2PTransaction = async (data) => { const p2pDeal = await getModel('p2pDeal').findOne({ where: { id: deal_id } }); - const { max_order_value, min_order_value, exchange_rate, spread } = p2pDeal; + const { max_order_value, min_order_value, spread, price_type } = p2pDeal; + let { exchange_rate } = p2pDeal; const { merchant_id } = p2pDeal; if (!p2pDeal) { @@ -512,6 +513,19 @@ const createP2PTransaction = async (data) => { const merchantBalance = await getP2PAccountBalance(side === 'buy' ? user_id : merchant_id, p2pDeal.buying_asset); + if (price_type === 'dynamic') { + const broker = await getModel('broker').findOne({ type: 'dynamic', symbol: p2pDeal.dynamic_pair }); + const { formula, increment_size } = broker; + + const result = await testBroker({ + formula, + increment_size, + spread: 1 + }); + + exchange_rate = result.buy_price; + + } const price = new BigNumber(exchange_rate).multipliedBy(p2pDeal.side === 'sell' ? (1 + (spread / 100)) : (1 - (spread / 100))); const amount_digital_currency = new BigNumber(amount_fiat).dividedBy(price).toNumber(); diff --git a/web/src/containers/P2P/P2POrder.js b/web/src/containers/P2P/P2POrder.js index 3df85d1a78..b8139c6b01 100644 --- a/web/src/containers/P2P/P2POrder.js +++ b/web/src/containers/P2P/P2POrder.js @@ -285,6 +285,11 @@ const P2POrder = ({ setLastClickTime(now); } }; + const formatAmount = (currency, amount) => { + const min = coins[currency].min; + const formattedAmount = formatToCurrency(amount, min); + return formattedAmount; + }; return ( <> @@ -1074,7 +1079,10 @@ const P2POrder = ({
- {selectedOrder?.price}{' '} + {formatAmount( + selectedOrder?.deal?.spending_asset, + selectedOrder?.price + )}{' '} {selectedOrder?.deal?.spending_asset?.toUpperCase()}
diff --git a/web/src/containers/P2P/P2POrders.js b/web/src/containers/P2P/P2POrders.js index 5b557eb393..81d410de48 100644 --- a/web/src/containers/P2P/P2POrders.js +++ b/web/src/containers/P2P/P2POrders.js @@ -190,7 +190,10 @@ const P2POrders = ({ {transaction?.deal?.spending_asset?.toUpperCase()}
- {transaction?.price}{' '} + {formatAmount( + transaction?.deal?.buying_asset, + transaction?.price + )}{' '} {transaction?.deal?.buying_asset?.toUpperCase()} From 024851961304a76f4e50ed13a569f1958f19468f Mon Sep 17 00:00:00 2001 From: fetok12 Date: Mon, 19 Aug 2024 05:57:39 +0300 Subject: [PATCH 084/108] p2p-feedback --- server/init.js | 2 +- web/src/containers/Admin/Trades/p2pDeals.js | 44 ++++++++++---------- web/src/containers/P2P/P2PPostDeal.js | 19 +++++---- web/src/containers/P2P/actions/p2pActions.js | 6 +++ 4 files changed, 39 insertions(+), 32 deletions(-) diff --git a/server/init.js b/server/init.js index 29476826b4..5ba9ea128c 100644 --- a/server/init.js +++ b/server/init.js @@ -125,7 +125,7 @@ const checkStatus = () => { status.constants ), Tier.findAll(), - Broker.findAll({ attributes: ['id', 'symbol', 'buy_price', 'sell_price', 'paused', 'min_size', 'max_size']}), + Broker.findAll({ attributes: ['id', 'symbol', 'buy_price', 'sell_price', 'paused', 'min_size', 'max_size', 'type' ]}), QuickTrade.findAll(), TransactionLimit.findAll(), status.dataValues diff --git a/web/src/containers/Admin/Trades/p2pDeals.js b/web/src/containers/Admin/Trades/p2pDeals.js index 395aa6c00c..260e3190fd 100644 --- a/web/src/containers/Admin/Trades/p2pDeals.js +++ b/web/src/containers/Admin/Trades/p2pDeals.js @@ -116,28 +116,28 @@ const P2PDeals = ({ coins }) => { return
{formatDate(data?.created_at)}
; }, }, - { - title: 'Edit', - dataIndex: 'edit', - key: 'edit', - render: (user_id, data) => { - return ( -
- -
- ); - }, - }, + // { + // title: 'Edit', + // dataIndex: 'edit', + // key: 'edit', + // render: (user_id, data) => { + // return ( + //
+ // + //
+ // ); + // }, + // }, // { // title: 'Action', diff --git a/web/src/containers/P2P/P2PPostDeal.js b/web/src/containers/P2P/P2PPostDeal.js index 9d631dd075..28778395f8 100644 --- a/web/src/containers/P2P/P2PPostDeal.js +++ b/web/src/containers/P2P/P2PPostDeal.js @@ -9,7 +9,7 @@ import { createTestBroker } from 'containers/Admin/Trades/actions'; import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; import { Switch, Select, Input, InputNumber } from 'antd'; -import { postDeal, editDeal } from './actions/p2pActions'; +import { postDeal, editDeal, getQuickTrade } from './actions/p2pActions'; import { CloseOutlined } from '@ant-design/icons'; import { formatToCurrency } from 'utils/currency'; import { COUNTRIES_OPTIONS } from 'utils/countries'; @@ -25,6 +25,7 @@ const P2PPostDeal = ({ pairs, constants = {}, icons: ICONS, + broker, transaction_limits, tiers = {}, p2p_config, @@ -106,7 +107,7 @@ const P2PPostDeal = ({ const getBrokerData = async () => { try { - const res = await getBroker(); + const res = broker; setBrokerData(res); } catch (error) { if (error) { @@ -117,15 +118,14 @@ const P2PPostDeal = ({ const getDynamicRate = async (pair) => { try { - const broker = brokerData.find((broker) => broker.symbol === pair); - const { formula, increment_size } = broker; - const result = await createTestBroker({ - formula, - increment_size, - spread: 1, + const assets = pair.split('-'); + const result = await getQuickTrade({ + spending_currency: assets[0], + receiving_currency: assets[1], + spending_amount: 1, }); - setDynamicRate(result.data.buy_price); + setDynamicRate(result.receiving_amount); } catch (error) { if (error) { message.error(error.message); @@ -1140,6 +1140,7 @@ const P2PPostDeal = ({ const mapStateToProps = (state) => ({ pairs: state.app.pairs, coins: state.app.coins, + broker: state.app.broker, constants: state.app.constants, transaction_limits: state.app.transaction_limits, p2p_config: state.app.constants.p2p_config, diff --git a/web/src/containers/P2P/actions/p2pActions.js b/web/src/containers/P2P/actions/p2pActions.js index 1c749e7b11..19a6a7eb25 100644 --- a/web/src/containers/P2P/actions/p2pActions.js +++ b/web/src/containers/P2P/actions/p2pActions.js @@ -76,6 +76,12 @@ export const createFeedback = (values) => { return requestAuthenticated('/p2p/feedback', options); }; +export const getQuickTrade = (values) => { + const queryValues = + values && Object.keys(values).length ? querystring.stringify(values) : ''; + return requestAuthenticated(`/quick-trade?${queryValues}`); +}; + export const fetchFeedback = (values) => { const queryValues = values && Object.keys(values).length ? querystring.stringify(values) : ''; From fae68b212193820c94f91447c7c4663944d0a62c Mon Sep 17 00:00:00 2001 From: fetok12 Date: Mon, 19 Aug 2024 06:00:50 +0300 Subject: [PATCH 085/108] p2p-feedback --- web/src/config/lang/en.json | 2 ++ web/src/containers/P2P/P2PPostDeal.js | 15 ++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/web/src/config/lang/en.json b/web/src/config/lang/en.json index 9a483ebe02..a1feda819c 100644 --- a/web/src/config/lang/en.json +++ b/web/src/config/lang/en.json @@ -2005,6 +2005,8 @@ "ACTIVATE": "ACTIVATE", "TAKE_OFFLINE": "TAKE OFFLINE", "REMOVE": "REMOVE", + "DYNAMIC": "DYNAMIC", + "TYPE": "TYPE", "EDIT": "Edit", "SIDE": "Side", "STATUS": "Status", diff --git a/web/src/containers/P2P/P2PPostDeal.js b/web/src/containers/P2P/P2PPostDeal.js index 28778395f8..e37340d866 100644 --- a/web/src/containers/P2P/P2PPostDeal.js +++ b/web/src/containers/P2P/P2PPostDeal.js @@ -319,10 +319,10 @@ const P2PPostDeal = ({
- {/* - {STRINGS['P2P.PRICE_UPPER']} - */} - TYPE: + + {STRINGS['P2P.TYPE']} + + :
From c6f676292dbec94053cc4102e2ea839f7cab2438 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Mon, 19 Aug 2024 14:55:29 +0300 Subject: [PATCH 086/108] change-broker-price-api --- server/api/swagger/broker.yaml | 2 +- server/init.js | 2 +- web/src/containers/P2P/P2PPostDeal.js | 13 +++++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/server/api/swagger/broker.yaml b/server/api/swagger/broker.yaml index a2923875c0..96ceb4529d 100644 --- a/server/api/swagger/broker.yaml +++ b/server/api/swagger/broker.yaml @@ -173,7 +173,7 @@ paths: x-security-types: - bearer x-security-scopes: - - admin + - user /broker/connect: x-swagger-router-controller: broker get: diff --git a/server/init.js b/server/init.js index 5ba9ea128c..ff9350fdeb 100644 --- a/server/init.js +++ b/server/init.js @@ -125,7 +125,7 @@ const checkStatus = () => { status.constants ), Tier.findAll(), - Broker.findAll({ attributes: ['id', 'symbol', 'buy_price', 'sell_price', 'paused', 'min_size', 'max_size', 'type' ]}), + Broker.findAll({ attributes: ['id', 'symbol', 'buy_price', 'sell_price', 'paused', 'min_size', 'max_size', 'type', 'formula' ]}), QuickTrade.findAll(), TransactionLimit.findAll(), status.dataValues diff --git a/web/src/containers/P2P/P2PPostDeal.js b/web/src/containers/P2P/P2PPostDeal.js index e37340d866..b99204fa5c 100644 --- a/web/src/containers/P2P/P2PPostDeal.js +++ b/web/src/containers/P2P/P2PPostDeal.js @@ -118,14 +118,15 @@ const P2PPostDeal = ({ const getDynamicRate = async (pair) => { try { - const assets = pair.split('-'); - const result = await getQuickTrade({ - spending_currency: assets[0], - receiving_currency: assets[1], - spending_amount: 1, + const broker = brokerData.find((broker) => broker.symbol === pair); + const { formula, increment_size } = broker; + const result = await createTestBroker({ + formula, + increment_size, + spread: 1, }); - setDynamicRate(result.receiving_amount); + setDynamicRate(result.data.buy_price); } catch (error) { if (error) { message.error(error.message); From eff145c3f925e30565f5d30d2308b3cb7698f8a3 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Mon, 19 Aug 2024 16:22:46 +0300 Subject: [PATCH 087/108] get rid of individual socket --- server/ws/chat/index.js | 12 --- server/ws/sub.js | 1 - web/src/actions/p2pAction.js | 14 ++++ web/src/containers/App/Socket.js | 18 ++-- web/src/containers/P2P/P2POrder.js | 127 +++++++++++++---------------- web/src/reducers/p2pReducer.js | 17 ++++ web/src/reducers/reducer.js | 2 + 7 files changed, 101 insertions(+), 90 deletions(-) create mode 100644 web/src/actions/p2pAction.js create mode 100644 web/src/reducers/p2pReducer.js diff --git a/server/ws/chat/index.js b/server/ws/chat/index.js index 0fd7f6c652..6fbe021e0f 100644 --- a/server/ws/chat/index.js +++ b/server/ws/chat/index.js @@ -114,18 +114,6 @@ const publishChatMessage = (event, data) => { }; const publishP2PChatMessage = (event, data) => { - const topic = `p2pChat${data.id}` - - each(getChannels()[WEBSOCKET_CHANNEL('p2pChat', data.id)], (ws) => { - if (ws.readyState === WebSocket.OPEN) { - ws.send(JSON.stringify({ - topic: topic, - action: event, - data - })); - } - }); - each(getChannels()[WEBSOCKET_CHANNEL('p2pChat', data.receiver_id)], (ws) => { if (ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify({ diff --git a/server/ws/sub.js b/server/ws/sub.js index 89519f5379..c9c0ab6a10 100644 --- a/server/ws/sub.js +++ b/server/ws/sub.js @@ -103,7 +103,6 @@ const initializeTopic = (topic, ws, symbol) => { break; case 'p2pChat': - addSubscriber(WEBSOCKET_CHANNEL(topic, symbol), ws); addSubscriber(WEBSOCKET_CHANNEL(topic, ws.auth.sub.id), ws); break; case 'admin': diff --git a/web/src/actions/p2pAction.js b/web/src/actions/p2pAction.js new file mode 100644 index 0000000000..bdbf5e036d --- /dev/null +++ b/web/src/actions/p2pAction.js @@ -0,0 +1,14 @@ +// Set p2pChat from websocket +export function p2pAddMessage(message) { + return { + type: 'P2P_ADD_MESSAGE', + payload: message, + }; +} + +export function p2pGetStatus(message) { + return { + type: 'P2P_GET_STATUS', + payload: message, + }; +} diff --git a/web/src/containers/App/Socket.js b/web/src/containers/App/Socket.js index 276abdae6f..1b274dda67 100644 --- a/web/src/containers/App/Socket.js +++ b/web/src/containers/App/Socket.js @@ -42,6 +42,7 @@ import { setSnackDialog, requestTiers, } from 'actions/appActions'; +import { p2pAddMessage, p2pGetStatus } from 'actions/p2pAction'; import { playBackgroundAudioNotification } from 'utils/utils'; import { getToken, isLoggedIn } from 'utils/token'; import { NORMAL_CLOSURE_CODE, isIntentionalClosure } from 'utils/webSocket'; @@ -262,14 +263,7 @@ class Container extends Component { privateSocket.send( JSON.stringify({ op: 'subscribe', - args: [ - 'trade', - 'wallet', - 'order', - 'deposit', - 'usertrade', - `p2pChat:${this.props.user.id}`, - ], + args: ['trade', 'wallet', 'order', 'deposit', 'usertrade', `p2pChat`], }) ); // this.wsInterval = setInterval(() => { @@ -431,6 +425,12 @@ class Container extends Component { } break; case 'p2pChat': + if (data.action === 'getStatus') { + this.props.p2pGetStatus(data.data); + } else { + this.props.p2pAddMessage(data.data); + } + notification.open({ message: (data.action = 'getStatus' ? STRINGS['P2P.STATUS_UPDATE'] @@ -735,6 +735,8 @@ const mapDispatchToProps = (dispatch) => ({ setMe: bindActionCreators(setMe, dispatch), setBalance: bindActionCreators(setBalance, dispatch), setUserOrders: bindActionCreators(setUserOrders, dispatch), + p2pAddMessage: bindActionCreators(p2pAddMessage, dispatch), + p2pGetStatus: bindActionCreators(p2pGetStatus, dispatch), addOrder: bindActionCreators(addOrder, dispatch), updateOrder: bindActionCreators(updateOrder, dispatch), removeOrder: bindActionCreators(removeOrder, dispatch), diff --git a/web/src/containers/P2P/P2POrder.js b/web/src/containers/P2P/P2POrder.js index b8139c6b01..30b1afff71 100644 --- a/web/src/containers/P2P/P2POrder.js +++ b/web/src/containers/P2P/P2POrder.js @@ -41,6 +41,9 @@ const P2POrder = ({ user, router, p2p_config, + p2p_message, + p2p_status, + p2p_transaction_id, }) => { const coin = coins[selectedTransaction.deal.buying_asset]; const [selectedOrder, setSelectedOrder] = useState(selectedTransaction); @@ -87,76 +90,27 @@ const P2POrder = ({ }, []); useEffect(() => { - const url = `${WS_URL}/stream?authorization=Bearer ${getToken()}`; - const p2pWs = new WebSocket(url); - - p2pWs.onopen = (evt) => { - setWs(p2pWs); - setReady(true); - p2pWs.send( - JSON.stringify({ - op: 'subscribe', - args: [`p2pChat:${selectedTransaction.id}`], - }) - ); - setInterval(() => { - p2pWs.send( - JSON.stringify({ - op: 'ping', - }) - ); - }, 55000); - }; - - p2pWs.onmessage = (evt) => { - const data = JSON.parse(evt.data); - switch (data.action) { - case 'addMessage': { - if (data.data) { - const { id } = data.data; - if (selectedOrder.id === id) { - setSelectedOrder((prevState) => { - const messages = [...prevState.messages]; - - messages.push(data.data); - - return { - ...prevState, - messages, - }; - }); - } - } - break; + setSelectedOrder((prevState) => { + if ( + p2p_message.id === selectedOrder.id && + p2p_message.receiver_id === user.id && + (p2p_message.sender_id === prevState.merchant_id || + p2p_message.sender_id === prevState.user_id) + ) { + const found = + prevState?.messages?.[prevState?.messages?.length - 1]?.message === + p2p_message.message; + if (!found) { + prevState?.messages.push(p2p_message); } - - case 'getStatus': { - fetchTransactions({ id: selectedOrder.id }) - .then((transaction) => { - if (transaction.data[0].transaction_status === 'complete') { - setHasFeedback(false); - } - setSelectedOrder(transaction.data[0]); - }) - .catch((err) => err); - break; - } - - default: - break; } - }; + return { ...prevState, ...{ messages: prevState?.messages } }; + }); + }, [p2p_message]); - return () => { - p2pWs.send( - JSON.stringify({ - op: 'unsubscribe', - args: [`p2pChat:${selectedTransaction.id}`], - }) - ); - p2pWs.close(); - }; - }, []); + useEffect(() => { + if (p2p_transaction_id === selectedOrder.id) updateP2PStatus(); + }, [p2p_status]); useEffect(() => { fetchFeedback({ transaction_id: selectedOrder.id }) @@ -191,6 +145,30 @@ const P2POrder = ({ } }, []); + useEffect(() => { + const url = `${WS_URL}/stream?authorization=Bearer ${getToken()}`; + const p2pWs = new WebSocket(url); + + p2pWs.onopen = (evt) => { + setWs(p2pWs); + setReady(true); + }; + + return () => { + p2pWs.close(); + }; + }, []); + + const updateP2PStatus = () => { + fetchTransactions({ id: selectedOrder.id }) + .then((transaction) => { + if (transaction.data[0].transaction_status === 'complete') { + setHasFeedback(false); + } + setSelectedOrder(transaction.data[0]); + }) + .catch((err) => err); + }; const getTransaction = async () => { try { const transaction = await fetchTransactions({ @@ -214,6 +192,11 @@ const P2POrder = ({ ], }) ); + + setSelectedOrder((prevState) => { + prevState?.messages.push(message); + return prevState; + }); }; const updateStatus = (status) => { @@ -377,7 +360,7 @@ const P2POrder = ({ merchant_status: 'appeal', cancellation_reason: appealReason, }); - + updateP2PStatus(); updateStatus('appeal'); message.success(STRINGS['P2P.APPEALED_TRANSACTION']); } else { @@ -386,7 +369,7 @@ const P2POrder = ({ user_status: 'appeal', cancellation_reason: appealReason, }); - + updateP2PStatus(); updateStatus('appeal'); message.success(STRINGS['P2P.APPEALED_TRANSACTION']); } @@ -821,6 +804,7 @@ const P2POrder = ({ id: selectedOrder.id, user_status: 'cancelled', }); + updateP2PStatus(); updateStatus('cancelled'); message.success(STRINGS['P2P.TRANSACTION_CANCELLED']); setDisplayCancelWarning(false); @@ -915,6 +899,7 @@ const P2POrder = ({ id: selectedOrder.id, merchant_status: 'confirmed', }); + updateP2PStatus(); updateStatus('confirmed'); message.success(STRINGS['P2P.CONFIRMED_TRANSACTION']); setDisplayConfirmWarning(false); @@ -1909,6 +1894,7 @@ const P2POrder = ({ id: selectedOrder.id, user_status: 'confirmed', }); + updateP2PStatus(); updateStatus('confirmed'); message.success(STRINGS['P2P.CONFIRMED_TRANSACTION']); } catch (error) { @@ -1931,6 +1917,9 @@ const mapStateToProps = (state) => ({ coins: state.app.coins, constants: state.app.constants, transaction_limits: state.app.transaction_limits, + p2p_message: state.p2p.chat, + p2p_status: state.p2p.status, + p2p_transaction_id: state.p2p.transaction_id, user: state.user, p2p_config: state.app.constants.p2p_config, }); diff --git a/web/src/reducers/p2pReducer.js b/web/src/reducers/p2pReducer.js new file mode 100644 index 0000000000..c1e8b24e86 --- /dev/null +++ b/web/src/reducers/p2pReducer.js @@ -0,0 +1,17 @@ +const initialState = { + chat: {}, + status: true, + transaction_id: null, +}; + +export default (state = initialState, { type, payload }) => { + switch (type) { + case 'P2P_ADD_MESSAGE': + return { ...state, chat: payload, transaction_id: payload.id }; + case 'P2P_GET_STATUS': { + return { ...state, status: !state.status, transaction_id: payload.id }; + } + default: + return state; + } +}; diff --git a/web/src/reducers/reducer.js b/web/src/reducers/reducer.js index 8eb1d71982..6adb66e339 100644 --- a/web/src/reducers/reducer.js +++ b/web/src/reducers/reducer.js @@ -7,6 +7,7 @@ import app from './appReducer'; import wallet from './walletReducer'; import asset from './assetReducer'; import stake from './stakeReducer'; +import p2p from './p2pReducer'; import tools from './toolsReducer'; import adminBillingReducer from './adminBillingReducer'; import { reducer as formReducer } from 'redux-form'; @@ -23,6 +24,7 @@ const appReducer = combineReducers({ tools, admin: adminBillingReducer, form: formReducer, + p2p, }); const rootReducer = (state, action) => { From c8001d89040649d4c79eaa7804949609a3d67595 Mon Sep 17 00:00:00 2001 From: ram Date: Tue, 20 Aug 2024 11:54:52 +0530 Subject: [PATCH 088/108] Fixed the wallet deposit endpoint issue --- web/src/containers/Deposit/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/containers/Deposit/index.js b/web/src/containers/Deposit/index.js index 5c106bb2cc..bdaf70c142 100644 --- a/web/src/containers/Deposit/index.js +++ b/web/src/containers/Deposit/index.js @@ -118,7 +118,7 @@ class Deposit extends Component { } else if (selectedCurrency) { if (getDepositNetworkOptions) { return ( - val.network === getDepositNetworkOptions && + val.network === renderNetworkField(getDepositNetworkOptions) && val.currency === getDepositCurrency ); } else { @@ -224,7 +224,7 @@ class Deposit extends Component { const { currency } = this.state; const currentCurrency = getDepositCurrency ? getDepositCurrency : currency; const network = getDepositNetworkOptions - ? getDepositNetworkOptions + ? renderNetworkField(getDepositNetworkOptions) : getDepositCurrency ? getDepositNetwork : selectedNetwork; From 1faecfc155d974e73a15826b1e327032cd6b9151 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Tue, 20 Aug 2024 12:53:01 +0300 Subject: [PATCH 089/108] plugin-server-rate-limitter --- server/config/middleware.js | 37 +++++++++++++++++++++++++++++++++++++ server/plugins/index.js | 3 ++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/server/config/middleware.js b/server/config/middleware.js index 8cc3da645e..0625481e59 100644 --- a/server/config/middleware.js +++ b/server/config/middleware.js @@ -151,6 +151,43 @@ const rateLimitMiddleware = (app) => { return res.status(429).json({ message: 'Too many requests. Your account is blocked for 2 minutes' }); } }); + + limiter({ + path: '/plugins/sms/verify', + method: 'get', + total: 5, + expire: 1000 * 60 * 24, + lookup: (req, res, opts, next) => { + if (req.headers.hasOwnProperty('authorization') && req.headers.authorization.indexOf('Bearer ') > -1) { + opts.lookup = 'headers.authorization'; + } else { + opts.lookup = 'headers.x-forwarded-for'; + } + return next(); + }, + onRateLimited: function (req, res, next) { + logger.verbose('config/middleware/rateLimitMiddleware', 'abuse', 'request-withdrawal'); + return res.status(429).json({ message: 'Too many requests. Your account is blocked for 24 hours' }); + } + }); + limiter({ + path: '/plugins/sms/verify', + method: 'post', + total: 5, + expire: 1000 * 60 * 24, + lookup: (req, res, opts, next) => { + if (req.headers.hasOwnProperty('authorization') && req.headers.authorization.indexOf('Bearer ') > -1) { + opts.lookup = 'headers.authorization'; + } else { + opts.lookup = 'headers.x-forwarded-for'; + } + return next(); + }, + onRateLimited: function (req, res, next) { + logger.verbose('config/middleware/rateLimitMiddleware', 'abuse', 'request-withdrawal'); + return res.status(429).json({ message: 'Too many requests. Your account is blocked for 24 hours' }); + } + }); }; module.exports = { diff --git a/server/plugins/index.js b/server/plugins/index.js index 2c3857085b..974398dd94 100644 --- a/server/plugins/index.js +++ b/server/plugins/index.js @@ -7,7 +7,7 @@ const morgan = require('morgan'); const morganType = process.env.NODE_ENV === 'development' ? 'dev' : 'combined'; const { logEntryRequest, stream, loggerPlugin } = require('../config/logger'); const cors = require('cors'); -const { domainMiddleware, helmetMiddleware } = require('../config/middleware'); +const { domainMiddleware, helmetMiddleware, rateLimitMiddleware } = require('../config/middleware'); const routes = require('./routes'); const { Plugin } = require('../db/models'); const path = require('path'); @@ -174,6 +174,7 @@ checkStatus() app.use(cors()); app.use(logEntryRequest); app.use(domainMiddleware); + rateLimitMiddleware(app); helmetMiddleware(app); app.use(express.urlencoded({ extended: true })); app.use(express.json()); From dec0a6064db09f93ca736c51eeb1dfb9b0cd32ff Mon Sep 17 00:00:00 2001 From: fetok12 Date: Wed, 21 Aug 2024 00:30:58 +0300 Subject: [PATCH 090/108] update-limitter --- server/config/middleware.js | 37 -------------------------------- server/plugins/index.js | 3 +-- server/plugins/plugin-process.js | 3 ++- 3 files changed, 3 insertions(+), 40 deletions(-) diff --git a/server/config/middleware.js b/server/config/middleware.js index 0625481e59..8cc3da645e 100644 --- a/server/config/middleware.js +++ b/server/config/middleware.js @@ -151,43 +151,6 @@ const rateLimitMiddleware = (app) => { return res.status(429).json({ message: 'Too many requests. Your account is blocked for 2 minutes' }); } }); - - limiter({ - path: '/plugins/sms/verify', - method: 'get', - total: 5, - expire: 1000 * 60 * 24, - lookup: (req, res, opts, next) => { - if (req.headers.hasOwnProperty('authorization') && req.headers.authorization.indexOf('Bearer ') > -1) { - opts.lookup = 'headers.authorization'; - } else { - opts.lookup = 'headers.x-forwarded-for'; - } - return next(); - }, - onRateLimited: function (req, res, next) { - logger.verbose('config/middleware/rateLimitMiddleware', 'abuse', 'request-withdrawal'); - return res.status(429).json({ message: 'Too many requests. Your account is blocked for 24 hours' }); - } - }); - limiter({ - path: '/plugins/sms/verify', - method: 'post', - total: 5, - expire: 1000 * 60 * 24, - lookup: (req, res, opts, next) => { - if (req.headers.hasOwnProperty('authorization') && req.headers.authorization.indexOf('Bearer ') > -1) { - opts.lookup = 'headers.authorization'; - } else { - opts.lookup = 'headers.x-forwarded-for'; - } - return next(); - }, - onRateLimited: function (req, res, next) { - logger.verbose('config/middleware/rateLimitMiddleware', 'abuse', 'request-withdrawal'); - return res.status(429).json({ message: 'Too many requests. Your account is blocked for 24 hours' }); - } - }); }; module.exports = { diff --git a/server/plugins/index.js b/server/plugins/index.js index 974398dd94..2c3857085b 100644 --- a/server/plugins/index.js +++ b/server/plugins/index.js @@ -7,7 +7,7 @@ const morgan = require('morgan'); const morganType = process.env.NODE_ENV === 'development' ? 'dev' : 'combined'; const { logEntryRequest, stream, loggerPlugin } = require('../config/logger'); const cors = require('cors'); -const { domainMiddleware, helmetMiddleware, rateLimitMiddleware } = require('../config/middleware'); +const { domainMiddleware, helmetMiddleware } = require('../config/middleware'); const routes = require('./routes'); const { Plugin } = require('../db/models'); const path = require('path'); @@ -174,7 +174,6 @@ checkStatus() app.use(cors()); app.use(logEntryRequest); app.use(domainMiddleware); - rateLimitMiddleware(app); helmetMiddleware(app); app.use(express.urlencoded({ extended: true })); app.use(express.json()); diff --git a/server/plugins/plugin-process.js b/server/plugins/plugin-process.js index a7dc3c74e7..a623f3c546 100644 --- a/server/plugins/plugin-process.js +++ b/server/plugins/plugin-process.js @@ -45,7 +45,7 @@ const { isMainThread, workerData } = require('worker_threads'); const { Plugin } = require('../db/models'); const { checkStatus } = require('../init'); const { sleep } = require('../utils/hollaex-tools-lib/tools/common'); - +const rateLimit = require('express-rate-limit'); const initPluginProcess = async ({ PORT }) => { @@ -120,6 +120,7 @@ const initPluginProcess = async ({ PORT }) => { tripleBeam, bodyParser, morgan, + rateLimit, meta: plugin.meta, publicMeta: plugin.public_meta, installedLibraries: {} From db1fef81b41f5f50621bb764ce792c79e7e1c5dd Mon Sep 17 00:00:00 2001 From: fetok12 Date: Wed, 21 Aug 2024 00:32:00 +0300 Subject: [PATCH 091/108] add-limitter-to-dev.js --- server/plugins/dev.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/plugins/dev.js b/server/plugins/dev.js index ec45e42202..89a222043d 100644 --- a/server/plugins/dev.js +++ b/server/plugins/dev.js @@ -40,6 +40,7 @@ const geoipLite = require('geoip-lite'); const nodemailer = require('nodemailer'); const wsHeartbeatServer = require('ws-heartbeat/server'); const wsHeartbeatClient = require('ws-heartbeat/client'); +const rateLimit = require('express-rate-limit'); const winston = require('winston'); let pluginName = 'hello'; @@ -125,6 +126,7 @@ checkStatus() winston, bodyParser, morgan, + rateLimit, pluginLibraries: { app, toolsLib, From ab9eeff9d7eb50b0172c5db41aef71c18eeb8580 Mon Sep 17 00:00:00 2001 From: Ali Beikverdi Date: Wed, 21 Aug 2024 08:24:02 +0900 Subject: [PATCH 092/108] prevent duplicate address creation on the same network in the address book --- server/utils/hollaex-tools-lib/tools/user.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index 62f04fdf56..809fee9e72 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -17,7 +17,8 @@ const { isArray, isInteger, isEmpty, - uniq + uniq, + uniqWith } = require('lodash'); const { isEmail } = require('validator'); const randomString = require('random-string'); @@ -3323,6 +3324,12 @@ const updateUserAddresses = async (user_id, data) => { throw new Error(ADDRESSBOOK_ALREADY_EXISTS); } + // Check for duplicate address in the payload + const uniqueAddresses = uniqWith(addresses, (addresssA, addressB) => addresssA.address === addressB.address && addresssA.network === addressB.network && addresssA.currency === addressB.currency); + if (uniqueAddresses.length != addresses.length) { + throw new Error(ADDRESSBOOK_ALREADY_EXISTS); + } + const user = await getUserByKitId(user_id); if (!user) { @@ -3414,7 +3421,7 @@ const updatePaymentDetail = async (id, data, isAdmin = false) => { throw new Error(PAYMENT_DETAIL_NOT_FOUND); } - if (!isAdmin) { delete data.status }; + if (!isAdmin) { delete data.status; } if (data.status === 3) { const user = await getUserByKitId(data.user_id); From 2d8126d6644c3672aae092ac034a88496e64361e Mon Sep 17 00:00:00 2001 From: Ali Beikverdi Date: Wed, 21 Aug 2024 14:05:20 +0900 Subject: [PATCH 093/108] fix rate limit library import in plugin --- server/plugins/dev.js | 2 +- server/plugins/plugin-process.js | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/server/plugins/dev.js b/server/plugins/dev.js index 89a222043d..f8f6ce57d7 100644 --- a/server/plugins/dev.js +++ b/server/plugins/dev.js @@ -40,7 +40,7 @@ const geoipLite = require('geoip-lite'); const nodemailer = require('nodemailer'); const wsHeartbeatServer = require('ws-heartbeat/server'); const wsHeartbeatClient = require('ws-heartbeat/client'); -const rateLimit = require('express-rate-limit'); +const rateLimit = require('express-limiter'); const winston = require('winston'); let pluginName = 'hello'; diff --git a/server/plugins/plugin-process.js b/server/plugins/plugin-process.js index a623f3c546..42646f84f8 100644 --- a/server/plugins/plugin-process.js +++ b/server/plugins/plugin-process.js @@ -45,7 +45,7 @@ const { isMainThread, workerData } = require('worker_threads'); const { Plugin } = require('../db/models'); const { checkStatus } = require('../init'); const { sleep } = require('../utils/hollaex-tools-lib/tools/common'); -const rateLimit = require('express-rate-limit'); +const rateLimit = require('express-limiter'); const initPluginProcess = async ({ PORT }) => { @@ -168,12 +168,12 @@ const initPluginProcess = async ({ PORT }) => { const restartPluginProcess = () => { process.exit(0); -} +}; if (!isMainThread) { loggerPlugin.verbose( 'plugins/plugin-process', - `Plugin thread initializing` + 'Plugin thread initializing' ); checkStatus() .then(async () => { @@ -181,7 +181,7 @@ if (!isMainThread) { loggerPlugin.verbose( 'plugins/plugin-process', - `Plugin thread checkStatus complete` + 'Plugin thread checkStatus complete' ); try { initPluginProcess(JSON.parse(workerData)); @@ -200,7 +200,7 @@ if (!isMainThread) { err.message ); setTimeout(() => { process.exit(1); }, 1000 * 5); - }) + }); } From d4a7cb0064fcd11ec9108b8de100014f73a892e8 Mon Sep 17 00:00:00 2001 From: Ali Beikverdi Date: Thu, 22 Aug 2024 00:51:20 +0900 Subject: [PATCH 094/108] version update --- server/api/swagger/swagger.js | 2 +- server/package.json | 2 +- version | 2 +- web/package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/server/api/swagger/swagger.js b/server/api/swagger/swagger.js index 8999aecc1e..4a444663a2 100644 --- a/server/api/swagger/swagger.js +++ b/server/api/swagger/swagger.js @@ -4,7 +4,7 @@ const definition = { swagger: '2.0', info: { title: 'HollaEx Kit', - version: '2.11.5' + version: '2.12.0' }, host: 'api.hollaex.com', basePath: '/v2', diff --git a/server/package.json b/server/package.json index 73f9d349fd..7f26c8eaaa 100644 --- a/server/package.json +++ b/server/package.json @@ -1,5 +1,5 @@ { - "version": "2.11.5", + "version": "2.12.0", "private": false, "description": "HollaEx Kit", "keywords": [ diff --git a/version b/version index 9fb6511900..3ca2c9b2cc 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.11.5 \ No newline at end of file +2.12.0 \ No newline at end of file diff --git a/web/package.json b/web/package.json index 2b9afc69d4..e14387a94e 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "hollaex-kit", - "version": "2.11.5", + "version": "2.12.0", "private": true, "dependencies": { "@ant-design/compatible": "1.0.5", From 2b75b1c8190deeb224b37f4cdf94116d146686fa Mon Sep 17 00:00:00 2001 From: Yechan Kim Date: Thu, 22 Aug 2024 20:52:51 +0900 Subject: [PATCH 095/108] docker-compose installation --- install.sh | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/install.sh b/install.sh index 63b7b91ec1..6ec3dc6a98 100644 --- a/install.sh +++ b/install.sh @@ -78,22 +78,21 @@ if command apt -v > /dev/null 2>&1; then printf "\n\033[93mHollaEx CLI requires docker compose v2 to operate. Installing it now...\033[39m\n" - if [[ ! $IS_APT_UPDATED ]]; then + export DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} + mkdir -p $DOCKER_CONFIG/cli-plugins - echo "Updating APT list" - sudo apt update - fi + if command sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose; then - if command sudo apt install -y docker-compose-v2; then + chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose - printf "\n\033[92mdocker compose v2 has been successfully installed!\033[39m\n" + printf "\n\033[92mdocker compose has been successfully installed!\033[39m\n" echo "Info: $(docker compose version)" else - printf "\n\033[91mFailed to install docker compose v2.\033[39m\n" - echo "Please review the logs and try to manually install it. - 'sudo apt install -y docker compose'." + printf "\n\033[91mFailed to install docker compose.\033[39m\n" + echo "Please review the logs and try to manually install it. - 'https://github.com/docker/compose/releases'." exit 1; fi @@ -116,6 +115,8 @@ if command apt -v > /dev/null 2>&1; then echo "Info: $(jq --version)" + + else printf "\n\033[91mFailed to install jq.\033[39m\n" @@ -269,13 +270,12 @@ elif command brew -v > /dev/null 2>&1; then printf "\n\033[93mHollaEx CLI requires docker compose to operate. Installing it now...\033[39m\n" - if [[ ! $IS_BREW_UPDATED ]]; then + export DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} + mkdir -p $DOCKER_CONFIG/cli-plugins - echo "Updating Homebrew list" - brew update - fi + if command sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose; then - if command brew install docker compose; then + chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose printf "\n\033[92mdocker compose has been successfully installed!\033[39m\n" @@ -284,7 +284,7 @@ elif command brew -v > /dev/null 2>&1; then else printf "\n\033[91mFailed to install docker compose.\033[39m\n" - echo "Please review the logs and try to manually install it. - 'brew install docker compose'." + echo "Please review the logs and try to manually install it. - 'https://github.com/docker/compose/releases'." exit 1; fi @@ -432,9 +432,12 @@ elif command yum --version > /dev/null 2>&1; then printf "\n\033[93mHollaEx CLI requires docker compose to operate. Installing it now...\033[39m\n" - if command sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker compose; then + export DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} + mkdir -p $DOCKER_CONFIG/cli-plugins + + if command sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose; then - sudo chmod +x /usr/local/bin/docker compose + chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose printf "\n\033[92mdocker compose has been successfully installed!\033[39m\n" From c5857d93dd1fc0013f29972191e4f3f8994c703e Mon Sep 17 00:00:00 2001 From: Yechan Kim Date: Thu, 22 Aug 2024 21:31:27 +0900 Subject: [PATCH 096/108] Update install.sh --- install.sh | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/install.sh b/install.sh index 6ec3dc6a98..11c0564a8d 100644 --- a/install.sh +++ b/install.sh @@ -266,30 +266,32 @@ elif command brew -v > /dev/null 2>&1; then fi - if ! command docker compose version > /dev/null 2>&1; then + # No manual install for docker compose for mac since it's included in the docker for mac desktop. - printf "\n\033[93mHollaEx CLI requires docker compose to operate. Installing it now...\033[39m\n" + # if ! command docker compose version > /dev/null 2>&1; then - export DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} - mkdir -p $DOCKER_CONFIG/cli-plugins + # printf "\n\033[93mHollaEx CLI requires docker compose to operate. Installing it now...\033[39m\n" - if command sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose; then + # export DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} + # mkdir -p $DOCKER_CONFIG/cli-plugins - chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose + # if command sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose; then - printf "\n\033[92mdocker compose has been successfully installed!\033[39m\n" + # chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose - echo "Info: $(docker compose version)" + # printf "\n\033[92mdocker compose has been successfully installed!\033[39m\n" - else + # echo "Info: $(docker compose version)" - printf "\n\033[91mFailed to install docker compose.\033[39m\n" - echo "Please review the logs and try to manually install it. - 'https://github.com/docker/compose/releases'." - exit 1; + # else - fi + # printf "\n\033[91mFailed to install docker compose.\033[39m\n" + # echo "Please review the logs and try to manually install it. - 'https://github.com/docker/compose/releases'." + # exit 1; - fi + # fi + + # fi if ! command jq --version > /dev/null 2>&1; then From 8f683d0c5960aaeee8881d588e49257db7d5f4c1 Mon Sep 17 00:00:00 2001 From: Yechan Kim Date: Thu, 22 Aug 2024 23:37:28 +0900 Subject: [PATCH 097/108] docker-compose standalone installation --- install.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index 11c0564a8d..8d8b605df8 100644 --- a/install.sh +++ b/install.sh @@ -74,9 +74,9 @@ if command apt -v > /dev/null 2>&1; then fi - if ! command docker compose version > /dev/null 2>&1; then + if ! command docker-compose version > /dev/null 2>&1; then - printf "\n\033[93mHollaEx CLI requires docker compose v2 to operate. Installing it now...\033[39m\n" + printf "\n\033[93mHollaEx CLI requires docker-compose to operate. Installing it now...\033[39m\n" export DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} mkdir -p $DOCKER_CONFIG/cli-plugins @@ -85,6 +85,10 @@ if command apt -v > /dev/null 2>&1; then chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose + curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose + + chmod +x /usr/local/bin/docker-compose + printf "\n\033[92mdocker compose has been successfully installed!\033[39m\n" echo "Info: $(docker compose version)" From 018f8d4a854b5fa78702082345fdd0e20faa0099 Mon Sep 17 00:00:00 2001 From: Yechan Kim Date: Thu, 22 Aug 2024 23:38:15 +0900 Subject: [PATCH 098/108] Update install.sh --- install.sh | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/install.sh b/install.sh index 8d8b605df8..fcbcac7746 100644 --- a/install.sh +++ b/install.sh @@ -81,17 +81,13 @@ if command apt -v > /dev/null 2>&1; then export DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} mkdir -p $DOCKER_CONFIG/cli-plugins - if command sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose; then - - chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose - - curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose + if command sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose; then chmod +x /usr/local/bin/docker-compose printf "\n\033[92mdocker compose has been successfully installed!\033[39m\n" - echo "Info: $(docker compose version)" + echo "Info: $(docker-compose version)" else From a5b1166b42996b4885264f4ba138301736403d7a Mon Sep 17 00:00:00 2001 From: Yechan Kim Date: Thu, 22 Aug 2024 23:41:35 +0900 Subject: [PATCH 099/108] Update install.sh --- install.sh | 48 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/install.sh b/install.sh index fcbcac7746..959f3a9ad9 100644 --- a/install.sh +++ b/install.sh @@ -266,32 +266,30 @@ elif command brew -v > /dev/null 2>&1; then fi - # No manual install for docker compose for mac since it's included in the docker for mac desktop. - - # if ! command docker compose version > /dev/null 2>&1; then + if ! command docker-compose version > /dev/null 2>&1; then - # printf "\n\033[93mHollaEx CLI requires docker compose to operate. Installing it now...\033[39m\n" + printf "\n\033[93mHollaEx CLI requires docker-compose to operate. Installing it now...\033[39m\n" - # export DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} - # mkdir -p $DOCKER_CONFIG/cli-plugins + export DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} + mkdir -p $DOCKER_CONFIG/cli-plugins - # if command sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose; then + if command sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose; then - # chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose + chmod +x /usr/local/bin/docker-compose - # printf "\n\033[92mdocker compose has been successfully installed!\033[39m\n" + printf "\n\033[92mdocker compose has been successfully installed!\033[39m\n" - # echo "Info: $(docker compose version)" + echo "Info: $(docker-compose version)" - # else + else - # printf "\n\033[91mFailed to install docker compose.\033[39m\n" - # echo "Please review the logs and try to manually install it. - 'https://github.com/docker/compose/releases'." - # exit 1; + printf "\n\033[91mFailed to install docker compose.\033[39m\n" + echo "Please review the logs and try to manually install it. - 'https://github.com/docker/compose/releases'." + exit 1; - # fi + fi - # fi + fi if ! command jq --version > /dev/null 2>&1; then @@ -430,20 +428,20 @@ elif command yum --version > /dev/null 2>&1; then fi - if ! command docker compose version > /dev/null 2>&1; then + if ! command docker-compose version > /dev/null 2>&1; then - printf "\n\033[93mHollaEx CLI requires docker compose to operate. Installing it now...\033[39m\n" + printf "\n\033[93mHollaEx CLI requires docker-compose to operate. Installing it now...\033[39m\n" export DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} mkdir -p $DOCKER_CONFIG/cli-plugins - if command sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose; then + if command sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose; then - chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose + chmod +x /usr/local/bin/docker-compose printf "\n\033[92mdocker compose has been successfully installed!\033[39m\n" - echo "Info: $(docker compose version)" + echo "Info: $(docker-compose version)" else @@ -537,7 +535,7 @@ elif command yum --version > /dev/null 2>&1; then fi -if ! command docker -v > /dev/null 2>&1 || ! command docker compose version > /dev/null 2>&1 || ! command curl --version > /dev/null 2>&1 || ! command jq --version > /dev/null 2>&1 || ! command nslookup -version > /dev/null 2>&1 || ! command psql --version > /dev/null 2>&1; then +if ! command docker -v > /dev/null 2>&1 || ! command docker-compose version > /dev/null 2>&1 || ! command curl --version > /dev/null 2>&1 || ! command jq --version > /dev/null 2>&1 || ! command nslookup -version > /dev/null 2>&1 || ! command psql --version > /dev/null 2>&1; then if command docker -v > /dev/null 2>&1; then @@ -545,7 +543,7 @@ if ! command docker -v > /dev/null 2>&1 || ! command docker compose version > /d fi - if command docker compose version > /dev/null 2>&1; then + if command docker-compose version > /dev/null 2>&1; then IS_DOCKER_COMPOSE_INSTALLED=true @@ -736,8 +734,8 @@ function kit_cross_compatibility_converter() { if command docker ps | grep local.*-nginx > /dev/null ; then - docker compose -f $(pwd)/nginx/docker-compose.yaml down - docker compose -f $(pwd)/nginx/docker-compose.yaml up -d + docker-compose -f $(pwd)/nginx/docker-compose.yaml down + docker-compose -f $(pwd)/nginx/docker-compose.yaml up -d fi From f14d1ee3d2b728a333c8fdc96250cb61b0286d2f Mon Sep 17 00:00:00 2001 From: Yechan Kim Date: Sat, 24 Aug 2024 11:45:29 +0900 Subject: [PATCH 100/108] Update install.sh --- install.sh | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/install.sh b/install.sh index 959f3a9ad9..87ea22e4a3 100644 --- a/install.sh +++ b/install.sh @@ -74,24 +74,27 @@ if command apt -v > /dev/null 2>&1; then fi - if ! command docker-compose version > /dev/null 2>&1; then + + if ! command -v docker-compose > /dev/null 2>&1 || docker-compose --version | grep -q '^docker-compose version 1'; then + + echo "docker compose v2 is not installed or the current version is v1.x." - printf "\n\033[93mHollaEx CLI requires docker-compose to operate. Installing it now...\033[39m\n" + echo "Removing the old docker-compose v2 binary (if it exists)..." + rm -f $(which docker-compose) - export DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} - mkdir -p $DOCKER_CONFIG/cli-plugins + printf "\n\033[93mHollaEx CLI requires docker-compose v2 to operate. Installing it now...\033[39m\n" if command sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose; then chmod +x /usr/local/bin/docker-compose - printf "\n\033[92mdocker compose has been successfully installed!\033[39m\n" + printf "\n\033[92mdocker compose v2has been successfully installed!\033[39m\n" echo "Info: $(docker-compose version)" else - printf "\n\033[91mFailed to install docker compose.\033[39m\n" + printf "\n\033[91mFailed to install docker compose v2.\033[39m\n" echo "Please review the logs and try to manually install it. - 'https://github.com/docker/compose/releases'." exit 1; @@ -266,24 +269,26 @@ elif command brew -v > /dev/null 2>&1; then fi - if ! command docker-compose version > /dev/null 2>&1; then + if ! command -v docker-compose > /dev/null 2>&1 || docker-compose --version | grep -q '^docker-compose version 1'; then - printf "\n\033[93mHollaEx CLI requires docker-compose to operate. Installing it now...\033[39m\n" + echo "docker compose v2 is not installed or the current version is v1.x." - export DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} - mkdir -p $DOCKER_CONFIG/cli-plugins + echo "Removing the old docker-compose v2 binary (if it exists)..." + rm -f $(which docker-compose) + + printf "\n\033[93mHollaEx CLI requires docker-compose v2 to operate. Installing it now...\033[39m\n" if command sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose; then chmod +x /usr/local/bin/docker-compose - printf "\n\033[92mdocker compose has been successfully installed!\033[39m\n" + printf "\n\033[92mdocker compose v2has been successfully installed!\033[39m\n" echo "Info: $(docker-compose version)" else - printf "\n\033[91mFailed to install docker compose.\033[39m\n" + printf "\n\033[91mFailed to install docker compose v2.\033[39m\n" echo "Please review the logs and try to manually install it. - 'https://github.com/docker/compose/releases'." exit 1; @@ -428,24 +433,26 @@ elif command yum --version > /dev/null 2>&1; then fi - if ! command docker-compose version > /dev/null 2>&1; then + if ! command -v docker-compose > /dev/null 2>&1 || docker-compose --version | grep -q '^docker-compose version 1'; then + + echo "docker compose v2 is not installed or the current version is v1.x." - printf "\n\033[93mHollaEx CLI requires docker-compose to operate. Installing it now...\033[39m\n" + echo "Removing the old docker-compose v2 binary (if it exists)..." + rm -f $(which docker-compose) - export DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} - mkdir -p $DOCKER_CONFIG/cli-plugins + printf "\n\033[93mHollaEx CLI requires docker-compose v2 to operate. Installing it now...\033[39m\n" if command sudo curl -SL https://github.com/docker/compose/releases/download/v2.29.1/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose; then chmod +x /usr/local/bin/docker-compose - printf "\n\033[92mdocker compose has been successfully installed!\033[39m\n" + printf "\n\033[92mdocker compose v2has been successfully installed!\033[39m\n" echo "Info: $(docker-compose version)" else - printf "\n\033[91mFailed to install docker compose.\033[39m\n" + printf "\n\033[91mFailed to install docker compose v2.\033[39m\n" echo "Please review the logs and try to manually install it. - 'https://github.com/docker/compose/releases'." exit 1; @@ -592,7 +599,7 @@ if ! command docker -v > /dev/null 2>&1 || ! command docker-compose version > /d fi - # docker compose installation status check + # docker compose v2installation status check if [[ "$IS_DOCKER_COMPOSE_INSTALLED" ]]; then printf "\033[92mdocker compose: Installed\033[39m\n" From 519fc9d9b78978339739b47111f155e075eebfd1 Mon Sep 17 00:00:00 2001 From: Yechan Kim Date: Sat, 24 Aug 2024 11:58:28 +0900 Subject: [PATCH 101/108] Update install.sh --- install.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/install.sh b/install.sh index 87ea22e4a3..249d1c1325 100644 --- a/install.sh +++ b/install.sh @@ -91,6 +91,7 @@ if command apt -v > /dev/null 2>&1; then printf "\n\033[92mdocker compose v2has been successfully installed!\033[39m\n" echo "Info: $(docker-compose version)" + hash -r else @@ -285,6 +286,7 @@ elif command brew -v > /dev/null 2>&1; then printf "\n\033[92mdocker compose v2has been successfully installed!\033[39m\n" echo "Info: $(docker-compose version)" + hash -r else @@ -449,6 +451,7 @@ elif command yum --version > /dev/null 2>&1; then printf "\n\033[92mdocker compose v2has been successfully installed!\033[39m\n" echo "Info: $(docker-compose version)" + hash -r else From 0268acf8730d8551a8962681ec69fbc733c81354 Mon Sep 17 00:00:00 2001 From: Yechan Kim Date: Sat, 24 Aug 2024 12:04:12 +0900 Subject: [PATCH 102/108] Update install.sh --- install.sh | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/install.sh b/install.sh index 249d1c1325..87fa6afdae 100644 --- a/install.sh +++ b/install.sh @@ -75,12 +75,18 @@ if command apt -v > /dev/null 2>&1; then fi - if ! command -v docker-compose > /dev/null 2>&1 || docker-compose --version | grep -q '^docker-compose version 1'; then + if command docker-compose --version | grep -q '^docker-compose version 1'; then - echo "docker compose v2 is not installed or the current version is v1.x." + echo -e "\n\033[91mError: Detected Docker Compose v1 instead of v2.\033[39m" + echo "HollaEx CLI v3+ requires Docker Compose v2." + echo "To proceed, please uninstall the current Docker Compose v1 and then run the install.sh script." + echo -e "The install.sh script will automatically install Docker Compose v2 for you.\n" - echo "Removing the old docker-compose v2 binary (if it exists)..." - rm -f $(which docker-compose) + exit 1; + + fi + + if ! command -v docker-compose > /dev/null 2>&1; then printf "\n\033[93mHollaEx CLI requires docker-compose v2 to operate. Installing it now...\033[39m\n" @@ -270,12 +276,18 @@ elif command brew -v > /dev/null 2>&1; then fi - if ! command -v docker-compose > /dev/null 2>&1 || docker-compose --version | grep -q '^docker-compose version 1'; then + if command docker-compose --version | grep -q '^docker-compose version 1'; then + + echo -e "\n\033[91mError: Detected Docker Compose v1 instead of v2.\033[39m" + echo "HollaEx CLI v3+ requires Docker Compose v2." + echo "To proceed, please uninstall the current Docker Compose v1 and then run the install.sh script." + echo -e "The install.sh script will automatically install Docker Compose v2 for you.\n" + + exit 1; - echo "docker compose v2 is not installed or the current version is v1.x." + fi - echo "Removing the old docker-compose v2 binary (if it exists)..." - rm -f $(which docker-compose) + if ! command -v docker-compose > /dev/null 2>&1; then printf "\n\033[93mHollaEx CLI requires docker-compose v2 to operate. Installing it now...\033[39m\n" @@ -435,12 +447,18 @@ elif command yum --version > /dev/null 2>&1; then fi - if ! command -v docker-compose > /dev/null 2>&1 || docker-compose --version | grep -q '^docker-compose version 1'; then + if command docker-compose --version | grep -q '^docker-compose version 1'; then + + echo -e "\n\033[91mError: Detected Docker Compose v1 instead of v2.\033[39m" + echo "HollaEx CLI v3+ requires Docker Compose v2." + echo "To proceed, please uninstall the current Docker Compose v1 and then run the install.sh script." + echo -e "The install.sh script will automatically install Docker Compose v2 for you.\n" - echo "docker compose v2 is not installed or the current version is v1.x." + exit 1; + + fi - echo "Removing the old docker-compose v2 binary (if it exists)..." - rm -f $(which docker-compose) + if ! command -v docker-compose > /dev/null 2>&1; then printf "\n\033[93mHollaEx CLI requires docker-compose v2 to operate. Installing it now...\033[39m\n" From 178c63108b81f90966ddb71719e1b399a6484a5e Mon Sep 17 00:00:00 2001 From: Yechan Kim Date: Sat, 24 Aug 2024 12:04:31 +0900 Subject: [PATCH 103/108] Update install.sh --- install.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/install.sh b/install.sh index 87fa6afdae..f7446967a8 100644 --- a/install.sh +++ b/install.sh @@ -97,7 +97,7 @@ if command apt -v > /dev/null 2>&1; then printf "\n\033[92mdocker compose v2has been successfully installed!\033[39m\n" echo "Info: $(docker-compose version)" - hash -r + else @@ -298,7 +298,7 @@ elif command brew -v > /dev/null 2>&1; then printf "\n\033[92mdocker compose v2has been successfully installed!\033[39m\n" echo "Info: $(docker-compose version)" - hash -r + else @@ -469,7 +469,7 @@ elif command yum --version > /dev/null 2>&1; then printf "\n\033[92mdocker compose v2has been successfully installed!\033[39m\n" echo "Info: $(docker-compose version)" - hash -r + else From 366874a405836ecb6fb926eff897a317c95d89ad Mon Sep 17 00:00:00 2001 From: Yechan Kim Date: Sat, 24 Aug 2024 12:16:37 +0900 Subject: [PATCH 104/108] Update install.sh --- install.sh | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/install.sh b/install.sh index f7446967a8..8ab4cf105f 100644 --- a/install.sh +++ b/install.sh @@ -77,12 +77,24 @@ if command apt -v > /dev/null 2>&1; then if command docker-compose --version | grep -q '^docker-compose version 1'; then - echo -e "\n\033[91mError: Detected Docker Compose v1 instead of v2.\033[39m" + echo -e "\n\033[91mWarning: Detected Docker Compose v1 instead of v2.\033[39m" echo "HollaEx CLI v3+ requires Docker Compose v2." - echo "To proceed, please uninstall the current Docker Compose v1 and then run the install.sh script." - echo -e "The install.sh script will automatically install Docker Compose v2 for you.\n" - exit 1; + if command sudo apt list --installed docker-compose; then + + echo "Removing Docker-Compose v1 through the APT..." + + sudo apt remove -y docker-compose + hash -r + + else + + echo "To proceed, please uninstall the current Docker Compose v1 and then run the install.sh script." + echo -e "The install.sh script will automatically install Docker Compose v2 for you.\n" + + exit 1; + + fi fi From 64b0860e05c044679131282e73710d40c93b5d1f Mon Sep 17 00:00:00 2001 From: Yechan Kim Date: Sat, 24 Aug 2024 12:26:08 +0900 Subject: [PATCH 105/108] Update install.sh --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 8ab4cf105f..2fc8b06863 100644 --- a/install.sh +++ b/install.sh @@ -85,7 +85,6 @@ if command apt -v > /dev/null 2>&1; then echo "Removing Docker-Compose v1 through the APT..." sudo apt remove -y docker-compose - hash -r else @@ -109,6 +108,7 @@ if command apt -v > /dev/null 2>&1; then printf "\n\033[92mdocker compose v2has been successfully installed!\033[39m\n" echo "Info: $(docker-compose version)" + export PATH="/usr/local/bin:$PATH" else From dfaa8b8d480f7cdca3ba1869bfbb35bd54087c5d Mon Sep 17 00:00:00 2001 From: Yechan Kim Date: Sat, 24 Aug 2024 12:30:21 +0900 Subject: [PATCH 106/108] Update install.sh --- install.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/install.sh b/install.sh index 2fc8b06863..dc235d03ff 100644 --- a/install.sh +++ b/install.sh @@ -108,7 +108,6 @@ if command apt -v > /dev/null 2>&1; then printf "\n\033[92mdocker compose v2has been successfully installed!\033[39m\n" echo "Info: $(docker-compose version)" - export PATH="/usr/local/bin:$PATH" else From 5a34bed5f4201f7190ee8721831eb35785b8de16 Mon Sep 17 00:00:00 2001 From: Yechan Kim Date: Sat, 24 Aug 2024 19:38:01 +0900 Subject: [PATCH 107/108] App stream endpoint env removal --- web/.env | 1 - 1 file changed, 1 deletion(-) diff --git a/web/.env b/web/.env index 48e7b2bb48..3ac4476533 100644 --- a/web/.env +++ b/web/.env @@ -3,7 +3,6 @@ NODE_ENV=production REACT_APP_PUBLIC_URL=http://yourdomain.com REACT_APP_SERVER_ENDPOINT=http://localhost/api -REACT_APP_STREAM_ENDPOINT=ws://localhost/stream REACT_APP_NETWORK=mainnet From 491a7ef94e282505aef642b32a8ce5f473b8cc18 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Mon, 26 Aug 2024 00:52:00 +0300 Subject: [PATCH 108/108] p2p-fix-ws --- server/messages.js | 1 + server/utils/hollaex-tools-lib/tools/user.js | 5 ++ web/src/containers/P2P/P2POrder.js | 8 ++ web/src/containers/P2P/P2PProfile.js | 89 +++++++++++--------- 4 files changed, 62 insertions(+), 41 deletions(-) diff --git a/server/messages.js b/server/messages.js index 557975aeaf..f304b28e1f 100644 --- a/server/messages.js +++ b/server/messages.js @@ -266,4 +266,5 @@ exports.ADDRESSBOOK_MISSING_FIELDS = 'Each address must contain both address, ne exports.ADDRESSBOOK_ALREADY_EXISTS = 'Address label already exists in the payload'; exports.ADDRESSBOOK_NOT_FOUND = 'User address book not found'; exports.PAYMENT_DETAIL_NOT_FOUND = 'Payment detail not found'; +exports.UNAUTHORIZED_UPDATE_METHOD = 'You cannot update verified payment method'; exports.P2P_DEAL_NOT_FOUND = 'P2P Deal not found!'; \ No newline at end of file diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index 62f04fdf56..5b80066084 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -65,6 +65,7 @@ const { ADDRESSBOOK_MISSING_FIELDS, PAYMENT_DETAIL_NOT_FOUND, ADDRESSBOOK_ALREADY_EXISTS, + UNAUTHORIZED_UPDATE_METHOD, ADDRESSBOOK_NOT_FOUND } = require(`${SERVER_PATH}/messages`); const { publisher, client } = require('./database/redis'); @@ -3421,6 +3422,10 @@ const updatePaymentDetail = async (id, data, isAdmin = false) => { sendEmail(MAILTYPE.BANK_VERIFIED, user.email, { bankAccounts: paymentDetail?.details?.fields }, user.settings); } + if (!isAdmin && paymentDetail.status === 3) { + throw new Error(UNAUTHORIZED_UPDATE_METHOD); + } + await paymentDetail.update(data, { fields: [ 'name', diff --git a/web/src/containers/P2P/P2POrder.js b/web/src/containers/P2P/P2POrder.js index 30b1afff71..b1e47b3904 100644 --- a/web/src/containers/P2P/P2POrder.js +++ b/web/src/containers/P2P/P2POrder.js @@ -152,6 +152,14 @@ const P2POrder = ({ p2pWs.onopen = (evt) => { setWs(p2pWs); setReady(true); + + setInterval(() => { + p2pWs.send( + JSON.stringify({ + op: 'ping', + }) + ); + }, 55000); }; return () => { diff --git a/web/src/containers/P2P/P2PProfile.js b/web/src/containers/P2P/P2PProfile.js index 910064f5d3..9fa1e1fb47 100644 --- a/web/src/containers/P2P/P2PProfile.js +++ b/web/src/containers/P2P/P2PProfile.js @@ -368,24 +368,26 @@ const P2PProfile = ({ >
{method.system_name}
-
{ - setSelectedMethod(method); - setAddMethodDetails(true); - }} - className="whiteTextP2P" - style={{ - cursor: 'pointer', - position: 'relative', - top: 5, - }} - > - - - {STRINGS['P2P.EDIT_UPPERCASE']} - - -
+ {info?.status !== 3 && ( +
{ + setSelectedMethod(method); + setAddMethodDetails(true); + }} + className="whiteTextP2P" + style={{ + cursor: 'pointer', + position: 'relative', + top: 5, + }} + > + + + {STRINGS['P2P.EDIT_UPPERCASE']} + + +
+ )}
{ const found = myMethods.find( @@ -649,36 +651,41 @@ const P2PProfile = ({