From b5189ecfcb5020a74175356f2de53d0b5e36a203 Mon Sep 17 00:00:00 2001 From: AlphaX-Projects <77661270+AlphaX-Projects@users.noreply.github.com> Date: Sat, 19 Nov 2022 22:00:23 +0100 Subject: [PATCH] Auto Buy V2, Balances Ticker --- package.json | 4 +- qortal-ui-core/language/de.json | 10 +- qortal-ui-core/language/es.json | 10 +- qortal-ui-core/language/fr.json | 10 +- qortal-ui-core/language/hindi.json | 10 +- qortal-ui-core/language/hr.json | 13 +- qortal-ui-core/language/hu.json | 10 +- qortal-ui-core/language/it.json | 10 +- qortal-ui-core/language/ko.json | 10 +- qortal-ui-core/language/no.json | 10 +- qortal-ui-core/language/pl.json | 10 +- qortal-ui-core/language/pt.json | 10 +- qortal-ui-core/language/ro.json | 10 +- qortal-ui-core/language/rs.json | 10 +- qortal-ui-core/language/ru.json | 10 +- qortal-ui-core/language/us.json | 10 +- qortal-ui-core/language/zhc.json | 10 +- qortal-ui-core/language/zht.json | 10 +- qortal-ui-core/package.json | 8 +- qortal-ui-core/src/components/app-view.js | 1784 ++++++++- qortal-ui-core/src/components/main-app.js | 2 +- qortal-ui-core/src/components/sidenav-menu.js | 21 +- .../src/tradebot/addTradeBotRoutes.js | 7 + .../src/tradebot/trade-bot-routes.js | 253 ++ qortal-ui-plugins/build-config.js | 12 +- qortal-ui-plugins/package.json | 6 +- .../plugins/core/trade-bot/index.html | 4 +- .../core/trade-bot/trade-bot-btc/index.html | 55 - .../trade-bot-btc/trade-bot-btc.src.js | 2155 ---------- .../core/trade-bot/trade-bot-doge/index.html | 55 - .../trade-bot-doge/trade-bot-doge.src.js | 2155 ---------- .../core/trade-bot/trade-bot-ltc/index.html | 55 - .../trade-bot-ltc/trade-bot-ltc.src.js | 2155 ---------- .../core/trade-bot/trade-bot-portal.src.js | 3518 +++++++++++++++++ 34 files changed, 5696 insertions(+), 6726 deletions(-) create mode 100644 qortal-ui-core/src/tradebot/addTradeBotRoutes.js create mode 100644 qortal-ui-core/src/tradebot/trade-bot-routes.js delete mode 100644 qortal-ui-plugins/plugins/core/trade-bot/trade-bot-btc/index.html delete mode 100644 qortal-ui-plugins/plugins/core/trade-bot/trade-bot-btc/trade-bot-btc.src.js delete mode 100644 qortal-ui-plugins/plugins/core/trade-bot/trade-bot-doge/index.html delete mode 100644 qortal-ui-plugins/plugins/core/trade-bot/trade-bot-doge/trade-bot-doge.src.js delete mode 100644 qortal-ui-plugins/plugins/core/trade-bot/trade-bot-ltc/index.html delete mode 100644 qortal-ui-plugins/plugins/core/trade-bot/trade-bot-ltc/trade-bot-ltc.src.js create mode 100644 qortal-ui-plugins/plugins/core/trade-bot/trade-bot-portal.src.js diff --git a/package.json b/package.json index a2e16766..e3a24dfd 100644 --- a/package.json +++ b/package.json @@ -36,11 +36,11 @@ "electron-updater": "5.3.0" }, "devDependencies": { - "electron": "21.2.3", + "electron": "21.3.0", "electron-builder": "23.6.0", "electron-packager": "17.1.1", "@electron/notarize": "1.2.3", - "shelljs": "^0.8.5" + "shelljs": "0.8.5" }, "engines": { "node": ">=16.15.0" diff --git a/qortal-ui-core/language/de.json b/qortal-ui-core/language/de.json index ebbe5c20..fb8ab542 100644 --- a/qortal-ui-core/language/de.json +++ b/qortal-ui-core/language/de.json @@ -34,7 +34,8 @@ "qchat":"Q-CHAT", "groupmanagement":"GRUPPENMANAGEMENT", "puzzles":"RÄTSEL", - "nodemanagement":"KNOTENVERWALTUNG" + "nodemanagement":"KNOTENVERWALTUNG", + "trading":"HANDELN" }, "login":{ "login":"Einloggen", @@ -150,7 +151,9 @@ "next":"Weiter", "create":"Erstellen", "continue":"Fortsetzen", - "save":"Speichern" + "save":"Speichern", + "balance":"Guthaben", + "balances":"IHR WALLET-GUTHABEN" }, "startminting":{ "smchange1":"Prägekonten können nicht abgerufen werden", @@ -322,7 +325,8 @@ "tchange44":"Automatischer Kaufauftrag erfolgreich hinzugefügt!", "tchange45":"AUTO KAUFEN MIT", "tchange46":"AUTOKAUF", - "tchange47":"Verkaufe für diesen Preis" + "tchange47":"Verkaufe für diesen Preis", + "tchange48":"NICHT GENUG" }, "rewardsharepage":{ "rchange1":"Belohnungsanteile", diff --git a/qortal-ui-core/language/es.json b/qortal-ui-core/language/es.json index 4bc2e336..47c84b8a 100644 --- a/qortal-ui-core/language/es.json +++ b/qortal-ui-core/language/es.json @@ -34,7 +34,8 @@ "qchat":"Q-CHAT", "groupmanagement":"GESTIÓN DE GRUPO", "puzzles":"ROMPECABEZAS", - "nodemanagement":"GESTIÓN DE NODO" + "nodemanagement":"GESTIÓN DE NODO", + "trading":"COMERCIO" }, "login":{ "login":"Iniciar sesión", @@ -150,7 +151,9 @@ "next":"Siguiente", "create":"Crear", "continue":"Continuar", - "save":"Guardar" + "save":"Guardar", + "balance":"Saldo", + "balances":"LOS SALDOS DE TU BILLETERA" }, "startminting":{ "smchange1":"No se pueden obtener cuentas de acuñación", @@ -322,7 +325,8 @@ "tchange44":"Orden de compra automática agregada con éxito!", "tchange45":"AUTO COMPRAR CON", "tchange46":"COMPRA AUTOMÁTICA", - "tchange47":"Vender por este precio" + "tchange47":"Vender por este precio", + "tchange48":"NO ES SUFICIENTE" }, "rewardsharepage":{ "rchange1":"Rewardshares", diff --git a/qortal-ui-core/language/fr.json b/qortal-ui-core/language/fr.json index 728bc3f1..94cedf06 100644 --- a/qortal-ui-core/language/fr.json +++ b/qortal-ui-core/language/fr.json @@ -34,7 +34,8 @@ "qchat":"Q-CHAT", "groupmanagement":"GESTION DE GROUPES", "puzzles":"PUZZLES", - "nodemanagement":"GESTION DE NOEUDS" + "nodemanagement":"GESTION DE NOEUDS", + "trading":"COMMERCE" }, "login":{ "login":"Connexion", @@ -150,7 +151,9 @@ "next":"Suivant", "create":"Créer", "continue":"Continuer", - "save":"Sauvegarder" + "save":"Sauvegarder", + "balance":"Solde", + "balances":"VOS SOLDES DE PORTEFEUILLE" }, "startminting":{ "smchange1":"Impossible de récupérer les comptes de frappe", @@ -322,7 +325,8 @@ "tchange44":"Commande d'achat automatique ajoutée avec succès !", "tchange45":"ACHAT AUTO AVEC", "tchange46":"ACHAT AUTOMATIQUE", - "tchange47":"Vendre à ce prix" + "tchange47":"Vendre à ce prix", + "tchange48":"PAS ASSEZ" }, "rewardsharepage":{ "rchange1":"Récompenses", diff --git a/qortal-ui-core/language/hindi.json b/qortal-ui-core/language/hindi.json index 2a2feb50..714e82fa 100644 --- a/qortal-ui-core/language/hindi.json +++ b/qortal-ui-core/language/hindi.json @@ -35,7 +35,8 @@ "qchat":"क्यू-चैट", "groupmanagement":"समूह प्रबंधन", "puzzles":"पहेलि", - "nodemanagement":"नोड प्रबंधन" + "nodemanagement":"नोड प्रबंधन", + "trading":"व्यापार" }, "login":{ "login":"लॉग इन करें", @@ -151,7 +152,9 @@ "next":"अगला", "create":"बनाएं", "continue":"जारी रखें", - "save":"सहेजें" + "save":"सहेजें", + "balance":"संतुलन", + "balances":"आपका वॉलेट बैलेंस" }, "startminting":{ "smchange1":"खनन खाते नहीं लाए जा सकते", @@ -323,7 +326,8 @@ "tchange44":"स्वतः खरीद आदेश सफलतापूर्वक जोड़ा गया!", "tchange45":"ऑटो के साथ खरीदें", "tchange46":"ऑटो खरीदें", - "tchange47":"इस कीमत पर बेचें" + "tchange47":"इस कीमत पर बेचें", + "tchange48":"पर्याप्त नहीं" }, "rewardsharepage":{ "rchange1":"रिवॉर्डशेयर", diff --git a/qortal-ui-core/language/hr.json b/qortal-ui-core/language/hr.json index d83f334d..7ca85c71 100644 --- a/qortal-ui-core/language/hr.json +++ b/qortal-ui-core/language/hr.json @@ -34,7 +34,8 @@ "qchat":"Q-ČAVRLJANJE", "groupmanagement":"UPRAVLJANJE GRUPAMA", "puzzles":"ZAGONETKE", - "nodemanagement":"UPRAVLJANJE ČVOROVIMA" + "nodemanagement":"UPRAVLJANJE ČVOROVIMA", + "trading":"TRGOVANJE" }, "login":{ "login":"Prijavi se", @@ -133,7 +134,8 @@ "uiversion":"Verzija upravljačkog sučelja - UI", "coreversion":"Verzija jezgre - Core", "minting":"(Mintanje)", - "synchronizing":"Sinkroniziranje" + "synchronizing":"Sinkroniziranje", + "balance":"Balance" }, "walletprofile":{ "minterlevel":"Minter Level", @@ -150,7 +152,9 @@ "next":"Sljedeće", "create":"Stvori", "continue":"Nastavi", - "save":"Spremi" + "save":"Spremi", + "balance":"Kreditna", + "balances":"VAŠ NOVČANIK JE NA SALJU" }, "startminting":{ "smchange1":"Nije moguće dohvatiti račune za kovanje", @@ -322,7 +326,8 @@ "tchange44":"Uspješno dodana automatska narudžba za kupnju!", "tchange45":"AUTO KUPITE SA", "tchange46":"AUTO OTKUP", - "tchange47":"Prodaj za ovu cijenu" + "tchange47":"Prodaj za ovu cijenu", + "tchange48":"NEDOVOLJNO" }, "rewardsharepage":{ "rchange1":"Nagradni udio (Rewardshares)", diff --git a/qortal-ui-core/language/hu.json b/qortal-ui-core/language/hu.json index a71fd60e..ed3abedd 100644 --- a/qortal-ui-core/language/hu.json +++ b/qortal-ui-core/language/hu.json @@ -34,7 +34,8 @@ "qchat":"Q-CHAT", "groupmanagement":"CSOPORTKEZELÉS", "puzzles":"REJTVÉNYEK", - "nodemanagement":"CSOMÓPONTKEZELÉS" + "nodemanagement":"CSOMÓPONTKEZELÉS", + "trading":"KERESKEDÉS" }, "login":{ "login":"Bejelentkezés", @@ -150,7 +151,9 @@ "next":"Következő", "create":"Létrehozáshoz", "continue":"Folytatódik/folytatáshoz", - "save":"Mentéshez" + "save":"Mentéshez", + "balance":"Hitel", + "balances":"A PÉNZTÁRCSA EGYENLEGEK" }, "startminting":{ "smchange1":"Nem lehet lekérni a pénzverési számlákat", @@ -322,7 +325,8 @@ "tchange44":"Az automatikus vásárlási rendelés sikeresen hozzáadva!", "tchange45":"AUTOMATIKUS VÁSÁRLÁS", "tchange46":"AUTOMATIKUS VÁSÁRLÁS", - "tchange47":"Eladni ezen az áron" + "tchange47":"Eladni ezen az áron", + "tchange48":"NEM ELÉG" }, "rewardsharepage":{ "rchange1":"Jutalommegosztások", diff --git a/qortal-ui-core/language/it.json b/qortal-ui-core/language/it.json index 6c1acd65..b8cb7332 100644 --- a/qortal-ui-core/language/it.json +++ b/qortal-ui-core/language/it.json @@ -34,7 +34,8 @@ "qchat":"Q-CHAT", "groupmanagement":"GESTIONE DEI GRUPPI", "puzzles":"PUZZLES", - "nodemanagement":"GESTIONE DEI NODI" + "nodemanagement":"GESTIONE DEI NODI", + "trading":"COMMERCIO" }, "login":{ "login":"Login", @@ -150,7 +151,9 @@ "next":"Avanti", "create":"Creare", "continue":"Continua", - "save":"Salva" + "save":"Salva", + "balance":"Saldo", + "balances":"IL TUO SALDO DEL PORTAFOGLIO" }, "startminting":{ "smchange1":"Impossibile recuperare i conti di conio", @@ -322,7 +325,8 @@ "tchange44":"Ordine di acquisto automatico aggiunto con successo!", "tchange45":"ACQUISTA AUTO CON", "tchange46":"ACQUISTO AUTO", - "tchange47":"Vendi a questo prezzo" + "tchange47":"Vendi a questo prezzo", + "tchange48":"NON ABBASTANZA" }, "rewardsharepage":{ "rchange1":"Quote di ricompensa", diff --git a/qortal-ui-core/language/ko.json b/qortal-ui-core/language/ko.json index 791fac74..2dabfd6b 100644 --- a/qortal-ui-core/language/ko.json +++ b/qortal-ui-core/language/ko.json @@ -34,7 +34,8 @@ "qchat":"Q-CHAT", "groupmanagement":"그룹 관리", "puzzles":"퍼즐", - "nodemanagement":"노드 관리" + "nodemanagement":"노드 관리", + "trading":"무역" }, "login":{ "login":"로그인", @@ -150,7 +151,9 @@ "next":"다음", "create":"생성", "continue":"계속하다", - "save":"저장" + "save":"저장", + "balance":"균형", + "balances":"지갑 잔액" }, "startminting":{ "smchange1":"발행 계정을 가져올 수 없습니다", @@ -322,7 +325,8 @@ "tchange44":"자동 구매 주문을 성공적으로 추가했습니다!", "tchange45":"자동 구매", "tchange46":"자동 구매", - "tchange47":"이 가격에 팔아요" + "tchange47":"이 가격에 팔아요", + "tchange48":"부족한" }, "rewardsharepage":{ "rchange1":"보상 공유", diff --git a/qortal-ui-core/language/no.json b/qortal-ui-core/language/no.json index 39d3da2c..9b6d8151 100644 --- a/qortal-ui-core/language/no.json +++ b/qortal-ui-core/language/no.json @@ -34,7 +34,8 @@ "qchat":"Q-CHAT", "groupmanagement":"GRUPPEADMINISTRASJON", "puzzles":"PUZZLES", - "nodemanagement":"NODEADMINISTRASJON" + "nodemanagement":"NODEADMINISTRASJON", + "trading":"HANDEL" }, "login":{ "login":"Logg på", @@ -150,7 +151,9 @@ "next":"Neste", "create":"Opprett", "continue":"Fortsett", - "save":"Lagre" + "save":"Lagre", + "balance":"Saldo", + "balances":"DIN WALLET-SALDO" }, "startminting":{ "smchange1":"Kan ikke hente myntingkontoer", @@ -322,7 +325,8 @@ "tchange44":"Autokjøpsordre er lagt til!", "tchange45":"AUTOKJØP MED", "tchange46":"AUTOKJØP", - "tchange47":"Selges for denne prisen" + "tchange47":"Selges for denne prisen", + "tchange48":"IKKE NOK" }, "rewardsharepage":{ "rchange1":"Belønningsdel", diff --git a/qortal-ui-core/language/pl.json b/qortal-ui-core/language/pl.json index bc93b764..6e04b1a3 100644 --- a/qortal-ui-core/language/pl.json +++ b/qortal-ui-core/language/pl.json @@ -34,7 +34,8 @@ "qchat":"Q-CHAT", "groupmanagement":"ZARZĄDZANIE GRUPAMI", "puzzles":"PUZZLE", - "nodemanagement":"ZARZĄDZANIE WĘZŁAMI" + "nodemanagement":"ZARZĄDZANIE WĘZŁAMI", + "trading":"HANDLOWY" }, "login":{ "login":"Zaloguj się", @@ -150,7 +151,9 @@ "next":"Następny", "create":"Utwórz", "continue":"Kontynuuj", - "save":"Zapisz" + "save":"Zapisz", + "balance":"Saldo", + "balances":"SALDO TWOJEGO PORTFELA" }, "startminting":{ "smchange1":"Nie można pobrać kont menniczych", @@ -322,7 +325,8 @@ "tchange44":"Pomyślnie dodano automatyczne zamówienie zakupu!", "tchange45":"AUTO KUP Z", "tchange46":"AUTO KUP", - "tchange47":"Sprzedaj za tę cenę" + "tchange47":"Sprzedaj za tę cenę", + "tchange48":"NIEWYSTARCZAJĄCO" }, "rewardsharepage":{ "rchange1":"Podział nagród", diff --git a/qortal-ui-core/language/pt.json b/qortal-ui-core/language/pt.json index 513ff6ac..9563d8a9 100644 --- a/qortal-ui-core/language/pt.json +++ b/qortal-ui-core/language/pt.json @@ -34,7 +34,8 @@ "qchat":"Q-CHAT", "groupmanagement":"GESTÃO DE GRUPOS", "puzzles":"ENIGMAS", - "nodemanagement":"GERENCIAMENTO DO NÓDULO" + "nodemanagement":"GERENCIAMENTO DO NÓDULO", + "trading":"NEGOCIAÇÃO" }, "login":{ "login":"Login", @@ -150,7 +151,9 @@ "next":"Próximo", "create":"Criar", "continue":"Continuar", - "save":"Salvar" + "save":"Salvar", + "balance":"Saldo", + "balances":"SEUS SALDOS DE CARTEIRA" }, "startminting":{ "smchange1":"Não é possível buscar contas de cunhagem", @@ -322,7 +325,8 @@ "tchange44":"Pedido de compra automática adicionado com sucesso!", "tchange45":"COMPRA AUTOMÁTICA COM", "tchange46":"COMPRA AUTOMÁTICA", - "tchange47":"Vendo por este preço" + "tchange47":"Vendo por este preço", + "tchange48":"INSUFICIENTE" }, "rewardsharepage":{ "rchange1":"Ações de recompensa", diff --git a/qortal-ui-core/language/ro.json b/qortal-ui-core/language/ro.json index cee5d56e..a7ba9caf 100644 --- a/qortal-ui-core/language/ro.json +++ b/qortal-ui-core/language/ro.json @@ -34,7 +34,8 @@ "qchat":"Q-CHAT", "groupmanagement":"GESTIONARE GRUP", "puzzles":"PUZZLE-URI", - "nodemanagement":"GESTIONARE NOD" + "nodemanagement":"GESTIONARE NOD", + "trading":"COMERCIAL" }, "login":{ "login":"Login", @@ -150,7 +151,9 @@ "next":"Inainte", "create":"Creaza", "continue":"Continua", - "save":"Salveza" + "save":"Salveza", + "balance":"Credit", + "balances":"SOLDELE PORTOTELULUI DVS" }, "startminting":{ "smchange1":"Nu se pot prelua conturile de batere", @@ -322,7 +325,8 @@ "tchange44":"Comanda de cumparare automata a fost adaugata cu succes!", "tchange45":"CUMPARA AUTOMATA CU", "tchange46":"CUMPARARE AUTOMATA", - "tchange47":"Vinde la acest pret" + "tchange47":"Vinde la acest pret", + "tchange48":"INSUFICIENT" }, "rewardsharepage":{ "rchange1":"Cote de recompensa", diff --git a/qortal-ui-core/language/rs.json b/qortal-ui-core/language/rs.json index 819fc931..98adcb95 100644 --- a/qortal-ui-core/language/rs.json +++ b/qortal-ui-core/language/rs.json @@ -34,7 +34,8 @@ "qchat":"Q-ĆASKANJE", "groupmanagement":"MENADŽMENT GRUPA", "puzzles":"SLAGALICE", - "nodemanagement":"MENADŽMENT ČVORIŠTA" + "nodemanagement":"MENADŽMENT ČVORIŠTA", + "trading":"TRADING" }, "login":{ "login":"Prijava", @@ -150,7 +151,9 @@ "next":"Dalje", "create":"Napravite", "continue":"Nastavite", - "save":"Sačuvajte" + "save":"Sačuvajte", + "balance":"Kredit", + "balances":"VAŠI STANJE U NOVČANIKU" }, "startminting":{ "smchange1":"Nije moguće preuzeti naloge za kovanje", @@ -322,7 +325,8 @@ "tchange44":"Narudžbina za automatsku kupovinu je uspešno dodata!", "tchange45":"AUTO KUPI SA", "tchange46":"AUTO BUI", - "tchange47":"Prodaj za ovu cenu" + "tchange47":"Prodaj za ovu cenu", + "tchange48":"NEDOVOLJNO" }, "rewardsharepage":{ "rchange1":"Udeo nagrade", diff --git a/qortal-ui-core/language/ru.json b/qortal-ui-core/language/ru.json index bf0cf3cc..5e89430f 100644 --- a/qortal-ui-core/language/ru.json +++ b/qortal-ui-core/language/ru.json @@ -34,7 +34,8 @@ "qchat":"Q-ЧАТ", "groupmanagement":"УПРАВЛЕНИЕ ГРУППАМИ", "puzzles":"ГОЛОВОЛОМКИ", - "nodemanagement":"УПРАВЛЕНИЕ УЗЛАМИ" + "nodemanagement":"УПРАВЛЕНИЕ УЗЛАМИ", + "trading":"ТОРГОВЛЯ" }, "login":{ "login":"Войти", @@ -150,7 +151,9 @@ "next":"Следующий", "create":"Создать", "continue":"Продолжить", - "save":"Сохранить" + "save":"Сохранить", + "balance":"кредит", + "balances":"БАЛАНС ВАШЕГО КОШЕЛЬКА" }, "startminting":{ "smchange1":"Не удается получить учетные записи минтинга", @@ -322,7 +325,8 @@ "tchange44":"Заказ на автоматическую покупку успешно добавлен!", "tchange45":"АВТО КУПИТЬ С", "tchange46":"АВТО КУПИТЬ", - "tchange47":"Продать по этой цене" + "tchange47":"Продать по этой цене", + "tchange48":"НЕДОСТАТОЧНО" }, "rewardsharepage":{ "rchange1":"Вознаграждения", diff --git a/qortal-ui-core/language/us.json b/qortal-ui-core/language/us.json index e89fe59b..10413d15 100644 --- a/qortal-ui-core/language/us.json +++ b/qortal-ui-core/language/us.json @@ -34,7 +34,8 @@ "qchat":"Q-CHAT", "groupmanagement":"GROUP MANAGEMENT", "puzzles":"PUZZLES", - "nodemanagement":"NODE MANAGEMENT" + "nodemanagement":"NODE MANAGEMENT", + "trading":"TRADING" }, "login":{ "login":"Login", @@ -150,7 +151,9 @@ "next":"Next", "create":"Create", "continue":"Continue", - "save":"Save" + "save":"Save", + "balance":"Balance", + "balances":"YOUR WALLET BALANCES" }, "startminting":{ "smchange1":"Cannot fetch minting accounts", @@ -322,7 +325,8 @@ "tchange44":"Successfully added auto buy order!", "tchange45":"AUTO BUY WITH", "tchange46":"AUTO BUY", - "tchange47":"Sell for this price" + "tchange47":"Sell for this price", + "tchange48":"NOT ENOUGH" }, "rewardsharepage":{ "rchange1":"Rewardshares", diff --git a/qortal-ui-core/language/zhc.json b/qortal-ui-core/language/zhc.json index 770f63cd..d81132d4 100644 --- a/qortal-ui-core/language/zhc.json +++ b/qortal-ui-core/language/zhc.json @@ -34,7 +34,8 @@ "qchat":"Q-CHAT", "groupmanagement":"群组管理", "puzzles":"益智游戏", - "nodemanagement":"节点管理" + "nodemanagement":"节点管理", + "trading":"贸易" }, "login":{ "login":"登入", @@ -150,7 +151,9 @@ "next":"下一步", "create":"新建", "continue":"继续", - "save":"保存" + "save":"保存", + "balance":"信用", + "balances":"您的钱包余额" }, "startminting":{ "smchange1":"无法获取铸币帐户", @@ -322,7 +325,8 @@ "tchange44":"成功添加自动买单!", "tchange45":"自动购买", "tchange46":"自动购买", - "tchange47":"以这个价格出售" + "tchange47":"以这个价格出售", + "tchange48":"不够" }, "rewardsharepage":{ "rchange1":"铸币密钥", diff --git a/qortal-ui-core/language/zht.json b/qortal-ui-core/language/zht.json index 4ff9cd53..b82cfe0c 100644 --- a/qortal-ui-core/language/zht.json +++ b/qortal-ui-core/language/zht.json @@ -34,7 +34,8 @@ "qchat":"Q-CHAT", "groupmanagement":"群組管理", "puzzles":"益智遊戲", - "nodemanagement":"節點管理" + "nodemanagement":"節點管理", + "trading":"貿易" }, "login":{ "login":"登入", @@ -150,7 +151,9 @@ "next":"下一步", "create":"創建", "continue":"繼續", - "save":"保存" + "save":"保存", + "balance":"信用", + "balances":"您的錢包餘額" }, "startminting":{ "smchange1":"無法獲取鑄幣帳戶", @@ -322,7 +325,8 @@ "tchange44":"成功添加自動買單!", "tchange45":"自動購買", "tchange46":"自動購買", - "tchange47":"以這個價格出售" + "tchange47":"以這個價格出售", + "tchange48":"不夠" }, "rewardsharepage":{ "rchange1":"鑄幣密鑰", diff --git a/qortal-ui-core/package.json b/qortal-ui-core/package.json index 0e14cc33..24f76cf9 100644 --- a/qortal-ui-core/package.json +++ b/qortal-ui-core/package.json @@ -58,16 +58,16 @@ "@rollup/plugin-commonjs": "23.0.2", "@rollup/plugin-node-resolve": "15.0.1", "@rollup/plugin-replace": "5.0.1", - "@vaadin/grid": "23.2.8", - "@vaadin/icons": "23.2.8", - "@vaadin/password-field": "23.2.8", + "@vaadin/grid": "23.2.9", + "@vaadin/icons": "23.2.9", + "@vaadin/password-field": "23.2.9", "asmcrypto.js": "2.3.2", "bcryptjs": "2.4.3", "epml": "0.3.3", "file-saver": "2.0.5", "lit": "2.4.1", "lit-translate": "2.0.1", - "postcss": "8.4.18", + "postcss": "8.4.19", "pwa-helpers": "0.9.1", "random-sentence-generator": "0.0.8", "redux": "4.2.0", diff --git a/qortal-ui-core/src/components/app-view.js b/qortal-ui-core/src/components/app-view.js index 43d962f0..88a7e2ae 100644 --- a/qortal-ui-core/src/components/app-view.js +++ b/qortal-ui-core/src/components/app-view.js @@ -1,7 +1,9 @@ import { LitElement, html, css } from 'lit' import { connect } from 'pwa-helpers' import { store } from '../store.js' -import { translate, translateUnsafeHTML } from 'lit-translate' +import { Epml } from '../epml.js' +import { addTradeBotRoutes } from '../tradebot/addTradeBotRoutes.js' +import { get, translate, translateUnsafeHTML } from 'lit-translate' import '@polymer/paper-icon-button/paper-icon-button.js' import '@polymer/iron-icons/iron-icons.js' @@ -21,12 +23,78 @@ import './settings-view/user-settings.js' import './logout-view/logout-view.js' import './user-info-view/user-info-view.js' +const parentEpml = new Epml({type: 'WINDOW', source: window.parent}) + class AppView extends connect(store)(LitElement) { static get properties() { return { config: { type: Object }, theme: { type: String, reflect: true }, - searchContentString: { type: String } + searchContentString: { type: String }, + botQortWallet: { type: String }, + botBtcWallet: { type: String }, + botLtcWallet: { type: String }, + botDogeWallet: { type: String }, + botDgbWallet: { type: String }, + botRvnWallet: { type: String }, + botArrrWallet: { type: String }, + arrrWalletAddress: { type: String }, + qortWalletBalance: { type: Number }, + btcWalletBalance: { type: Number }, + ltcWalletBalance: { type: Number }, + dogeWalletBalance: { type: Number }, + dgbWalletBalance: { type: Number }, + rvnWalletBalance: { type: Number }, + arrrWalletBalance: { type: Number }, + tradesOpenBtcQortal: { type: Array }, + tradesOpenLtcQortal: { type: Array }, + tradesOpenDogeQortal: { type: Array }, + tradesOpenDgbQortal: { type: Array }, + tradesOpenRvnQortal: { type: Array }, + tradesOpenArrrQortal: { type: Array }, + tradeBotBtcBook: { type: Array }, + tradeBotLtcBook: { type: Array }, + tradeBotDogeBook: { type: Array }, + tradeBotDgbBook: { type: Array }, + tradeBotRvnBook: { type: Array }, + tradeBotArrrBook: { type: Array }, + tradeBotBtcAt: { type: Array }, + tradeBotLtcAt: { type: Array }, + tradeBotDogeAt: { type: Array }, + tradeBotDgbAt: { type: Array }, + tradeBotRvnAt: { type: Array }, + tradeBotArrrAt: { type: Array }, + tradeBotAvailableBtcQortal: { type: Array }, + tradeBotAvailableLtcQortal: { type: Array }, + tradeBotAvailableDogeQortal: { type: Array }, + tradeBotAvailableDgbQortal: { type: Array }, + tradeBotAvailableRvnQortal: { type: Array }, + tradeBotAvailableArrrQortal: { type: Array }, + checkBtcAlice: { type: String }, + checkLtcAlice: { type: String }, + checkDogeAlice: { type: String }, + checkDgbAlice: { type: String }, + checkRvnAlice: { type: String }, + checkArrrAlice: { type: String }, + reAddBtcAmount: { type: Number }, + reAddLtcAmount: { type: Number }, + reAddDogeAmount: { type: Number }, + reAddDgbAmount: { type: Number }, + reAddRvnAmount: { type: Number }, + reAddArrrAmount: { type: Number }, + reAddBtcPrice: { type: Number }, + reAddLtcPrice: { type: Number }, + reAddDogePrice: { type: Number }, + reAddDgbPrice: { type: Number }, + reAddRvnPrice: { type: Number }, + reAddArrrPrice: { type: Number }, + botBtcBuyAtAddress: { type: String }, + botLtcBuyAtAddress: { type: String }, + botDogeBuyAtAddress: { type: String }, + botDgbBuyAtAddress: { type: String }, + botRvnBuyAtAddress: { type: String }, + botArrrBuyAtAddress: { type: String }, + balanceTicker: { type: String } } } @@ -94,13 +162,134 @@ class AppView extends connect(store)(LitElement) { } #sideBar::-webkit-scrollbar-track { - background-color: transparent; + background-color: transparent; } #sideBar::-webkit-scrollbar-thumb { - background-color: #333; - border-radius: 6px; - border: 3px solid #333; + background-color: #333; + border-radius: 6px; + border: 3px solid #333; + } + + #balanceheader { + flex: 0 0 24px; + padding: 12px; + border-bottom: 1px solid var(--border); + background: var(--sidetopbar); + } + + .balanceheadertext { + position: absolute; + margin: auto; + font-size: 16px; + font-weight: 400; + width: 250px; + display: inline; + padding-top: 5px; + padding-bottom: 5px; + color: var(--nav-text-color); + } + + #balances { + flex: 0 0 24px; + padding: 12px; + background: var(--sidetopbar); + } + + .balancelist { + align-items: center; + float: left; + opacity: 1; + position: relative; + } + + .balanceinfo { + position: absolute; + margin: auto; + font-size: 14px; + font-weight: 100; + width: 250px; + display: inline; + padding-top: 5px; + padding-bottom: 5px; + color: var(--black); + } + + .qort { + animation: animate1 4s 2s 1 ease-in-out ; + color: var(--black); + opacity: 0; + } + + .btc { + animation: animate2 4s 8s 1 ease-in-out ; + color: var(--black); + opacity: 0; + } + + .ltc { + animation: animate3 4s 14s 1 ease-in-out ; + color: var(--black); + opacity: 0; + } + + .doge { + animation: animate4 4s 20s 1 ease-in-out ; + color: var(--black); + opacity: 0; + } + + .dgb { + animation: animate5 4s 26s 1 ease-in-out ; + color: var(--black); + opacity: 0; + } + + .rvn { + animation: animate6 4s 32s 1 ease-in-out ; + color: var(--black); + opacity: 0; + } + + .arrr { + animation: animate7 4s 38s 1 ease-in-out ; + color: var(--black); + opacity: 0; + } + + @keyframes animate1 { + 0%,100% { opacity: 0; } + 50% { opacity: 10; } + } + + @keyframes animate2 { + 0%,100% { opacity: 0; } + 50% { opacity: 10; } + } + + @keyframes animate3 { + 0%,100% { opacity: 0; } + 50% { opacity: 10; } + } + + @keyframes animate4 { + 0%,100% { opacity: 0; } + 50% { opacity: 10; } + } + + @keyframes animate5 { + 0%,100% { opacity: 0; } + 50% { opacity: 10; } + } + + @keyframes animate6 { + 0%,100% { opacity: 0; } + 50% { opacity: 10; } + } + + @keyframes animate7 { + 0%,100% { opacity: 0; } + 50% { opacity: 10; } } ` ] @@ -110,6 +299,74 @@ class AppView extends connect(store)(LitElement) { super() this.searchContentString = '' this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light' + this.botQortWallet = '' + this.botBtcWallet = '' + this.botLtcWallet = '' + this.botDogeWallet = '' + this.botDgbWallet = '' + this.botRvnWallet = '' + this.botArrrWallet = '' + this.arrrWalletAddress = '' + this.qortWalletBalance = 0 + this.btcWalletBalance = 0 + this.ltcWalletBalance = 0 + this.dogeWalletBalance = 0 + this.dgbWalletBalance = 0 + this.rvnWalletBalance = 0 + this.arrrWalletBalance = 0 + this.tradesOpenBtcQortal = [] + this.tradesOpenLtcQortal = [] + this.tradesOpenDogeQortal = [] + this.tradesOpenDgbQortal = [] + this.tradesOpenRvnQortal = [] + this.tradesOpenArrrQortal = [] + this.tradeBotBtcBook = [] + this.tradeBotLtcBook = [] + this.tradeBotDogeBook = [] + this.tradeBotDgbBook = [] + this.tradeBotRvnBook = [] + this.tradeBotArrrBook = [] + this.tradeBotBtcAt = [] + this.tradeBotLtcAt = [] + this.tradeBotDogeAt = [] + this.tradeBotDgbAt = [] + this.tradeBotRvnAt = [] + this.tradeBotArrrAt = [] + this.tradeBotAvailableBtcQortal = [] + this.tradeBotAvailableLtcQortal = [] + this.tradeBotAvailableDogeQortal = [] + this.tradeBotAvailableDgbQortal = [] + this.tradeBotAvailableRvnQortal = [] + this.tradeBotAvailableArrrQortal = [] + this.checkBtcAlice = '' + this.checkLtcAlice = '' + this.checkDogeAlice = '' + this.checkDgbAlice = '' + this.checkRvnAlice = '' + this.checkArrrAlice = '' + this.reAddBtcAmount = 0 + this.reAddLtcAmount = 0 + this.reAddDogeAmount = 0 + this.reAddDgbAmount = 0 + this.reAddRvnAmount = 0 + this.reAddArrrAmount = 0 + this.reAddBtcPrice = 0 + this.reAddLtcPrice = 0 + this.reAddDogePrice = 0 + this.reAddDgbPrice = 0 + this.reAddRvnPrice = 0 + this.reAddArrrPrice = 0 + this.botBtcBuyAtAddress = '' + this.botLtcBuyAtAddress = '' + this.botDogeBuyAtAddress = '' + this.botDgbBuyAtAddress = '' + this.botRvnBuyAtAddress = '' + this.botArrrBuyAtAddress = '' + this.balanceTicker = html` +
+
+
+ ` } render() { @@ -122,6 +379,10 @@ class AppView extends connect(store)(LitElement) {
+
+ ${translate("general.balances")} +
+ ${this.balanceTicker} @@ -177,7 +438,1498 @@ class AppView extends connect(store)(LitElement) { ` } - firstUpdated() { + async firstUpdated() { + + addTradeBotRoutes(parentEpml) + parentEpml.imReady() + + const myAppNode = store.getState().app.nodeConfig.knownNodes[store.getState().app.nodeConfig.node] + const nodeAppUrl = myAppNode.protocol + '://' + myAppNode.domain + ':' + myAppNode.port + const appDelay = ms => new Promise(res => setTimeout(res, ms)) + + await appDelay(3000) + + this.botQortWallet = store.getState().app.selectedAddress.address + await this.updateQortWalletBalance() + + this.botBtcWallet = store.getState().app.selectedAddress.btcWallet.address + await this.updateBtcWalletBalance() + + this.botLtcWallet = store.getState().app.selectedAddress.ltcWallet.address + await this.updateLtcWalletBalance() + + this.botDogeWallet = store.getState().app.selectedAddress.dogeWallet.address + await this.updateDogeWalletBalance() + + this.botDgbWallet = store.getState().app.selectedAddress.dgbWallet.address + await this.updateDgbWalletBalance() + + this.botRvnWallet = store.getState().app.selectedAddress.rvnWallet.address + await this.updateRvnWalletBalance() + + this.botArrrWallet = store.getState().app.selectedAddress.arrrWallet.address + await this.fetchArrrWalletAddress() + await this.updateArrrWalletBalance() + + await this.botBtcTradebook() + await this.botLtcTradebook() + await this.botDogeTradebook() + await this.botDgbTradebook() + await this.botRvnTradebook() + await this.botArrrTradebook() + + window.addEventListener('storage', async () => { + this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.botBtcWallet) || "[]") + await appDelay(500) + this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.botLtcWallet) || "[]") + await appDelay(500) + this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.botDogeWallet) || "[]") + await appDelay(500) + this.tradeBotDgbBook = JSON.parse(localStorage.getItem(this.botDgbWallet) || "[]") + await appDelay(500) + this.tradeBotRvnBook = JSON.parse(localStorage.getItem(this.botRvnWallet) || "[]") + await appDelay(500) + this.tradeBotArrrBook = JSON.parse(localStorage.getItem(this.botArrrWallet) || "[]") + await appDelay(500) + }) + + this.renderBalances() + + const getOpenTradesBTC = async () => { + let timerBTC + + if (this.isEmptyArray(this.tradeBotBtcBook) === true) { + clearTimeout(timerBTC) + timerBTC = setTimeout(getOpenTradesBTC, 150000) + } else { + const tradesOpenBtcQortalUrl = `${nodeAppUrl}/crosschain/tradeoffers?foreignBlockchain=BITCOIN&limit=0` + + const tradesOpenBtcQortal = await fetch(tradesOpenBtcQortalUrl).then(response => { + return response.json() + }) + + this.tradesOpenBtcQortal = tradesOpenBtcQortal.map(item => { + const expiryTime = item.creatorPresenceExpiry + if (Number(expiryTime) > Date.now()) { + const calcedPrice = parseFloat(item.expectedForeignAmount) / parseFloat(item.qortAmount) + const roundedPrice = (Math.round(parseFloat(calcedPrice) * 1e8) / 1e8).toFixed(8) + return { + qortAmount: item.qortAmount, + price: roundedPrice, + foreignAmount: item.expectedForeignAmount, + qortalCreator: item.qortalCreator, + qortalAtAddress: item.qortalAtAddress + } + } + }).filter(item => !!item) + + await this.updateBtcWalletBalance() + filterMyBotPriceTradesBTC() + setTimeout(getOpenTradesBTC, 150000) + } + } + + const filterMyBotPriceTradesBTC = async () => { + const tradeBotBtcUrl = `${nodeAppUrl}/crosschain/tradebot?foreignBlockchain=BITCOIN&apiKey=${this.getApiKey()}` + + const tradeBotBtcAt = await fetch(tradeBotBtcUrl).then(response => { + return response.json() + }) + + this.tradeBotBtcAt = tradeBotBtcAt + + await appDelay(1000) + + this.tradeBotAvailableBtcQortal = this.tradesOpenBtcQortal.map(item => { + const listprice = parseFloat(item.price) + const listamount = parseFloat(item.qortAmount) + const checkprice = parseFloat(this.tradeBotBtcBook[0].botBtcPrice) + const checkamount = parseFloat(this.tradeBotBtcBook[0].botBtcQortAmount) + if (Number(listprice) <= Number(checkprice) && Number(listamount) <= Number(checkamount)) { + return { + qortAmount: item.qortAmount, + price: item.price, + foreignAmount: item.foreignAmount, + qortalCreator: item.qortalCreator, + qortalAtAddress: item.qortalAtAddress + } + } + }).filter(item => !!item) + + this.tradeBotAvailableBtcQortal.sort((a, b) => parseFloat(a.price) - parseFloat(b.price)) + + if (this.isEmptyArray(this.tradeBotAvailableBtcQortal) === true) { + return + } else { + this.checkBtcAlice = this.tradeBotAvailableBtcQortal[0].qortalAtAddress + } + + await appDelay(1000) + + if (this.tradeBotBtcAt.some(item => item.atAddress === this.checkBtcAlice)) { + return + } else { + this.tradeBotAvailableBtcQortal = this.tradeBotAvailableBtcQortal + } + + await appDelay(1000) + + if (this.isEmptyArray(this.tradeBotAvailableBtcQortal) === true) { + return + } else { + const botbtcprice = this.round(parseFloat(this.tradeBotBtcBook[0].botBtcPrice)) + const changebtcamount = parseFloat(this.tradeBotBtcBook[0].botBtcQortAmount) + const reducebtcamount = parseFloat(this.tradeBotAvailableBtcQortal[0].qortAmount) + const tradebtcataddress = this.tradeBotAvailableBtcQortal[0].qortalAtAddress + const newbtcamount = this.round(parseFloat(changebtcamount - reducebtcamount)) + + this.reAddBtcAmount = this.round(parseFloat(this.tradeBotBtcBook[0].botBtcQortAmount)) + this.reAddBtcPrice = this.round(parseFloat(this.tradeBotBtcBook[0].botBtcPrice)) + + localStorage.removeItem(this.botBtcWallet) + localStorage.setItem(this.botBtcWallet, "") + + var oldBtcTradebook = JSON.parse(localStorage.getItem(this.botBtcWallet) || "[]") + + const newBtcTradebookItem = { + botBtcQortAmount: newbtcamount, + botBtcPrice: botbtcprice + } + + oldBtcTradebook.push(newBtcTradebookItem) + + localStorage.setItem(this.botBtcWallet, JSON.stringify(oldBtcTradebook)) + + this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.botBtcWallet) || "[]") + + await appDelay(1000) + + this.botBtcBuyAtAddress = tradebtcataddress + + this.buyBtcAction() + + if (this.isEmptyArray(this.tradeBotBtcBook) === true) { + return + } else { + const botamount = parseFloat(this.tradeBotBtcBook[0].botBtcQortAmount) + + if (Number(botamount) === 0) { + this.removeBotBTCTradebook() + } else { + this.tradeBotBtcBook = this.tradeBotBtcBook + } + } + + if (this.isEmptyArray(this.tradeBotBtcBook) === true) { + return + } else { + await this.updateBtcWalletBalance() + const checkBotBtcFunds = this.round(parseFloat(this.tradeBotBtcBook[0].botBtcQortAmount) * parseFloat(this.tradeBotBtcBook[0].botBtcPrice)) + const myBotBtcFunds = this.round(parseFloat(this.btcWalletBalance)) + + if (Number(myBotBtcFunds) < Number(checkBotBtcFunds)) { + this.removeBotBTCTradebook() + } else { + this.tradeBotBtcBook = this.tradeBotBtcBook + } + } + } + } + + const getOpenTradesLTC = async () => { + let timerLTC + + if (this.isEmptyArray(this.tradeBotLtcBook) === true) { + clearTimeout(timerLTC) + timerLTC = setTimeout(getOpenTradesLTC, 150000) + } else { + const tradesOpenLtcQortalUrl = `${nodeAppUrl}/crosschain/tradeoffers?foreignBlockchain=LITECOIN&limit=0` + + const tradesOpenLtcQortal = await fetch(tradesOpenLtcQortalUrl).then(response => { + return response.json() + }) + + this.tradesOpenLtcQortal = tradesOpenLtcQortal.map(item => { + const expiryTime = item.creatorPresenceExpiry + if (Number(expiryTime) > Date.now()) { + const calcedPrice = parseFloat(item.expectedForeignAmount) / parseFloat(item.qortAmount) + const roundedPrice = (Math.round(parseFloat(calcedPrice) * 1e8) / 1e8).toFixed(8) + return { + qortAmount: item.qortAmount, + price: roundedPrice, + foreignAmount: item.expectedForeignAmount, + qortalCreator: item.qortalCreator, + qortalAtAddress: item.qortalAtAddress + } + } + }).filter(item => !!item) + + await this.updateLtcWalletBalance() + filterMyBotPriceTradesLTC() + setTimeout(getOpenTradesLTC, 150000) + } + } + + const filterMyBotPriceTradesLTC = async () => { + const tradeBotLtcUrl = `${nodeAppUrl}/crosschain/tradebot?foreignBlockchain=LITECOIN&apiKey=${this.getApiKey()}` + + const tradeBotLtcAt = await fetch(tradeBotLtcUrl).then(response => { + return response.json() + }) + + this.tradeBotLtcAt = tradeBotLtcAt + + await appDelay(1000) + + this.tradeBotAvailableLtcQortal = this.tradesOpenLtcQortal.map(item => { + const listprice = parseFloat(item.price) + const listamount = parseFloat(item.qortAmount) + const checkprice = parseFloat(this.tradeBotLtcBook[0].botLtcPrice) + const checkamount = parseFloat(this.tradeBotLtcBook[0].botLtcQortAmount) + if (Number(listprice) <= Number(checkprice) && Number(listamount) <= Number(checkamount)) { + return { + qortAmount: item.qortAmount, + price: item.price, + foreignAmount: item.foreignAmount, + qortalCreator: item.qortalCreator, + qortalAtAddress: item.qortalAtAddress + } + } + }).filter(item => !!item) + + this.tradeBotAvailableLtcQortal.sort((a, b) => parseFloat(a.price) - parseFloat(b.price)) + + if (this.isEmptyArray(this.tradeBotAvailableLtcQortal) === true) { + return + } else { + this.checkLtcAlice = this.tradeBotAvailableLtcQortal[0].qortalAtAddress + } + + await appDelay(1000) + + if (this.tradeBotLtcAt.some(item => item.atAddress === this.checkLtcAlice)) { + return + } else { + this.tradeBotAvailableLtcQortal = this.tradeBotAvailableLtcQortal + } + + await appDelay(1000) + + if (this.isEmptyArray(this.tradeBotAvailableLtcQortal) === true) { + return + } else { + const botltcprice = this.round(parseFloat(this.tradeBotLtcBook[0].botLtcPrice)) + const changeltcamount = parseFloat(this.tradeBotLtcBook[0].botLtcQortAmount) + const reduceltcamount = parseFloat(this.tradeBotAvailableLtcQortal[0].qortAmount) + const tradeltcataddress = this.tradeBotAvailableLtcQortal[0].qortalAtAddress + const newltcamount = this.round(parseFloat(changeltcamount - reduceltcamount)) + + this.reAddLtcAmount = this.round(parseFloat(this.tradeBotLtcBook[0].botLtcQortAmount)) + this.reAddLtcPrice = this.round(parseFloat(this.tradeBotLtcBook[0].botLtcPrice)) + + localStorage.removeItem(this.botLtcWallet) + localStorage.setItem(this.botLtcWallet, "") + + var oldLtcTradebook = JSON.parse(localStorage.getItem(this.botLtcWallet) || "[]") + + const newLtcTradebookItem = { + botLtcQortAmount: newltcamount, + botLtcPrice: botltcprice + } + + oldLtcTradebook.push(newLtcTradebookItem) + + localStorage.setItem(this.botLtcWallet, JSON.stringify(oldLtcTradebook)) + + this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.botLtcWallet) || "[]") + + await appDelay(1000) + + this.botLtcBuyAtAddress = tradeltcataddress + + this.buyLtcAction() + + if (this.isEmptyArray(this.tradeBotLtcBook) === true) { + return + } else { + const botamount = parseFloat(this.tradeBotLtcBook[0].botLtcQortAmount) + + if (Number(botamount) === 0) { + this.removeBotLTCTradebook() + } else { + this.tradeBotLtcBook = this.tradeBotLtcBook + } + } + + if (this.isEmptyArray(this.tradeBotLtcBook) === true) { + return + } else { + await this.updateLtcWalletBalance() + const checkBotLtcFunds = this.round(parseFloat(this.tradeBotLtcBook[0].botLtcQortAmount) * parseFloat(this.tradeBotLtcBook[0].botLtcPrice)) + const myBotLtcFunds = this.round(parseFloat(this.ltcWalletBalance)) + + if (Number(myBotLtcFunds) < Number(checkBotLtcFunds)) { + this.removeBotLTCTradebook() + } else { + this.tradeBotLtcBook = this.tradeBotLtcBook + } + } + } + } + + const getOpenTradesDOGE = async () => { + let timerDOGE + + if (this.isEmptyArray(this.tradeBotDogeBook) === true) { + clearTimeout(timerDOGE) + timerDOGE = setTimeout(getOpenTradesDOGE, 150000) + } else { + const tradesOpenDogeQortalUrl = `${nodeAppUrl}/crosschain/tradeoffers?foreignBlockchain=DOGECOIN&limit=0` + + const tradesOpenDogeQortal = await fetch(tradesOpenDogeQortalUrl).then(response => { + return response.json() + }) + + this.tradesOpenDogeQortal = tradesOpenDogeQortal.map(item => { + const expiryTime = item.creatorPresenceExpiry + if (Number(expiryTime) > Date.now()) { + const calcedPrice = parseFloat(item.expectedForeignAmount) / parseFloat(item.qortAmount) + const roundedPrice = (Math.round(parseFloat(calcedPrice) * 1e8) / 1e8).toFixed(8) + return { + qortAmount: item.qortAmount, + price: roundedPrice, + foreignAmount: item.expectedForeignAmount, + qortalCreator: item.qortalCreator, + qortalAtAddress: item.qortalAtAddress + } + } + }).filter(item => !!item) + + await this.updateDogeWalletBalance() + filterMyBotPriceTradesDOGE() + setTimeout(getOpenTradesDOGE, 150000) + } + } + + const filterMyBotPriceTradesDOGE = async () => { + const tradeBotDogeUrl = `${nodeAppUrl}/crosschain/tradebot?foreignBlockchain=DOGECOIN&apiKey=${this.getApiKey()}` + + const tradeBotDogeAt = await fetch(tradeBotDogeUrl).then(response => { + return response.json() + }) + + this.tradeBotDogeAt = tradeBotDogeAt + + await appDelay(1000) + + this.tradeBotAvailableDogeQortal = this.tradesOpenDogeQortal.map(item => { + const listprice = parseFloat(item.price) + const listamount = parseFloat(item.qortAmount) + const checkprice = parseFloat(this.tradeBotDogeBook[0].botDogePrice) + const checkamount = parseFloat(this.tradeBotDogeBook[0].botDogeQortAmount) + if (Number(listprice) <= Number(checkprice) && Number(listamount) <= Number(checkamount)) { + return { + qortAmount: item.qortAmount, + price: item.price, + foreignAmount: item.foreignAmount, + qortalCreator: item.qortalCreator, + qortalAtAddress: item.qortalAtAddress + } + } + }).filter(item => !!item) + + this.tradeBotAvailableDogeQortal.sort((a, b) => parseFloat(a.price) - parseFloat(b.price)) + + if (this.isEmptyArray(this.tradeBotAvailableDogeQortal) === true) { + return + } else { + this.checkDogeAlice = this.tradeBotAvailableDogeQortal[0].qortalAtAddress + } + + await appDelay(1000) + + if (this.tradeBotDogeAt.some(item => item.atAddress === this.checkDogeAlice)) { + return + } else { + this.tradeBotAvailableDogeQortal = this.tradeBotAvailableDogeQortal + } + + await appDelay(1000) + + if (this.isEmptyArray(this.tradeBotAvailableDogeQortal) === true) { + return + } else { + const botdogeprice = this.round(parseFloat(this.tradeBotDogeBook[0].botDogePrice)) + const changedogeamount = parseFloat(this.tradeBotDogeBook[0].botDogeQortAmount) + const reducedogeamount = parseFloat(this.tradeBotAvailableDogeQortal[0].qortAmount) + const tradedogeataddress = this.tradeBotAvailableDogeQortal[0].qortalAtAddress + const newdogeamount = this.round(parseFloat(changedogeamount - reducedogeamount)) + + this.reAddDogeAmount = this.round(parseFloat(this.tradeBotDogeBook[0].botDogeQortAmount)) + this.reAddDogePrice = this.round(parseFloat(this.tradeBotDogeBook[0].botDogePrice)) + + localStorage.removeItem(this.botDogeWallet) + localStorage.setItem(this.botDogeWallet, "") + + var oldDogeTradebook = JSON.parse(localStorage.getItem(this.botDogeWallet) || "[]") + + const newDogeTradebookItem = { + botDogeQortAmount: newdogeamount, + botDogePrice: botdogeprice + } + + oldDogeTradebook.push(newDogeTradebookItem) + + localStorage.setItem(this.botDogeWallet, JSON.stringify(oldDogeTradebook)) + + this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.botDogeWallet) || "[]") + + await appDelay(1000) + + this.botDogeBuyAtAddress = tradedogeataddress + + this.buyDogeAction() + + if (this.isEmptyArray(this.tradeBotDogeBook) === true) { + return + } else { + const botamount = parseFloat(this.tradeBotDogeBook[0].botDogeQortAmount) + + if (Number(botamount) === 0) { + this.removeBotDOGETradebook() + } else { + this.tradeBotDogeBook = this.tradeBotDogeBook + } + } + + if (this.isEmptyArray(this.tradeBotDogeBook) === true) { + return + } else { + await this.updateDogeWalletBalance() + const checkBotDogeFunds = this.round(parseFloat(this.tradeBotDogeBook[0].botDogeQortAmount) * parseFloat(this.tradeBotDogeBook[0].botDogePrice)) + const myBotDogeFunds = this.round(parseFloat(this.dogeWalletBalance)) + + if (Number(myBotDogeFunds) < Number(checkBotDogeFunds)) { + this.removeBotDOGETradebook() + } else { + this.tradeBotDogeBook = this.tradeBotDogeBook + } + } + } + } + + const getOpenTradesDGB = async () => { + let timerDGB + + if (this.isEmptyArray(this.tradeBotDgbBook) === true) { + clearTimeout(timerDGB) + timerDGB = setTimeout(getOpenTradesDGB, 150000) + } else { + const tradesOpenDgbQortalUrl = `${nodeAppUrl}/crosschain/tradeoffers?foreignBlockchain=DIGIYBYTE&limit=0` + + const tradesOpenDgbQortal = await fetch(tradesOpenDgbQortalUrl).then(response => { + return response.json() + }) + + this.tradesOpenDgbQortal = tradesOpenDgbQortal.map(item => { + const expiryTime = item.creatorPresenceExpiry + if (Number(expiryTime) > Date.now()) { + const calcedPrice = parseFloat(item.expectedForeignAmount) / parseFloat(item.qortAmount) + const roundedPrice = (Math.round(parseFloat(calcedPrice) * 1e8) / 1e8).toFixed(8) + return { + qortAmount: item.qortAmount, + price: roundedPrice, + foreignAmount: item.expectedForeignAmount, + qortalCreator: item.qortalCreator, + qortalAtAddress: item.qortalAtAddress + } + } + }).filter(item => !!item) + + setTimeout(getOpenTradesDGB, 150000) + } + } + + const filterMyBotPriceTradesDGB = async () => { + const tradeBotDgbUrl = `${nodeAppUrl}/crosschain/tradebot?foreignBlockchain=DIGIBYTE&apiKey=${this.getApiKey()}` + + const tradeBotDgbAt = await fetch(tradeBotDgbUrl).then(response => { + return response.json() + }) + + this.tradeBotDgbAt = tradeBotDgbAt + + await appDelay(1000) + + this.tradeBotAvailableDgbQortal = this.tradesOpenDgbQortal.map(item => { + const listprice = parseFloat(item.price) + const listamount = parseFloat(item.qortAmount) + const checkprice = parseFloat(this.tradeBotDgbBook[0].botDgbPrice) + const checkamount = parseFloat(this.tradeBotDgbBook[0].botDgbQortAmount) + if (Number(listprice) <= Number(checkprice) && Number(listamount) <= Number(checkamount)) { + return { + qortAmount: item.qortAmount, + price: item.price, + foreignAmount: item.foreignAmount, + qortalCreator: item.qortalCreator, + qortalAtAddress: item.qortalAtAddress + } + } + }).filter(item => !!item) + + this.tradeBotAvailableDgbQortal.sort((a, b) => parseFloat(a.price) - parseFloat(b.price)) + + if (this.isEmptyArray(this.tradeBotAvailableDgbQortal) === true) { + return + } else { + this.checkDgbAlice = this.tradeBotAvailableDgbQortal[0].qortalAtAddress + } + + await appDelay(1000) + + if (this.tradeBotDgbAt.some(item => item.atAddress === this.checkDgbAlice)) { + return + } else { + this.tradeBotAvailableDgbQortal = this.tradeBotAvailableDgbQortal + } + + await appDelay(1000) + + if (this.isEmptyArray(this.tradeBotAvailableDgbQortal) === true) { + return + } else { + const botdgbprice = this.round(parseFloat(this.tradeBotDgbBook[0].botDgbPrice)) + const changedgbamount = parseFloat(this.tradeBotDgbBook[0].botDgbQortAmount) + const reducedgbamount = parseFloat(this.tradeBotAvailableDgbQortal[0].qortAmount) + const tradedgbataddress = this.tradeBotAvailableDgbQortal[0].qortalAtAddress + const newdgbamount = this.round(parseFloat(changedgbamount - reducedgbamount)) + + this.reAddDgbAmount = this.round(parseFloat(this.tradeBotDgbBook[0].botDgbQortAmount)) + this.reAddDgbPrice = this.round(parseFloat(this.tradeBotDgbBook[0].botDgbPrice)) + + localStorage.removeItem(this.botDgbWallet) + localStorage.setItem(this.botDgbWallet, "") + + var oldDgbTradebook = JSON.parse(localStorage.getItem(this.botDgbWallet) || "[]") + + const newDgbTradebookItem = { + botDgbQortAmount: newdgbamount, + botDgbPrice: botdgbprice + } + + oldDgbTradebook.push(newDgbTradebookItem) + + localStorage.setItem(this.botDgbWallet, JSON.stringify(oldDgbTradebook)) + + this.tradeBotDgbBook = JSON.parse(localStorage.getItem(this.botDgbWallet) || "[]") + + await appDelay(1000) + + this.botDgbBuyAtAddress = tradedgbataddress + + this.buyDgbAction() + + if (this.isEmptyArray(this.tradeBotDgbBook) === true) { + return + } else { + const botamount = parseFloat(this.tradeBotDgbBook[0].botDgbQortAmount) + + if (Number(botamount) === 0) { + this.removeBotDGBTradebook() + } else { + this.tradeBotDgbBook = this.tradeBotDgbBook + } + } + + if (this.isEmptyArray(this.tradeBotDgbBook) === true) { + return + } else { + await this.updateDgbWalletBalance() + const checkBotDgbFunds = this.round(parseFloat(this.tradeBotDgbBook[0].botDgbQortAmount) * parseFloat(this.tradeBotDgbBook[0].botDgbPrice)) + const myBotDgbFunds = this.round(parseFloat(this.dgbWalletBalance)) + + if (Number(myBotDgbFunds) < Number(checkBotDgbFunds)) { + this.removeBotDGBTradebook() + } else { + this.tradeBotDgbBook = this.tradeBotDgbBook + } + } + } + } + + const getOpenTradesRVN = async () => { + let timerRVN + + if (this.isEmptyArray(this.tradeBotRvnBook) === true) { + clearTimeout(timerRVN) + timerRVN = setTimeout(getOpenTradesRVN, 150000) + } else { + const tradesOpenRvnQortalUrl = `${nodeAppUrl}/crosschain/tradeoffers?foreignBlockchain=RAVENCOIN&limit=0` + + const tradesOpenRvnQortal = await fetch(tradesOpenRvnQortalUrl).then(response => { + return response.json() + }) + + this.tradesOpenRvnQortal = tradesOpenRvnQortal.map(item => { + const expiryTime = item.creatorPresenceExpiry + if (Number(expiryTime) > Date.now()) { + const calcedPrice = parseFloat(item.expectedForeignAmount) / parseFloat(item.qortAmount) + const roundedPrice = (Math.round(parseFloat(calcedPrice) * 1e8) / 1e8).toFixed(8) + return { + qortAmount: item.qortAmount, + price: roundedPrice, + foreignAmount: item.expectedForeignAmount, + qortalCreator: item.qortalCreator, + qortalAtAddress: item.qortalAtAddress + } + } + }).filter(item => !!item) + + setTimeout(getOpenTradesRVN, 150000) + } + } + + const filterMyBotPriceTradesRVN = async () => { + const tradeBotRvnUrl = `${nodeAppUrl}/crosschain/tradebot?foreignBlockchain=RAVENCOIN&apiKey=${this.getApiKey()}` + + const tradeBotRvnAt = await fetch(tradeBotRvnUrl).then(response => { + return response.json() + }) + + this.tradeBotRvnAt = tradeBotRvnAt + + await appDelay(1000) + + this.tradeBotAvailableRvnQortal = this.tradesOpenRvnQortal.map(item => { + const listprice = parseFloat(item.price) + const listamount = parseFloat(item.qortAmount) + const checkprice = parseFloat(this.tradeBotRvnBook[0].botRvnPrice) + const checkamount = parseFloat(this.tradeBotRvnBook[0].botRvnQortAmount) + if (Number(listprice) <= Number(checkprice) && Number(listamount) <= Number(checkamount)) { + return { + qortAmount: item.qortAmount, + price: item.price, + foreignAmount: item.foreignAmount, + qortalCreator: item.qortalCreator, + qortalAtAddress: item.qortalAtAddress + } + } + }).filter(item => !!item) + + this.tradeBotAvailableRvnQortal.sort((a, b) => parseFloat(a.price) - parseFloat(b.price)) + + if (this.isEmptyArray(this.tradeBotAvailableRvnQortal) === true) { + return + } else { + this.checkRvnAlice = this.tradeBotAvailableRvnQortal[0].qortalAtAddress + } + + await appDelay(1000) + + if (this.tradeBotRvnAt.some(item => item.atAddress === this.checkRvnAlice)) { + return + } else { + this.tradeBotAvailableRvnQortal = this.tradeBotAvailableRvnQortal + } + + await appDelay(1000) + + if (this.isEmptyArray(this.tradeBotAvailableRvnQortal) === true) { + return + } else { + const botrvnprice = this.round(parseFloat(this.tradeBotRvnBook[0].botRvnPrice)) + const changervnamount = parseFloat(this.tradeBotRvnBook[0].botRvnQortAmount) + const reducervnamount = parseFloat(this.tradeBotAvailableRvnQortal[0].qortAmount) + const tradervnataddress = this.tradeBotAvailableRvnQortal[0].qortalAtAddress + const newrvnamount = this.round(parseFloat(changervnamount - reducervnamount)) + + this.reAddRvnAmount = this.round(parseFloat(this.tradeBotRvnBook[0].botRvnQortAmount)) + this.reAddRvnPrice = this.round(parseFloat(this.tradeBotRvnBook[0].botRvnPrice)) + + localStorage.removeItem(this.botRvnWallet) + localStorage.setItem(this.botRvnWallet, "") + + var oldRvnTradebook = JSON.parse(localStorage.getItem(this.botRvnWallet) || "[]") + + const newRvnTradebookItem = { + botRvnQortAmount: newrvnamount, + botRvnPrice: botrvnprice + } + + oldRvnTradebook.push(newRvnTradebookItem) + + localStorage.setItem(this.botRvnWallet, JSON.stringify(oldRvnTradebook)) + + this.tradeBotRvnBook = JSON.parse(localStorage.getItem(this.botRvnWallet) || "[]") + + await appDelay(1000) + + this.botRvnBuyAtAddress = tradervnataddress + + this.buyRvnAction() + + if (this.isEmptyArray(this.tradeBotRvnBook) === true) { + return + } else { + const botamount = parseFloat(this.tradeBotRvnBook[0].botRvnQortAmount) + + if (Number(botamount) === 0) { + this.removeBotRVNTradebook() + } else { + this.tradeBotRvnBook = this.tradeBotRvnBook + } + } + + if (this.isEmptyArray(this.tradeBotRvnBook) === true) { + return + } else { + await this.updateRvnWalletBalance() + const checkBotRvnFunds = this.round(parseFloat(this.tradeBotRvnBook[0].botRvnQortAmount) * parseFloat(this.tradeBotRvnBook[0].botRvnPrice)) + const myBotRvnFunds = this.round(parseFloat(this.rvnWalletBalance)) + + if (Number(myBotRvnFunds) < Number(checkBotRvnFunds)) { + this.removeBotRVNTradebook() + } else { + this.tradeBotRvnBook = this.tradeBotRvnBook + } + } + } + } + + const getOpenTradesARRR = async () => { + let timerARRR + + if (this.isEmptyArray(this.tradeBotArrrBook) === true) { + clearTimeout(timerARRR) + timerARRR = setTimeout(getOpenTradesARRR, 150000) + } else { + const tradesOpenArrrQortalUrl = `${nodeAppUrl}/crosschain/tradeoffers?foreignBlockchain=PIRATECHAIN&limit=0` + + const tradesOpenArrrQortal = await fetch(tradesOpenArrrQortalUrl).then(response => { + return response.json() + }) + + this.tradesOpenArrrQortal = tradesOpenArrrQortal.map(item => { + const expiryTime = item.creatorPresenceExpiry + if (Number(expiryTime) > Date.now()) { + const calcedPrice = parseFloat(item.expectedForeignAmount) / parseFloat(item.qortAmount) + const roundedPrice = (Math.round(parseFloat(calcedPrice) * 1e8) / 1e8).toFixed(8) + return { + qortAmount: item.qortAmount, + price: roundedPrice, + foreignAmount: item.expectedForeignAmount, + qortalCreator: item.qortalCreator, + qortalAtAddress: item.qortalAtAddress + } + } + }).filter(item => !!item) + + setTimeout(getOpenTradesARRR, 150000) + } + } + + const filterMyBotPriceTradesARRR = async () => { + const tradeBotArrrUrl = `${nodeAppUrl}/crosschain/tradebot?foreignBlockchain=PIRATECHAIN&apiKey=${this.getApiKey()}` + + const tradeBotArrrAt = await fetch(tradeBotArrrUrl).then(response => { + return response.json() + }) + + this.tradeBotArrrAt = tradeBotArrrAt + + await appDelay(1000) + + this.tradeBotAvailableArrrQortal = this.tradesOpenArrrQortal.map(item => { + const listprice = parseFloat(item.price) + const listamount = parseFloat(item.qortAmount) + const checkprice = parseFloat(this.tradeBotArrrBook[0].botArrrPrice) + const checkamount = parseFloat(this.tradeBotArrrBook[0].botArrrQortAmount) + if (Number(listprice) <= Number(checkprice) && Number(listamount) <= Number(checkamount)) { + return { + qortAmount: item.qortAmount, + price: item.price, + foreignAmount: item.foreignAmount, + qortalCreator: item.qortalCreator, + qortalAtAddress: item.qortalAtAddress + } + } + }).filter(item => !!item) + + this.tradeBotAvailableArrrQortal.sort((a, b) => parseFloat(a.price) - parseFloat(b.price)) + + if (this.isEmptyArray(this.tradeBotAvailableArrrQortal) === true) { + return + } else { + this.checkArrrAlice = this.tradeBotAvailableArrrQortal[0].qortalAtAddress + } + + await appDelay(1000) + + if (this.tradeBotArrrAt.some(item => item.atAddress === this.checkArrrAlice)) { + return + } else { + this.tradeBotAvailableArrrQortal = this.tradeBotAvailableArrrQortal + } + + await appDelay(1000) + + if (this.isEmptyArray(this.tradeBotAvailableArrrQortal) === true) { + return + } else { + const botarrrprice = this.round(parseFloat(this.tradeBotArrrBook[0].botArrrPrice)) + const changearrramount = parseFloat(this.tradeBotArrrBook[0].botArrrQortAmount) + const reducearrramount = parseFloat(this.tradeBotAvailableArrrQortal[0].qortAmount) + const tradearrrataddress = this.tradeBotAvailableArrrQortal[0].qortalAtAddress + const newarrramount = this.round(parseFloat(changearrramount - reducearrramount)) + + this.reAddArrrAmount = this.round(parseFloat(this.tradeBotArrrBook[0].botArrrQortAmount)) + this.reAddArrrPrice = this.round(parseFloat(this.tradeBotArrrBook[0].botArrrPrice)) + + localStorage.removeItem(this.botArrrWallet) + localStorage.setItem(this.botArrrWallet, "") + + var oldArrrTradebook = JSON.parse(localStorage.getItem(this.botArrrWallet) || "[]") + + const newArrrTradebookItem = { + botArrrQortAmount: newarrramount, + botArrrPrice: botarrrprice + } + + oldArrrTradebook.push(newArrrTradebookItem) + + localStorage.setItem(this.botArrrWallet, JSON.stringify(oldArrrTradebook)) + + this.tradeBotArrrBook = JSON.parse(localStorage.getItem(this.botArrrWallet) || "[]") + + await appDelay(1000) + + this.botArrrBuyAtAddress = tradearrrataddress + + this.buyArrrAction() + + if (this.isEmptyArray(this.tradeBotArrrBook) === true) { + return + } else { + const botamount = parseFloat(this.tradeBotArrrBook[0].botArrrQortAmount) + + if (Number(botamount) === 0) { + this.removeBotARRRTradebook() + } else { + this.tradeBotArrrBook = this.tradeBotArrrBook + } + } + + if (this.isEmptyArray(this.tradeBotArrrBook) === true) { + return + } else { + await this.updateArrrWalletBalance() + const checkBotArrrFunds = this.round(parseFloat(this.tradeBotArrrBook[0].botArrrQortAmount) * parseFloat(this.tradeBotArrrBook[0].botArrrPrice)) + const myBotArrrFunds = this.round(parseFloat(this.arrrWalletBalance)) + + if (Number(myBotArrrFunds) < Number(checkBotArrrFunds)) { + this.removeBotARRRTradebook() + } else { + this.tradeBotArrrBook = this.tradeBotArrrBook + } + } + } + } + + await getOpenTradesBTC() + await appDelay(1000) + await getOpenTradesLTC() + await appDelay(1000) + await getOpenTradesDOGE() + await appDelay(1000) + await getOpenTradesDGB() + await appDelay(1000) + await getOpenTradesRVN() + await appDelay(1000) + await getOpenTradesARRR() + } + + async renderBalances() { + const tickerTime = ms => new Promise(res => setTimeout(res, ms)) + clearTimeout(this.updateBalancesTimeout) + this.balanceTicker = html` +
+
+
+ ` + await tickerTime(1000) + this.balanceTicker = html` +
+
+ QORT ${translate("general.balance")}: ${this.qortWalletBalance} + BTC ${translate("general.balance")}: ${this.btcWalletBalance} + LTC ${translate("general.balance")}: ${this.ltcWalletBalance} + DOGE ${translate("general.balance")}: ${this.dogeWalletBalance} + DGB ${translate("general.balance")}: ${this.dgbWalletBalance} + RVN ${translate("general.balance")}: ${this.rvnWalletBalance} + ARRR ${translate("general.balance")}: ${this.arrrWalletBalance} +
+
+ ` + this.updateBalancesTimeout = setTimeout(() => this.renderBalances(), 45000) + } + + async fetchArrrWalletAddress() { + let res = await parentEpml.request('apiCall', { + url: `/crosschain/arrr/walletaddress?apiKey=${this.getApiKey()}`, + method: 'POST', + body: `${store.getState().app.selectedAddress.arrrWallet.seed58}`, + }) + if (res != null && res.error != 1201) { + this.arrrWalletAddress = res + } + } + + async updateQortWalletBalance() { + clearTimeout(this.updateQortBalanceTimeout) + let qortAddress = store.getState().app.selectedAddress.address + await parentEpml.request('apiCall', { + url: `/addresses/balance/${qortAddress}?apiKey=${this.getApiKey()}`, + }).then((res) => { + this.qortWalletBalance = res + this.updateQortBalanceTimeout = setTimeout(() => this.updateQortWalletBalance(), 120000) + }) + } + + async updateBtcWalletBalance() { + clearTimeout(this.updateBtcBalanceTimeout) + let _url = `/crosschain/btc/walletbalance?apiKey=${this.getApiKey()}` + let _body = store.getState().app.selectedAddress.btcWallet.derivedMasterPublicKey + + await parentEpml.request('apiCall', { + url: _url, + method: 'POST', + body: _body, + }).then((res) => { + if (isNaN(Number(res))) { + let snack1string = get("tradepage.tchange30") + parentEpml.request('showSnackBar', `${snack1string}`) + } else { + this.btcWalletBalance = (Number(res) / 1e8).toFixed(8) + } + }) + this.updateBtcBalanceTimeout = setTimeout(() => this.updateBtcWalletBalance(), 120000) + } + + async updateLtcWalletBalance() { + clearTimeout(this.updateLtcBalanceTimeout) + let _url = `/crosschain/ltc/walletbalance?apiKey=${this.getApiKey()}` + let _body = store.getState().app.selectedAddress.ltcWallet.derivedMasterPublicKey + + await parentEpml.request('apiCall', { + url: _url, + method: 'POST', + body: _body, + }).then((res) => { + if (isNaN(Number(res))) { + let snack1string = get("tradepage.tchange30") + parentEpml.request('showSnackBar', `${snack1string}`) + } else { + this.ltcWalletBalance = (Number(res) / 1e8).toFixed(8) + } + }) + this.updateLtcBalanceTimeout = setTimeout(() => this.updateLtcWalletBalance(), 120000) + } + + async updateDogeWalletBalance() { + clearTimeout(this.updateDogeBalanceTimeout) + let _url = `/crosschain/doge/walletbalance?apiKey=${this.getApiKey()}` + let _body = store.getState().app.selectedAddress.dogeWallet.derivedMasterPublicKey + + await parentEpml.request('apiCall', { + url: _url, + method: 'POST', + body: _body, + }).then((res) => { + if (isNaN(Number(res))) { + let snack1string = get("tradepage.tchange30") + parentEpml.request('showSnackBar', `${snack1string}`) + } else { + this.dogeWalletBalance = (Number(res) / 1e8).toFixed(8) + } + }) + this.updateDogeBalanceTimeout = setTimeout(() => this.updateDogeWalletBalance(), 120000) + } + + async updateDgbWalletBalance() { + clearTimeout(this.updateDgbBalanceTimeout) + let _url = `/crosschain/dgb/walletbalance?apiKey=${this.getApiKey()}` + let _body = store.getState().app.selectedAddress.dgbWallet.derivedMasterPublicKey + + await parentEpml.request('apiCall', { + url: _url, + method: 'POST', + body: _body, + }).then((res) => { + if (isNaN(Number(res))) { + let snack1string = get("tradepage.tchange30") + parentEpml.request('showSnackBar', `${snack1string}`) + } else { + this.dgbWalletBalance = (Number(res) / 1e8).toFixed(8) + } + }) + this.updateDgbBalanceTimeout = setTimeout(() => this.updateDgbWalletBalance(), 120000) + } + + async updateRvnWalletBalance() { + clearTimeout(this.updateRvnBalanceTimeout) + let _url = `/crosschain/rvn/walletbalance?apiKey=${this.getApiKey()}` + let _body = store.getState().app.selectedAddress.rvnWallet.derivedMasterPublicKey + + await parentEpml.request('apiCall', { + url: _url, + method: 'POST', + body: _body, + }).then((res) => { + if (isNaN(Number(res))) { + let snack1string = get("tradepage.tchange30") + parentEpml.request('showSnackBar', `${snack1string}`) + } else { + this.rvnWalletBalance = (Number(res) / 1e8).toFixed(8) + } + }) + this.updateRvnBalanceTimeout = setTimeout(() => this.updateRvnWalletBalance(), 120000) + } + + async updateArrrWalletBalance() { + clearTimeout(this.updateArrrBalanceTimeout) + let _url = `/crosschain/arrr/walletbalance?apiKey=${this.getApiKey()}` + let _body = store.getState().app.selectedAddress.arrrWallet.seed58 + + await parentEpml.request('apiCall', { + url: _url, + method: 'POST', + body: _body, + }).then((res) => { + if (isNaN(Number(res))) { + let snack1string = get("tradepage.tchange30") + parentEpml.request('showSnackBar', `${snack1string}`) + } else { + this.arrrWalletBalance = (Number(res) / 1e8).toFixed(8) + } + }) + this.updateArrrBalanceTimeout = setTimeout(() => this.updateArrrWalletBalance(), 120000) + } + + botBtcTradebook() { + if (localStorage.getItem(this.botBtcWallet) === null) { + localStorage.setItem(this.botBtcWallet, "") + } else { + this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.botBtcWallet) || "[]") + } + } + + removeBotBTCTradebook() { + localStorage.removeItem(this.botBtcWallet) + localStorage.setItem(this.botBtcWallet, "") + this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.botBtcWallet) || "[]") + this.tradeBotAvailableBtcQortal = [] + } + + botLtcTradebook() { + if (localStorage.getItem(this.botLtcWallet) === null) { + localStorage.setItem(this.botLtcWallet, "") + } else { + this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.botLtcWallet) || "[]") + } + } + + removeBotLTCTradebook() { + localStorage.removeItem(this.botLtcWallet) + localStorage.setItem(this.botLtcWallet, "") + this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.botLtcWallet) || "[]") + this.tradeBotAvailableLtcQortal = [] + } + + botDogeTradebook() { + if (localStorage.getItem(this.botDogeWallet) === null) { + localStorage.setItem(this.botDogeWallet, "") + } else { + this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.botDogeWallet) || "[]") + } + } + + removeBotDOGETradebook() { + localStorage.removeItem(this.botDogeWallet) + localStorage.setItem(this.botDogeWallet, "") + this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.botDogeWallet) || "[]") + this.tradeBotAvailableDogeQortal = [] + } + + botDgbTradebook() { + if (localStorage.getItem(this.botDgbWallet) === null) { + localStorage.setItem(this.botDgbWallet, "") + } else { + this.tradeBotDgbBook = JSON.parse(localStorage.getItem(this.botDgbWallet) || "[]") + } + } + + botRvnTradebook() { + if (localStorage.getItem(this.botRvnWallet) === null) { + localStorage.setItem(this.botRvnWallet, "") + } else { + this.tradeBotRvnBook = JSON.parse(localStorage.getItem(this.botRvnWallet) || "[]") + } + } + + botArrrTradebook() { + if (localStorage.getItem(this.botArrrWallet) === null) { + localStorage.setItem(this.botArrrWallet, "") + } else { + this.tradeBotArrrBook = JSON.parse(localStorage.getItem(this.botArrrWallet) || "[]") + } + } + + async buyBtcAction() { + const makeRequest = async () => { + const response = await parentEpml.request('tradeBotRespondRequest', { + atAddress: this.botBtcBuyAtAddress, + foreignKey: store.getState().app.selectedAddress.btcWallet.derivedMasterPrivateKey, + receivingAddress: store.getState().app.selectedAddress.address, + }) + return response + } + + const manageResponse = (response) => { + if (response === true) { + let snack5string = get("tradepage.tchange23") + parentEpml.request('showSnackBar', `${snack5string}`) + } else if (response === false) { + localStorage.removeItem(this.botBtcWallet) + localStorage.setItem(this.botBtcWallet, "") + + var oldBtcTradebook = JSON.parse(localStorage.getItem(this.botBtcWallet) || "[]") + + const newBtcTradebookItem = { + botBtcQortAmount: this.reAddBtcAmount, + botBtcPrice: this.reAddBtcPrice + } + + oldBtcTradebook.push(newBtcTradebookItem) + + localStorage.setItem(this.botBtcWallet, JSON.stringify(oldBtcTradebook)) + + this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.botBtcWallet) || "[]") + + let snack6string = get("tradepage.tchange24") + parentEpml.request('showSnackBar', `${snack6string}`) + } else { + localStorage.removeItem(this.botBtcWallet) + localStorage.setItem(this.botBtcWallet, "") + + var oldBtcTradebook = JSON.parse(localStorage.getItem(this.botBtcWallet) || "[]") + + const newBtcTradebookItem = { + botBtcQortAmount: this.reAddBtcAmount, + botBtcPrice: this.reAddBtcPrice + } + + oldBtcTradebook.push(newBtcTradebookItem) + + localStorage.setItem(this.botBtcWallet, JSON.stringify(oldBtcTradebook)) + + this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.botBtcWallet) || "[]") + + let snack7string = get("tradepage.tchange25") + parentEpml.request('showSnackBar', `${snack7string}: ${response.message}`) + } + } + const res = await makeRequest() + manageResponse(res) + } + + async buyLtcAction() { + const makeRequest = async () => { + const response = await parentEpml.request('tradeBotRespondRequest', { + atAddress: this.botLtcBuyAtAddress, + foreignKey: store.getState().app.selectedAddress.ltcWallet.derivedMasterPrivateKey, + receivingAddress: store.getState().app.selectedAddress.address, + }) + return response + } + + const manageResponse = (response) => { + if (response === true) { + let snack5string = get("tradepage.tchange23") + parentEpml.request('showSnackBar', `${snack5string}`) + } else if (response === false) { + localStorage.removeItem(this.botLtcWallet) + localStorage.setItem(this.botLtcWallet, "") + + var oldLtcTradebook = JSON.parse(localStorage.getItem(this.botLtcWallet) || "[]") + + const newLtcTradebookItem = { + botLtcQortAmount: this.reAddLtcAmount, + botLtcPrice: this.reAddLtcPrice + } + + oldLtcTradebook.push(newLtcTradebookItem) + + localStorage.setItem(this.botLtcWallet, JSON.stringify(oldLtcTradebook)) + + this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.botLtcWallet) || "[]") + + let snack6string = get("tradepage.tchange24") + parentEpml.request('showSnackBar', `${snack6string}`) + } else { + localStorage.removeItem(this.botLtcWallet) + localStorage.setItem(this.botLtcWallet, "") + + var oldLtcTradebook = JSON.parse(localStorage.getItem(this.botLtcWallet) || "[]") + + const newLtcTradebookItem = { + botLtcQortAmount: this.reAddLtcAmount, + botLtcPrice: this.reAddLtcPrice + } + + oldLtcTradebook.push(newLtcTradebookItem) + + localStorage.setItem(this.botLtcWallet, JSON.stringify(oldLtcTradebook)) + + this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.botLtcWallet) || "[]") + + let snack7string = get("tradepage.tchange25") + parentEpml.request('showSnackBar', `${snack7string}: ${response.message}`) + } + } + const res = await makeRequest() + manageResponse(res) + } + + async buyDogeAction() { + const makeRequest = async () => { + const response = await parentEpml.request('tradeBotRespondRequest', { + atAddress: this.botDogeBuyAtAddress, + foreignKey: store.getState().app.selectedAddress.dogeWallet.derivedMasterPrivateKey, + receivingAddress: store.getState().app.selectedAddress.address, + }) + return response + } + + const manageResponse = (response) => { + if (response === true) { + let snack5string = get("tradepage.tchange23") + parentEpml.request('showSnackBar', `${snack5string}`) + } else if (response === false) { + localStorage.removeItem(this.botDogeWallet) + localStorage.setItem(this.botDogeWallet, "") + + var oldDogeTradebook = JSON.parse(localStorage.getItem(this.botDogeWallet) || "[]") + + const newDogeTradebookItem = { + botDogeQortAmount: this.reAddDogeAmount, + botDogePrice: this.reAddDogePrice + } + + oldDogeTradebook.push(newDogeTradebookItem) + + localStorage.setItem(this.botDogeWallet, JSON.stringify(oldDogeTradebook)) + + this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.botDogeWallet) || "[]") + + let snack6string = get("tradepage.tchange24") + parentEpml.request('showSnackBar', `${snack6string}`) + } else { + localStorage.removeItem(this.botDogeWallet) + localStorage.setItem(this.botDogeWallet, "") + + var oldDogeTradebook = JSON.parse(localStorage.getItem(this.botDogeWallet) || "[]") + + const newDogeTradebookItem = { + botDogeQortAmount: this.reAddDogeAmount, + botDogePrice: this.reAddDogePrice + } + + oldDogeTradebook.push(newDogeTradebookItem) + + localStorage.setItem(this.botDogeWallet, JSON.stringify(oldDogeTradebook)) + + this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.botDogeWallet) || "[]") + + let snack7string = get("tradepage.tchange25") + parentEpml.request('showSnackBar', `${snack7string}: ${response.message}`) + } + } + const res = await makeRequest() + manageResponse(res) + } + + async buyDgbAction() { + const makeRequest = async () => { + const response = await parentEpml.request('tradeBotRespondRequest', { + atAddress: this.botDgbBuyAtAddress, + foreignKey: store.getState().app.selectedAddress.dgbWallet.derivedMasterPrivateKey, + receivingAddress: store.getState().app.selectedAddress.address, + }) + return response + } + + const manageResponse = (response) => { + if (response === true) { + let snack5string = get("tradepage.tchange23") + parentEpml.request('showSnackBar', `${snack5string}`) + } else if (response === false) { + localStorage.removeItem(this.botDgbWallet) + localStorage.setItem(this.botDgbWallet, "") + + var oldDgbTradebook = JSON.parse(localStorage.getItem(this.botDgbWallet) || "[]") + + const newDgbTradebookItem = { + botDgbQortAmount: this.reAddDgbAmount, + botDgbPrice: this.reAddDgbPrice + } + + oldDgbTradebook.push(newDgbTradebookItem) + + localStorage.setItem(this.botDgbWallet, JSON.stringify(oldDgbTradebook)) + + this.tradeBotDgbBook = JSON.parse(localStorage.getItem(this.botDgbWallet) || "[]") + + let snack6string = get("tradepage.tchange24") + parentEpml.request('showSnackBar', `${snack6string}`) + } else { + localStorage.removeItem(this.botDgbWallet) + localStorage.setItem(this.botDgbWallet, "") + + var oldDgbTradebook = JSON.parse(localStorage.getItem(this.botDgbWallet) || "[]") + + const newDgbTradebookItem = { + botDgbQortAmount: this.reAddDgbAmount, + botDgbPrice: this.reAddDgbPrice + } + + oldDgbTradebook.push(newDgbTradebookItem) + + localStorage.setItem(this.botDgbWallet, JSON.stringify(oldDgbTradebook)) + + this.tradeBotDgbBook = JSON.parse(localStorage.getItem(this.botDgbWallet) || "[]") + + let snack7string = get("tradepage.tchange25") + parentEpml.request('showSnackBar', `${snack7string}: ${response.message}`) + } + } + const res = await makeRequest() + manageResponse(res) + } + + async buyRvnAction() { + const makeRequest = async () => { + const response = await parentEpml.request('tradeBotRespondRequest', { + atAddress: this.botRvnBuyAtAddress, + foreignKey: store.getState().app.selectedAddress.rvnWallet.derivedMasterPrivateKey, + receivingAddress: store.getState().app.selectedAddress.address, + }) + return response + } + + const manageResponse = (response) => { + if (response === true) { + let snack5string = get("tradepage.tchange23") + parentEpml.request('showSnackBar', `${snack5string}`) + } else if (response === false) { + localStorage.removeItem(this.botRvnWallet) + localStorage.setItem(this.botRvnWallet, "") + + var oldRvnTradebook = JSON.parse(localStorage.getItem(this.botRvnWallet) || "[]") + + const newRvnTradebookItem = { + botRvnQortAmount: this.reAddRvnAmount, + botRvnPrice: this.reAddRvnPrice + } + + oldRvnTradebook.push(newRvnTradebookItem) + + localStorage.setItem(this.botRvnWallet, JSON.stringify(oldRvnTradebook)) + + this.tradeBotRvnBook = JSON.parse(localStorage.getItem(this.botRvnWallet) || "[]") + + let snack6string = get("tradepage.tchange24") + parentEpml.request('showSnackBar', `${snack6string}`) + } else { + localStorage.removeItem(this.botRvnWallet) + localStorage.setItem(this.botRvnWallet, "") + + var oldRvnTradebook = JSON.parse(localStorage.getItem(this.botRvnWallet) || "[]") + + const newRvnTradebookItem = { + botRvnQortAmount: this.reAddRvnAmount, + botRvnPrice: this.reAddRvnPrice + } + + oldRvnTradebook.push(newRvnTradebookItem) + + localStorage.setItem(this.botRvnWallet, JSON.stringify(oldRvnTradebook)) + + this.tradeBotRvnBook = JSON.parse(localStorage.getItem(this.botRvnWallet) || "[]") + + let snack7string = get("tradepage.tchange25") + parentEpml.request('showSnackBar', `${snack7string}: ${response.message}`) + } + } + const res = await makeRequest() + manageResponse(res) + } + + async buyArrrAction() { + const makeRequest = async () => { + const response = await parentEpml.request('tradeBotRespondRequest', { + atAddress: this.botArrrBuyAtAddress, + foreignKey: store.getState().app.selectedAddress.arrrWallet.seed58, + receivingAddress: store.getState().app.selectedAddress.address, + }) + return response + } + + const manageResponse = (response) => { + if (response === true) { + let snack5string = get("tradepage.tchange23") + parentEpml.request('showSnackBar', `${snack5string}`) + } else if (response === false) { + localStorage.removeItem(this.botArrrWallet) + localStorage.setItem(this.botArrrWallet, "") + + var oldArrrTradebook = JSON.parse(localStorage.getItem(this.botArrrWallet) || "[]") + + const newArrrTradebookItem = { + botArrrQortAmount: this.reAddArrrAmount, + botArrrPrice: this.reAddArrrPrice + } + + oldArrrTradebook.push(newArrrTradebookItem) + + localStorage.setItem(this.botArrrWallet, JSON.stringify(oldArrrTradebook)) + + this.tradeBotArrrBook = JSON.parse(localStorage.getItem(this.botArrrWallet) || "[]") + + let snack6string = get("tradepage.tchange24") + parentEpml.request('showSnackBar', `${snack6string}`) + } else { + localStorage.removeItem(this.botArrrWallet) + localStorage.setItem(this.botArrrWallet, "") + + var oldArrrTradebook = JSON.parse(localStorage.getItem(this.botArrrWallet) || "[]") + + const newArrrTradebookItem = { + botArrrQortAmount: this.reAddArrrAmount, + botArrrPrice: this.reAddArrrPrice + } + + oldArrrTradebook.push(newArrrTradebookItem) + + localStorage.setItem(this.botArrrWallet, JSON.stringify(oldArrrTradebook)) + + this.tradeBotArrrBook = JSON.parse(localStorage.getItem(this.botArrrWallet) || "[]") + + let snack7string = get("tradepage.tchange25") + parentEpml.request('showSnackBar', `${snack7string}: ${response.message}`) + } + } + const res = await makeRequest() + manageResponse(res) } stateChanged(state) { @@ -210,6 +1962,24 @@ class AppView extends connect(store)(LitElement) { const logoutDialog = document.getElementById('main-app').shadowRoot.querySelector('app-view').shadowRoot.querySelector('logout-view') logoutDialog.openLogout() } + + getApiKey() { + const apiNode = store.getState().app.nodeConfig.knownNodes[store.getState().app.nodeConfig.node] + let apiKey = apiNode.apiKey + return apiKey + } + + isEmptyArray(arr) { + if (!arr) { + return true + } + return arr.length === 0 + } + + round(number) { + let result = (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8) + return result + } } window.customElements.define('app-view', AppView) diff --git a/qortal-ui-core/src/components/main-app.js b/qortal-ui-core/src/components/main-app.js index 0d09d1ef..36574cea 100644 --- a/qortal-ui-core/src/components/main-app.js +++ b/qortal-ui-core/src/components/main-app.js @@ -12,7 +12,7 @@ import './login-view/login-view.js' import './app-view.js' import copyTextMenu from '../functional-components/copy-text-menu.js' -import framePasteMenu from '../functional-components/frame-paste-menu.js'; +import framePasteMenu from '../functional-components/frame-paste-menu.js' installRouter((location) => store.dispatch(doNavigate(location))) diff --git a/qortal-ui-core/src/components/sidenav-menu.js b/qortal-ui-core/src/components/sidenav-menu.js index f36f0796..69118c91 100644 --- a/qortal-ui-core/src/components/sidenav-menu.js +++ b/qortal-ui-core/src/components/sidenav-menu.js @@ -162,22 +162,13 @@ class SidenavMenu extends connect(store)(LitElement) { > - - - - - - - + + + + - - - - - + + { + Object.entries(routes).forEach(([route, handler]) => { + epmlInstance.route(route, handler) + }) +} diff --git a/qortal-ui-core/src/tradebot/trade-bot-routes.js b/qortal-ui-core/src/tradebot/trade-bot-routes.js new file mode 100644 index 00000000..aecb989f --- /dev/null +++ b/qortal-ui-core/src/tradebot/trade-bot-routes.js @@ -0,0 +1,253 @@ +import { store } from '../store.js' +import * as api from 'qortal-ui-crypto' +import snackbar from '../functional-components/snackbar.js' + +const createTransaction = api.createTransaction +const processTransaction = api.processTransaction +const tradeBotCreateRequest = api.tradeBotCreateRequest +const tradeBotRespondRequest = api.tradeBotRespondRequest +const signTradeBotTxn = api.signTradeBotTxn +const deleteTradeOffer = api.deleteTradeOffer +const cancelAllOffers = api.cancelAllOffers +const sendBtc = api.sendBtc +const sendLtc = api.sendLtc +const sendDoge = api.sendDoge +const sendDgb = api.sendDgb +const sendRvn = api.sendRvn +const sendArrr = api.sendArrr + +export const routes = { + apiCall: async (req) => { + const url = req.data.url + delete req.data.url + return api.request(url, req.data) + }, + + transaction: async (req) => { + let response + try { + const tx = createTransaction( + req.data.type, + store.getState().app.wallet._addresses[req.data.nonce].keyPair, + req.data.params + ) + + if (!req.disableModal && !req.data.disableModal) { + await requestTransactionDialog.requestTransaction(tx) + } + + const res = await processTransaction(tx.signedBytes) + let extraData = {} + if(req.data.type === 38 && tx && tx._rewardShareKeyPair && tx._rewardShareKeyPair.secretKey){ + extraData.rewardSharePrivateKey = Base58.encode(tx._rewardShareKeyPair.secretKey) + } + + + response = { + success: true, + data: res, + extraData + } + } catch (e) { + console.error(e) + console.error(e.message) + response = { + success: false, + message: e.message, + } + } + return response + }, + + standaloneTransaction: async (req) => { + const rebuildUint8Array = (obj) => { + let _array = new Uint8Array(Object.keys(obj).length) + for (let i = 0; i < _array.byteLength; ++i) { + _array.set([obj[i]], i) + } + return _array + } + + let response + try { + let _keyPair = {} + for (let _keyName in req.data.keyPair) { + _keyPair[_keyName] = rebuildUint8Array( + req.data.keyPair[_keyName] + ) + } + const tx = createTransaction( + req.data.type, + _keyPair, + req.data.params + ) + const res = await processTransaction(tx.signedBytes) + response = { + success: true, + data: res, + } + } catch (e) { + console.error(e) + console.error(e.message) + response = { + success: false, + message: e.message, + } + } + return response + }, + + showSnackBar: async (req) => { + snackbar.add({ + labelText: req.data, + dismiss: true, + }) + }, + + tradeBotCreateRequest: async (req) => { + let response + try { + const unsignedTxn = await tradeBotCreateRequest(req.data) + + const signedTxnBytes = await signTradeBotTxn( + unsignedTxn, + store.getState().app.selectedAddress.keyPair + ) + + const res = await processTransaction(signedTxnBytes) + response = res + } catch (e) { + console.error(e) + console.error(e.message) + response = e.message + } + return response + }, + + tradeBotRespondRequest: async (req) => { + let response + try { + const res = await tradeBotRespondRequest(req.data) + response = res + } catch (e) { + console.error(e) + console.error(e.message) + response = e.message + } + return response + }, + + deleteTradeOffer: async (req) => { + let response + try { + const unsignedTxn = await deleteTradeOffer(req.data) + + const signedTxnBytes = await signTradeBotTxn( + unsignedTxn, + store.getState().app.selectedAddress.keyPair + ) + + const res = await processTransaction(signedTxnBytes) + + response = res + } catch (e) { + console.error(e) + console.error(e.message) + response = e.message + } + return response + }, + + cancelAllOffers: async (req) => { + let response + try { + const res = await cancelAllOffers( + store.getState().app.selectedAddress + ) + response = res + } catch (e) { + console.error(e) + console.error(e.message) + response = e.message + } + return response + }, + + sendBtc: async (req) => { + let response + try { + const res = await sendBtc(req.data) + response = res + } catch (e) { + console.error(e) + console.error(e.message) + response = e.message + } + return response + }, + + sendLtc: async (req) => { + let response + try { + const res = await sendLtc(req.data) + response = res + } catch (e) { + console.error(e) + console.error(e.message) + response = e.message + } + return response + }, + + sendDoge: async (req) => { + let response + try { + const res = await sendDoge(req.data) + response = res + } catch (e) { + console.error(e) + console.error(e.message) + response = e.message + } + return response + }, + + sendDgb: async (req) => { + let response + try { + const res = await sendDgb(req.data) + response = res + } catch (e) { + console.error(e) + console.error(e.message) + response = e.message + } + return response + }, + + sendRvn: async (req) => { + let response + try { + const res = await sendRvn(req.data) + response = res + } catch (e) { + console.error(e) + console.error(e.message) + response = e.message + } + return response + }, + + sendArrr: async (req) => { + let response + try { + const res = await sendArrr(req.data) + response = res + } catch (e) { + console.error(e) + console.error(e.message) + response = e.message + } + return response + }, +} diff --git a/qortal-ui-plugins/build-config.js b/qortal-ui-plugins/build-config.js index 5595e9db..e21fa127 100644 --- a/qortal-ui-plugins/build-config.js +++ b/qortal-ui-plugins/build-config.js @@ -70,16 +70,8 @@ const generateForPlugins = () => { out: 'plugins/core/trade-portal/trade-portal.js', }, { - in: 'plugins/core/trade-bot/trade-bot-btc/trade-bot-btc.src.js', - out: 'plugins/core/trade-bot/trade-bot-btc/trade-bot-btc.js', - }, - { - in: 'plugins/core/trade-bot/trade-bot-ltc/trade-bot-ltc.src.js', - out: 'plugins/core/trade-bot/trade-bot-ltc/trade-bot-ltc.js', - }, - { - in: 'plugins/core/trade-bot/trade-bot-doge/trade-bot-doge.src.js', - out: 'plugins/core/trade-bot/trade-bot-doge/trade-bot-doge.js', + in: 'plugins/core/trade-bot/trade-bot-portal.src.js', + out: 'plugins/core/trade-bot/trade-bot-portal.js', }, { in: 'plugins/core/wallet/wallet-app.src.js', diff --git a/qortal-ui-plugins/package.json b/qortal-ui-plugins/package.json index ce8ec663..8d95633e 100644 --- a/qortal-ui-plugins/package.json +++ b/qortal-ui-plugins/package.json @@ -46,9 +46,9 @@ "@rollup/plugin-commonjs": "23.0.2", "@rollup/plugin-node-resolve": "15.0.1", "@rollup/plugin-replace": "5.0.1", - "@vaadin/button": "23.2.8", - "@vaadin/grid": "23.2.8", - "@vaadin/icons": "23.2.8", + "@vaadin/button": "23.2.9", + "@vaadin/grid": "23.2.9", + "@vaadin/icons": "23.2.9", "epml": "0.3.3", "file-saver": "2.0.5", "html-escaper": "3.0.3", diff --git a/qortal-ui-plugins/plugins/core/trade-bot/index.html b/qortal-ui-plugins/plugins/core/trade-bot/index.html index 79f7583b..5fc2b1c9 100644 --- a/qortal-ui-plugins/plugins/core/trade-bot/index.html +++ b/qortal-ui-plugins/plugins/core/trade-bot/index.html @@ -48,8 +48,8 @@ - - + + \ No newline at end of file diff --git a/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-btc/index.html b/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-btc/index.html deleted file mode 100644 index de1e0b41..00000000 --- a/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-btc/index.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-btc/trade-bot-btc.src.js b/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-btc/trade-bot-btc.src.js deleted file mode 100644 index e91c0e71..00000000 --- a/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-btc/trade-bot-btc.src.js +++ /dev/null @@ -1,2155 +0,0 @@ -import { LitElement, html, css } from 'lit' -import { render } from 'lit/html.js' -import { Epml } from '../../../../epml.js' -import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate' - -registerTranslateConfig({ - loader: lang => fetch(`/language/${lang}.json`).then(res => res.json()) -}) - -import '@material/mwc-button' -import '@material/mwc-textfield' -import '@material/mwc-icon' -import '@material/mwc-icon-button' -import '@material/mwc-dialog' -import '@material/mwc-tab-bar' -import '@material/mwc-tab' -import '@material/mwc-list/mwc-list-item' -import '@material/mwc-select' -import '@polymer/iron-icons/iron-icons.js' -import '@polymer/paper-icon-button/paper-icon-button.js' -import '@polymer/paper-spinner/paper-spinner-lite.js' -import '@vaadin/grid' -import '@vaadin/grid/vaadin-grid-sorter' - -const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }) - -let workers = new Map() - -class TradeBotBTC extends LitElement { - static get properties() { - return { - selectedAddress: { type: Object }, - config: { type: Object }, - listedCoins: { type: Map }, - sellBtnDisable: { type: Boolean }, - isSellLoading: { type: Boolean }, - isBuyLoading: { type: Boolean }, - buyBtnDisable: { type: Boolean }, - autoBuyWarning: { type: Boolean }, - autoBuyBtnDisable: { type: Boolean }, - autoBuyBotDisable: { type: Boolean }, - initialAmount: { type: Number }, - cancelBtnDisable: { type: Boolean }, - cancelStuckOfferBtnDisable: { type: Boolean }, - selectedCoin: { type: String }, - isLoadingHistoricTrades: { type: Boolean }, - isLoadingOpenTrades: { type: Boolean }, - isLoadingMyOpenOrders: { type: Boolean }, - showGetWalletBance: { type: Boolean }, - showAddAutoBuy: { type: Boolean }, - theme: { type: String, reflect: true }, - btcWallet: { type: String }, - qortbtc: { type: Number }, - btcqort: { type: Number }, - tradeBotBtcBook: { type: Array }, - tradesBtcQortal: { type: Array }, - doneTradesBtcQortal: { type: Array }, - tradesAvailableBtcQortal: { type: Array }, - tradeBotBtcQortal: { type: Array }, - tradeBotAvailableBtcQortal: { type: Array }, - checkAlice: { type: String }, - botBuyAtAddress: { type: String }, - reAddAmount: { type: Number }, - reAddPrice: { type: Number } - } - } - - static get styles() { - return css` - * { - --mdc-theme-primary: rgb(3, 169, 244); - --mdc-theme-secondary: var(--mdc-theme-primary); - --mdc-theme-error: rgb(255, 89, 89); - --mdc-text-field-outlined-idle-border-color: var(--txtfieldborder); - --mdc-text-field-outlined-hover-border-color: var(--txtfieldhoverborder); - --mdc-text-field-label-ink-color: var(--black); - --mdc-text-field-ink-color: var(--black); - --mdc-select-outlined-idle-border-color: var(--txtfieldborder); - --mdc-select-outlined-hover-border-color: var(--txtfieldhoverborder); - --mdc-select-label-ink-color: var(--black); - --mdc-select-ink-color: var(--black); - --mdc-theme-surface: var(--white); - --mdc-dialog-content-ink-color: var(--black); - --mdc-dialog-shape-radius: 25px; - --paper-input-container-focus-color: var(--mdc-theme-primary); - --lumo-primary-text-color: rgb(0, 167, 245); - --lumo-primary-color-50pct: rgba(0, 167, 245, 0.5); - --lumo-primary-color-10pct: rgba(0, 167, 245, 0.1); - --lumo-primary-color: hsl(199, 100%, 48%); - --lumo-base-color: var(--white); - --lumo-body-text-color: var(--black); - --lumo-secondary-text-color: var(--sectxt); - --lumo-contrast-60pct: var(--vdicon); - --_lumo-grid-border-color: var(--border); - --_lumo-grid-secondary-border-color: var(--border2); - } - paper-spinner-lite { - height: 30px; - width: 30px; - --paper-spinner-color: var(--mdc-theme-primary); - --paper-spinner-stroke-width: 3px; - } - mwc-tab-bar { - --mdc-text-transform: none; - --mdc-tab-color-default: var(--black); - --mdc-tab-text-label-color-default: var(--black); - } - #tabs-1 { - --mdc-tab-height: 42px; - border-left: 1px solid var(--tradeborder); - border-top: 1px solid var(--tradeborder); - border-right: 1px solid var(--tradeborder); - color: var(--black); - } - #tab-buy[active] { - --mdc-theme-primary: rgba(55, 160, 51, 0.9); - } - #tabs-1-content { - height: 100%; - padding-bottom: 10px; - } - #tabs-1-content > div { - height: 100%; - border: 1px solid var(--tradeborder); - } - #tabs-1-content .card { - border: none; - } - #tabs-1-content .btn-clear { - --mdc-icon-button-size: 32px; - color: var(--black); - } - .btn-clear-bot { - --mdc-icon-button-size: 32px; - color: var(--black); - float: right; - } - .btn-info { - color: var(--black); - --mdc-icon-size: 16px; - padding-top: 3px; - } - #tab-sell[active] { - --mdc-theme-primary: rgb(255, 89, 89); - } - #trade-portal-page { - background: var(--white); - padding: 12px 24px; - } - .divCard { - border: 1px solid var(--black); - padding: 1em; - box-shadow: 0 0.3px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 1px -1px rgba(0, 0, 0, 0.12), 0 1px 2px 0 rgba(0, 0, 0, 0.2); - } - h2 { - margin: 10px 0; - } - - h4 { - margin: 5px 0; - } - - p { - font-size: 14px; - line-height: 21px; - } - - .card-body { - background-color: var(--white); - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - min-height: 100vh; - margin: 0; - } - - .card-container { - background-color: var(--white); - border-radius: 5px; - color: var(--black); - padding-top: 30px; - position: relative; - width: 350px; - max-width: 100%; - text-align: center; - } - - .card-container .level { - color: #ffffff; - background-color: #03a9f4; - border-radius: 3px; - font-size: 14px; - font-weight: bold; - padding: 3px 7px; - position: absolute; - top: 30px; - left: 30px; - } - - .card-container .founder { - color: #ffffff; - background-color: #03a9f4; - border-radius: 3px; - font-size: 14px; - font-weight: bold; - padding: 3px 7px; - position: absolute; - top: 30px; - right: 30px; - } - - .card-container .round { - width: 96px; - height: 96px; - border: 1px solid #03a9f4; - border-radius: 50%; - padding: 2px; - } - - .card-container .badge { - width: 200px; - height: 135px; - border: 1px solid transparent; - border-radius: 10%; - padding: 2px; - } - - .userdata { - background-color: #1F1A36; - text-align: left; - padding: 15px; - margin-top: 30px; - } - - .userdata ul { - list-style-type: none; - margin: 0; - padding: 0; - } - - .userdata ul li { - border: 1px solid #2D2747; - border-radius: 2px; - display: inline-block; - font-size: 12px; - margin: 0 7px 7px 0; - padding: 7px; - } - - h2, - h3, - h4, - h5 { - color: var(--black); - font-weight: 400; - } - header { - display: flex; - flex: 0 1 auto; - align-items: center; - justify-content: center; - padding: 0px 10px; - font-size: 16px; - color: var(--white); - background-color: var(--tradehead); - border-left: 1px solid var(--tradeborder); - border-top: 1px solid var(--tradeborder); - border-right: 1px solid var(--tradeborder); - min-height: 40px; - } - p { - margin-bottom: 12px; - } - #trade-portal { - max-width: 100vw; - margin-left: auto; - margin-right: auto; - } - .box { - margin: 0; - padding: 0; - display: flex; - flex-flow: column; - height: 100%; - } - .box-bot { - margin: 0; - padding: 0; - display: flex; - flex-flow: column; - height: 150px; - } - #first-trade-section { - margin-bottom: 10px; - } - #first-trade-section > div { - } - #second-trade-section { - margin-bottom: 10px; - } - #second-trade-section > div { - } - #third-trade-section { - margin-bottom: 10px; - } - #third-trade-section > div { - } - .trade-chart { - background-color: var(--white); - border: 2px #ddd solid; - text-align: center; - } - .open-trades { - text-align: center; - } - .open-market-container { - text-align: center; - } - .trade-bot-container { - text-align: center; - } - .no-last-seen { - background: rgb(255, 89, 89); - padding: 9px 1.3px; - border-radius: 50%; - width: 1rem; - margin: 0 auto; - } - .card { - padding: 1em; - border: 1px var(--tradeborder) solid; - flex: 1 1 auto; - display: flex; - flex-flow: column; - justify-content: space-evenly; - min-height: inherit; - } - .card-bot { - padding: 1em; - flex: 1 1 auto; - display: flex; - flex-flow: column; - justify-content: space-evenly; - width: 350px; - min-height: inherit; - } - .cancel { - --mdc-theme-primary: rgb(255, 89, 89); - } - .border-wrapper { - border: 1px var(--tradeborder) solid; - overflow: hidden; - } - .amt-text { - color: var(--tradehave); - font-size: 15px; - margin-top: 5px; - margin-bottom: 12px; - } - .exchange { - color: var(--black); - font-size: 18px; - font-weight: bold; - margin-top: 5px; - margin-bottom: 10px; - } - .clear-button { - display: inline; - float: right; - margin-bottom: 5px; - } - .exhcnage-text { - display: inline; - float: left; - margin-bottom: 5px; - } - .balance-text { - display: inline; - float: right; - margin-bottom: 5px; - } - .fee-text { - display: inline; - float: left; - margin-bottom: 5px; - } - .tab-text { - color: var(--tradehave); - font-size: 12px; - text-align: left; - margin-top: 2px; - margin-bottom: -12px; - } - .historic-trades { - text-align: center; - } - .my-open-orders { - text-align: center; - } - .my-historic-trades { - text-align: center; - } - .buttons { - width: auto !important; - } - .buy-button { - --mdc-theme-primary: rgba(55, 160, 51, 0.9); - } - .sell-button { - --mdc-theme-primary: rgb(255, 89, 89); - } - .trade-bot-button { - margin-top: 20px; - margin-bottom: 20px; - --mdc-theme-primary: rgba(55, 160, 51, 0.9); - } - .full-width { - background-color: var(--white); - border: 2px var(--black); - height: 200px; - text-align: center; - } - vaading-grid { - font-size: .8em; - } - vaadin-grid-column { - flex-grow: 1; - } - .loadingContainer { - height: 100%; - width: 100%; - } - .loading, - .loading:after { - border-radius: 50%; - width: 5em; - height: 5em; - } - .loading { - margin: 10px auto; - border-width: .6em; - border-style: solid; - border-color: rgba(3, 169, 244, 0.2) rgba(3, 169, 244, 0.2) rgba(3, 169, 244, 0.2) rgb(3, 169, 244); - font-size: 10px; - position: relative; - text-indent: -9999em; - transform: translateZ(0px); - animation: 1.1s linear 0s infinite normal none running loadingAnimation; - } - mwc-select#coinSelectionMenu { - font-size: 24px; - width:220px; - } - mwc-select#coinSelectionMenu mwc-list-item { - line-height: 30px; - } - .coinName::before { - content: ""; - display: inline-block; - height: 26px; - width: 45px; - position: absolute; - background-repeat: no-repeat; - background-size: cover; - left: 10px; - top: 10px; - } - .coinName { - display: inline-block; - height: 26px; - padding-left: 45px; - } - .warning-text { - animation: blinker 1.5s linear infinite; - display: inline; - float: left; - margin-bottom: 5px; - color: rgb(255, 89, 89); - } - .warning-bot-text { - animation: blinker 1.5s linear infinite; - display: inline; - text-align: center; - color: rgb(255, 89, 89); - } - .red { - --mdc-theme-primary: #F44336; - } - @-webkit-keyframes loadingAnimation { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - @keyframes loadingAnimation { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - @keyframes blinker { - 50% { - opacity: 0; - } - } - @media (min-width: 701px) { - * { - } - #trade-portal {} - #first-trade-section { - display: grid; - grid-template-columns:1fr 4fr 1fr; - grid-auto-rows: max(350px); - column-gap: 0.5em; - row-gap: 0.4em; - justify-items: stretch; - align-items: stretch; - margin-bottom: 10px; - } - #second-trade-section { - display: grid; - grid-template-columns:1fr 4fr 1fr; - grid-auto-rows: max(350px); - column-gap: 0.5em; - row-gap: 0.4em; - justify-items: stretch; - align-items: stretch; - margin-bottom: 10px; - } - #third-trade-section { - display: grid; - grid-template-columns: 1fr 4fr 1fr; - grid-auto-rows: max(150px); - column-gap: 0.5em; - row-gap: 0.4em; - justify-items: stretch; - align-items: stretch; - margin-bottom: 10px; - } - #fourth-trade-section { - display: grid; - grid-template-columns: 1fr 4fr 1fr; - grid-auto-rows: max(150px); - column-gap: 0.5em; - row-gap: 0.4em; - justify-items: stretch; - align-items: stretch; - margin-bottom: 10px; - } - } - ` - } - - constructor() { - super() - let qortal = { - name: "QORTAL", - balance: "0", - coinCode: "QORT", - coinAmount: this.amountString, - tradeFee: "0.002" - } - - let bitcoin = { - name: "BITCOIN", - balance: "0", - coinCode: "BTC", - openOrders: [], - openFilteredOrders: [], - historicTrades: [], - myOrders: [], - myHistoricTrades: [], - myOfferingOrders: [], - openTradeOrders: null, - tradeOffersSocketCounter: 1, - coinAmount: this.amountString, - tradeFee: "~0.0001" - } - - this.listedCoins = new Map() - this.listedCoins.set("QORTAL", qortal) - this.listedCoins.set("BITCOIN", bitcoin) - - workers.set("QORTAL", { - tradesConnectedWorker: null, - handleStuckTradesConnectedWorker: null - }) - - workers.set("BITCOIN", { - tradesConnectedWorker: null, - handleStuckTradesConnectedWorker: null - }) - - this.selectedCoin = "BITCOIN" - this.selectedAddress = {} - this.config = {} - this.sellBtnDisable = false - this.isSellLoading = false - this.buyBtnDisable = true - this.autoBuyWarning = false - this.autoBuyBtnDisable = true - this.autoBuyBotDisable = false - this.isBuyLoading = false - this.initialAmount = 0 - this.cancelBtnDisable = false - this.cancelStuckOfferBtnDisable = false - this.isLoadingHistoricTrades = true - this.isLoadingOpenTrades = true - this.isLoadingMyOpenOrders = false - this.showGetWalletBance = true - this.showAddAutoBuy = false - this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light' - this.btcWallet = '' - this.qortbtc = 0 - this.btcqort = 0 - this.tradeBotBtcBook = [] - this.tradesBtcQortal = [] - this.doneTradesBtcQortal = [] - this.tradesAvailableBtcQortal = [] - this.tradeBotBtcQortal = [] - this.tradeBotAvailableBtcQortal = [] - this.checkAlice = '' - this.botBuyAtAddress = '' - this.reAddAmount = 0 - this.reAddPrice = 0 - } - - openTradesTemplate() { - return html` -
-
-
${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange42")}
-
-
${translate("login.loading")}
- - { - render(html`${this.round(data.item.qortAmount)}`, root) - }} - > - - { - render(html`${this.round(data.item.price)}`, root) - }} - > - - { - render(html`${data.item.foreignAmount}`, root) - }} - > - - { - render(html`${data.item.qortalCreator}`, root) - }} - > - - -
-
-
- ` - } - - myOpenOrdersTemplate() { - return html` -
-
-
${translate("tradepage.tchange36")}
-
-
${translate("login.loading")}
- - { - const dateString = new Date(data.item.timestamp).toLocaleString() - render(html`${dateString}`, root) - }} - > - - { - render(html` ${data.item._tradeState} `, root) - }} - > - - { - const price = this.round(parseFloat(data.item.foreignAmount) / parseFloat(data.item.qortAmount)) - render(html`${price}`, root) - }} - > - - - - - - -
-
-
- ` - } - - myDoneTradesTemplate() { - return html` -
-
-
${translate("tradepage.tchange43")} (${this.listedCoins.get(this.selectedCoin).coinCode})
-
-
${translate("login.loading")}
- - { - const dateString = new Date(data.item.timestamp).toLocaleString() - render(html`${dateString}`, root) - }} - > - - { - return render(html` ${translate("tradepage.tchange32")} `, root) - }} - > - - { - const price = this.round(parseFloat(data.item.foreignAmount) / parseFloat(data.item.qortAmount)) - render(html`${price}`, root) - }} - > - - - - { - render(html` ${data.item.foreignAmount} `, root) - }} - > - - -
-
-
- ` - } - - myHistoricTradesTemplate() { - return html` -
-
-
${translate("tradepage.tchange4")}
-
- - { - const dateString = new Date(data.item.timestamp).toLocaleString() - render(html`${dateString}`, root) - }} - > - - { - if (data.item.mode === 'SOLD') return render(html` ${translate("tradepage.tchange31")} `, root) - if (data.item.mode === 'BOUGHT') return render(html` ${translate("tradepage.tchange32")} `, root) - return render(html` ${data.item.mode} `, root) - }} - > - - { - const price = this.round(parseFloat(data.item.foreignAmount) / parseFloat(data.item.qortAmount)) - render(html`${price}`, root) - }} - > - - - - { - render(html` ${data.item.foreignAmount} `, root) - }} - > - - -
-
-
- ` - } - - tradeBotBTCTemplate() { - return html` -
-
-
${translate("tradepage.tchange39")} ${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT
-
- - { - render(html`${data.item.botBtcQortAmount}`, root) - }} - > - - { - render(html`${data.item.botBtcPrice}`, root) - }} - > - - { - const totalCoins = this.round(parseFloat(data.item.botBtcQortAmount) * parseFloat(data.item.botBtcPrice)) - const myBotFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) - if (Number(myBotFunds) > Number(totalCoins)) { - this.autoBuyBotDisable = false - render(html`${totalCoins}`, root) - } else { - this.autoBuyBotDisable = true - render(html`${totalCoins}`, root) - } - }} - > - - { - render(html` this.removeBTCTradebook()}>delete ${translate("nodepage.nchange12")}`, root) - }} - > - - - ${this.isEmptyArray(this.tradeBotBtcBook) ? html` - - ${translate("tradepage.tchange38")} ${translate("tradepage.tchange39")} - - `: ''} -
- ${this.autoBuyBotDisable ? html` -
${this.renderBotWarning()}
- `: ''} -
-
- ` - } - - render() { - return html` -
-
-
-
- ${this.openTradesTemplate()} -
-
-
-
- ${this.myDoneTradesTemplate()} -
-
-
-
- ${this.myOpenOrdersTemplate()} -
-
-
-
- ${this.showAutoBuyGrid()} -
-
-
-

${translate("tradepage.tchange33")} ${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange40")}

-

1 QORT = ${this.exchangeRateQort()} ${this.listedCoins.get(this.selectedCoin).coinCode}

-
-
-
- - -
-

${this.renderFetchText()}

-
-
-
-

${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT

-
-
-
-
${this.renderWarning()}
- -
- ${translate("tradepage.tchange8")} (QORT)* -

- - -

- ${translate("tradepage.tchange14")} (${this.listedCoins.get(this.selectedCoin).coinCode})* -

- - -

- ${translate("tradepage.tchange10")} (${this.listedCoins.get(this.selectedCoin).coinCode})* -

- - -

- - ${translate("tradepage.tchange16")}: ${this.listedCoins.get(this.selectedCoin).balance} ${this.listedCoins.get(this.selectedCoin).coinCode} - -
-
- - ${translate("tradepage.tchange38")} ${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange39")} - -
-
-
- ${translate("general.close")} -
- ` - } - - async firstUpdated() { - - let _this = this - - this.changeTheme() - this.changeLanguage() - await this.updateWalletBalance() - - this._openOrdersGrid = this.shadowRoot.getElementById('openOrdersGrid') - - this._openOrdersGrid.querySelector('#priceColumn').headerRenderer = function (root) { - const priceString = get("tradepage.tchange9") - root.innerHTML = '' + priceString + ' (' + _this.listedCoins.get(_this.selectedCoin).coinCode + ')' - } - - this._openOrdersGrid.querySelector('#qortAmountColumn').headerRenderer = function (root) { - const amountString = get("tradepage.tchange8") - root.innerHTML = '' + amountString + ' (QORT)' - } - - this._myOrdersGrid = this.shadowRoot.getElementById('myOrdersGrid') - this._myHistoricTradesGrid = this.shadowRoot.getElementById('myHistoricTradesGrid') - - const delay = ms => new Promise(res => setTimeout(res, ms)) - - const getQortBtcPrice = () => { - parentEpml.request("apiCall", { url: `/crosschain/price/BITCOIN?inverse=true` }).then((res) => { - setTimeout(() => { this.qortbtc = (Number(res) / 1e8).toFixed(8) }, 1) - }) - setTimeout(getQortBtcPrice, 300000) - } - - const filterMyPriceTradesBTC = async () => { - const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] - const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port - const tradeBotBtcQortalUrl = `${nodeUrl}/crosschain/tradebot?foreignBlockchain=BITCOIN&apiKey=${this.getApiKey()}` - const waitFor = ms => new Promise(res => setTimeout(res, ms)) - let timer - - const tradeBotBtcQortal = await fetch(tradeBotBtcQortalUrl).then(response => { - return response.json() - }) - - this.tradeBotBtcQortal = tradeBotBtcQortal - - await waitFor(1000) - - if (this.isEmptyArray(this.tradeBotBtcBook) === true) { - clearTimeout(timer) - timer = setTimeout(filterMyPriceTradesBTC, 180000) - return - } else { - clearTimeout(timer) - timer = setTimeout(filterMyPriceTradesBTC, 180000) - - this.tradeBotAvailableBtcQortal = this.listedCoins.get(this.selectedCoin).openFilteredOrders.map(item => { - const listprice = parseFloat(item.price) - const listamount = parseFloat(item.qortAmount) - const checkprice = parseFloat(this.tradeBotBtcBook[0].botBtcPrice) - const checkamount = parseFloat(this.tradeBotBtcBook[0].botBtcQortAmount) - if (Number(listprice) <= Number(checkprice) && Number(listamount) <= Number(checkamount)) { - return { - qortAmount: item.qortAmount, - price: item.price, - foreignAmount: item.foreignAmount, - qortalCreator: item.qortalCreator, - qortalAtAddress: item.qortalAtAddress - } - } - }).filter(item => !!item) - - this.tradeBotAvailableBtcQortal.sort((a, b) => parseFloat(a.price) - parseFloat(b.price)) - - if (this.isEmptyArray(this.tradeBotAvailableBtcQortal) === true) { - return - } else { - this.checkAlice = this.tradeBotAvailableBtcQortal[0].qortalAtAddress - } - - await waitFor(1000) - - if (this.tradeBotBtcQortal.some(item => item.atAddress === this.checkAlice)) { - return - } else { - this.tradesAvailableBtcQortal = this.tradeBotAvailableBtcQortal - } - } - - await waitFor(1000) - - if (this.isEmptyArray(this.tradesAvailableBtcQortal) === true) { - return - } else { - const botprice = this.round(parseFloat(this.tradeBotBtcBook[0].botBtcPrice)) - const changeamount = parseFloat(this.tradeBotBtcBook[0].botBtcQortAmount) - const reduceamount = parseFloat(this.tradesAvailableBtcQortal[0].qortAmount) - const tradeataddress = this.tradesAvailableBtcQortal[0].qortalAtAddress - const newamount = this.round(parseFloat(changeamount - reduceamount)) - - this.reAddAmount = this.round(parseFloat(this.tradeBotBtcBook[0].botBtcQortAmount)) - this.reAddPrice = this.round(parseFloat(this.tradeBotBtcBook[0].botBtcPrice)) - - localStorage.removeItem(this.btcWallet) - localStorage.setItem(this.btcWallet, "") - - var oldBtcTradebook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]") - - const newBtcTradebookItem = { - botBtcQortAmount: newamount, - botBtcPrice: botprice - } - - oldBtcTradebook.push(newBtcTradebookItem) - - localStorage.setItem(this.btcWallet, JSON.stringify(oldBtcTradebook)) - - this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]") - - await waitFor(1000) - - this.botBuyAtAddress = tradeataddress - - this.buyAction() - - if (this.isEmptyArray(this.tradeBotBtcBook) === true) { - return - } else { - const botamount = parseFloat(this.tradeBotBtcBook[0].botBtcQortAmount) - - if (Number(botamount) === 0) { - this.removeBTCTradebook() - } else { - this.tradeBotBtcBook = this.tradeBotBtcBook - } - } - - if (this.isEmptyArray(this.tradeBotBtcBook) === true) { - return - } else { - const checkBotFunds = this.round(parseFloat(this.tradeBotBtcBook[0].botBtcQortAmount) * parseFloat(this.tradeBotBtcBook[0].botBtcPrice)) - const myBotFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) - - if (Number(myBotFunds) < Number(checkBotFunds)) { - this.removeBTCTradebook() - } else { - this.tradeBotBtcBook = this.tradeBotBtcBook - } - } - } - } - - const getDoneTradeBTC = async () => { - this.isLoadingDoneTrades = true - const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] - const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port - const doneBtcQortalUrl = `${nodeUrl}/crosschain/trades?foreignBlockchain=BITCOIN&minimumTimestamp=1597310000000&limit=0&reverse=true` - const myAddress = window.parent.reduxStore.getState().app.selectedAddress.address - - const doneBtcQortal = await fetch(doneBtcQortalUrl).then(response => { - return response.json() - }) - - this.doneTradesBtcQortal = doneBtcQortal.map(item => { - const searchAddress = item.buyerReceivingAddress - if (searchAddress == myAddress) { - return { - timestamp: item.tradeTimestamp, - foreignAmount: item.foreignAmount, - qortAmount: item.qortAmount - } - } - }).filter(item => !!item) - - this.isLoadingDoneTrades = false - setTimeout(getDoneTradeBTC, 600000) - } - - window.addEventListener('contextmenu', (event) => { - event.preventDefault() - this._textMenu(event)}, - { passive: true } - ) - - window.addEventListener('click', () => { - parentEpml.request('closeCopyTextMenu', null)}, - { passive: true } - ) - - window.addEventListener('storage', () => { - const checkLanguage = localStorage.getItem('qortalLanguage') - const checkTheme = localStorage.getItem('qortalTheme') - - use(checkLanguage) - - if (checkTheme === 'dark') { - this.theme = 'dark' - } else { - this.theme = 'light' - } - document.querySelector('html').setAttribute('theme', this.theme) - }) - - window.onkeyup = (e) => { - if (e.keyCode === 27) parentEpml.request('closeCopyTextMenu', null) - } - - this.btcWallet = window.parent.reduxStore.getState().app.selectedAddress.btcWallet.address - - let configLoaded = false - - parentEpml.ready().then(() => { - parentEpml.subscribe('selected_address', async (selectedAddress) => { - this.selectedAddress = {} - selectedAddress = JSON.parse(selectedAddress) - if (!selectedAddress || Object.entries(selectedAddress).length === 0) return - this.selectedAddress = selectedAddress - this.btcWwallet = window.parent.reduxStore.getState().app.selectedAddress.btcWallet.address - await this.updateAccountBalance() - await this.btcTradebook() - }) - - parentEpml.subscribe('config', (c) => { - if (!configLoaded) { - setTimeout(getQortBtcPrice, 1) - setTimeout(getDoneTradeBTC, 1) - configLoaded = true - } - this.config = JSON.parse(c) - }) - - parentEpml.subscribe('copy_menu_switch', async (value) => { - if (value === 'false' && window.getSelection().toString().length !== 0) this.clearSelection() - }) - this.setForeignCoin() - }) - parentEpml.imReady() - - setTimeout(() => this.shadowRoot.querySelector('[slot="vaadin-grid-cell-content-3"]').setAttribute('title', 'Last Seen'), 3000) - - this.btcTradebook() - await delay(3000) - filterMyPriceTradesBTC() - } - - changeTheme() { - const checkTheme = localStorage.getItem('qortalTheme') - if (checkTheme === 'dark') { - this.theme = 'dark'; - } else { - this.theme = 'light'; - } - document.querySelector('html').setAttribute('theme', this.theme); - } - - changeLanguage() { - const checkLanguage = localStorage.getItem('qortalLanguage') - - if (checkLanguage === null || checkLanguage.length === 0) { - localStorage.setItem('qortalLanguage', 'us') - use('us') - } else { - use(checkLanguage) - } - } - - renderFetchText() { - return html`${translate("walletpage.wchange1")}` - } - - renderWarning() { - return html`NOT ENOUGH ${this.listedCoins.get(this.selectedCoin).coinCode}` - } - - renderBotWarning() { - return html`NOT ENOUGH ${this.listedCoins.get(this.selectedCoin).coinCode} ! AUTO BUY BOT IS STOPPED` - } - - exchangeRateQort() { - return html`${this.qortbtc}` - } - - showAutoBuyGrid() { - return html`${this.tradeBotBTCTemplate()}` - } - - showAddToAutoBuyStore() { - this.addToBTCTradebook() - } - - btcTradebook() { - if (localStorage.getItem(this.btcWallet) === null) { - localStorage.setItem(this.btcWallet, "") - } else { - this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]") - } - } - - addToBTCTradebook() { - const addBotBtcQortAmount = this.shadowRoot.getElementById('autoBuyBTCQortAmountInput').value - const addBotBtcPrice = this.shadowRoot.getElementById('autoBuyBTCPriceInput').value - const addBtcQortAmount = this.round(parseFloat(addBotBtcQortAmount)) - const addBtcPrice = this.round(parseFloat(addBotBtcPrice)) - - var oldBtcTradebook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]") - - const newBtcTradebookItem = { - botBtcQortAmount: addBtcQortAmount, - botBtcPrice: addBtcPrice - } - - oldBtcTradebook.push(newBtcTradebookItem) - - localStorage.setItem(this.btcWallet, JSON.stringify(oldBtcTradebook)) - - let btctradebookstring = get("tradepage.tchange44") - parentEpml.request('showSnackBar', `${btctradebookstring}`) - - this.closeBTCTradebookDialog() - this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]") - this.firstUpdated() - } - - closeBTCTradebookDialog() { - this.shadowRoot.querySelector('#tradeBotBTCAddDialog').close() - this.clearTradeBotForm() - } - - removeBTCTradebook() { - localStorage.removeItem(this.btcWallet) - localStorage.setItem(this.btcWallet, "") - this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]") - - this.autoBuyBotDisable = false - - let btcstring = get("tradepage.tchange41") - parentEpml.request('showSnackBar', `${btcstring}`) - this.tradesAvailableBtcQortal = [] - } - - exchangeRateForeign() { - parentEpml.request('apiCall', { - url: `/crosschain/price/BITCOIN?inverse=false` - }).then((res) => { - this.btcqort = (Number(res) / 1e8).toFixed(8) - }) - return html`${this.btcqort}` - } - - async updateWalletBalance() { - let _url = `/crosschain/btc/walletbalance?apiKey=${this.getApiKey()}` - let _body = window.parent.reduxStore.getState().app.selectedAddress.btcWallet.derivedMasterPublicKey - - this.showGetWalletBance = true - this.showAddAutoBuy = false - - await parentEpml.request('apiCall', { - url: _url, - method: 'POST', - body: _body, - }).then((res) => { - if (isNaN(Number(res))) { - let snack1string = get("tradepage.tchange30") - parentEpml.request('showSnackBar', `${snack1string}`) - } else { - this.listedCoins.get(this.selectedCoin).balance = (Number(res) / 1e8).toFixed(8) - } - }) - - this.showGetWalletBance = false - this.showAddAutoBuy = true - } - - async setForeignCoin() { - let _this = this - this.selectedCoin = "BITCOIN" - - this.isLoadingOpenTrades = true - await this.createConnection() - - this._openOrdersGrid.querySelector('#priceColumn').headerRenderer = function (root) { - const priceString2 = get("tradepage.tchange9") - root.innerHTML = '' + priceString2 + ' (' + _this.listedCoins.get(_this.selectedCoin).coinCode + ')' - } - - this.autoBuyBotDisable = false - await this.updateWalletBalance() - } - - async reRenderOpenFilteredOrders() { - this.requestUpdate() - await this.updateComplete - this.isLoadingOpenTrades = false - } - - async reRenderMyOpenOrders() { - this.requestUpdate() - await this.updateComplete - this.isLoadingMyOpenOrders = false - } - - addAutoBuyAction() { - this.autoBuyWarning = false - this.clearTradeBotForm() - this.shadowRoot.querySelector('#tradeBot' + this.listedCoins.get(this.selectedCoin).coinCode + 'AddDialog').show() - } - - checkTradeBotValues() { - const checkTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value - const checkTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value - const checkAmount = this.round(parseFloat(checkTradeBotAmountInput)) - const checkPrice = this.round(parseFloat(checkTradeBotPriceInput)) - - if (Number(checkAmount) === 0) { - let amountString = get("tradepage.tchange34") - parentEpml.request('showSnackBar', `${amountString}`) - } else if (Number(checkPrice) === 0) { - let priceString = get("tradepage.tchange35") - parentEpml.request('showSnackBar', `${priceString}`) - } else { - this.showAddToAutoBuyStore() - } - } - - processOfferingTrade(offer) { - try { - if(this.listedCoins.get(offer.foreignBlockchain).name!='') { - const offerItem = { - ...offer, - qortAmount: parseFloat(offer.qortAmount), - price: parseFloat(offer.foreignAmount) / parseFloat(offer.qortAmount), - } - const addOffer = () => { - this.listedCoins.get(offer.foreignBlockchain).openOrders.unshift(offerItem) - } - const initOffer = () => { - this.listedCoins.get(offer.foreignBlockchain).openOrders.push(offerItem) - } - this.listedCoins.get(offer.foreignBlockchain).openOrders.length === 0 ? initOffer() : addOffer() - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._openOrdersGrid.clearCache() : null - } - } catch(e) { - console.log("Error adding offer from "+offer.foreignBlockchain) - } - } - - processRedeemedTrade(offer) { - try { - if (this.listedCoins.get(offer.foreignBlockchain).name!='') { - - if (offer.qortalCreator === this.selectedAddress.address) { - if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { - this.updateWalletBalance() - } - const offerItem = { - ...offer, - mode: 'SOLD', - } - this._myHistoricTradesGrid.items.unshift(offerItem) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null - } else if (offer.partnerQortalReceivingAddress === this.selectedAddress.address) { - if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { - this.updateWalletBalance() - } - const offerItem = { - ...offer, - mode: 'BOUGHT', - } - this._myHistoricTradesGrid.items.unshift(offerItem) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null - } - const addNewHistoricTrade = () => { - this._historicTradesGrid.items.unshift(offer) - this._historicTradesGrid.clearCache() - } - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? addNewHistoricTrade() : null - - } - } catch(e) { - console.log("Error processing redeemed trade offer from "+offer.foreignBlockchain) - } - } - - processTradingTrade(offer) { - try { - if (this.listedCoins.get(offer.foreignBlockchain).name!='') { - - if (offer.qortalCreator === this.selectedAddress.address && this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { - this.updateWalletBalance() - } - this._openOrdersGrid.items.forEach((item, index) => { - if (item.qortalAtAddress === offer.qortalAtAddress) { - this._openOrdersGrid.items.splice(index, 1) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._openOrdersGrid.clearCache() : null - } - }) - this.listedCoins.get(offer.foreignBlockchain).openOrders = this.listedCoins.get(offer.foreignBlockchain).openOrders.filter((order) => order.qortalAtAddress !== offer.qortalAtAddress) - } - } catch(e) { - console.log("Error processing trading trade offer from "+offer.foreignBlockchain) - } - } - - processRefundedTrade(offer) { - try { - if (this.listedCoins.get(offer.foreignBlockchain).name!='') { - - if (offer.qortalCreator === this.selectedAddress.address) { - if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { - this.updateWalletBalance() - } - this._myHistoricTradesGrid.items.unshift(offer) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null - } - - } - } catch(e) { - console.log("Error processing refunded trade offer from "+offer.foreignBlockchain) - } - } - - processCancelledTrade(offer) { - try { - if (this.listedCoins.get(offer.foreignBlockchain).name!='') { - - if (offer.qortalCreator === this.selectedAddress.address) { - if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { - this.updateWalletBalance() - } - this._myHistoricTradesGrid.items.unshift(offer) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null - } - this._openOrdersGrid.items.forEach((item, index) => { - if (item.qortalAtAddress === offer.qortalAtAddress) { - this._openOrdersGrid.items.splice(index, 1) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._openOrdersGrid.clearCache() : null - } - }) - this.listedCoins.get(offer.foreignBlockchain).openOrders = this.listedCoins.get(offer.foreignBlockchain).openOrders.filter((order) => order.qortalAtAddress !== offer.qortalAtAddress) - this._stuckOrdersGrid.items.forEach((item, index) => { - if (item.qortalAtAddress === offer.qortalAtAddress) { - this._stuckOrdersGrid.items.splice(index, 1) - this._stuckOrdersGrid.clearCache() - } - }) - } - } catch(e) { - console.log("Error processing cancelled trade offer from "+offer.foreignBlockchain) - } - } - - /** - * TRADE OFFER STATES or MODE - * - OFFERING - */ - - processTradeOffers(offers) { - offers.forEach((offer) => { - if (offer.mode === 'OFFERING') { - this.processOfferingTrade(offer) - } - }) - } - - processTradeBotStates(tradeStates) { - - const BitcoinACCTv1 = (states) => { - states.reverse() - states.forEach((state) => { - if (state.creatorAddress === this.selectedAddress.address) { - if (state.tradeState == 'ALICE_WAITING_FOR_AT_LOCK') { - this.changeTradeBotState(state, 'BUYING') - } else if (state.tradeState == 'ALICE_DONE') { - this.handleCompletedState(state) - } else if (state.tradeState == 'ALICE_REFUNDING_A') { - this.changeTradeBotState(state, 'REFUNDING') - } else if (state.tradeState == 'ALICE_REFUNDED') { - this.handleCompletedState(state) - } - } - }) - } - - switch (this.selectedCoin) { - case 'BITCOIN': - BitcoinACCTv1(tradeStates) - break - default: - break - } - } - - changeTradeBotState(state, tradeState) { - this.isLoadingMyOpenOrders = true - const stateItem = { - ...state, - _tradeState: tradeState, - } - const item = this._myOrdersGrid.querySelector(`#${state.atAddress}`) - const addStateItem = () => { - this.reRenderMyOpenOrders() - this._myOrdersGrid.items.unshift(stateItem) - this._myOrdersGrid.clearCache() - } - const updateStateItem = () => { - this._myOrdersGrid.items.forEach((item, index) => { - if (item.atAddress === state.atAddress) { - this.reRenderMyOpenOrders() - this._myOrdersGrid.items.splice(index, 1) - this._myOrdersGrid.items.unshift(stateItem) - this._myOrdersGrid.clearCache() - } - }) - } - item ? updateStateItem() : addStateItem() - } - - handleCompletedState(state) { - this._myOrdersGrid.items.forEach((item, index) => { - if (item.atAddress === state.atAddress) { - this.reRenderMyOpenOrders() - this._myOrdersGrid.items.splice(index, 1) - this._myOrdersGrid.clearCache() - } - }) - } - - initSocket() { - let _relatedCoin = "" - let tradePresenceTxns = null - let offeringTrades = null - - self.addEventListener('message', function (event) { - switch (event.data.type) { - case 'open_orders': - offeringTrades = event.data.content - processOffersWithPresence() - break - case 'set_coin': - _relatedCoin = event.data.content - break - default: - break - } - }) - - const lessThanThirtyMinsAgo = (timestamp) => { - const THIRTYMINS = 1000 * 60 * 30 - const thirtyMinsAgo = Date.now() - THIRTYMINS - return timestamp > thirtyMinsAgo - } - - const filterOffersUsingTradePresence = (offeringTrade) => { - return offeringTrade.tradePresenceExpiry > Date.now(); - } - - const processOffersWithPresence = () => { - if (offeringTrades === null) return - - async function asyncForEach(array, callback) { - for (let index = 0; index < array.length; index++) { - await callback(array[index], index, array) - } - } - - const startOfferPresenceMapping = async () => { - - if (tradePresenceTxns !== null) { - await asyncForEach(tradePresenceTxns, async (tradePresence) => { - let offerIndex = offeringTrades.findIndex((offeringTrade) => offeringTrade.qortalCreatorTradeAddress === tradePresence.tradeAddress) - offerIndex !== -1 ? (offeringTrades[offerIndex].tradePresenceExpiry = tradePresence.timestamp) : null - }) - } - - let filteredOffers = offeringTrades.filter((offeringTrade) => filterOffersUsingTradePresence(offeringTrade)) - self.postMessage({ type: 'PRESENCE', data: { offers: offeringTrades, filteredOffers: filteredOffers, relatedCoin: _relatedCoin } }) - } - - startOfferPresenceMapping() - } - - const initTradeOffersWebSocket = (restarted = false) => { - let tradeOffersSocketCounter = 0 - let socketTimeout - let socketLink = `ws://NODEURL/websockets/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN&includeHistoric=true` - const socket = new WebSocket(socketLink) - socket.onopen = () => { - setTimeout(pingSocket, 50) - tradeOffersSocketCounter += 1 - } - socket.onmessage = (e) => { - e.relatedCoin = _relatedCoin - self.postMessage({ - type: 'TRADE_OFFERS', - data: e.data, - counter: tradeOffersSocketCounter, - isRestarted: restarted, - }) - tradeOffersSocketCounter += 1 - restarted = false - } - socket.onclose = () => { - clearTimeout(socketTimeout) - restartTradeOffersWebSocket() - } - socket.onerror = (e) => { - clearTimeout(socketTimeout) - } - const pingSocket = () => { - socket.send('ping') - socketTimeout = setTimeout(pingSocket, 150000) - } - } - - const initTradeBotWebSocket = (restarted = false) => { - let socketTimeout - let socketLink = `ws://NODEURL/websockets/crosschain/tradebot?foreignBlockchain=FOREIGN_BLOCKCHAIN` - const socket = new WebSocket(socketLink) - socket.onopen = () => { - setTimeout(pingSocket, 50) - } - socket.onmessage = (e) => { - e.relatedCoin = _relatedCoin - self.postMessage({ - type: 'TRADE_BOT', - data: e.data, - isRestarted: restarted, - }) - restarted = false - } - socket.onclose = () => { - clearTimeout(socketTimeout) - restartTradeBotWebSocket() - } - socket.onerror = (e) => { - clearTimeout(socketTimeout) - } - const pingSocket = () => { - socket.send('ping') - socketTimeout = setTimeout(pingSocket, 150000) - } - } - - const initTradePresenceWebSocket = (restarted = false) => { - let socketTimeout - let socketLink = `ws://NODEURL/websockets/crosschain/tradepresence` - const socket = new WebSocket(socketLink) - socket.onopen = () => { - setTimeout(pingSocket, 50) - } - socket.onmessage = (e) => { - tradePresenceTxns = JSON.parse(e.data) - processOffersWithPresence() - restarted = false - } - socket.onclose = () => { - clearTimeout(socketTimeout) - restartTradePresenceWebSocket() - } - socket.onerror = (e) => { - clearTimeout(socketTimeout) - } - const pingSocket = () => { - socket.send('ping') - socketTimeout = setTimeout(pingSocket, 150000) - } - } - - const restartTradePresenceWebSocket = () => { - setTimeout(() => initTradePresenceWebSocket(true), 50) - } - - const restartTradeOffersWebSocket = () => { - setTimeout(() => initTradeOffersWebSocket(true), 50) - } - - const restartTradeBotWebSocket = () => { - setTimeout(() => initTradeBotWebSocket(true), 50) - } - - initTradeOffersWebSocket() - initTradePresenceWebSocket() - initTradeBotWebSocket() - } - - async buyAction() { - const qortalAtAddress = this.botBuyAtAddress - let _foreignKey = this.selectedAddress.btcWallet.derivedMasterPrivateKey - - const makeRequest = async () => { - const response = await parentEpml.request('tradeBotRespondRequest', { - atAddress: qortalAtAddress, - foreignKey: _foreignKey, - receivingAddress: this.selectedAddress.address, - }) - return response - } - - const manageResponse = (response) => { - if (response === true) { - this.isBuyLoading = false - this.buyBtnDisable = true - let snack5string = get("tradepage.tchange23") - parentEpml.request('showSnackBar', `${snack5string}`) - } else if (response === false) { - this.isBuyLoading = false - this.buyBtnDisable = false - - localStorage.removeItem(this.btcWallet) - localStorage.setItem(this.btcWallet, "") - - var oldBtcTradebook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]") - - const newBtcTradebookItem = { - botBtcQortAmount: this.reAddAmount, - botBtcPrice: this.reAddPrice - } - - oldBtcTradebook.push(newBtcTradebookItem) - - localStorage.setItem(this.btcWallet, JSON.stringify(oldBtcTradebook)) - - this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]") - - let snack6string = get("tradepage.tchange24") - parentEpml.request('showSnackBar', `${snack6string}`) - } else { - this.isBuyLoading = false - this.buyBtnDisable = false - - localStorage.removeItem(this.btcWallet) - localStorage.setItem(this.btcWallet, "") - - var oldBtcTradebook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]") - - const newBtcTradebookItem = { - botBtcQortAmount: this.reAddAmount, - botBtcPrice: this.reAddPrice - } - - oldBtcTradebook.push(newBtcTradebookItem) - - localStorage.setItem(this.btcWallet, JSON.stringify(oldBtcTradebook)) - - this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]") - - let snack7string = get("tradepage.tchange25") - parentEpml.request('showSnackBar', `${snack7string}: ${response.message}`) - } - } - const res = await makeRequest() - manageResponse(res) - } - - updateAccountBalance() { - clearTimeout(this.updateAccountBalanceTimeout) - parentEpml.request('apiCall', { - url: `/addresses/balance/${this.selectedAddress.address}?apiKey=${this.getApiKey()}`, - }).then((res) => { - this.listedCoins.get("QORTAL").balance = res - this.updateAccountBalanceTimeout = setTimeout(() => this.updateAccountBalance(), 10000) - }) - } - - _checkBuyAmount(e) { - const targetAmount = e.target.value - const target = e.target - - if (targetAmount.length === 0) { - this.isValidAmount = false - this.sellBtnDisable = true - e.target.blur() - e.target.focus() - e.target.invalid = true - } else { - this.buyBtnDisable = false - } - - e.target.blur() - e.target.focus() - - e.target.validityTransform = (newValue, nativeValidity) => { - if (newValue.includes('-') === true) { - this.buyBtnDisable = true - return { - valid: false, - } - } else if (!nativeValidity.valid) { - if (newValue.includes('.') === true) { - let myAmount = newValue.split('.') - if (myAmount[1].length > 8) { - this.buyBtnDisable = true - } else { - this.buyBtnDisable = false - return { - valid: true, - } - } - } - } else { - this.buyBtnDisable = false - } - } - } - - checkTradeBotAmount(e) { - const targetAmount = e.target.value - const target = e.target - this.autoBuyWarning = false - - if (targetAmount.length === 0) { - this.isValidAmount = false - this.autoBuyBtnDisable = true - this.autoBuyWarning = false - e.target.blur() - e.target.focus() - e.target.invalid = true - } else { - const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value - const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value - const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) - if (Number(myFunds) > Number(checkFunds)) { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = false - this.autoBuyWarning = false - } else { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = true - this.autoBuyWarning = true - } - } - - e.target.blur() - e.target.focus() - - e.target.validityTransform = (newValue, nativeValidity) => { - if (newValue.includes('-') === true) { - this.autoBuyBtnDisable = true - this.autoBuyWarning = false - return { - valid: false, - } - } else if (!nativeValidity.valid) { - if (newValue.includes('.') === true) { - let myAmount = newValue.split('.') - if (myAmount[1].length > 8) { - this.autoBuyBtnDisable = true - this.autoBuyWarning = false - } else { - const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value - const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value - const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) - if (Number(myFunds) > Number(checkFunds)) { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = false - this.autoBuyWarning = false - } else { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = true - this.autoBuyWarning = true - } - return { - valid: true, - } - } - } - } else { - const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value - const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value - const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) - if (Number(myFunds) > Number(checkFunds)) { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = false - this.autoBuyWarning = false - } else { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = true - this.autoBuyWarning = true - } - } - } - } - - getApiKey() { - const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]; - let apiKey = myNode.apiKey; - return apiKey; - } - - clearSelection() { - window.getSelection().removeAllRanges() - window.parent.getSelection().removeAllRanges() - } - - _textMenu(event) { - const getSelectedText = () => { - var text = '' - if (typeof window.getSelection != 'undefined') { - text = window.getSelection().toString() - } else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') { - text = this.shadowRoot.selection.createRange().text - } - return text - } - - const checkSelectedTextAndShowMenu = () => { - let selectedText = getSelectedText() - if (selectedText && typeof selectedText === 'string') { - let _eve = { - pageX: event.pageX, - pageY: event.pageY, - clientX: event.clientX, - clientY: event.clientY, - } - let textMenuObject = { - selectedText: selectedText, - eventObject: _eve, - isFrame: true, - } - parentEpml.request('openCopyTextMenu', textMenuObject) - } - } - checkSelectedTextAndShowMenu() - } - - clearTradeBotForm() { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value = this.initialBotAmount - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value = this.initialAmount - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.initialBotAmount - this.autoBuyBtnDisable = true - } - - isEmptyArray(arr) { - if (!arr) { - return true - } - return arr.length === 0 - } - - round(number) { - let result = (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8) - return result - } - - inlineWorker(passedFunction, modifiers) { - let parsedFunction = `` - - modifiers.forEach((modifier) => { - let regex = new RegExp(modifier.searchValue, 'g') - parsedFunction = parsedFunction.length === 0 ? `(function ${passedFunction.toString().trim().replace(regex, modifier.replaceValue)})()` : parsedFunction.toString().trim().replace(regex, modifier.replaceValue) - }) - - const workerUrl = URL.createObjectURL(new Blob([parsedFunction], { type: 'text/javascript' })) - const worker = new Worker(workerUrl) - URL.revokeObjectURL(workerUrl) - return worker - } - - clearPaneCache() { - this._openOrdersGrid.clearCache() - this._myOrdersGrid.clearCache() - } - - createConnection() { - if (workers.get(this.selectedCoin).tradesConnectedWorker !== null) { - this.isLoadingOpenTrades = false - return - } - - const handleMessage = (message) => { - switch (message.type) { - case 'TRADE_OFFERS': - if (!message.isRestarted) { - this.listedCoins.get(this.selectedCoin).tradeOffersSocketCounter = message.counter - this.processTradeOffers(JSON.parse(message.data)) - this.listedCoins.get(this.selectedCoin).tradeOffersSocketCounter === 1 ? this.clearPaneCache() : null - workers.get(this.selectedCoin).tradesConnectedWorker.postMessage(this.listedCoins.get(this.selectedCoin).openOrders) - workers.get(this.selectedCoin).tradesConnectedWorker.postMessage({ type: "open_orders", content: this.listedCoins.get(this.selectedCoin).openOrders }) - } - return null - case 'TRADE_BOT': - if (!message.isRestarted) this.processTradeBotStates(JSON.parse(message.data)) - return null - case 'PRESENCE': - this.listedCoins.get(message.data.relatedCoin).openOrders = message.data.offers - this.listedCoins.get(message.data.relatedCoin).openFilteredOrders = message.data.filteredOffers - this.reRenderOpenFilteredOrders() - return null - default: - break - } - } - - let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] - let nodeUrl = myNode.domain + ':' + myNode.port - - const modifiers = [ - { searchValue: 'NODEURL', replaceValue: nodeUrl }, - { searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin }, - ] - - workers.get(this.selectedCoin).tradesConnectedWorker = this.inlineWorker(this.initSocket, modifiers) - - workers.get(this.selectedCoin).tradesConnectedWorker.addEventListener('message', function (event) { handleMessage(event.data) }, { passive: true }) - - workers.get(this.selectedCoin).tradesConnectedWorker.postMessage({ type: "set_coin", content: this.selectedCoin }) - - } -} - -window.customElements.define('trade-bot-btc', TradeBotBTC) \ No newline at end of file diff --git a/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-doge/index.html b/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-doge/index.html deleted file mode 100644 index a02e4a70..00000000 --- a/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-doge/index.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-doge/trade-bot-doge.src.js b/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-doge/trade-bot-doge.src.js deleted file mode 100644 index d76e1d4f..00000000 --- a/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-doge/trade-bot-doge.src.js +++ /dev/null @@ -1,2155 +0,0 @@ -import { LitElement, html, css } from 'lit' -import { render } from 'lit/html.js' -import { Epml } from '../../../../epml.js' -import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate' - -registerTranslateConfig({ - loader: lang => fetch(`/language/${lang}.json`).then(res => res.json()) -}) - -import '@material/mwc-button' -import '@material/mwc-textfield' -import '@material/mwc-icon' -import '@material/mwc-icon-button' -import '@material/mwc-dialog' -import '@material/mwc-tab-bar' -import '@material/mwc-tab' -import '@material/mwc-list/mwc-list-item' -import '@material/mwc-select' -import '@polymer/iron-icons/iron-icons.js' -import '@polymer/paper-icon-button/paper-icon-button.js' -import '@polymer/paper-spinner/paper-spinner-lite.js' -import '@vaadin/grid' -import '@vaadin/grid/vaadin-grid-sorter' - -const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }) - -let workers = new Map() - -class TradeBotDOGE extends LitElement { - static get properties() { - return { - selectedAddress: { type: Object }, - config: { type: Object }, - listedCoins: { type: Map }, - sellBtnDisable: { type: Boolean }, - isSellLoading: { type: Boolean }, - isBuyLoading: { type: Boolean }, - buyBtnDisable: { type: Boolean }, - autoBuyWarning: { type: Boolean }, - autoBuyBtnDisable: { type: Boolean }, - autoBuyBotDisable: { type: Boolean }, - initialAmount: { type: Number }, - cancelBtnDisable: { type: Boolean }, - cancelStuckOfferBtnDisable: { type: Boolean }, - selectedCoin: { type: String }, - isLoadingHistoricTrades: { type: Boolean }, - isLoadingOpenTrades: { type: Boolean }, - isLoadingMyOpenOrders: { type: Boolean }, - showGetWalletBance: { type: Boolean }, - showAddAutoBuy: { type: Boolean }, - theme: { type: String, reflect: true }, - dogeWallet: { type: String }, - qortdoge: { type: Number }, - dogeqort: { type: Number }, - tradeBotDogeBook: { type: Array }, - tradesDogeQortal: { type: Array }, - doneTradesDogeQortal: { type: Array }, - tradesAvailableDogeQortal: { type: Array }, - tradeBotDogeQortal: { type: Array }, - tradeBotAvailableDogeQortal: { type: Array }, - checkAlice: { type: String }, - botBuyAtAddress: { type: String }, - reAddAmount: { type: Number }, - reAddPrice: { type: Number } - } - } - - static get styles() { - return css` - * { - --mdc-theme-primary: rgb(3, 169, 244); - --mdc-theme-secondary: var(--mdc-theme-primary); - --mdc-theme-error: rgb(255, 89, 89); - --mdc-text-field-outlined-idle-border-color: var(--txtfieldborder); - --mdc-text-field-outlined-hover-border-color: var(--txtfieldhoverborder); - --mdc-text-field-label-ink-color: var(--black); - --mdc-text-field-ink-color: var(--black); - --mdc-select-outlined-idle-border-color: var(--txtfieldborder); - --mdc-select-outlined-hover-border-color: var(--txtfieldhoverborder); - --mdc-select-label-ink-color: var(--black); - --mdc-select-ink-color: var(--black); - --mdc-theme-surface: var(--white); - --mdc-dialog-content-ink-color: var(--black); - --mdc-dialog-shape-radius: 25px; - --paper-input-container-focus-color: var(--mdc-theme-primary); - --lumo-primary-text-color: rgb(0, 167, 245); - --lumo-primary-color-50pct: rgba(0, 167, 245, 0.5); - --lumo-primary-color-10pct: rgba(0, 167, 245, 0.1); - --lumo-primary-color: hsl(199, 100%, 48%); - --lumo-base-color: var(--white); - --lumo-body-text-color: var(--black); - --lumo-secondary-text-color: var(--sectxt); - --lumo-contrast-60pct: var(--vdicon); - --_lumo-grid-border-color: var(--border); - --_lumo-grid-secondary-border-color: var(--border2); - } - paper-spinner-lite { - height: 30px; - width: 30px; - --paper-spinner-color: var(--mdc-theme-primary); - --paper-spinner-stroke-width: 3px; - } - mwc-tab-bar { - --mdc-text-transform: none; - --mdc-tab-color-default: var(--black); - --mdc-tab-text-label-color-default: var(--black); - } - #tabs-1 { - --mdc-tab-height: 42px; - border-left: 1px solid var(--tradeborder); - border-top: 1px solid var(--tradeborder); - border-right: 1px solid var(--tradeborder); - color: var(--black); - } - #tab-buy[active] { - --mdc-theme-primary: rgba(55, 160, 51, 0.9); - } - #tabs-1-content { - height: 100%; - padding-bottom: 10px; - } - #tabs-1-content > div { - height: 100%; - border: 1px solid var(--tradeborder); - } - #tabs-1-content .card { - border: none; - } - #tabs-1-content .btn-clear { - --mdc-icon-button-size: 32px; - color: var(--black); - } - .btn-clear-bot { - --mdc-icon-button-size: 32px; - color: var(--black); - float: right; - } - .btn-info { - color: var(--black); - --mdc-icon-size: 16px; - padding-top: 3px; - } - #tab-sell[active] { - --mdc-theme-primary: rgb(255, 89, 89); - } - #trade-portal-page { - background: var(--white); - padding: 12px 24px; - } - .divCard { - border: 1px solid var(--black); - padding: 1em; - box-shadow: 0 0.3px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 1px -1px rgba(0, 0, 0, 0.12), 0 1px 2px 0 rgba(0, 0, 0, 0.2); - } - h2 { - margin: 10px 0; - } - - h4 { - margin: 5px 0; - } - - p { - font-size: 14px; - line-height: 21px; - } - - .card-body { - background-color: var(--white); - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - min-height: 100vh; - margin: 0; - } - - .card-container { - background-color: var(--white); - border-radius: 5px; - color: var(--black); - padding-top: 30px; - position: relative; - width: 350px; - max-width: 100%; - text-align: center; - } - - .card-container .level { - color: #ffffff; - background-color: #03a9f4; - border-radius: 3px; - font-size: 14px; - font-weight: bold; - padding: 3px 7px; - position: absolute; - top: 30px; - left: 30px; - } - - .card-container .founder { - color: #ffffff; - background-color: #03a9f4; - border-radius: 3px; - font-size: 14px; - font-weight: bold; - padding: 3px 7px; - position: absolute; - top: 30px; - right: 30px; - } - - .card-container .round { - width: 96px; - height: 96px; - border: 1px solid #03a9f4; - border-radius: 50%; - padding: 2px; - } - - .card-container .badge { - width: 200px; - height: 135px; - border: 1px solid transparent; - border-radius: 10%; - padding: 2px; - } - - .userdata { - background-color: #1F1A36; - text-align: left; - padding: 15px; - margin-top: 30px; - } - - .userdata ul { - list-style-type: none; - margin: 0; - padding: 0; - } - - .userdata ul li { - border: 1px solid #2D2747; - border-radius: 2px; - display: inline-block; - font-size: 12px; - margin: 0 7px 7px 0; - padding: 7px; - } - - h2, - h3, - h4, - h5 { - color: var(--black); - font-weight: 400; - } - header { - display: flex; - flex: 0 1 auto; - align-items: center; - justify-content: center; - padding: 0px 10px; - font-size: 16px; - color: var(--white); - background-color: var(--tradehead); - border-left: 1px solid var(--tradeborder); - border-top: 1px solid var(--tradeborder); - border-right: 1px solid var(--tradeborder); - min-height: 40px; - } - p { - margin-bottom: 12px; - } - #trade-portal { - max-width: 100vw; - margin-left: auto; - margin-right: auto; - } - .box { - margin: 0; - padding: 0; - display: flex; - flex-flow: column; - height: 100%; - } - .box-bot { - margin: 0; - padding: 0; - display: flex; - flex-flow: column; - height: 150px; - } - #first-trade-section { - margin-bottom: 10px; - } - #first-trade-section > div { - } - #second-trade-section { - margin-bottom: 10px; - } - #second-trade-section > div { - } - #third-trade-section { - margin-bottom: 10px; - } - #third-trade-section > div { - } - .trade-chart { - background-color: var(--white); - border: 2px #ddd solid; - text-align: center; - } - .open-trades { - text-align: center; - } - .open-market-container { - text-align: center; - } - .trade-bot-container { - text-align: center; - } - .no-last-seen { - background: rgb(255, 89, 89); - padding: 9px 1.3px; - border-radius: 50%; - width: 1rem; - margin: 0 auto; - } - .card { - padding: 1em; - border: 1px var(--tradeborder) solid; - flex: 1 1 auto; - display: flex; - flex-flow: column; - justify-content: space-evenly; - min-height: inherit; - } - .card-bot { - padding: 1em; - flex: 1 1 auto; - display: flex; - flex-flow: column; - justify-content: space-evenly; - width: 350px; - min-height: inherit; - } - .cancel { - --mdc-theme-primary: rgb(255, 89, 89); - } - .border-wrapper { - border: 1px var(--tradeborder) solid; - overflow: hidden; - } - .amt-text { - color: var(--tradehave); - font-size: 15px; - margin-top: 5px; - margin-bottom: 12px; - } - .exchange { - color: var(--black); - font-size: 18px; - font-weight: bold; - margin-top: 5px; - margin-bottom: 10px; - } - .clear-button { - display: inline; - float: right; - margin-bottom: 5px; - } - .exhcnage-text { - display: inline; - float: left; - margin-bottom: 5px; - } - .balance-text { - display: inline; - float: right; - margin-bottom: 5px; - } - .fee-text { - display: inline; - float: left; - margin-bottom: 5px; - } - .tab-text { - color: var(--tradehave); - font-size: 12px; - text-align: left; - margin-top: 2px; - margin-bottom: -12px; - } - .historic-trades { - text-align: center; - } - .my-open-orders { - text-align: center; - } - .my-historic-trades { - text-align: center; - } - .buttons { - width: auto !important; - } - .buy-button { - --mdc-theme-primary: rgba(55, 160, 51, 0.9); - } - .sell-button { - --mdc-theme-primary: rgb(255, 89, 89); - } - .trade-bot-button { - margin-top: 20px; - margin-bottom: 20px; - --mdc-theme-primary: rgba(55, 160, 51, 0.9); - } - .full-width { - background-color: var(--white); - border: 2px var(--black); - height: 200px; - text-align: center; - } - vaading-grid { - font-size: .8em; - } - vaadin-grid-column { - flex-grow: 1; - } - .loadingContainer { - height: 100%; - width: 100%; - } - .loading, - .loading:after { - border-radius: 50%; - width: 5em; - height: 5em; - } - .loading { - margin: 10px auto; - border-width: .6em; - border-style: solid; - border-color: rgba(3, 169, 244, 0.2) rgba(3, 169, 244, 0.2) rgba(3, 169, 244, 0.2) rgb(3, 169, 244); - font-size: 10px; - position: relative; - text-indent: -9999em; - transform: translateZ(0px); - animation: 1.1s linear 0s infinite normal none running loadingAnimation; - } - mwc-select#coinSelectionMenu { - font-size: 24px; - width:220px; - } - mwc-select#coinSelectionMenu mwc-list-item { - line-height: 30px; - } - .coinName::before { - content: ""; - display: inline-block; - height: 26px; - width: 45px; - position: absolute; - background-repeat: no-repeat; - background-size: cover; - left: 10px; - top: 10px; - } - .coinName { - display: inline-block; - height: 26px; - padding-left: 45px; - } - .warning-text { - animation: blinker 1.5s linear infinite; - display: inline; - float: left; - margin-bottom: 5px; - color: rgb(255, 89, 89); - } - .warning-bot-text { - animation: blinker 1.5s linear infinite; - display: inline; - text-align: center; - color: rgb(255, 89, 89); - } - .red { - --mdc-theme-primary: #F44336; - } - @-webkit-keyframes loadingAnimation { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - @keyframes loadingAnimation { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - @keyframes blinker { - 50% { - opacity: 0; - } - } - @media (min-width: 701px) { - * { - } - #trade-portal {} - #first-trade-section { - display: grid; - grid-template-columns:1fr 4fr 1fr; - grid-auto-rows: max(350px); - column-gap: 0.5em; - row-gap: 0.4em; - justify-items: stretch; - align-items: stretch; - margin-bottom: 10px; - } - #second-trade-section { - display: grid; - grid-template-columns:1fr 4fr 1fr; - grid-auto-rows: max(350px); - column-gap: 0.5em; - row-gap: 0.4em; - justify-items: stretch; - align-items: stretch; - margin-bottom: 10px; - } - #third-trade-section { - display: grid; - grid-template-columns: 1fr 4fr 1fr; - grid-auto-rows: max(150px); - column-gap: 0.5em; - row-gap: 0.4em; - justify-items: stretch; - align-items: stretch; - margin-bottom: 10px; - } - #fourth-trade-section { - display: grid; - grid-template-columns: 1fr 4fr 1fr; - grid-auto-rows: max(150px); - column-gap: 0.5em; - row-gap: 0.4em; - justify-items: stretch; - align-items: stretch; - margin-bottom: 10px; - } - } - ` - } - - constructor() { - super() - let qortal = { - name: "QORTAL", - balance: "0", - coinCode: "QORT", - coinAmount: this.amountString, - tradeFee: "0.002" - } - - let dogecoin = { - name: "DOGECOIN", - balance: "0", - coinCode: "DOGE", - openOrders: [], - openFilteredOrders: [], - historicTrades: [], - myOrders: [], - myHistoricTrades: [], - myOfferingOrders: [], - openTradeOrders: null, - tradeOffersSocketCounter: 1, - coinAmount: this.amountString, - tradeFee: "~0.005" - } - - this.listedCoins = new Map() - this.listedCoins.set("QORTAL", qortal) - this.listedCoins.set("DOGECOIN", dogecoin) - - workers.set("QORTAL", { - tradesConnectedWorker: null, - handleStuckTradesConnectedWorker: null - }) - - workers.set("DOGECOIN", { - tradesConnectedWorker: null, - handleStuckTradesConnectedWorker: null - }) - - this.selectedCoin = "DOGECOIN" - this.selectedAddress = {} - this.config = {} - this.sellBtnDisable = false - this.isSellLoading = false - this.buyBtnDisable = true - this.autoBuyWarning = false - this.autoBuyBtnDisable = true - this.autoBuyBotDisable = false - this.isBuyLoading = false - this.initialAmount = 0 - this.cancelBtnDisable = false - this.cancelStuckOfferBtnDisable = false - this.isLoadingHistoricTrades = true - this.isLoadingOpenTrades = true - this.isLoadingMyOpenOrders = false - this.showGetWalletBance = true - this.showAddAutoBuy = false - this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light' - this.dogeWallet = '' - this.qortdoge = 0 - this.dogeqort = 0 - this.tradeBotDogeBook = [] - this.tradesDogeQortal = [] - this.doneTradesDogeQortal = [] - this.tradesAvailableDogeQortal = [] - this.tradeBotDogeQortal = [] - this.tradeBotAvailableDogeQortal = [] - this.checkAlice = '' - this.botBuyAtAddress = '' - this.reAddAmount = 0 - this.reAddPrice = 0 - } - - openTradesTemplate() { - return html` -
-
-
${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange42")}
-
-
${translate("login.loading")}
- - { - render(html`${this.round(data.item.qortAmount)}`, root) - }} - > - - { - render(html`${this.round(data.item.price)}`, root) - }} - > - - { - render(html`${data.item.foreignAmount}`, root) - }} - > - - { - render(html`${data.item.qortalCreator}`, root) - }} - > - - -
-
-
- ` - } - - myOpenOrdersTemplate() { - return html` -
-
-
${translate("tradepage.tchange36")}
-
-
${translate("login.loading")}
- - { - const dateString = new Date(data.item.timestamp).toLocaleString() - render(html`${dateString}`, root) - }} - > - - { - render(html` ${data.item._tradeState} `, root) - }} - > - - { - const price = this.round(parseFloat(data.item.foreignAmount) / parseFloat(data.item.qortAmount)) - render(html`${price}`, root) - }} - > - - - - - - -
-
-
- ` - } - - myDoneTradesTemplate() { - return html` -
-
-
${translate("tradepage.tchange43")} (${this.listedCoins.get(this.selectedCoin).coinCode})
-
-
${translate("login.loading")}
- - { - const dateString = new Date(data.item.timestamp).toLocaleString() - render(html`${dateString}`, root) - }} - > - - { - return render(html` ${translate("tradepage.tchange32")} `, root) - }} - > - - { - const price = this.round(parseFloat(data.item.foreignAmount) / parseFloat(data.item.qortAmount)) - render(html`${price}`, root) - }} - > - - - - { - render(html` ${data.item.foreignAmount} `, root) - }} - > - - -
-
-
- ` - } - - myHistoricTradesTemplate() { - return html` -
-
-
${translate("tradepage.tchange4")}
-
- - { - const dateString = new Date(data.item.timestamp).toLocaleString() - render(html`${dateString}`, root) - }} - > - - { - if (data.item.mode === 'SOLD') return render(html` ${translate("tradepage.tchange31")} `, root) - if (data.item.mode === 'BOUGHT') return render(html` ${translate("tradepage.tchange32")} `, root) - return render(html` ${data.item.mode} `, root) - }} - > - - { - const price = this.round(parseFloat(data.item.foreignAmount) / parseFloat(data.item.qortAmount)) - render(html`${price}`, root) - }} - > - - - - { - render(html` ${data.item.foreignAmount} `, root) - }} - > - - -
-
-
- ` - } - - tradeBotDOGETemplate() { - return html` -
-
-
${translate("tradepage.tchange39")} ${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT
-
- - { - render(html`${data.item.botDogeQortAmount}`, root) - }} - > - - { - render(html`${data.item.botDogePrice}`, root) - }} - > - - { - const totalCoins = this.round(parseFloat(data.item.botDogeQortAmount) * parseFloat(data.item.botDogePrice)) - const myBotFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) - if (Number(myBotFunds) > Number(totalCoins)) { - this.autoBuyBotDisable = false - render(html`${totalCoins}`, root) - } else { - this.autoBuyBotDisable = true - render(html`${totalCoins}`, root) - } - }} - > - - { - render(html` this.removeDOGETradebook()}>delete ${translate("nodepage.nchange12")}`, root) - }} - > - - - ${this.isEmptyArray(this.tradeBotDogeBook) ? html` - - ${translate("tradepage.tchange38")} ${translate("tradepage.tchange39")} - - `: ''} -
- ${this.autoBuyBotDisable ? html` -
${this.renderBotWarning()}
- `: ''} -
-
- ` - } - - render() { - return html` -
-
-
-
- ${this.openTradesTemplate()} -
-
-
-
- ${this.myDoneTradesTemplate()} -
-
-
-
- ${this.myOpenOrdersTemplate()} -
-
-
-
- ${this.showAutoBuyGrid()} -
-
-
-

${translate("tradepage.tchange33")} ${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange40")}

-

1 QORT = ${this.exchangeRateQort()} ${this.listedCoins.get(this.selectedCoin).coinCode}

-
-
-
- - -
-

${this.renderFetchText()}

-
-
-
-

${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT

-
-
-
-
${this.renderWarning()}
- -
- ${translate("tradepage.tchange8")} (QORT)* -

- - -

- ${translate("tradepage.tchange14")} (${this.listedCoins.get(this.selectedCoin).coinCode})* -

- - -

- ${translate("tradepage.tchange10")} (${this.listedCoins.get(this.selectedCoin).coinCode})* -

- - -

- - ${translate("tradepage.tchange16")}: ${this.listedCoins.get(this.selectedCoin).balance} ${this.listedCoins.get(this.selectedCoin).coinCode} - -
-
- - ${translate("tradepage.tchange38")} ${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange39")} - -
-
-
- ${translate("general.close")} -
- ` - } - - async firstUpdated() { - - let _this = this - - this.changeTheme() - this.changeLanguage() - await this.updateWalletBalance() - - this._openOrdersGrid = this.shadowRoot.getElementById('openOrdersGrid') - - this._openOrdersGrid.querySelector('#priceColumn').headerRenderer = function (root) { - const priceString = get("tradepage.tchange9") - root.innerHTML = '' + priceString + ' (' + _this.listedCoins.get(_this.selectedCoin).coinCode + ')' - } - - this._openOrdersGrid.querySelector('#qortAmountColumn').headerRenderer = function (root) { - const amountString = get("tradepage.tchange8") - root.innerHTML = '' + amountString + ' (QORT)' - } - - this._myOrdersGrid = this.shadowRoot.getElementById('myOrdersGrid') - this._myHistoricTradesGrid = this.shadowRoot.getElementById('myHistoricTradesGrid') - - const delay = ms => new Promise(res => setTimeout(res, ms)) - - const getQortDogePrice = () => { - parentEpml.request("apiCall", { url: `/crosschain/price/DOGECOIN?inverse=true` }).then((res) => { - setTimeout(() => { this.qortdoge = (Number(res) / 1e8).toFixed(8) }, 1) - }) - setTimeout(getQortDogePrice, 300000) - } - - const filterMyPriceTradesDOGE = async () => { - const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] - const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port - const tradeBotDogeQortalUrl = `${nodeUrl}/crosschain/tradebot?foreignBlockchain=DOGECOIN&apiKey=${this.getApiKey()}` - const waitFor = ms => new Promise(res => setTimeout(res, ms)) - let timer - - const tradeBotDogeQortal = await fetch(tradeBotDogeQortalUrl).then(response => { - return response.json() - }) - - this.tradeBotDogeQortal = tradeBotDogeQortal - - await waitFor(1000) - - if (this.isEmptyArray(this.tradeBotDogeBook) === true) { - clearTimeout(timer) - timer = setTimeout(filterMyPriceTradesDOGE, 180000) - return - } else { - clearTimeout(timer) - timer = setTimeout(filterMyPriceTradesDOGE, 180000) - - this.tradeBotAvailableDogeQortal = this.listedCoins.get(this.selectedCoin).openFilteredOrders.map(item => { - const listprice = parseFloat(item.price) - const listamount = parseFloat(item.qortAmount) - const checkprice = parseFloat(this.tradeBotDogeBook[0].botDogePrice) - const checkamount = parseFloat(this.tradeBotDogeBook[0].botDogeQortAmount) - if (Number(listprice) <= Number(checkprice) && Number(listamount) <= Number(checkamount)) { - return { - qortAmount: item.qortAmount, - price: item.price, - foreignAmount: item.foreignAmount, - qortalCreator: item.qortalCreator, - qortalAtAddress: item.qortalAtAddress - } - } - }).filter(item => !!item) - - this.tradeBotAvailableDogeQortal.sort((a, b) => parseFloat(a.price) - parseFloat(b.price)) - - if (this.isEmptyArray(this.tradeBotAvailableDogeQortal) === true) { - return - } else { - this.checkAlice = this.tradeBotAvailableDogeQortal[0].qortalAtAddress - } - - await waitFor(1000) - - if (this.tradeBotDogeQortal.some(item => item.atAddress === this.checkAlice)) { - return - } else { - this.tradesAvailableDogeQortal = this.tradeBotAvailableDogeQortal - } - } - - await waitFor(1000) - - if (this.isEmptyArray(this.tradesAvailableDogeQortal) === true) { - return - } else { - const botprice = this.round(parseFloat(this.tradeBotDogeBook[0].botDogePrice)) - const changeamount = parseFloat(this.tradeBotDogeBook[0].botDogeQortAmount) - const reduceamount = parseFloat(this.tradesAvailableDogeQortal[0].qortAmount) - const tradeataddress = this.tradesAvailableDogeQortal[0].qortalAtAddress - const newamount = this.round(parseFloat(changeamount - reduceamount)) - - this.reAddAmount = this.round(parseFloat(this.tradeBotDogeBook[0].botDogeQortAmount)) - this.reAddPrice = this.round(parseFloat(this.tradeBotDogeBook[0].botDogePrice)) - - localStorage.removeItem(this.dogeWallet) - localStorage.setItem(this.dogeWallet, "") - - var oldDogeTradebook = JSON.parse(localStorage.getItem(this.dogeWallet) || "[]") - - const newDogeTradebookItem = { - botDogeQortAmount: newamount, - botDogePrice: botprice - } - - oldDogeTradebook.push(newDogeTradebookItem) - - localStorage.setItem(this.dogeWallet, JSON.stringify(oldDogeTradebook)) - - this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.dogeWallet) || "[]") - - await waitFor(1000) - - this.botBuyAtAddress = tradeataddress - - this.buyAction() - - if (this.isEmptyArray(this.tradeBotDogeBook) === true) { - return - } else { - const botamount = parseFloat(this.tradeBotDogeBook[0].botDogeQortAmount) - - if (Number(botamount) === 0) { - this.removeDOGETradebook() - } else { - this.tradeBotDogeBook = this.tradeBotDogeBook - } - } - - if (this.isEmptyArray(this.tradeBotDogeBook) === true) { - return - } else { - const checkBotFunds = this.round(parseFloat(this.tradeBotDogeBook[0].botDogeQortAmount) * parseFloat(this.tradeBotDogeBook[0].botDogePrice)) - const myBotFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) - - if (Number(myBotFunds) < Number(checkBotFunds)) { - this.removeDOGETradebook() - } else { - this.tradeBotDogeBook = this.tradeBotDogeBook - } - } - } - } - - const getDoneTradeDOGE = async () => { - this.isLoadingDoneTrades = true - const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] - const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port - const doneDogeQortalUrl = `${nodeUrl}/crosschain/trades?foreignBlockchain=DOGECOIN&minimumTimestamp=1597310000000&limit=0&reverse=true` - const myAddress = window.parent.reduxStore.getState().app.selectedAddress.address - - const doneDogeQortal = await fetch(doneDogeQortalUrl).then(response => { - return response.json() - }) - - this.doneTradesDogeQortal = doneDogeQortal.map(item => { - const searchAddress = item.buyerReceivingAddress - if (searchAddress == myAddress) { - return { - timestamp: item.tradeTimestamp, - foreignAmount: item.foreignAmount, - qortAmount: item.qortAmount - } - } - }).filter(item => !!item) - - this.isLoadingDoneTrades = false - setTimeout(getDoneTradeDOGE, 600000) - } - - window.addEventListener('contextmenu', (event) => { - event.preventDefault() - this._textMenu(event)}, - { passive: true } - ) - - window.addEventListener('click', () => { - parentEpml.request('closeCopyTextMenu', null)}, - { passive: true } - ) - - window.addEventListener('storage', () => { - const checkLanguage = localStorage.getItem('qortalLanguage') - const checkTheme = localStorage.getItem('qortalTheme') - - use(checkLanguage) - - if (checkTheme === 'dark') { - this.theme = 'dark' - } else { - this.theme = 'light' - } - document.querySelector('html').setAttribute('theme', this.theme) - }) - - window.onkeyup = (e) => { - if (e.keyCode === 27) parentEpml.request('closeCopyTextMenu', null) - } - - this.dogeWallet = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet.address - - let configLoaded = false - - parentEpml.ready().then(() => { - parentEpml.subscribe('selected_address', async (selectedAddress) => { - this.selectedAddress = {} - selectedAddress = JSON.parse(selectedAddress) - if (!selectedAddress || Object.entries(selectedAddress).length === 0) return - this.selectedAddress = selectedAddress - this.dogeWwallet = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet.address - await this.updateAccountBalance() - await this.dogeTradebook() - }) - - parentEpml.subscribe('config', (c) => { - if (!configLoaded) { - setTimeout(getQortDogePrice, 1) - setTimeout(getDoneTradeDOGE, 1) - configLoaded = true - } - this.config = JSON.parse(c) - }) - - parentEpml.subscribe('copy_menu_switch', async (value) => { - if (value === 'false' && window.getSelection().toString().length !== 0) this.clearSelection() - }) - this.setForeignCoin() - }) - parentEpml.imReady() - - setTimeout(() => this.shadowRoot.querySelector('[slot="vaadin-grid-cell-content-3"]').setAttribute('title', 'Last Seen'), 3000) - - this.dogeTradebook() - await delay(3000) - filterMyPriceTradesDOGE() - } - - changeTheme() { - const checkTheme = localStorage.getItem('qortalTheme') - if (checkTheme === 'dark') { - this.theme = 'dark'; - } else { - this.theme = 'light'; - } - document.querySelector('html').setAttribute('theme', this.theme); - } - - changeLanguage() { - const checkLanguage = localStorage.getItem('qortalLanguage') - - if (checkLanguage === null || checkLanguage.length === 0) { - localStorage.setItem('qortalLanguage', 'us') - use('us') - } else { - use(checkLanguage) - } - } - - renderFetchText() { - return html`${translate("walletpage.wchange1")}` - } - - renderWarning() { - return html`NOT ENOUGH ${this.listedCoins.get(this.selectedCoin).coinCode}` - } - - renderBotWarning() { - return html`NOT ENOUGH ${this.listedCoins.get(this.selectedCoin).coinCode} ! AUTO BUY BOT IS STOPPED` - } - - exchangeRateQort() { - return html`${this.qortdoge}` - } - - showAutoBuyGrid() { - return html`${this.tradeBotDOGETemplate()}` - } - - showAddToAutoBuyStore() { - this.addToDOGETradebook() - } - - dogeTradebook() { - if (localStorage.getItem(this.dogeWallet) === null) { - localStorage.setItem(this.dogeWallet, "") - } else { - this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.dogeWallet) || "[]") - } - } - - addToDOGETradebook() { - const addBotDogeQortAmount = this.shadowRoot.getElementById('autoBuyDOGEQortAmountInput').value - const addBotDogePrice = this.shadowRoot.getElementById('autoBuyDOGEPriceInput').value - const addDogeQortAmount = this.round(parseFloat(addBotDogeQortAmount)) - const addDogePrice = this.round(parseFloat(addBotDogePrice)) - - var oldDogeTradebook = JSON.parse(localStorage.getItem(this.dogeWallet) || "[]") - - const newDogeTradebookItem = { - botDogeQortAmount: addDogeQortAmount, - botDogePrice: addDogePrice - } - - oldDogeTradebook.push(newDogeTradebookItem) - - localStorage.setItem(this.dogeWallet, JSON.stringify(oldDogeTradebook)) - - let dogetradebookstring = get("tradepage.tchange44") - parentEpml.request('showSnackBar', `${dogetradebookstring}`) - - this.closeDOGETradebookDialog() - this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.dogeWallet) || "[]") - this.firstUpdated() - } - - closeDOGETradebookDialog() { - this.shadowRoot.querySelector('#tradeBotDOGEAddDialog').close() - this.clearTradeBotForm() - } - - removeDOGETradebook() { - localStorage.removeItem(this.dogeWallet) - localStorage.setItem(this.dogeWallet, "") - this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.dogeWallet) || "[]") - - this.autoBuyBotDisable = false - - let dogestring = get("tradepage.tchange41") - parentEpml.request('showSnackBar', `${dogestring}`) - this.tradesAvailableDogeQortal = [] - } - - exchangeRateForeign() { - parentEpml.request('apiCall', { - url: `/crosschain/price/DOGECOIN?inverse=false` - }).then((res) => { - this.dogeqort = (Number(res) / 1e8).toFixed(8) - }) - return html`${this.dogeqort}` - } - - async updateWalletBalance() { - let _url = `/crosschain/doge/walletbalance?apiKey=${this.getApiKey()}` - let _body = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet.derivedMasterPublicKey - - this.showGetWalletBance = true - this.showAddAutoBuy = false - - await parentEpml.request('apiCall', { - url: _url, - method: 'POST', - body: _body, - }).then((res) => { - if (isNaN(Number(res))) { - let snack1string = get("tradepage.tchange30") - parentEpml.request('showSnackBar', `${snack1string}`) - } else { - this.listedCoins.get(this.selectedCoin).balance = (Number(res) / 1e8).toFixed(8) - } - }) - - this.showGetWalletBance = false - this.showAddAutoBuy = true - } - - async setForeignCoin() { - let _this = this - this.selectedCoin = "DOGECOIN" - - this.isLoadingOpenTrades = true - await this.createConnection() - - this._openOrdersGrid.querySelector('#priceColumn').headerRenderer = function (root) { - const priceString2 = get("tradepage.tchange9") - root.innerHTML = '' + priceString2 + ' (' + _this.listedCoins.get(_this.selectedCoin).coinCode + ')' - } - - this.autoBuyBotDisable = false - await this.updateWalletBalance() - } - - async reRenderOpenFilteredOrders() { - this.requestUpdate() - await this.updateComplete - this.isLoadingOpenTrades = false - } - - async reRenderMyOpenOrders() { - this.requestUpdate() - await this.updateComplete - this.isLoadingMyOpenOrders = false - } - - addAutoBuyAction() { - this.autoBuyWarning = false - this.clearTradeBotForm() - this.shadowRoot.querySelector('#tradeBot' + this.listedCoins.get(this.selectedCoin).coinCode + 'AddDialog').show() - } - - checkTradeBotValues() { - const checkTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value - const checkTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value - const checkAmount = this.round(parseFloat(checkTradeBotAmountInput)) - const checkPrice = this.round(parseFloat(checkTradeBotPriceInput)) - - if (Number(checkAmount) === 0) { - let amountString = get("tradepage.tchange34") - parentEpml.request('showSnackBar', `${amountString}`) - } else if (Number(checkPrice) === 0) { - let priceString = get("tradepage.tchange35") - parentEpml.request('showSnackBar', `${priceString}`) - } else { - this.showAddToAutoBuyStore() - } - } - - processOfferingTrade(offer) { - try { - if(this.listedCoins.get(offer.foreignBlockchain).name!='') { - const offerItem = { - ...offer, - qortAmount: parseFloat(offer.qortAmount), - price: parseFloat(offer.foreignAmount) / parseFloat(offer.qortAmount), - } - const addOffer = () => { - this.listedCoins.get(offer.foreignBlockchain).openOrders.unshift(offerItem) - } - const initOffer = () => { - this.listedCoins.get(offer.foreignBlockchain).openOrders.push(offerItem) - } - this.listedCoins.get(offer.foreignBlockchain).openOrders.length === 0 ? initOffer() : addOffer() - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._openOrdersGrid.clearCache() : null - } - } catch(e) { - console.log("Error adding offer from "+offer.foreignBlockchain) - } - } - - processRedeemedTrade(offer) { - try { - if (this.listedCoins.get(offer.foreignBlockchain).name!='') { - - if (offer.qortalCreator === this.selectedAddress.address) { - if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { - this.updateWalletBalance() - } - const offerItem = { - ...offer, - mode: 'SOLD', - } - this._myHistoricTradesGrid.items.unshift(offerItem) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null - } else if (offer.partnerQortalReceivingAddress === this.selectedAddress.address) { - if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { - this.updateWalletBalance() - } - const offerItem = { - ...offer, - mode: 'BOUGHT', - } - this._myHistoricTradesGrid.items.unshift(offerItem) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null - } - const addNewHistoricTrade = () => { - this._historicTradesGrid.items.unshift(offer) - this._historicTradesGrid.clearCache() - } - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? addNewHistoricTrade() : null - - } - } catch(e) { - console.log("Error processing redeemed trade offer from "+offer.foreignBlockchain) - } - } - - processTradingTrade(offer) { - try { - if (this.listedCoins.get(offer.foreignBlockchain).name!='') { - - if (offer.qortalCreator === this.selectedAddress.address && this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { - this.updateWalletBalance() - } - this._openOrdersGrid.items.forEach((item, index) => { - if (item.qortalAtAddress === offer.qortalAtAddress) { - this._openOrdersGrid.items.splice(index, 1) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._openOrdersGrid.clearCache() : null - } - }) - this.listedCoins.get(offer.foreignBlockchain).openOrders = this.listedCoins.get(offer.foreignBlockchain).openOrders.filter((order) => order.qortalAtAddress !== offer.qortalAtAddress) - } - } catch(e) { - console.log("Error processing trading trade offer from "+offer.foreignBlockchain) - } - } - - processRefundedTrade(offer) { - try { - if (this.listedCoins.get(offer.foreignBlockchain).name!='') { - - if (offer.qortalCreator === this.selectedAddress.address) { - if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { - this.updateWalletBalance() - } - this._myHistoricTradesGrid.items.unshift(offer) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null - } - - } - } catch(e) { - console.log("Error processing refunded trade offer from "+offer.foreignBlockchain) - } - } - - processCancelledTrade(offer) { - try { - if (this.listedCoins.get(offer.foreignBlockchain).name!='') { - - if (offer.qortalCreator === this.selectedAddress.address) { - if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { - this.updateWalletBalance() - } - this._myHistoricTradesGrid.items.unshift(offer) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null - } - this._openOrdersGrid.items.forEach((item, index) => { - if (item.qortalAtAddress === offer.qortalAtAddress) { - this._openOrdersGrid.items.splice(index, 1) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._openOrdersGrid.clearCache() : null - } - }) - this.listedCoins.get(offer.foreignBlockchain).openOrders = this.listedCoins.get(offer.foreignBlockchain).openOrders.filter((order) => order.qortalAtAddress !== offer.qortalAtAddress) - this._stuckOrdersGrid.items.forEach((item, index) => { - if (item.qortalAtAddress === offer.qortalAtAddress) { - this._stuckOrdersGrid.items.splice(index, 1) - this._stuckOrdersGrid.clearCache() - } - }) - } - } catch(e) { - console.log("Error processing cancelled trade offer from "+offer.foreignBlockchain) - } - } - - /** - * TRADE OFFER STATES or MODE - * - OFFERING - */ - - processTradeOffers(offers) { - offers.forEach((offer) => { - if (offer.mode === 'OFFERING') { - this.processOfferingTrade(offer) - } - }) - } - - processTradeBotStates(tradeStates) { - - const DogecoinACCTv1 = (states) => { - states.reverse() - states.forEach((state) => { - if (state.creatorAddress === this.selectedAddress.address) { - if (state.tradeState == 'ALICE_WAITING_FOR_AT_LOCK') { - this.changeTradeBotState(state, 'BUYING') - } else if (state.tradeState == 'ALICE_DONE') { - this.handleCompletedState(state) - } else if (state.tradeState == 'ALICE_REFUNDING_A') { - this.changeTradeBotState(state, 'REFUNDING') - } else if (state.tradeState == 'ALICE_REFUNDED') { - this.handleCompletedState(state) - } - } - }) - } - - switch (this.selectedCoin) { - case 'DOGECOIN': - DogecoinACCTv1(tradeStates) - break - default: - break - } - } - - changeTradeBotState(state, tradeState) { - this.isLoadingMyOpenOrders = true - const stateItem = { - ...state, - _tradeState: tradeState, - } - const item = this._myOrdersGrid.querySelector(`#${state.atAddress}`) - const addStateItem = () => { - this.reRenderMyOpenOrders() - this._myOrdersGrid.items.unshift(stateItem) - this._myOrdersGrid.clearCache() - } - const updateStateItem = () => { - this._myOrdersGrid.items.forEach((item, index) => { - if (item.atAddress === state.atAddress) { - this.reRenderMyOpenOrders() - this._myOrdersGrid.items.splice(index, 1) - this._myOrdersGrid.items.unshift(stateItem) - this._myOrdersGrid.clearCache() - } - }) - } - item ? updateStateItem() : addStateItem() - } - - handleCompletedState(state) { - this._myOrdersGrid.items.forEach((item, index) => { - if (item.atAddress === state.atAddress) { - this.reRenderMyOpenOrders() - this._myOrdersGrid.items.splice(index, 1) - this._myOrdersGrid.clearCache() - } - }) - } - - initSocket() { - let _relatedCoin = "" - let tradePresenceTxns = null - let offeringTrades = null - - self.addEventListener('message', function (event) { - switch (event.data.type) { - case 'open_orders': - offeringTrades = event.data.content - processOffersWithPresence() - break - case 'set_coin': - _relatedCoin = event.data.content - break - default: - break - } - }) - - const lessThanThirtyMinsAgo = (timestamp) => { - const THIRTYMINS = 1000 * 60 * 30 - const thirtyMinsAgo = Date.now() - THIRTYMINS - return timestamp > thirtyMinsAgo - } - - const filterOffersUsingTradePresence = (offeringTrade) => { - return offeringTrade.tradePresenceExpiry > Date.now(); - } - - const processOffersWithPresence = () => { - if (offeringTrades === null) return - - async function asyncForEach(array, callback) { - for (let index = 0; index < array.length; index++) { - await callback(array[index], index, array) - } - } - - const startOfferPresenceMapping = async () => { - - if (tradePresenceTxns !== null) { - await asyncForEach(tradePresenceTxns, async (tradePresence) => { - let offerIndex = offeringTrades.findIndex((offeringTrade) => offeringTrade.qortalCreatorTradeAddress === tradePresence.tradeAddress) - offerIndex !== -1 ? (offeringTrades[offerIndex].tradePresenceExpiry = tradePresence.timestamp) : null - }) - } - - let filteredOffers = offeringTrades.filter((offeringTrade) => filterOffersUsingTradePresence(offeringTrade)) - self.postMessage({ type: 'PRESENCE', data: { offers: offeringTrades, filteredOffers: filteredOffers, relatedCoin: _relatedCoin } }) - } - - startOfferPresenceMapping() - } - - const initTradeOffersWebSocket = (restarted = false) => { - let tradeOffersSocketCounter = 0 - let socketTimeout - let socketLink = `ws://NODEURL/websockets/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN&includeHistoric=true` - const socket = new WebSocket(socketLink) - socket.onopen = () => { - setTimeout(pingSocket, 50) - tradeOffersSocketCounter += 1 - } - socket.onmessage = (e) => { - e.relatedCoin = _relatedCoin - self.postMessage({ - type: 'TRADE_OFFERS', - data: e.data, - counter: tradeOffersSocketCounter, - isRestarted: restarted, - }) - tradeOffersSocketCounter += 1 - restarted = false - } - socket.onclose = () => { - clearTimeout(socketTimeout) - restartTradeOffersWebSocket() - } - socket.onerror = (e) => { - clearTimeout(socketTimeout) - } - const pingSocket = () => { - socket.send('ping') - socketTimeout = setTimeout(pingSocket, 150000) - } - } - - const initTradeBotWebSocket = (restarted = false) => { - let socketTimeout - let socketLink = `ws://NODEURL/websockets/crosschain/tradebot?foreignBlockchain=FOREIGN_BLOCKCHAIN` - const socket = new WebSocket(socketLink) - socket.onopen = () => { - setTimeout(pingSocket, 50) - } - socket.onmessage = (e) => { - e.relatedCoin = _relatedCoin - self.postMessage({ - type: 'TRADE_BOT', - data: e.data, - isRestarted: restarted, - }) - restarted = false - } - socket.onclose = () => { - clearTimeout(socketTimeout) - restartTradeBotWebSocket() - } - socket.onerror = (e) => { - clearTimeout(socketTimeout) - } - const pingSocket = () => { - socket.send('ping') - socketTimeout = setTimeout(pingSocket, 150000) - } - } - - const initTradePresenceWebSocket = (restarted = false) => { - let socketTimeout - let socketLink = `ws://NODEURL/websockets/crosschain/tradepresence` - const socket = new WebSocket(socketLink) - socket.onopen = () => { - setTimeout(pingSocket, 50) - } - socket.onmessage = (e) => { - tradePresenceTxns = JSON.parse(e.data) - processOffersWithPresence() - restarted = false - } - socket.onclose = () => { - clearTimeout(socketTimeout) - restartTradePresenceWebSocket() - } - socket.onerror = (e) => { - clearTimeout(socketTimeout) - } - const pingSocket = () => { - socket.send('ping') - socketTimeout = setTimeout(pingSocket, 150000) - } - } - - const restartTradePresenceWebSocket = () => { - setTimeout(() => initTradePresenceWebSocket(true), 50) - } - - const restartTradeOffersWebSocket = () => { - setTimeout(() => initTradeOffersWebSocket(true), 50) - } - - const restartTradeBotWebSocket = () => { - setTimeout(() => initTradeBotWebSocket(true), 50) - } - - initTradeOffersWebSocket() - initTradePresenceWebSocket() - initTradeBotWebSocket() - } - - async buyAction() { - const qortalAtAddress = this.botBuyAtAddress - let _foreignKey = this.selectedAddress.dogeWallet.derivedMasterPrivateKey - - const makeRequest = async () => { - const response = await parentEpml.request('tradeBotRespondRequest', { - atAddress: qortalAtAddress, - foreignKey: _foreignKey, - receivingAddress: this.selectedAddress.address, - }) - return response - } - - const manageResponse = (response) => { - if (response === true) { - this.isBuyLoading = false - this.buyBtnDisable = true - let snack5string = get("tradepage.tchange23") - parentEpml.request('showSnackBar', `${snack5string}`) - } else if (response === false) { - this.isBuyLoading = false - this.buyBtnDisable = false - - localStorage.removeItem(this.dogeWallet) - localStorage.setItem(this.dogeWallet, "") - - var oldDogeTradebook = JSON.parse(localStorage.getItem(this.dogeWallet) || "[]") - - const newDogeTradebookItem = { - botDogeQortAmount: this.reAddAmount, - botDogePrice: this.reAddPrice - } - - oldDogeTradebook.push(newDogeTradebookItem) - - localStorage.setItem(this.dogeWallet, JSON.stringify(oldDogeTradebook)) - - this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.dogeWallet) || "[]") - - let snack6string = get("tradepage.tchange24") - parentEpml.request('showSnackBar', `${snack6string}`) - } else { - this.isBuyLoading = false - this.buyBtnDisable = false - - localStorage.removeItem(this.dogeWallet) - localStorage.setItem(this.dogeWallet, "") - - var oldDogeTradebook = JSON.parse(localStorage.getItem(this.dogeWallet) || "[]") - - const newDogeTradebookItem = { - botDogeQortAmount: this.reAddAmount, - botDogePrice: this.reAddPrice - } - - oldDogeTradebook.push(newDogeTradebookItem) - - localStorage.setItem(this.dogeWallet, JSON.stringify(oldDogeTradebook)) - - this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.dogeWallet) || "[]") - - let snack7string = get("tradepage.tchange25") - parentEpml.request('showSnackBar', `${snack7string}: ${response.message}`) - } - } - const res = await makeRequest() - manageResponse(res) - } - - updateAccountBalance() { - clearTimeout(this.updateAccountBalanceTimeout) - parentEpml.request('apiCall', { - url: `/addresses/balance/${this.selectedAddress.address}?apiKey=${this.getApiKey()}`, - }).then((res) => { - this.listedCoins.get("QORTAL").balance = res - this.updateAccountBalanceTimeout = setTimeout(() => this.updateAccountBalance(), 10000) - }) - } - - _checkBuyAmount(e) { - const targetAmount = e.target.value - const target = e.target - - if (targetAmount.length === 0) { - this.isValidAmount = false - this.sellBtnDisable = true - e.target.blur() - e.target.focus() - e.target.invalid = true - } else { - this.buyBtnDisable = false - } - - e.target.blur() - e.target.focus() - - e.target.validityTransform = (newValue, nativeValidity) => { - if (newValue.includes('-') === true) { - this.buyBtnDisable = true - return { - valid: false, - } - } else if (!nativeValidity.valid) { - if (newValue.includes('.') === true) { - let myAmount = newValue.split('.') - if (myAmount[1].length > 8) { - this.buyBtnDisable = true - } else { - this.buyBtnDisable = false - return { - valid: true, - } - } - } - } else { - this.buyBtnDisable = false - } - } - } - - checkTradeBotAmount(e) { - const targetAmount = e.target.value - const target = e.target - this.autoBuyWarning = false - - if (targetAmount.length === 0) { - this.isValidAmount = false - this.autoBuyBtnDisable = true - this.autoBuyWarning = false - e.target.blur() - e.target.focus() - e.target.invalid = true - } else { - const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value - const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value - const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) - if (Number(myFunds) > Number(checkFunds)) { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = false - this.autoBuyWarning = false - } else { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = true - this.autoBuyWarning = true - } - } - - e.target.blur() - e.target.focus() - - e.target.validityTransform = (newValue, nativeValidity) => { - if (newValue.includes('-') === true) { - this.autoBuyBtnDisable = true - this.autoBuyWarning = false - return { - valid: false, - } - } else if (!nativeValidity.valid) { - if (newValue.includes('.') === true) { - let myAmount = newValue.split('.') - if (myAmount[1].length > 8) { - this.autoBuyBtnDisable = true - this.autoBuyWarning = false - } else { - const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value - const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value - const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) - if (Number(myFunds) > Number(checkFunds)) { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = false - this.autoBuyWarning = false - } else { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = true - this.autoBuyWarning = true - } - return { - valid: true, - } - } - } - } else { - const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value - const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value - const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) - if (Number(myFunds) > Number(checkFunds)) { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = false - this.autoBuyWarning = false - } else { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = true - this.autoBuyWarning = true - } - } - } - } - - getApiKey() { - const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]; - let apiKey = myNode.apiKey; - return apiKey; - } - - clearSelection() { - window.getSelection().removeAllRanges() - window.parent.getSelection().removeAllRanges() - } - - _textMenu(event) { - const getSelectedText = () => { - var text = '' - if (typeof window.getSelection != 'undefined') { - text = window.getSelection().toString() - } else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') { - text = this.shadowRoot.selection.createRange().text - } - return text - } - - const checkSelectedTextAndShowMenu = () => { - let selectedText = getSelectedText() - if (selectedText && typeof selectedText === 'string') { - let _eve = { - pageX: event.pageX, - pageY: event.pageY, - clientX: event.clientX, - clientY: event.clientY, - } - let textMenuObject = { - selectedText: selectedText, - eventObject: _eve, - isFrame: true, - } - parentEpml.request('openCopyTextMenu', textMenuObject) - } - } - checkSelectedTextAndShowMenu() - } - - clearTradeBotForm() { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value = this.initialBotAmount - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value = this.initialAmount - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.initialBotAmount - this.autoBuyBtnDisable = true - } - - isEmptyArray(arr) { - if (!arr) { - return true - } - return arr.length === 0 - } - - round(number) { - let result = (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8) - return result - } - - inlineWorker(passedFunction, modifiers) { - let parsedFunction = `` - - modifiers.forEach((modifier) => { - let regex = new RegExp(modifier.searchValue, 'g') - parsedFunction = parsedFunction.length === 0 ? `(function ${passedFunction.toString().trim().replace(regex, modifier.replaceValue)})()` : parsedFunction.toString().trim().replace(regex, modifier.replaceValue) - }) - - const workerUrl = URL.createObjectURL(new Blob([parsedFunction], { type: 'text/javascript' })) - const worker = new Worker(workerUrl) - URL.revokeObjectURL(workerUrl) - return worker - } - - clearPaneCache() { - this._openOrdersGrid.clearCache() - this._myOrdersGrid.clearCache() - } - - createConnection() { - if (workers.get(this.selectedCoin).tradesConnectedWorker !== null) { - this.isLoadingOpenTrades = false - return - } - - const handleMessage = (message) => { - switch (message.type) { - case 'TRADE_OFFERS': - if (!message.isRestarted) { - this.listedCoins.get(this.selectedCoin).tradeOffersSocketCounter = message.counter - this.processTradeOffers(JSON.parse(message.data)) - this.listedCoins.get(this.selectedCoin).tradeOffersSocketCounter === 1 ? this.clearPaneCache() : null - workers.get(this.selectedCoin).tradesConnectedWorker.postMessage(this.listedCoins.get(this.selectedCoin).openOrders) - workers.get(this.selectedCoin).tradesConnectedWorker.postMessage({ type: "open_orders", content: this.listedCoins.get(this.selectedCoin).openOrders }) - } - return null - case 'TRADE_BOT': - if (!message.isRestarted) this.processTradeBotStates(JSON.parse(message.data)) - return null - case 'PRESENCE': - this.listedCoins.get(message.data.relatedCoin).openOrders = message.data.offers - this.listedCoins.get(message.data.relatedCoin).openFilteredOrders = message.data.filteredOffers - this.reRenderOpenFilteredOrders() - return null - default: - break - } - } - - let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] - let nodeUrl = myNode.domain + ':' + myNode.port - - const modifiers = [ - { searchValue: 'NODEURL', replaceValue: nodeUrl }, - { searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin }, - ] - - workers.get(this.selectedCoin).tradesConnectedWorker = this.inlineWorker(this.initSocket, modifiers) - - workers.get(this.selectedCoin).tradesConnectedWorker.addEventListener('message', function (event) { handleMessage(event.data) }, { passive: true }) - - workers.get(this.selectedCoin).tradesConnectedWorker.postMessage({ type: "set_coin", content: this.selectedCoin }) - - } -} - -window.customElements.define('trade-bot-doge', TradeBotDOGE) \ No newline at end of file diff --git a/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-ltc/index.html b/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-ltc/index.html deleted file mode 100644 index b9666aa2..00000000 --- a/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-ltc/index.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-ltc/trade-bot-ltc.src.js b/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-ltc/trade-bot-ltc.src.js deleted file mode 100644 index 7955c5c0..00000000 --- a/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-ltc/trade-bot-ltc.src.js +++ /dev/null @@ -1,2155 +0,0 @@ -import { LitElement, html, css } from 'lit' -import { render } from 'lit/html.js' -import { Epml } from '../../../../epml.js' -import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate' - -registerTranslateConfig({ - loader: lang => fetch(`/language/${lang}.json`).then(res => res.json()) -}) - -import '@material/mwc-button' -import '@material/mwc-textfield' -import '@material/mwc-icon' -import '@material/mwc-icon-button' -import '@material/mwc-dialog' -import '@material/mwc-tab-bar' -import '@material/mwc-tab' -import '@material/mwc-list/mwc-list-item' -import '@material/mwc-select' -import '@polymer/iron-icons/iron-icons.js' -import '@polymer/paper-icon-button/paper-icon-button.js' -import '@polymer/paper-spinner/paper-spinner-lite.js' -import '@vaadin/grid' -import '@vaadin/grid/vaadin-grid-sorter' - -const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }) - -let workers = new Map() - -class TradeBotLTC extends LitElement { - static get properties() { - return { - selectedAddress: { type: Object }, - config: { type: Object }, - listedCoins: { type: Map }, - sellBtnDisable: { type: Boolean }, - isSellLoading: { type: Boolean }, - isBuyLoading: { type: Boolean }, - buyBtnDisable: { type: Boolean }, - autoBuyWarning: { type: Boolean }, - autoBuyBtnDisable: { type: Boolean }, - autoBuyBotDisable: { type: Boolean }, - initialAmount: { type: Number }, - cancelBtnDisable: { type: Boolean }, - cancelStuckOfferBtnDisable: { type: Boolean }, - selectedCoin: { type: String }, - isLoadingHistoricTrades: { type: Boolean }, - isLoadingOpenTrades: { type: Boolean }, - isLoadingMyOpenOrders: { type: Boolean }, - showGetWalletBance: { type: Boolean }, - showAddAutoBuy: { type: Boolean }, - theme: { type: String, reflect: true }, - ltcWallet: { type: String }, - qortltc: { type: Number }, - ltcqort: { type: Number }, - tradeBotLtcBook: { type: Array }, - tradesLtcQortal: { type: Array }, - doneTradesLtcQortal: { type: Array }, - tradesAvailableLtcQortal: { type: Array }, - tradeBotLtcQortal: { type: Array }, - tradeBotAvailableLtcQortal: { type: Array }, - checkAlice: { type: String }, - botBuyAtAddress: { type: String }, - reAddAmount: { type: Number }, - reAddPrice: { type: Number } - } - } - - static get styles() { - return css` - * { - --mdc-theme-primary: rgb(3, 169, 244); - --mdc-theme-secondary: var(--mdc-theme-primary); - --mdc-theme-error: rgb(255, 89, 89); - --mdc-text-field-outlined-idle-border-color: var(--txtfieldborder); - --mdc-text-field-outlined-hover-border-color: var(--txtfieldhoverborder); - --mdc-text-field-label-ink-color: var(--black); - --mdc-text-field-ink-color: var(--black); - --mdc-select-outlined-idle-border-color: var(--txtfieldborder); - --mdc-select-outlined-hover-border-color: var(--txtfieldhoverborder); - --mdc-select-label-ink-color: var(--black); - --mdc-select-ink-color: var(--black); - --mdc-theme-surface: var(--white); - --mdc-dialog-content-ink-color: var(--black); - --mdc-dialog-shape-radius: 25px; - --paper-input-container-focus-color: var(--mdc-theme-primary); - --lumo-primary-text-color: rgb(0, 167, 245); - --lumo-primary-color-50pct: rgba(0, 167, 245, 0.5); - --lumo-primary-color-10pct: rgba(0, 167, 245, 0.1); - --lumo-primary-color: hsl(199, 100%, 48%); - --lumo-base-color: var(--white); - --lumo-body-text-color: var(--black); - --lumo-secondary-text-color: var(--sectxt); - --lumo-contrast-60pct: var(--vdicon); - --_lumo-grid-border-color: var(--border); - --_lumo-grid-secondary-border-color: var(--border2); - } - paper-spinner-lite { - height: 30px; - width: 30px; - --paper-spinner-color: var(--mdc-theme-primary); - --paper-spinner-stroke-width: 3px; - } - mwc-tab-bar { - --mdc-text-transform: none; - --mdc-tab-color-default: var(--black); - --mdc-tab-text-label-color-default: var(--black); - } - #tabs-1 { - --mdc-tab-height: 42px; - border-left: 1px solid var(--tradeborder); - border-top: 1px solid var(--tradeborder); - border-right: 1px solid var(--tradeborder); - color: var(--black); - } - #tab-buy[active] { - --mdc-theme-primary: rgba(55, 160, 51, 0.9); - } - #tabs-1-content { - height: 100%; - padding-bottom: 10px; - } - #tabs-1-content > div { - height: 100%; - border: 1px solid var(--tradeborder); - } - #tabs-1-content .card { - border: none; - } - #tabs-1-content .btn-clear { - --mdc-icon-button-size: 32px; - color: var(--black); - } - .btn-clear-bot { - --mdc-icon-button-size: 32px; - color: var(--black); - float: right; - } - .btn-info { - color: var(--black); - --mdc-icon-size: 16px; - padding-top: 3px; - } - #tab-sell[active] { - --mdc-theme-primary: rgb(255, 89, 89); - } - #trade-portal-page { - background: var(--white); - padding: 12px 24px; - } - .divCard { - border: 1px solid var(--black); - padding: 1em; - box-shadow: 0 0.3px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 1px -1px rgba(0, 0, 0, 0.12), 0 1px 2px 0 rgba(0, 0, 0, 0.2); - } - h2 { - margin: 10px 0; - } - - h4 { - margin: 5px 0; - } - - p { - font-size: 14px; - line-height: 21px; - } - - .card-body { - background-color: var(--white); - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - min-height: 100vh; - margin: 0; - } - - .card-container { - background-color: var(--white); - border-radius: 5px; - color: var(--black); - padding-top: 30px; - position: relative; - width: 350px; - max-width: 100%; - text-align: center; - } - - .card-container .level { - color: #ffffff; - background-color: #03a9f4; - border-radius: 3px; - font-size: 14px; - font-weight: bold; - padding: 3px 7px; - position: absolute; - top: 30px; - left: 30px; - } - - .card-container .founder { - color: #ffffff; - background-color: #03a9f4; - border-radius: 3px; - font-size: 14px; - font-weight: bold; - padding: 3px 7px; - position: absolute; - top: 30px; - right: 30px; - } - - .card-container .round { - width: 96px; - height: 96px; - border: 1px solid #03a9f4; - border-radius: 50%; - padding: 2px; - } - - .card-container .badge { - width: 200px; - height: 135px; - border: 1px solid transparent; - border-radius: 10%; - padding: 2px; - } - - .userdata { - background-color: #1F1A36; - text-align: left; - padding: 15px; - margin-top: 30px; - } - - .userdata ul { - list-style-type: none; - margin: 0; - padding: 0; - } - - .userdata ul li { - border: 1px solid #2D2747; - border-radius: 2px; - display: inline-block; - font-size: 12px; - margin: 0 7px 7px 0; - padding: 7px; - } - - h2, - h3, - h4, - h5 { - color: var(--black); - font-weight: 400; - } - header { - display: flex; - flex: 0 1 auto; - align-items: center; - justify-content: center; - padding: 0px 10px; - font-size: 16px; - color: var(--white); - background-color: var(--tradehead); - border-left: 1px solid var(--tradeborder); - border-top: 1px solid var(--tradeborder); - border-right: 1px solid var(--tradeborder); - min-height: 40px; - } - p { - margin-bottom: 12px; - } - #trade-portal { - max-width: 100vw; - margin-left: auto; - margin-right: auto; - } - .box { - margin: 0; - padding: 0; - display: flex; - flex-flow: column; - height: 100%; - } - .box-bot { - margin: 0; - padding: 0; - display: flex; - flex-flow: column; - height: 150px; - } - #first-trade-section { - margin-bottom: 10px; - } - #first-trade-section > div { - } - #second-trade-section { - margin-bottom: 10px; - } - #second-trade-section > div { - } - #third-trade-section { - margin-bottom: 10px; - } - #third-trade-section > div { - } - .trade-chart { - background-color: var(--white); - border: 2px #ddd solid; - text-align: center; - } - .open-trades { - text-align: center; - } - .open-market-container { - text-align: center; - } - .trade-bot-container { - text-align: center; - } - .no-last-seen { - background: rgb(255, 89, 89); - padding: 9px 1.3px; - border-radius: 50%; - width: 1rem; - margin: 0 auto; - } - .card { - padding: 1em; - border: 1px var(--tradeborder) solid; - flex: 1 1 auto; - display: flex; - flex-flow: column; - justify-content: space-evenly; - min-height: inherit; - } - .card-bot { - padding: 1em; - flex: 1 1 auto; - display: flex; - flex-flow: column; - justify-content: space-evenly; - width: 350px; - min-height: inherit; - } - .cancel { - --mdc-theme-primary: rgb(255, 89, 89); - } - .border-wrapper { - border: 1px var(--tradeborder) solid; - overflow: hidden; - } - .amt-text { - color: var(--tradehave); - font-size: 15px; - margin-top: 5px; - margin-bottom: 12px; - } - .exchange { - color: var(--black); - font-size: 18px; - font-weight: bold; - margin-top: 5px; - margin-bottom: 10px; - } - .clear-button { - display: inline; - float: right; - margin-bottom: 5px; - } - .exhcnage-text { - display: inline; - float: left; - margin-bottom: 5px; - } - .balance-text { - display: inline; - float: right; - margin-bottom: 5px; - } - .fee-text { - display: inline; - float: left; - margin-bottom: 5px; - } - .tab-text { - color: var(--tradehave); - font-size: 12px; - text-align: left; - margin-top: 2px; - margin-bottom: -12px; - } - .historic-trades { - text-align: center; - } - .my-open-orders { - text-align: center; - } - .my-historic-trades { - text-align: center; - } - .buttons { - width: auto !important; - } - .buy-button { - --mdc-theme-primary: rgba(55, 160, 51, 0.9); - } - .sell-button { - --mdc-theme-primary: rgb(255, 89, 89); - } - .trade-bot-button { - margin-top: 20px; - margin-bottom: 20px; - --mdc-theme-primary: rgba(55, 160, 51, 0.9); - } - .full-width { - background-color: var(--white); - border: 2px var(--black); - height: 200px; - text-align: center; - } - vaading-grid { - font-size: .8em; - } - vaadin-grid-column { - flex-grow: 1; - } - .loadingContainer { - height: 100%; - width: 100%; - } - .loading, - .loading:after { - border-radius: 50%; - width: 5em; - height: 5em; - } - .loading { - margin: 10px auto; - border-width: .6em; - border-style: solid; - border-color: rgba(3, 169, 244, 0.2) rgba(3, 169, 244, 0.2) rgba(3, 169, 244, 0.2) rgb(3, 169, 244); - font-size: 10px; - position: relative; - text-indent: -9999em; - transform: translateZ(0px); - animation: 1.1s linear 0s infinite normal none running loadingAnimation; - } - mwc-select#coinSelectionMenu { - font-size: 24px; - width:220px; - } - mwc-select#coinSelectionMenu mwc-list-item { - line-height: 30px; - } - .coinName::before { - content: ""; - display: inline-block; - height: 26px; - width: 45px; - position: absolute; - background-repeat: no-repeat; - background-size: cover; - left: 10px; - top: 10px; - } - .coinName { - display: inline-block; - height: 26px; - padding-left: 45px; - } - .warning-text { - animation: blinker 1.5s linear infinite; - display: inline; - float: left; - margin-bottom: 5px; - color: rgb(255, 89, 89); - } - .warning-bot-text { - animation: blinker 1.5s linear infinite; - display: inline; - text-align: center; - color: rgb(255, 89, 89); - } - .red { - --mdc-theme-primary: #F44336; - } - @-webkit-keyframes loadingAnimation { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - @keyframes loadingAnimation { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - @keyframes blinker { - 50% { - opacity: 0; - } - } - @media (min-width: 701px) { - * { - } - #trade-portal {} - #first-trade-section { - display: grid; - grid-template-columns:1fr 4fr 1fr; - grid-auto-rows: max(350px); - column-gap: 0.5em; - row-gap: 0.4em; - justify-items: stretch; - align-items: stretch; - margin-bottom: 10px; - } - #second-trade-section { - display: grid; - grid-template-columns:1fr 4fr 1fr; - grid-auto-rows: max(350px); - column-gap: 0.5em; - row-gap: 0.4em; - justify-items: stretch; - align-items: stretch; - margin-bottom: 10px; - } - #third-trade-section { - display: grid; - grid-template-columns: 1fr 4fr 1fr; - grid-auto-rows: max(150px); - column-gap: 0.5em; - row-gap: 0.4em; - justify-items: stretch; - align-items: stretch; - margin-bottom: 10px; - } - #fourth-trade-section { - display: grid; - grid-template-columns: 1fr 4fr 1fr; - grid-auto-rows: max(150px); - column-gap: 0.5em; - row-gap: 0.4em; - justify-items: stretch; - align-items: stretch; - margin-bottom: 10px; - } - } - ` - } - - constructor() { - super() - let qortal = { - name: "QORTAL", - balance: "0", - coinCode: "QORT", - coinAmount: this.amountString, - tradeFee: "0.002" - } - - let litecoin = { - name: "LITECOIN", - balance: "0", - coinCode: "LTC", - openOrders: [], - openFilteredOrders: [], - historicTrades: [], - myOrders: [], - myHistoricTrades: [], - myOfferingOrders: [], - openTradeOrders: null, - tradeOffersSocketCounter: 1, - coinAmount: this.amountString, - tradeFee: "~0.00005" - } - - this.listedCoins = new Map() - this.listedCoins.set("QORTAL", qortal) - this.listedCoins.set("LITECOIN", litecoin) - - workers.set("QORTAL", { - tradesConnectedWorker: null, - handleStuckTradesConnectedWorker: null - }) - - workers.set("LITECOIN", { - tradesConnectedWorker: null, - handleStuckTradesConnectedWorker: null - }) - - this.selectedCoin = "LITECOIN" - this.selectedAddress = {} - this.config = {} - this.sellBtnDisable = false - this.isSellLoading = false - this.buyBtnDisable = true - this.autoBuyWarning = false - this.autoBuyBtnDisable = true - this.autoBuyBotDisable = false - this.isBuyLoading = false - this.initialAmount = 0 - this.cancelBtnDisable = false - this.cancelStuckOfferBtnDisable = false - this.isLoadingHistoricTrades = true - this.isLoadingOpenTrades = true - this.isLoadingMyOpenOrders = false - this.showGetWalletBance = true - this.showAddAutoBuy = false - this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light' - this.ltcWallet = '' - this.qortltc = 0 - this.ltcqort = 0 - this.tradeBotLtcBook = [] - this.tradesLtcQortal = [] - this.doneTradesLtcQortal = [] - this.tradesAvailableLtcQortal = [] - this.tradeBotLtcQortal = [] - this.tradeBotAvailableLtcQortal = [] - this.checkAlice = '' - this.botBuyAtAddress = '' - this.reAddAmount = 0 - this.reAddPrice = 0 - } - - openTradesTemplate() { - return html` -
-
-
${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange42")}
-
-
${translate("login.loading")}
- - { - render(html`${this.round(data.item.qortAmount)}`, root) - }} - > - - { - render(html`${this.round(data.item.price)}`, root) - }} - > - - { - render(html`${data.item.foreignAmount}`, root) - }} - > - - { - render(html`${data.item.qortalCreator}`, root) - }} - > - - -
-
-
- ` - } - - myOpenOrdersTemplate() { - return html` -
-
-
${translate("tradepage.tchange36")}
-
-
${translate("login.loading")}
- - { - const dateString = new Date(data.item.timestamp).toLocaleString() - render(html`${dateString}`, root) - }} - > - - { - render(html` ${data.item._tradeState} `, root) - }} - > - - { - const price = this.round(parseFloat(data.item.foreignAmount) / parseFloat(data.item.qortAmount)) - render(html`${price}`, root) - }} - > - - - - - - -
-
-
- ` - } - - myDoneTradesTemplate() { - return html` -
-
-
${translate("tradepage.tchange43")} (${this.listedCoins.get(this.selectedCoin).coinCode})
-
-
${translate("login.loading")}
- - { - const dateString = new Date(data.item.timestamp).toLocaleString() - render(html`${dateString}`, root) - }} - > - - { - return render(html` ${translate("tradepage.tchange32")} `, root) - }} - > - - { - const price = this.round(parseFloat(data.item.foreignAmount) / parseFloat(data.item.qortAmount)) - render(html`${price}`, root) - }} - > - - - - { - render(html` ${data.item.foreignAmount} `, root) - }} - > - - -
-
-
- ` - } - - myHistoricTradesTemplate() { - return html` -
-
-
${translate("tradepage.tchange4")}
-
- - { - const dateString = new Date(data.item.timestamp).toLocaleString() - render(html`${dateString}`, root) - }} - > - - { - if (data.item.mode === 'SOLD') return render(html` ${translate("tradepage.tchange31")} `, root) - if (data.item.mode === 'BOUGHT') return render(html` ${translate("tradepage.tchange32")} `, root) - return render(html` ${data.item.mode} `, root) - }} - > - - { - const price = this.round(parseFloat(data.item.foreignAmount) / parseFloat(data.item.qortAmount)) - render(html`${price}`, root) - }} - > - - - - { - render(html` ${data.item.foreignAmount} `, root) - }} - > - - -
-
-
- ` - } - - tradeBotLTCTemplate() { - return html` -
-
-
${translate("tradepage.tchange39")} ${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT
-
- - { - render(html`${data.item.botLtcQortAmount}`, root) - }} - > - - { - render(html`${data.item.botLtcPrice}`, root) - }} - > - - { - const totalCoins = this.round(parseFloat(data.item.botLtcQortAmount) * parseFloat(data.item.botLtcPrice)) - const myBotFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) - if (Number(myBotFunds) > Number(totalCoins)) { - this.autoBuyBotDisable = false - render(html`${totalCoins}`, root) - } else { - this.autoBuyBotDisable = true - render(html`${totalCoins}`, root) - } - }} - > - - { - render(html` this.removeLTCTradebook()}>delete ${translate("nodepage.nchange12")}`, root) - }} - > - - - ${this.isEmptyArray(this.tradeBotLtcBook) ? html` - - ${translate("tradepage.tchange38")} ${translate("tradepage.tchange39")} - - `: ''} -
- ${this.autoBuyBotDisable ? html` -
${this.renderBotWarning()}
- `: ''} -
-
- ` - } - - render() { - return html` -
-
-
-
- ${this.openTradesTemplate()} -
-
-
-
- ${this.myDoneTradesTemplate()} -
-
-
-
- ${this.myOpenOrdersTemplate()} -
-
-
-
- ${this.showAutoBuyGrid()} -
-
-
-

${translate("tradepage.tchange33")} ${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange40")}

-

1 QORT = ${this.exchangeRateQort()} ${this.listedCoins.get(this.selectedCoin).coinCode}

-
-
-
- - -
-

${this.renderFetchText()}

-
-
-
-

${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT

-
-
-
-
${this.renderWarning()}
- -
- ${translate("tradepage.tchange8")} (QORT)* -

- - -

- ${translate("tradepage.tchange14")} (${this.listedCoins.get(this.selectedCoin).coinCode})* -

- - -

- ${translate("tradepage.tchange10")} (${this.listedCoins.get(this.selectedCoin).coinCode})* -

- - -

- - ${translate("tradepage.tchange16")}: ${this.listedCoins.get(this.selectedCoin).balance} ${this.listedCoins.get(this.selectedCoin).coinCode} - -
-
- - ${translate("tradepage.tchange38")} ${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange39")} - -
-
-
- ${translate("general.close")} -
- ` - } - - async firstUpdated() { - - let _this = this - - this.changeTheme() - this.changeLanguage() - await this.updateWalletBalance() - - this._openOrdersGrid = this.shadowRoot.getElementById('openOrdersGrid') - - this._openOrdersGrid.querySelector('#priceColumn').headerRenderer = function (root) { - const priceString = get("tradepage.tchange9") - root.innerHTML = '' + priceString + ' (' + _this.listedCoins.get(_this.selectedCoin).coinCode + ')' - } - - this._openOrdersGrid.querySelector('#qortAmountColumn').headerRenderer = function (root) { - const amountString = get("tradepage.tchange8") - root.innerHTML = '' + amountString + ' (QORT)' - } - - this._myOrdersGrid = this.shadowRoot.getElementById('myOrdersGrid') - this._myHistoricTradesGrid = this.shadowRoot.getElementById('myHistoricTradesGrid') - - const delay = ms => new Promise(res => setTimeout(res, ms)) - - const getQortLtcPrice = () => { - parentEpml.request("apiCall", { url: `/crosschain/price/LITECOIN?inverse=true` }).then((res) => { - setTimeout(() => { this.qortltc = (Number(res) / 1e8).toFixed(8) }, 1) - }) - setTimeout(getQortLtcPrice, 300000) - } - - const filterMyPriceTradesLTC = async () => { - const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] - const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port - const tradeBotLtcQortalUrl = `${nodeUrl}/crosschain/tradebot?foreignBlockchain=LITECOIN&apiKey=${this.getApiKey()}` - const waitFor = ms => new Promise(res => setTimeout(res, ms)) - let timer - - const tradeBotLtcQortal = await fetch(tradeBotLtcQortalUrl).then(response => { - return response.json() - }) - - this.tradeBotLtcQortal = tradeBotLtcQortal - - await waitFor(1000) - - if (this.isEmptyArray(this.tradeBotLtcBook) === true) { - clearTimeout(timer) - timer = setTimeout(filterMyPriceTradesLTC, 180000) - return - } else { - clearTimeout(timer) - timer = setTimeout(filterMyPriceTradesLTC, 180000) - - this.tradeBotAvailableLtcQortal = this.listedCoins.get(this.selectedCoin).openFilteredOrders.map(item => { - const listprice = parseFloat(item.price) - const listamount = parseFloat(item.qortAmount) - const checkprice = parseFloat(this.tradeBotLtcBook[0].botLtcPrice) - const checkamount = parseFloat(this.tradeBotLtcBook[0].botLtcQortAmount) - if (Number(listprice) <= Number(checkprice) && Number(listamount) <= Number(checkamount)) { - return { - qortAmount: item.qortAmount, - price: item.price, - foreignAmount: item.foreignAmount, - qortalCreator: item.qortalCreator, - qortalAtAddress: item.qortalAtAddress - } - } - }).filter(item => !!item) - - this.tradeBotAvailableLtcQortal.sort((a, b) => parseFloat(a.price) - parseFloat(b.price)) - - if (this.isEmptyArray(this.tradeBotAvailableLtcQortal) === true) { - return - } else { - this.checkAlice = this.tradeBotAvailableLtcQortal[0].qortalAtAddress - } - - await waitFor(1000) - - if (this.tradeBotLtcQortal.some(item => item.atAddress === this.checkAlice)) { - return - } else { - this.tradesAvailableLtcQortal = this.tradeBotAvailableLtcQortal - } - } - - await waitFor(1000) - - if (this.isEmptyArray(this.tradesAvailableLtcQortal) === true) { - return - } else { - const botprice = this.round(parseFloat(this.tradeBotLtcBook[0].botLtcPrice)) - const changeamount = parseFloat(this.tradeBotLtcBook[0].botLtcQortAmount) - const reduceamount = parseFloat(this.tradesAvailableLtcQortal[0].qortAmount) - const tradeataddress = this.tradesAvailableLtcQortal[0].qortalAtAddress - const newamount = this.round(parseFloat(changeamount - reduceamount)) - - this.reAddAmount = this.round(parseFloat(this.tradeBotLtcBook[0].botLtcQortAmount)) - this.reAddPrice = this.round(parseFloat(this.tradeBotLtcBook[0].botLtcPrice)) - - localStorage.removeItem(this.ltcWallet) - localStorage.setItem(this.ltcWallet, "") - - var oldLtcTradebook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]") - - const newLtcTradebookItem = { - botLtcQortAmount: newamount, - botLtcPrice: botprice - } - - oldLtcTradebook.push(newLtcTradebookItem) - - localStorage.setItem(this.ltcWallet, JSON.stringify(oldLtcTradebook)) - - this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]") - - await waitFor(1000) - - this.botBuyAtAddress = tradeataddress - - this.buyAction() - - if (this.isEmptyArray(this.tradeBotLtcBook) === true) { - return - } else { - const botamount = parseFloat(this.tradeBotLtcBook[0].botLtcQortAmount) - - if (Number(botamount) === 0) { - this.removeLTCTradebook() - } else { - this.tradeBotLtcBook = this.tradeBotLtcBook - } - } - - if (this.isEmptyArray(this.tradeBotLtcBook) === true) { - return - } else { - const checkBotFunds = this.round(parseFloat(this.tradeBotLtcBook[0].botLtcQortAmount) * parseFloat(this.tradeBotLtcBook[0].botLtcPrice)) - const myBotFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) - - if (Number(myBotFunds) < Number(checkBotFunds)) { - this.removeLTCTradebook() - } else { - this.tradeBotLtcBook = this.tradeBotLtcBook - } - } - } - } - - const getDoneTradeLTC = async () => { - this.isLoadingDoneTrades = true - const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] - const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port - const doneLtcQortalUrl = `${nodeUrl}/crosschain/trades?foreignBlockchain=LITECOIN&minimumTimestamp=1597310000000&limit=0&reverse=true` - const myAddress = window.parent.reduxStore.getState().app.selectedAddress.address - - const doneLtcQortal = await fetch(doneLtcQortalUrl).then(response => { - return response.json() - }) - - this.doneTradesLtcQortal = doneLtcQortal.map(item => { - const searchAddress = item.buyerReceivingAddress - if (searchAddress == myAddress) { - return { - timestamp: item.tradeTimestamp, - foreignAmount: item.foreignAmount, - qortAmount: item.qortAmount - } - } - }).filter(item => !!item) - - this.isLoadingDoneTrades = false - setTimeout(getDoneTradeLTC, 600000) - } - - window.addEventListener('contextmenu', (event) => { - event.preventDefault() - this._textMenu(event)}, - { passive: true } - ) - - window.addEventListener('click', () => { - parentEpml.request('closeCopyTextMenu', null)}, - { passive: true } - ) - - window.addEventListener('storage', () => { - const checkLanguage = localStorage.getItem('qortalLanguage') - const checkTheme = localStorage.getItem('qortalTheme') - - use(checkLanguage) - - if (checkTheme === 'dark') { - this.theme = 'dark' - } else { - this.theme = 'light' - } - document.querySelector('html').setAttribute('theme', this.theme) - }) - - window.onkeyup = (e) => { - if (e.keyCode === 27) parentEpml.request('closeCopyTextMenu', null) - } - - this.ltcWallet = window.parent.reduxStore.getState().app.selectedAddress.ltcWallet.address - - let configLoaded = false - - parentEpml.ready().then(() => { - parentEpml.subscribe('selected_address', async (selectedAddress) => { - this.selectedAddress = {} - selectedAddress = JSON.parse(selectedAddress) - if (!selectedAddress || Object.entries(selectedAddress).length === 0) return - this.selectedAddress = selectedAddress - this.ltcWwallet = window.parent.reduxStore.getState().app.selectedAddress.ltcWallet.address - await this.updateAccountBalance() - await this.ltcTradebook() - }) - - parentEpml.subscribe('config', (c) => { - if (!configLoaded) { - setTimeout(getQortLtcPrice, 1) - setTimeout(getDoneTradeLTC, 1) - configLoaded = true - } - this.config = JSON.parse(c) - }) - - parentEpml.subscribe('copy_menu_switch', async (value) => { - if (value === 'false' && window.getSelection().toString().length !== 0) this.clearSelection() - }) - this.setForeignCoin() - }) - parentEpml.imReady() - - setTimeout(() => this.shadowRoot.querySelector('[slot="vaadin-grid-cell-content-3"]').setAttribute('title', 'Last Seen'), 3000) - - this.ltcTradebook() - await delay(3000) - filterMyPriceTradesLTC() - } - - changeTheme() { - const checkTheme = localStorage.getItem('qortalTheme') - if (checkTheme === 'dark') { - this.theme = 'dark'; - } else { - this.theme = 'light'; - } - document.querySelector('html').setAttribute('theme', this.theme); - } - - changeLanguage() { - const checkLanguage = localStorage.getItem('qortalLanguage') - - if (checkLanguage === null || checkLanguage.length === 0) { - localStorage.setItem('qortalLanguage', 'us') - use('us') - } else { - use(checkLanguage) - } - } - - renderFetchText() { - return html`${translate("walletpage.wchange1")}` - } - - renderWarning() { - return html`NOT ENOUGH ${this.listedCoins.get(this.selectedCoin).coinCode}` - } - - renderBotWarning() { - return html`NOT ENOUGH ${this.listedCoins.get(this.selectedCoin).coinCode} ! AUTO BUY BOT IS STOPPED` - } - - exchangeRateQort() { - return html`${this.qortltc}` - } - - showAutoBuyGrid() { - return html`${this.tradeBotLTCTemplate()}` - } - - showAddToAutoBuyStore() { - this.addToLTCTradebook() - } - - ltcTradebook() { - if (localStorage.getItem(this.ltcWallet) === null) { - localStorage.setItem(this.ltcWallet, "") - } else { - this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]") - } - } - - addToLTCTradebook() { - const addBotLtcQortAmount = this.shadowRoot.getElementById('autoBuyLTCQortAmountInput').value - const addBotLtcPrice = this.shadowRoot.getElementById('autoBuyLTCPriceInput').value - const addLtcQortAmount = this.round(parseFloat(addBotLtcQortAmount)) - const addLtcPrice = this.round(parseFloat(addBotLtcPrice)) - - var oldLtcTradebook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]") - - const newLtcTradebookItem = { - botLtcQortAmount: addLtcQortAmount, - botLtcPrice: addLtcPrice - } - - oldLtcTradebook.push(newLtcTradebookItem) - - localStorage.setItem(this.ltcWallet, JSON.stringify(oldLtcTradebook)) - - let ltctradebookstring = get("tradepage.tchange44") - parentEpml.request('showSnackBar', `${ltctradebookstring}`) - - this.closeLTCTradebookDialog() - this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]") - this.firstUpdated() - } - - closeLTCTradebookDialog() { - this.shadowRoot.querySelector('#tradeBotLTCAddDialog').close() - this.clearTradeBotForm() - } - - removeLTCTradebook() { - localStorage.removeItem(this.ltcWallet) - localStorage.setItem(this.ltcWallet, "") - this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]") - - this.autoBuyBotDisable = false - - let ltcstring = get("tradepage.tchange41") - parentEpml.request('showSnackBar', `${ltcstring}`) - this.tradesAvailableLtcQortal = [] - } - - exchangeRateForeign() { - parentEpml.request('apiCall', { - url: `/crosschain/price/LITECOIN?inverse=false` - }).then((res) => { - this.ltcqort = (Number(res) / 1e8).toFixed(8) - }) - return html`${this.ltcqort}` - } - - async updateWalletBalance() { - let _url = `/crosschain/ltc/walletbalance?apiKey=${this.getApiKey()}` - let _body = window.parent.reduxStore.getState().app.selectedAddress.ltcWallet.derivedMasterPublicKey - - this.showGetWalletBance = true - this.showAddAutoBuy = false - - await parentEpml.request('apiCall', { - url: _url, - method: 'POST', - body: _body, - }).then((res) => { - if (isNaN(Number(res))) { - let snack1string = get("tradepage.tchange30") - parentEpml.request('showSnackBar', `${snack1string}`) - } else { - this.listedCoins.get(this.selectedCoin).balance = (Number(res) / 1e8).toFixed(8) - } - }) - - this.showGetWalletBance = false - this.showAddAutoBuy = true - } - - async setForeignCoin() { - let _this = this - this.selectedCoin = "LITECOIN" - - this.isLoadingOpenTrades = true - await this.createConnection() - - this._openOrdersGrid.querySelector('#priceColumn').headerRenderer = function (root) { - const priceString2 = get("tradepage.tchange9") - root.innerHTML = '' + priceString2 + ' (' + _this.listedCoins.get(_this.selectedCoin).coinCode + ')' - } - - this.autoBuyBotDisable = false - await this.updateWalletBalance() - } - - async reRenderOpenFilteredOrders() { - this.requestUpdate() - await this.updateComplete - this.isLoadingOpenTrades = false - } - - async reRenderMyOpenOrders() { - this.requestUpdate() - await this.updateComplete - this.isLoadingMyOpenOrders = false - } - - addAutoBuyAction() { - this.autoBuyWarning = false - this.clearTradeBotForm() - this.shadowRoot.querySelector('#tradeBot' + this.listedCoins.get(this.selectedCoin).coinCode + 'AddDialog').show() - } - - checkTradeBotValues() { - const checkTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value - const checkTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value - const checkAmount = this.round(parseFloat(checkTradeBotAmountInput)) - const checkPrice = this.round(parseFloat(checkTradeBotPriceInput)) - - if (Number(checkAmount) === 0) { - let amountString = get("tradepage.tchange34") - parentEpml.request('showSnackBar', `${amountString}`) - } else if (Number(checkPrice) === 0) { - let priceString = get("tradepage.tchange35") - parentEpml.request('showSnackBar', `${priceString}`) - } else { - this.showAddToAutoBuyStore() - } - } - - processOfferingTrade(offer) { - try { - if(this.listedCoins.get(offer.foreignBlockchain).name!='') { - const offerItem = { - ...offer, - qortAmount: parseFloat(offer.qortAmount), - price: parseFloat(offer.foreignAmount) / parseFloat(offer.qortAmount), - } - const addOffer = () => { - this.listedCoins.get(offer.foreignBlockchain).openOrders.unshift(offerItem) - } - const initOffer = () => { - this.listedCoins.get(offer.foreignBlockchain).openOrders.push(offerItem) - } - this.listedCoins.get(offer.foreignBlockchain).openOrders.length === 0 ? initOffer() : addOffer() - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._openOrdersGrid.clearCache() : null - } - } catch(e) { - console.log("Error adding offer from "+offer.foreignBlockchain) - } - } - - processRedeemedTrade(offer) { - try { - if (this.listedCoins.get(offer.foreignBlockchain).name!='') { - - if (offer.qortalCreator === this.selectedAddress.address) { - if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { - this.updateWalletBalance() - } - const offerItem = { - ...offer, - mode: 'SOLD', - } - this._myHistoricTradesGrid.items.unshift(offerItem) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null - } else if (offer.partnerQortalReceivingAddress === this.selectedAddress.address) { - if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { - this.updateWalletBalance() - } - const offerItem = { - ...offer, - mode: 'BOUGHT', - } - this._myHistoricTradesGrid.items.unshift(offerItem) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null - } - const addNewHistoricTrade = () => { - this._historicTradesGrid.items.unshift(offer) - this._historicTradesGrid.clearCache() - } - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? addNewHistoricTrade() : null - - } - } catch(e) { - console.log("Error processing redeemed trade offer from "+offer.foreignBlockchain) - } - } - - processTradingTrade(offer) { - try { - if (this.listedCoins.get(offer.foreignBlockchain).name!='') { - - if (offer.qortalCreator === this.selectedAddress.address && this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { - this.updateWalletBalance() - } - this._openOrdersGrid.items.forEach((item, index) => { - if (item.qortalAtAddress === offer.qortalAtAddress) { - this._openOrdersGrid.items.splice(index, 1) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._openOrdersGrid.clearCache() : null - } - }) - this.listedCoins.get(offer.foreignBlockchain).openOrders = this.listedCoins.get(offer.foreignBlockchain).openOrders.filter((order) => order.qortalAtAddress !== offer.qortalAtAddress) - } - } catch(e) { - console.log("Error processing trading trade offer from "+offer.foreignBlockchain) - } - } - - processRefundedTrade(offer) { - try { - if (this.listedCoins.get(offer.foreignBlockchain).name!='') { - - if (offer.qortalCreator === this.selectedAddress.address) { - if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { - this.updateWalletBalance() - } - this._myHistoricTradesGrid.items.unshift(offer) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null - } - - } - } catch(e) { - console.log("Error processing refunded trade offer from "+offer.foreignBlockchain) - } - } - - processCancelledTrade(offer) { - try { - if (this.listedCoins.get(offer.foreignBlockchain).name!='') { - - if (offer.qortalCreator === this.selectedAddress.address) { - if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { - this.updateWalletBalance() - } - this._myHistoricTradesGrid.items.unshift(offer) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null - } - this._openOrdersGrid.items.forEach((item, index) => { - if (item.qortalAtAddress === offer.qortalAtAddress) { - this._openOrdersGrid.items.splice(index, 1) - this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._openOrdersGrid.clearCache() : null - } - }) - this.listedCoins.get(offer.foreignBlockchain).openOrders = this.listedCoins.get(offer.foreignBlockchain).openOrders.filter((order) => order.qortalAtAddress !== offer.qortalAtAddress) - this._stuckOrdersGrid.items.forEach((item, index) => { - if (item.qortalAtAddress === offer.qortalAtAddress) { - this._stuckOrdersGrid.items.splice(index, 1) - this._stuckOrdersGrid.clearCache() - } - }) - } - } catch(e) { - console.log("Error processing cancelled trade offer from "+offer.foreignBlockchain) - } - } - - /** - * TRADE OFFER STATES or MODE - * - OFFERING - */ - - processTradeOffers(offers) { - offers.forEach((offer) => { - if (offer.mode === 'OFFERING') { - this.processOfferingTrade(offer) - } - }) - } - - processTradeBotStates(tradeStates) { - - const LitecoinACCTv1 = (states) => { - states.reverse() - states.forEach((state) => { - if (state.creatorAddress === this.selectedAddress.address) { - if (state.tradeState == 'ALICE_WAITING_FOR_AT_LOCK') { - this.changeTradeBotState(state, 'BUYING') - } else if (state.tradeState == 'ALICE_DONE') { - this.handleCompletedState(state) - } else if (state.tradeState == 'ALICE_REFUNDING_A') { - this.changeTradeBotState(state, 'REFUNDING') - } else if (state.tradeState == 'ALICE_REFUNDED') { - this.handleCompletedState(state) - } - } - }) - } - - switch (this.selectedCoin) { - case 'LITECOIN': - LitecoinACCTv1(tradeStates) - break - default: - break - } - } - - changeTradeBotState(state, tradeState) { - this.isLoadingMyOpenOrders = true - const stateItem = { - ...state, - _tradeState: tradeState, - } - const item = this._myOrdersGrid.querySelector(`#${state.atAddress}`) - const addStateItem = () => { - this.reRenderMyOpenOrders() - this._myOrdersGrid.items.unshift(stateItem) - this._myOrdersGrid.clearCache() - } - const updateStateItem = () => { - this._myOrdersGrid.items.forEach((item, index) => { - if (item.atAddress === state.atAddress) { - this.reRenderMyOpenOrders() - this._myOrdersGrid.items.splice(index, 1) - this._myOrdersGrid.items.unshift(stateItem) - this._myOrdersGrid.clearCache() - } - }) - } - item ? updateStateItem() : addStateItem() - } - - handleCompletedState(state) { - this._myOrdersGrid.items.forEach((item, index) => { - if (item.atAddress === state.atAddress) { - this.reRenderMyOpenOrders() - this._myOrdersGrid.items.splice(index, 1) - this._myOrdersGrid.clearCache() - } - }) - } - - initSocket() { - let _relatedCoin = "" - let tradePresenceTxns = null - let offeringTrades = null - - self.addEventListener('message', function (event) { - switch (event.data.type) { - case 'open_orders': - offeringTrades = event.data.content - processOffersWithPresence() - break - case 'set_coin': - _relatedCoin = event.data.content - break - default: - break - } - }) - - const lessThanThirtyMinsAgo = (timestamp) => { - const THIRTYMINS = 1000 * 60 * 30 - const thirtyMinsAgo = Date.now() - THIRTYMINS - return timestamp > thirtyMinsAgo - } - - const filterOffersUsingTradePresence = (offeringTrade) => { - return offeringTrade.tradePresenceExpiry > Date.now(); - } - - const processOffersWithPresence = () => { - if (offeringTrades === null) return - - async function asyncForEach(array, callback) { - for (let index = 0; index < array.length; index++) { - await callback(array[index], index, array) - } - } - - const startOfferPresenceMapping = async () => { - - if (tradePresenceTxns !== null) { - await asyncForEach(tradePresenceTxns, async (tradePresence) => { - let offerIndex = offeringTrades.findIndex((offeringTrade) => offeringTrade.qortalCreatorTradeAddress === tradePresence.tradeAddress) - offerIndex !== -1 ? (offeringTrades[offerIndex].tradePresenceExpiry = tradePresence.timestamp) : null - }) - } - - let filteredOffers = offeringTrades.filter((offeringTrade) => filterOffersUsingTradePresence(offeringTrade)) - self.postMessage({ type: 'PRESENCE', data: { offers: offeringTrades, filteredOffers: filteredOffers, relatedCoin: _relatedCoin } }) - } - - startOfferPresenceMapping() - } - - const initTradeOffersWebSocket = (restarted = false) => { - let tradeOffersSocketCounter = 0 - let socketTimeout - let socketLink = `ws://NODEURL/websockets/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN&includeHistoric=true` - const socket = new WebSocket(socketLink) - socket.onopen = () => { - setTimeout(pingSocket, 50) - tradeOffersSocketCounter += 1 - } - socket.onmessage = (e) => { - e.relatedCoin = _relatedCoin - self.postMessage({ - type: 'TRADE_OFFERS', - data: e.data, - counter: tradeOffersSocketCounter, - isRestarted: restarted, - }) - tradeOffersSocketCounter += 1 - restarted = false - } - socket.onclose = () => { - clearTimeout(socketTimeout) - restartTradeOffersWebSocket() - } - socket.onerror = (e) => { - clearTimeout(socketTimeout) - } - const pingSocket = () => { - socket.send('ping') - socketTimeout = setTimeout(pingSocket, 150000) - } - } - - const initTradeBotWebSocket = (restarted = false) => { - let socketTimeout - let socketLink = `ws://NODEURL/websockets/crosschain/tradebot?foreignBlockchain=FOREIGN_BLOCKCHAIN` - const socket = new WebSocket(socketLink) - socket.onopen = () => { - setTimeout(pingSocket, 50) - } - socket.onmessage = (e) => { - e.relatedCoin = _relatedCoin - self.postMessage({ - type: 'TRADE_BOT', - data: e.data, - isRestarted: restarted, - }) - restarted = false - } - socket.onclose = () => { - clearTimeout(socketTimeout) - restartTradeBotWebSocket() - } - socket.onerror = (e) => { - clearTimeout(socketTimeout) - } - const pingSocket = () => { - socket.send('ping') - socketTimeout = setTimeout(pingSocket, 150000) - } - } - - const initTradePresenceWebSocket = (restarted = false) => { - let socketTimeout - let socketLink = `ws://NODEURL/websockets/crosschain/tradepresence` - const socket = new WebSocket(socketLink) - socket.onopen = () => { - setTimeout(pingSocket, 50) - } - socket.onmessage = (e) => { - tradePresenceTxns = JSON.parse(e.data) - processOffersWithPresence() - restarted = false - } - socket.onclose = () => { - clearTimeout(socketTimeout) - restartTradePresenceWebSocket() - } - socket.onerror = (e) => { - clearTimeout(socketTimeout) - } - const pingSocket = () => { - socket.send('ping') - socketTimeout = setTimeout(pingSocket, 150000) - } - } - - const restartTradePresenceWebSocket = () => { - setTimeout(() => initTradePresenceWebSocket(true), 50) - } - - const restartTradeOffersWebSocket = () => { - setTimeout(() => initTradeOffersWebSocket(true), 50) - } - - const restartTradeBotWebSocket = () => { - setTimeout(() => initTradeBotWebSocket(true), 50) - } - - initTradeOffersWebSocket() - initTradePresenceWebSocket() - initTradeBotWebSocket() - } - - async buyAction() { - const qortalAtAddress = this.botBuyAtAddress - let _foreignKey = this.selectedAddress.ltcWallet.derivedMasterPrivateKey - - const makeRequest = async () => { - const response = await parentEpml.request('tradeBotRespondRequest', { - atAddress: qortalAtAddress, - foreignKey: _foreignKey, - receivingAddress: this.selectedAddress.address, - }) - return response - } - - const manageResponse = (response) => { - if (response === true) { - this.isBuyLoading = false - this.buyBtnDisable = true - let snack5string = get("tradepage.tchange23") - parentEpml.request('showSnackBar', `${snack5string}`) - } else if (response === false) { - this.isBuyLoading = false - this.buyBtnDisable = false - - localStorage.removeItem(this.ltcWallet) - localStorage.setItem(this.ltcWallet, "") - - var oldLtcTradebook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]") - - const newLtcTradebookItem = { - botLtcQortAmount: this.reAddAmount, - botLtcPrice: this.reAddPrice - } - - oldLtcTradebook.push(newLtcTradebookItem) - - localStorage.setItem(this.ltcWallet, JSON.stringify(oldLtcTradebook)) - - this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]") - - let snack6string = get("tradepage.tchange24") - parentEpml.request('showSnackBar', `${snack6string}`) - } else { - this.isBuyLoading = false - this.buyBtnDisable = false - - localStorage.removeItem(this.ltcWallet) - localStorage.setItem(this.ltcWallet, "") - - var oldLtcTradebook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]") - - const newLtcTradebookItem = { - botLtcQortAmount: this.reAddAmount, - botLtcPrice: this.reAddPrice - } - - oldLtcTradebook.push(newLtcTradebookItem) - - localStorage.setItem(this.ltcWallet, JSON.stringify(oldLtcTradebook)) - - this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]") - - let snack7string = get("tradepage.tchange25") - parentEpml.request('showSnackBar', `${snack7string}: ${response.message}`) - } - } - const res = await makeRequest() - manageResponse(res) - } - - updateAccountBalance() { - clearTimeout(this.updateAccountBalanceTimeout) - parentEpml.request('apiCall', { - url: `/addresses/balance/${this.selectedAddress.address}?apiKey=${this.getApiKey()}`, - }).then((res) => { - this.listedCoins.get("QORTAL").balance = res - this.updateAccountBalanceTimeout = setTimeout(() => this.updateAccountBalance(), 10000) - }) - } - - _checkBuyAmount(e) { - const targetAmount = e.target.value - const target = e.target - - if (targetAmount.length === 0) { - this.isValidAmount = false - this.sellBtnDisable = true - e.target.blur() - e.target.focus() - e.target.invalid = true - } else { - this.buyBtnDisable = false - } - - e.target.blur() - e.target.focus() - - e.target.validityTransform = (newValue, nativeValidity) => { - if (newValue.includes('-') === true) { - this.buyBtnDisable = true - return { - valid: false, - } - } else if (!nativeValidity.valid) { - if (newValue.includes('.') === true) { - let myAmount = newValue.split('.') - if (myAmount[1].length > 8) { - this.buyBtnDisable = true - } else { - this.buyBtnDisable = false - return { - valid: true, - } - } - } - } else { - this.buyBtnDisable = false - } - } - } - - checkTradeBotAmount(e) { - const targetAmount = e.target.value - const target = e.target - this.autoBuyWarning = false - - if (targetAmount.length === 0) { - this.isValidAmount = false - this.autoBuyBtnDisable = true - this.autoBuyWarning = false - e.target.blur() - e.target.focus() - e.target.invalid = true - } else { - const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value - const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value - const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) - if (Number(myFunds) > Number(checkFunds)) { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = false - this.autoBuyWarning = false - } else { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = true - this.autoBuyWarning = true - } - } - - e.target.blur() - e.target.focus() - - e.target.validityTransform = (newValue, nativeValidity) => { - if (newValue.includes('-') === true) { - this.autoBuyBtnDisable = true - this.autoBuyWarning = false - return { - valid: false, - } - } else if (!nativeValidity.valid) { - if (newValue.includes('.') === true) { - let myAmount = newValue.split('.') - if (myAmount[1].length > 8) { - this.autoBuyBtnDisable = true - this.autoBuyWarning = false - } else { - const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value - const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value - const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) - if (Number(myFunds) > Number(checkFunds)) { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = false - this.autoBuyWarning = false - } else { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = true - this.autoBuyWarning = true - } - return { - valid: true, - } - } - } - } else { - const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value - const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value - const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) - if (Number(myFunds) > Number(checkFunds)) { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = false - this.autoBuyWarning = false - } else { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) - this.autoBuyBtnDisable = true - this.autoBuyWarning = true - } - } - } - } - - getApiKey() { - const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]; - let apiKey = myNode.apiKey; - return apiKey; - } - - clearSelection() { - window.getSelection().removeAllRanges() - window.parent.getSelection().removeAllRanges() - } - - _textMenu(event) { - const getSelectedText = () => { - var text = '' - if (typeof window.getSelection != 'undefined') { - text = window.getSelection().toString() - } else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') { - text = this.shadowRoot.selection.createRange().text - } - return text - } - - const checkSelectedTextAndShowMenu = () => { - let selectedText = getSelectedText() - if (selectedText && typeof selectedText === 'string') { - let _eve = { - pageX: event.pageX, - pageY: event.pageY, - clientX: event.clientX, - clientY: event.clientY, - } - let textMenuObject = { - selectedText: selectedText, - eventObject: _eve, - isFrame: true, - } - parentEpml.request('openCopyTextMenu', textMenuObject) - } - } - checkSelectedTextAndShowMenu() - } - - clearTradeBotForm() { - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value = this.initialBotAmount - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value = this.initialAmount - this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.initialBotAmount - this.autoBuyBtnDisable = true - } - - isEmptyArray(arr) { - if (!arr) { - return true - } - return arr.length === 0 - } - - round(number) { - let result = (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8) - return result - } - - inlineWorker(passedFunction, modifiers) { - let parsedFunction = `` - - modifiers.forEach((modifier) => { - let regex = new RegExp(modifier.searchValue, 'g') - parsedFunction = parsedFunction.length === 0 ? `(function ${passedFunction.toString().trim().replace(regex, modifier.replaceValue)})()` : parsedFunction.toString().trim().replace(regex, modifier.replaceValue) - }) - - const workerUrl = URL.createObjectURL(new Blob([parsedFunction], { type: 'text/javascript' })) - const worker = new Worker(workerUrl) - URL.revokeObjectURL(workerUrl) - return worker - } - - clearPaneCache() { - this._openOrdersGrid.clearCache() - this._myOrdersGrid.clearCache() - } - - createConnection() { - if (workers.get(this.selectedCoin).tradesConnectedWorker !== null) { - this.isLoadingOpenTrades = false - return - } - - const handleMessage = (message) => { - switch (message.type) { - case 'TRADE_OFFERS': - if (!message.isRestarted) { - this.listedCoins.get(this.selectedCoin).tradeOffersSocketCounter = message.counter - this.processTradeOffers(JSON.parse(message.data)) - this.listedCoins.get(this.selectedCoin).tradeOffersSocketCounter === 1 ? this.clearPaneCache() : null - workers.get(this.selectedCoin).tradesConnectedWorker.postMessage(this.listedCoins.get(this.selectedCoin).openOrders) - workers.get(this.selectedCoin).tradesConnectedWorker.postMessage({ type: "open_orders", content: this.listedCoins.get(this.selectedCoin).openOrders }) - } - return null - case 'TRADE_BOT': - if (!message.isRestarted) this.processTradeBotStates(JSON.parse(message.data)) - return null - case 'PRESENCE': - this.listedCoins.get(message.data.relatedCoin).openOrders = message.data.offers - this.listedCoins.get(message.data.relatedCoin).openFilteredOrders = message.data.filteredOffers - this.reRenderOpenFilteredOrders() - return null - default: - break - } - } - - let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] - let nodeUrl = myNode.domain + ':' + myNode.port - - const modifiers = [ - { searchValue: 'NODEURL', replaceValue: nodeUrl }, - { searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin }, - ] - - workers.get(this.selectedCoin).tradesConnectedWorker = this.inlineWorker(this.initSocket, modifiers) - - workers.get(this.selectedCoin).tradesConnectedWorker.addEventListener('message', function (event) { handleMessage(event.data) }, { passive: true }) - - workers.get(this.selectedCoin).tradesConnectedWorker.postMessage({ type: "set_coin", content: this.selectedCoin }) - - } -} - -window.customElements.define('trade-bot-ltc', TradeBotLTC) \ No newline at end of file diff --git a/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-portal.src.js b/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-portal.src.js new file mode 100644 index 00000000..86f9f57d --- /dev/null +++ b/qortal-ui-plugins/plugins/core/trade-bot/trade-bot-portal.src.js @@ -0,0 +1,3518 @@ +import { LitElement, html, css } from 'lit' +import { render } from 'lit/html.js' +import { Epml } from '../../../epml.js' +import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate' + +registerTranslateConfig({ + loader: lang => fetch(`/language/${lang}.json`).then(res => res.json()) +}) + +import '@material/mwc-button' +import '@material/mwc-textfield' +import '@material/mwc-icon' +import '@material/mwc-icon-button' +import '@material/mwc-dialog' +import '@material/mwc-tab-bar' +import '@material/mwc-tab' +import '@material/mwc-list/mwc-list-item' +import '@material/mwc-select' +import '@polymer/iron-icons/iron-icons.js' +import '@polymer/paper-icon-button/paper-icon-button.js' +import '@polymer/paper-spinner/paper-spinner-lite.js' +import '@vaadin/grid' +import '@vaadin/grid/vaadin-grid-sorter' + +const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }) + +let workers = new Map() + +class TradeBotPortal extends LitElement { + static get properties() { + return { + selectedAddress: { type: Object }, + config: { type: Object }, + listedCoins: { type: Map }, + sellBtnDisable: { type: Boolean }, + isSellLoading: { type: Boolean }, + isBuyLoading: { type: Boolean }, + buyBtnDisable: { type: Boolean }, + autoBuyWarning: { type: Boolean }, + autoBuyBtnDisable: { type: Boolean }, + autoBuyBotDisable: { type: Boolean }, + initialAmount: { type: Number }, + cancelBtnDisable: { type: Boolean }, + cancelStuckOfferBtnDisable: { type: Boolean }, + selectedCoin: { type: String }, + isLoadingHistoricTrades: { type: Boolean }, + isLoadingOpenTrades: { type: Boolean }, + isLoadingMyOpenOrders: { type: Boolean }, + showGetWalletBance: { type: Boolean }, + showAddAutoBuy: { type: Boolean }, + theme: { type: String, reflect: true }, + btcWallet: { type: String }, + ltcWallet: { type: String }, + dogeWallet: { type: String }, + dgbWallet: { type: String }, + rvnWallet: { type: String }, + arrrWallet: { type: String }, + arrrWalletAddress: { type: String }, + qortbtc: { type: Number }, + qortltc: { type: Number }, + qortdoge: { type: Number }, + qortdgb: { type: Number }, + qortrvn: { type: Number }, + qortarrr: { type: Number }, + btcqort: { type: Number }, + ltcqort: { type: Number }, + dogeqort: { type: Number }, + dgbqort: { type: Number }, + rvnqort: { type: Number }, + arrrqort: { type: Number }, + tradeBotBtcBook: { type: Array }, + tradeBotLtcBook: { type: Array }, + tradeBotDogeBook: { type: Array }, + tradeBotDgbBook: { type: Array }, + tradeBotRvnBook: { type: Array }, + tradeBotArrrBook: { type: Array } + } + } + + static get styles() { + return css` + * { + --mdc-theme-primary: rgb(3, 169, 244); + --mdc-theme-secondary: var(--mdc-theme-primary); + --mdc-theme-error: rgb(255, 89, 89); + --mdc-text-field-outlined-idle-border-color: var(--txtfieldborder); + --mdc-text-field-outlined-hover-border-color: var(--txtfieldhoverborder); + --mdc-text-field-label-ink-color: var(--black); + --mdc-text-field-ink-color: var(--black); + --mdc-select-outlined-idle-border-color: var(--txtfieldborder); + --mdc-select-outlined-hover-border-color: var(--txtfieldhoverborder); + --mdc-select-label-ink-color: var(--black); + --mdc-select-ink-color: var(--black); + --mdc-theme-surface: var(--white); + --mdc-dialog-content-ink-color: var(--black); + --mdc-dialog-shape-radius: 25px; + --paper-input-container-focus-color: var(--mdc-theme-primary); + --lumo-primary-text-color: rgb(0, 167, 245); + --lumo-primary-color-50pct: rgba(0, 167, 245, 0.5); + --lumo-primary-color-10pct: rgba(0, 167, 245, 0.1); + --lumo-primary-color: hsl(199, 100%, 48%); + --lumo-base-color: var(--white); + --lumo-body-text-color: var(--black); + --lumo-secondary-text-color: var(--sectxt); + --lumo-contrast-60pct: var(--vdicon); + --_lumo-grid-border-color: var(--border); + --_lumo-grid-secondary-border-color: var(--border2); + } + paper-spinner-lite { + height: 30px; + width: 30px; + --paper-spinner-color: var(--mdc-theme-primary); + --paper-spinner-stroke-width: 3px; + } + mwc-tab-bar { + --mdc-text-transform: none; + --mdc-tab-color-default: var(--black); + --mdc-tab-text-label-color-default: var(--black); + } + #tabs-1 { + --mdc-tab-height: 42px; + border-left: 1px solid var(--tradeborder); + border-top: 1px solid var(--tradeborder); + border-right: 1px solid var(--tradeborder); + color: var(--black); + } + #tab-buy[active] { + --mdc-theme-primary: rgba(55, 160, 51, 0.9); + } + #tabs-1-content { + height: 100%; + padding-bottom: 10px; + } + #tabs-1-content > div { + height: 100%; + border: 1px solid var(--tradeborder); + } + #tabs-1-content .card { + border: none; + } + #tabs-1-content .btn-clear { + --mdc-icon-button-size: 32px; + color: var(--black); + } + .btn-clear-bot { + --mdc-icon-button-size: 32px; + color: var(--black); + float: right; + } + .btn-info { + color: #03a9f4; + --mdc-icon-size: 16px; + padding-top: 3px; + } + #tab-sell[active] { + --mdc-theme-primary: rgb(255, 89, 89); + } + #trade-portal-page { + background: var(--white); + padding: 12px 24px; + } + .divCard { + border: 1px solid var(--black); + padding: 1em; + box-shadow: 0 0.3px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 1px -1px rgba(0, 0, 0, 0.12), 0 1px 2px 0 rgba(0, 0, 0, 0.2); + } + h2 { + margin: 10px 0; + } + + h4 { + margin: 5px 0; + } + + p { + font-size: 14px; + line-height: 21px; + } + + .card-body { + background-color: var(--white); + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + min-height: 100vh; + margin: 0; + } + + .card-container { + background-color: var(--white); + border-radius: 5px; + color: var(--black); + padding-top: 30px; + position: relative; + width: 350px; + max-width: 100%; + text-align: center; + } + + .card-container .level { + color: #ffffff; + background-color: #03a9f4; + border-radius: 3px; + font-size: 14px; + font-weight: bold; + padding: 3px 7px; + position: absolute; + top: 30px; + left: 30px; + } + + .card-container .founder { + color: #ffffff; + background-color: #03a9f4; + border-radius: 3px; + font-size: 14px; + font-weight: bold; + padding: 3px 7px; + position: absolute; + top: 30px; + right: 30px; + } + + .card-container .round { + width: 96px; + height: 96px; + border: 1px solid #03a9f4; + border-radius: 50%; + padding: 2px; + } + + .card-container .badge { + width: 200px; + height: 135px; + border: 1px solid transparent; + border-radius: 10%; + padding: 2px; + } + + .userdata { + background-color: #1F1A36; + text-align: left; + padding: 15px; + margin-top: 30px; + } + + .userdata ul { + list-style-type: none; + margin: 0; + padding: 0; + } + + .userdata ul li { + border: 1px solid #2D2747; + border-radius: 2px; + display: inline-block; + font-size: 12px; + margin: 0 7px 7px 0; + padding: 7px; + } + + h2, + h3, + h4, + h5 { + color: var(--black); + font-weight: 400; + } + header { + display: flex; + flex: 0 1 auto; + align-items: center; + justify-content: center; + padding: 0px 10px; + font-size: 16px; + color: var(--white); + background-color: var(--tradehead); + border-left: 1px solid var(--tradeborder); + border-top: 1px solid var(--tradeborder); + border-right: 1px solid var(--tradeborder); + min-height: 40px; + } + p { + margin-bottom: 12px; + } + #trade-portal { + max-width: 100vw; + margin-left: auto; + margin-right: auto; + } + .box { + margin: 0; + padding: 0; + display: flex; + flex-flow: column; + height: 100%; + } + .box-bot { + margin: 0; + padding: 0; + display: flex; + flex-flow: column; + height: 150px; + } + #first-trade-section { + margin-bottom: 10px; + } + #first-trade-section > div { + } + #second-trade-section { + margin-bottom: 10px; + } + #second-trade-section > div { + } + #third-trade-section { + margin-bottom: 10px; + } + #third-trade-section > div { + } + .trade-chart { + background-color: var(--white); + border: 2px #ddd solid; + text-align: center; + } + .open-trades { + text-align: center; + } + .open-market-container { + text-align: center; + } + .trade-bot-container { + text-align: center; + } + .no-last-seen { + background: rgb(255, 89, 89); + padding: 9px 1.3px; + border-radius: 50%; + width: 1rem; + margin: 0 auto; + } + .card { + padding: 1em; + border: 1px var(--tradeborder) solid; + flex: 1 1 auto; + display: flex; + flex-flow: column; + justify-content: space-evenly; + min-height: inherit; + } + .card-bot { + padding: 1em; + flex: 1 1 auto; + display: flex; + flex-flow: column; + justify-content: space-evenly; + width: 350px; + min-height: inherit; + } + .cancel { + --mdc-theme-primary: rgb(255, 89, 89); + } + .border-wrapper { + border: 1px var(--tradeborder) solid; + overflow: hidden; + } + .amt-text { + color: var(--tradehave); + font-size: 15px; + margin-top: 5px; + margin-bottom: 12px; + } + .exchange { + color: var(--black); + font-size: 18px; + font-weight: bold; + margin-top: 5px; + margin-bottom: 10px; + } + .clear-button { + display: inline; + float: right; + margin-bottom: 5px; + } + .exhcnage-text { + display: inline; + float: left; + margin-bottom: 5px; + } + .balance-text { + display: inline; + float: right; + margin-bottom: 5px; + } + .fee-text { + display: inline; + float: left; + margin-bottom: 5px; + } + .tab-text { + color: var(--tradehave); + font-size: 12px; + text-align: left; + margin-top: 2px; + margin-bottom: -12px; + } + .historic-trades { + text-align: center; + } + .my-open-orders { + text-align: center; + } + .my-historic-trades { + text-align: center; + } + .buttons { + width: auto !important; + } + .buy-button { + --mdc-theme-primary: rgba(55, 160, 51, 0.9); + } + .sell-button { + --mdc-theme-primary: rgb(255, 89, 89); + } + .trade-bot-button { + margin-top: 20px; + margin-bottom: 20px; + --mdc-theme-primary: rgba(55, 160, 51, 0.9); + } + .full-width { + background-color: var(--white); + border: 2px var(--black); + height: 200px; + text-align: center; + } + vaading-grid { + font-size: .8em; + } + vaadin-grid-column { + flex-grow: 1; + } + .loadingContainer { + height: 100%; + width: 100%; + } + .loading, + .loading:after { + border-radius: 50%; + width: 5em; + height: 5em; + } + .loading { + margin: 10px auto; + border-width: .6em; + border-style: solid; + border-color: rgba(3, 169, 244, 0.2) rgba(3, 169, 244, 0.2) rgba(3, 169, 244, 0.2) rgb(3, 169, 244); + font-size: 10px; + position: relative; + text-indent: -9999em; + transform: translateZ(0px); + animation: 1.1s linear 0s infinite normal none running loadingAnimation; + } + mwc-select#coinSelectionMenu { + font-size: 24px; + width:220px; + } + mwc-select#coinSelectionMenu mwc-list-item { + line-height: 30px; + } + .coinName::before { + content: ""; + display: inline-block; + height: 26px; + width: 45px; + position: absolute; + background-repeat: no-repeat; + background-size: cover; + left: 10px; + top: 10px; + } + .btc.coinName:before { + background-image: url('/img/qortbtc.png'); + } + .ltc.coinName:before { + background-image: url('/img/qortltc.png'); + } + .doge.coinName:before { + background-image: url('/img/qortdoge.png'); + } + .dgb.coinName:before { + background-image: url('/img/qortdgb.png'); + } + .rvn.coinName:before { + background-image: url('/img/qortrvn.png'); + } + .arrr.coinName:before { + background-image: url('/img/qortarrr.png'); + } + .coinName { + display: inline-block; + height: 26px; + padding-left: 45px; + } + .warning-text { + animation: blinker 1.5s linear infinite; + display: inline; + float: left; + margin-bottom: 5px; + color: rgb(255, 89, 89); + } + .warning-bot-text { + animation: blinker 1.5s linear infinite; + display: inline; + text-align: center; + color: rgb(255, 89, 89); + } + .red { + --mdc-theme-primary: #F44336; + } + @-webkit-keyframes loadingAnimation { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } + } + @keyframes loadingAnimation { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } + } + @keyframes blinker { + 50% { + opacity: 0; + } + } + @media (min-width: 701px) { + * { + } + #trade-bot-portal { + display: grid; + grid-template-columns:3fr 4fr 3fr; + grid-auto-rows: max(80px); + column-gap: 0.5em; + row-gap: 0.4em; + justify-items: stretch; + align-items: stretch; + margin-bottom: 10px; + } + #first-trade-section { + display: grid; + grid-template-columns:1fr 4fr 1fr; + grid-auto-rows: max(250px); + column-gap: 0.5em; + row-gap: 0.4em; + justify-items: stretch; + align-items: stretch; + margin-bottom: 10px; + } + #second-trade-section { + display: grid; + grid-template-columns:1fr 4fr 1fr; + grid-auto-rows: max(250px); + column-gap: 0.5em; + row-gap: 0.4em; + justify-items: stretch; + align-items: stretch; + margin-bottom: 10px; + } + #third-trade-section { + display: grid; + grid-template-columns: 1fr 4fr 1fr; + grid-auto-rows: max(150px); + column-gap: 0.5em; + row-gap: 0.4em; + justify-items: stretch; + align-items: stretch; + margin-bottom: 10px; + } + #fourth-trade-section { + display: grid; + grid-template-columns: 1fr 4fr 1fr; + grid-auto-rows: max(150px); + column-gap: 0.5em; + row-gap: 0.4em; + justify-items: stretch; + align-items: stretch; + margin-bottom: 10px; + } + } + ` + } + + constructor() { + super() + let qortal = { + name: "QORTAL", + balance: "0", + coinCode: "QORT", + coinAmount: this.amountString, + tradeFee: "0.002" + } + + let bitcoin = { + name: "BITCOIN", + balance: "0", + coinCode: "BTC", + openOrders: [], + openFilteredOrders: [], + historicTrades: [], + myOrders: [], + myHistoricTrades: [], + myOfferingOrders: [], + myGridBoughtItems: [], + openTradeOrders: null, + tradeOffersSocketCounter: 1, + coinAmount: this.amountString, + tradeFee: "~0.0001" + } + + let litecoin = { + name: "LITECOIN", + balance: "0", + coinCode: "LTC", + openOrders: [], + openFilteredOrders: [], + historicTrades: [], + myOrders: [], + myHistoricTrades: [], + myOfferingOrders: [], + myGridBoughtItems: [], + openTradeOrders: null, + tradeOffersSocketCounter: 1, + coinAmount: this.amountString, + tradeFee: "~0.00005" + } + + let dogecoin = { + name: "DOGECOIN", + balance: "0", + coinCode: "DOGE", + openOrders: [], + openFilteredOrders: [], + historicTrades: [], + myOrders: [], + myHistoricTrades: [], + myOfferingOrders: [], + myGridBoughtItems: [], + openTradeOrders: null, + tradeOffersSocketCounter: 1, + coinAmount: this.amountString, + tradeFee: "~0.005" + } + + let digibyte = { + name: "DIGIBYTE", + balance: "0", + coinCode: "DGB", + openOrders: [], + openFilteredOrders: [], + historicTrades: [], + myOrders: [], + myHistoricTrades: [], + myOfferingOrders: [], + myGridBoughtItems: [], + openTradeOrders: null, + tradeOffersSocketCounter: 1, + coinAmount: this.amountString, + tradeFee: "~0.0005" + } + + let ravencoin = { + name: "RAVENCOIN", + balance: "0", + coinCode: "RVN", + openOrders: [], + openFilteredOrders: [], + historicTrades: [], + myOrders: [], + myHistoricTrades: [], + myOfferingOrders: [], + myGridBoughtItems: [], + openTradeOrders: null, + tradeOffersSocketCounter: 1, + coinAmount: this.amountString, + tradeFee: "~0.006" + } + + let piratechain = { + name: "PIRATECHAIN", + balance: "0", + coinCode: "ARRR", + openOrders: [], + openFilteredOrders: [], + historicTrades: [], + myOrders: [], + myHistoricTrades: [], + myOfferingOrders: [], + myGridBoughtItems: [], + openTradeOrders: null, + tradeOffersSocketCounter: 1, + coinAmount: this.amountString, + tradeFee: "~0.0002" + } + + this.listedCoins = new Map() + this.listedCoins.set("QORTAL", qortal) + this.listedCoins.set("BITCOIN", bitcoin) + this.listedCoins.set("LITECOIN", litecoin) + this.listedCoins.set("DOGECOIN", dogecoin) + this.listedCoins.set("DIGIBYTE", digibyte) + this.listedCoins.set("RAVENCOIN", ravencoin) + this.listedCoins.set("PIRATECHAIN", piratechain) + + workers.set("QORTAL", { + tradesConnectedWorker: null, + handleStuckTradesConnectedWorker: null + }) + + workers.set("BITCOIN", { + tradesConnectedWorker: null, + handleStuckTradesConnectedWorker: null + }) + + workers.set("LITECOIN", { + tradesConnectedWorker: null, + handleStuckTradesConnectedWorker: null + }) + + workers.set("DOGECOIN", { + tradesConnectedWorker: null, + handleStuckTradesConnectedWorker: null + }) + + workers.set("DIGIBYTE", { + tradesConnectedWorker: null, + handleStuckTradesConnectedWorker: null + }) + + workers.set("RAVENCOIN", { + tradesConnectedWorker: null, + handleStuckTradesConnectedWorker: null + }) + + workers.set("PIRATECHAIN", { + tradesConnectedWorker: null, + handleStuckTradesConnectedWorker: null + }) + + this.selectedCoin = "BITCOIN" + this.selectedAddress = {} + this.config = {} + this.sellBtnDisable = false + this.isSellLoading = false + this.buyBtnDisable = true + this.autoBuyWarning = false + this.autoBuyBtnDisable = true + this.autoBuyBotDisable = false + this.isBuyLoading = false + this.initialAmount = 0 + this.cancelBtnDisable = false + this.cancelStuckOfferBtnDisable = false + this.isLoadingHistoricTrades = true + this.isLoadingOpenTrades = true + this.isLoadingMyOpenOrders = false + this.showGetWalletBance = true + this.showAddAutoBuy = false + this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light' + this.btcWallet = '' + this.ltcWallet = '' + this.dogeWallet = '' + this.dgbWallet = '' + this.rvnWallet = '' + this.arrrWallet = '' + this.arrrWalletAddress = '' + this.qortbtc = 0 + this.qortltc = 0 + this.qortdoge = 0 + this.qortdgb = 0 + this.qortrvn = 0 + this.qortarrr = 0 + this.btcqort = 0 + this.ltcqort = 0 + this.dogeqort = 0 + this.dgbqort = 0 + this.rvnqort = 0 + this.arrrqort = 0 + this.tradeInfoAccountName = '' + this.tradeImageUrl = '' + this.tradeAddressResult = [] + this.displayTradeAddress = '' + this.displayTradeLevel = '' + this.displayTradeBalance = '' + } + + openTradesTemplate() { + return html` +
+
+
${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange42")}
+
+
${translate("login.loading")}
+ + { + render(html`${this.round(data.item.qortAmount)}`, root) + }} + > + + { + render(html`${this.round(data.item.price)}`, root) + }} + > + + { + render(html`${data.item.foreignAmount}`, root) + }} + > + + { + render(html`${data.item.qortalCreator}`, root) + }} + > + + +
+
+
+ ` + } + + myOpenOrdersTemplate() { + return html` +
+
+
${translate("tradepage.tchange36")}
+
+
${translate("login.loading")}
+ + { + const dateString = new Date(data.item.timestamp).toLocaleString() + render(html`${dateString}`, root) + }} + > + + { + render(html` ${data.item._tradeState} `, root) + }} + > + + { + const price = this.round(parseFloat(data.item.foreignAmount) / parseFloat(data.item.qortAmount)) + render(html`${price}`, root) + }} + > + + + + + + +
+
+
+ ` + } + + myDoneTradesTemplate() { + return html` +
+
+
${translate("tradepage.tchange43")} (${this.listedCoins.get(this.selectedCoin).coinCode})
+
+
${translate("login.loading")}
+ + { + const dateString = new Date(data.item.timestamp).toLocaleString() + render(html`${dateString}`, root) + }} + > + + { + return render(html` ${translate("tradepage.tchange32")} `, root) + }} + > + + { + const price = this.round(parseFloat(data.item.foreignAmount) / parseFloat(data.item.qortAmount)) + render(html`${price}`, root) + }} + > + + + + { + render(html` ${data.item.foreignAmount} `, root) + }} + > + + +
+
+
+ ` + } + + myHistoricTradesTemplate() { + return html` +
+
+
${translate("tradepage.tchange4")}
+
+ + { + const dateString = new Date(data.item.timestamp).toLocaleString() + render(html`${dateString}`, root) + }} + > + + { + if (data.item.mode === 'SOLD') return render(html` ${translate("tradepage.tchange31")} `, root) + if (data.item.mode === 'BOUGHT') return render(html` ${translate("tradepage.tchange32")} `, root) + return render(html` ${data.item.mode} `, root) + }} + > + + { + const price = this.round(parseFloat(data.item.foreignAmount) / parseFloat(data.item.qortAmount)) + render(html`${price}`, root) + }} + > + + + + { + render(html` ${data.item.foreignAmount} `, root) + }} + > + + +
+
+
+ ` + } + + tradeBotBTCTemplate() { + return html` +
+
+
${translate("tradepage.tchange39")} ${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT
+
+ + { + render(html`${data.item.botBtcQortAmount}`, root) + }} + > + + { + render(html`${data.item.botBtcPrice}`, root) + }} + > + + { + const totalCoins = this.round(parseFloat(data.item.botBtcQortAmount) * parseFloat(data.item.botBtcPrice)) + const myBotFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) + if (Number(myBotFunds) > Number(totalCoins)) { + this.autoBuyBotDisable = false + render(html`${totalCoins}`, root) + } else { + this.autoBuyBotDisable = true + render(html`${totalCoins}`, root) + } + }} + > + + { + render(html` this.removeBTCTradebook()}>delete ${translate("nodepage.nchange12")}`, root) + }} + > + + + ${this.isEmptyArray(this.tradeBotBtcBook) ? html` + + ${translate("tradepage.tchange38")} ${translate("tradepage.tchange39")} + + `: ''} +
+ ${this.autoBuyBotDisable ? html` +
${this.renderBotWarning()}
+ `: ''} +
+
+ ` + } + + tradeBotLTCTemplate() { + return html` +
+
+
${translate("tradepage.tchange39")} ${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT
+
+ + { + render(html`${data.item.botLtcQortAmount}`, root) + }} + > + + { + render(html`${data.item.botLtcPrice}`, root) + }} + > + + { + const totalCoins = this.round(parseFloat(data.item.botLtcQortAmount) * parseFloat(data.item.botLtcPrice)) + const myBotFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) + if (Number(myBotFunds) > Number(totalCoins)) { + this.autoBuyBotDisable = false + render(html`${totalCoins}`, root) + } else { + this.autoBuyBotDisable = true + render(html`${totalCoins}`, root) + } + }} + > + + { + render(html` this.removeLTCTradebook()}>delete ${translate("nodepage.nchange12")}`, root) + }} + > + + + ${this.isEmptyArray(this.tradeBotLtcBook) ? html` + + ${translate("tradepage.tchange38")} ${translate("tradepage.tchange39")} + + `: ''} +
+ ${this.autoBuyBotDisable ? html` +
${this.renderBotWarning()}
+ `: ''} +
+
+ ` + } + + tradeBotDOGETemplate() { + return html` +
+
+
${translate("tradepage.tchange39")} ${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT
+
+ + { + render(html`${data.item.botDogeQortAmount}`, root) + }} + > + + { + render(html`${data.item.botDogePrice}`, root) + }} + > + + { + const totalCoins = this.round(parseFloat(data.item.botDogeQortAmount) * parseFloat(data.item.botDogePrice)) + const myBotFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) + if (Number(myBotFunds) > Number(totalCoins)) { + this.autoBuyBotDisable = false + render(html`${totalCoins}`, root) + } else { + this.autoBuyBotDisable = true + render(html`${totalCoins}`, root) + } + }} + > + + { + render(html` this.removeDOGETradebook()}>delete ${translate("nodepage.nchange12")}`, root) + }} + > + + + ${this.isEmptyArray(this.tradeBotDogeBook) ? html` + + ${translate("tradepage.tchange38")} ${translate("tradepage.tchange39")} + + `: ''} +
+ ${this.autoBuyBotDisable ? html` +
${this.renderBotWarning()}
+ `: ''} +
+
+ ` + } + + tradeBotDGBTemplate() { + return html` +
+
+
${translate("tradepage.tchange39")} ${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT
+
+ + { + render(html`${data.item.botDgbQortAmount}`, root) + }} + > + + { + render(html`${data.item.botDgbPrice}`, root) + }} + > + + { + const totalCoins = this.round(parseFloat(data.item.botDgbQortAmount) * parseFloat(data.item.botDgbPrice)) + const myBotFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) + if (Number(myBotFunds) > Number(totalCoins)) { + this.autoBuyBotDisable = false + render(html`${totalCoins}`, root) + } else { + this.autoBuyBotDisable = true + render(html`${totalCoins}`, root) + } + }} + > + + { + render(html` this.removeDGBTradebook()}>delete ${translate("nodepage.nchange12")}`, root) + }} + > + + + ${this.isEmptyArray(this.tradeBotDgbBook) ? html` + + ${translate("tradepage.tchange38")} ${translate("tradepage.tchange39")} + + `: ''} +
+ ${this.autoBuyBotDisable ? html` +
${this.renderBotWarning()}
+ `: ''} +
+
+ ` + } + + tradeBotRVNTemplate() { + return html` +
+
+
${translate("tradepage.tchange39")} ${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT
+
+ + { + render(html`${data.item.botRvnQortAmount}`, root) + }} + > + + { + render(html`${data.item.botRvnPrice}`, root) + }} + > + + { + const totalCoins = this.round(parseFloat(data.item.botRvnQortAmount) * parseFloat(data.item.botRvnPrice)) + const myBotFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) + if (Number(myBotFunds) > Number(totalCoins)) { + this.autoBuyBotDisable = false + render(html`${totalCoins}`, root) + } else { + this.autoBuyBotDisable = true + render(html`${totalCoins}`, root) + } + }} + > + + { + render(html` this.removeRVNTradebook()}>delete ${translate("nodepage.nchange12")}`, root) + }} + > + + + ${this.isEmptyArray(this.tradeBotRvnBook) ? html` + + ${translate("tradepage.tchange38")} ${translate("tradepage.tchange39")} + + `: ''} +
+ ${this.autoBuyBotDisable ? html` +
${this.renderBotWarning()}
+ `: ''} +
+
+ ` + } + + tradeBotARRRTemplate() { + return html` +
+
+
${translate("tradepage.tchange39")} ${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT
+
+ + { + render(html`${data.item.botArrrQortAmount}`, root) + }} + > + + { + render(html`${data.item.botArrrPrice}`, root) + }} + > + + { + const totalCoins = this.round(parseFloat(data.item.botArrrQortAmount) * parseFloat(data.item.botArrrPrice)) + const myBotFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) + if (Number(myBotFunds) > Number(totalCoins)) { + this.autoBuyBotDisable = false + render(html`${totalCoins}`, root) + } else { + this.autoBuyBotDisable = true + render(html`${totalCoins}`, root) + } + }} + > + + { + render(html` this.removeARRRTradebook()}>delete ${translate("nodepage.nchange12")}`, root) + }} + > + + + ${this.isEmptyArray(this.tradeBotArrrBook) ? html` + + ${translate("tradepage.tchange38")} ${translate("tradepage.tchange39")} + + `: ''} +
+ ${this.autoBuyBotDisable ? html` +
${this.renderBotWarning()}
+ `: ''} +
+
+ ` + } + + render() { + return html` +
+
+
+
+

${translate("tradepage.tchange39")} -  

+ + BTC / QORT + LTC / QORT + DOGE / QORT + DGB / QORT + RVN / QORT + ARRR / QORT + +
+
+
+
+
+
+ ${this.openTradesTemplate()} +
+
+
+
+ ${this.myDoneTradesTemplate()} +
+
+
+
+ ${this.myOpenOrdersTemplate()} +
+
+
+
+ ${this.showAutoBuyGrid()} +
+
+
+

${translate("tradepage.tchange33")} ${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange40")}

+

1 QORT = ${this.exchangeRateQort()} ${this.listedCoins.get(this.selectedCoin).coinCode}

+
+
+
+ + +
+

${this.renderFetchText()}

+
+
+
+

${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT

+
+
+
+
${this.renderWarning()}
+ +
+ ${translate("tradepage.tchange8")} (QORT)* +

+ + +

+ ${translate("tradepage.tchange14")} (${this.listedCoins.get(this.selectedCoin).coinCode})* +

+ + +

+ ${translate("tradepage.tchange10")} (${this.listedCoins.get(this.selectedCoin).coinCode})* +

+ + +

+ + ${translate("tradepage.tchange16")}: ${this.listedCoins.get(this.selectedCoin).balance} ${this.listedCoins.get(this.selectedCoin).coinCode} + +
+
+ + ${translate("tradepage.tchange38")} ${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange39")} + +
+
+
+ ${translate("general.close")} +
+ + +
+

${this.renderFetchText()}

+
+
+
+

${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT

+
+
+
+
${this.renderWarning()}
+ +
+ ${translate("tradepage.tchange8")} (QORT)* +

+ + +

+ ${translate("tradepage.tchange14")} (${this.listedCoins.get(this.selectedCoin).coinCode})* +

+ + +

+ ${translate("tradepage.tchange10")} (${this.listedCoins.get(this.selectedCoin).coinCode})* +

+ + +

+ + ${translate("tradepage.tchange16")}: ${this.listedCoins.get(this.selectedCoin).balance} ${this.listedCoins.get(this.selectedCoin).coinCode} + +
+
+ + ${translate("tradepage.tchange38")} ${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange39")} + +
+
+
+ ${translate("general.close")} +
+ + +
+

${this.renderFetchText()}

+
+
+
+

${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT

+
+
+
+
${this.renderWarning()}
+ +
+ ${translate("tradepage.tchange8")} (QORT)* +

+ + +

+ ${translate("tradepage.tchange14")} (${this.listedCoins.get(this.selectedCoin).coinCode})* +

+ + +

+ ${translate("tradepage.tchange10")} (${this.listedCoins.get(this.selectedCoin).coinCode})* +

+ + +

+ + ${translate("tradepage.tchange16")}: ${this.listedCoins.get(this.selectedCoin).balance} ${this.listedCoins.get(this.selectedCoin).coinCode} + +
+
+ + ${translate("tradepage.tchange38")} ${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange39")} + +
+
+
+ ${translate("general.close")} +
+ + +
+

${this.renderFetchText()}

+
+
+
+

${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT

+
+
+
+
${this.renderWarning()}
+ +
+ ${translate("tradepage.tchange8")} (QORT)* +

+ + +

+ ${translate("tradepage.tchange14")} (${this.listedCoins.get(this.selectedCoin).coinCode})* +

+ + +

+ ${translate("tradepage.tchange10")} (${this.listedCoins.get(this.selectedCoin).coinCode})* +

+ + +

+ + ${translate("tradepage.tchange16")}: ${this.listedCoins.get(this.selectedCoin).balance} ${this.listedCoins.get(this.selectedCoin).coinCode} + +
+
+ + ${translate("tradepage.tchange38")} ${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange39")} + +
+
+
+ ${translate("general.close")} +
+ + +
+

${this.renderFetchText()}

+
+
+
+

${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT

+
+
+
+
${this.renderWarning()}
+ +
+ ${translate("tradepage.tchange8")} (QORT)* +

+ + +

+ ${translate("tradepage.tchange14")} (${this.listedCoins.get(this.selectedCoin).coinCode})* +

+ + +

+ ${translate("tradepage.tchange10")} (${this.listedCoins.get(this.selectedCoin).coinCode})* +

+ + +

+ + ${translate("tradepage.tchange16")}: ${this.listedCoins.get(this.selectedCoin).balance} ${this.listedCoins.get(this.selectedCoin).coinCode} + +
+
+ + ${translate("tradepage.tchange38")} ${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange39")} + +
+
+
+ ${translate("general.close")} +
+ + +
+

${this.renderFetchText()}

+
+
+
+

${this.listedCoins.get(this.selectedCoin).coinCode} ==> QORT

+
+
+
+
${this.renderWarning()}
+ +
+ ${translate("tradepage.tchange8")} (QORT)* +

+ + +

+ ${translate("tradepage.tchange14")} (${this.listedCoins.get(this.selectedCoin).coinCode})* +

+ + +

+ ${translate("tradepage.tchange10")} (${this.listedCoins.get(this.selectedCoin).coinCode})* +

+ + +

+ + ${translate("tradepage.tchange16")}: ${this.listedCoins.get(this.selectedCoin).balance} ${this.listedCoins.get(this.selectedCoin).coinCode} + +
+
+ + ${translate("tradepage.tchange38")} ${this.listedCoins.get(this.selectedCoin).coinCode} ${translate("tradepage.tchange39")} + +
+
+
+ ${translate("general.close")} +
+ ` + } + + firstUpdated() { + + let _this = this + + this.changeTheme() + this.changeLanguage() + this.updateWalletBalance() + this.fetchWalletAddress(this.selectedCoin) + + this._openOrdersGrid = this.shadowRoot.getElementById('openOrdersGrid') + + this._openOrdersGrid.querySelector('#priceColumn').headerRenderer = function (root) { + const priceString = get("tradepage.tchange9") + root.innerHTML = '' + priceString + ' (' + _this.listedCoins.get(_this.selectedCoin).coinCode + ')' + } + + this._openOrdersGrid.querySelector('#qortAmountColumn').headerRenderer = function (root) { + const amountString = get("tradepage.tchange8") + root.innerHTML = '' + amountString + ' (QORT)' + } + + this._myOrdersGrid = this.shadowRoot.getElementById('myOrdersGrid') + + const getQortBtcPrice = () => { + parentEpml.request("apiCall", { url: `/crosschain/price/BITCOIN?inverse=true` }).then((res) => { + setTimeout(() => { this.qortbtc = (Number(res) / 1e8).toFixed(8) }, 1) + }) + setTimeout(getQortBtcPrice, 300000) + } + + const getQortLtcPrice = () => { + parentEpml.request("apiCall", { url: `/crosschain/price/LITECOIN?inverse=true` }).then((res) => { + setTimeout(() => { this.qortltc = (Number(res) / 1e8).toFixed(8) }, 1) + }) + setTimeout(getQortLtcPrice, 300000) + } + + const getQortDogePrice = () => { + parentEpml.request("apiCall", { url: `/crosschain/price/DOGECOIN?inverse=true` }).then((res) => { + setTimeout(() => { this.qortdoge = (Number(res) / 1e8).toFixed(8) }, 1) + }) + setTimeout(getQortDogePrice, 300000) + } + + const getQortDgbPrice = () => { + parentEpml.request("apiCall", { url: `/crosschain/price/DIGIBYTE?inverse=true` }).then((res) => { + setTimeout(() => { this.qortdgb = (Number(res) / 1e8).toFixed(8) }, 1) + }) + setTimeout(getQortDgbPrice, 300000) + } + + const getQortRvnPrice = () => { + parentEpml.request("apiCall", { url: `/crosschain/price/RAVENCOIN?inverse=true` }).then((res) => { + setTimeout(() => { this.qortrvn = (Number(res) / 1e8).toFixed(8) }, 1) + }) + setTimeout(getQortRvnPrice, 300000) + } + + const getQortArrrPrice = () => { + parentEpml.request("apiCall", { url: `/crosschain/price/PIRATECHAIN?inverse=true` }).then((res) => { + setTimeout(() => { this.qortarrr = (Number(res) / 1e8).toFixed(8) }, 1) + }) + setTimeout(getQortArrrPrice, 300000) + } + + window.addEventListener('contextmenu', (event) => { + event.preventDefault() + this._textMenu(event)}, + { passive: true } + ) + + window.addEventListener('click', () => { + parentEpml.request('closeCopyTextMenu', null)}, + { passive: true } + ) + + window.addEventListener('storage', () => { + const checkLanguage = localStorage.getItem('qortalLanguage') + const checkTheme = localStorage.getItem('qortalTheme') + + use(checkLanguage) + + this.theme = (checkTheme === 'dark') ? 'dark' : 'light' + document.querySelector('html').setAttribute('theme', this.theme) + this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]") + this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]") + this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.dogeWallet) || "[]") + this.tradeBotDgbBook = JSON.parse(localStorage.getItem(this.dgbWallet) || "[]") + this.tradeBotRvnBook = JSON.parse(localStorage.getItem(this.rvnWallet) || "[]") + this.tradeBotArrrBook = JSON.parse(localStorage.getItem(this.arrrWallet) || "[]") + }) + + window.onkeyup = (e) => { + if (e.keyCode === 27) parentEpml.request('closeCopyTextMenu', null) + } + + this.btcWallet = window.parent.reduxStore.getState().app.selectedAddress.btcWallet.address + this.ltcWallet = window.parent.reduxStore.getState().app.selectedAddress.ltcWallet.address + this.dogeWallet = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet.address + this.dgbWallet = window.parent.reduxStore.getState().app.selectedAddress.dgbWallet.address + this.rvnWallet = window.parent.reduxStore.getState().app.selectedAddress.rvnWallet.address + this.arrrWallet = window.parent.reduxStore.getState().app.selectedAddress.arrrWallet.address + + let configLoaded = false + + parentEpml.ready().then(() => { + parentEpml.subscribe('selected_address', async (selectedAddress) => { + this.selectedAddress = {} + selectedAddress = JSON.parse(selectedAddress) + if (!selectedAddress || Object.entries(selectedAddress).length === 0) return + this.selectedAddress = selectedAddress + + this.btcWallet = window.parent.reduxStore.getState().app.selectedAddress.btcWallet.address + this.ltcWwallet = window.parent.reduxStore.getState().app.selectedAddress.ltcWallet.address + this.dogeWallet = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet.address + this.dgbWallet = window.parent.reduxStore.getState().app.selectedAddress.dgbWallet.address + this.rvnWallet = window.parent.reduxStore.getState().app.selectedAddress.rvnWallet.address + this.arrrWallet = window.parent.reduxStore.getState().app.selectedAddress.arrrWallet.address + + this.updateAccountBalance() + }) + + parentEpml.subscribe('config', (c) => { + if (!configLoaded) { + setTimeout(getQortBtcPrice, 1) + setTimeout(getQortLtcPrice, 1) + setTimeout(getQortDogePrice, 1) + setTimeout(getQortDgbPrice, 1) + setTimeout(getQortRvnPrice, 1) + setTimeout(getQortArrrPrice, 1) + configLoaded = true + } + this.config = JSON.parse(c) + }) + + parentEpml.subscribe('copy_menu_switch', async (value) => { + if (value === 'false' && window.getSelection().toString().length !== 0) this.clearSelection() + }) + + let coinSelectionMenu = this.shadowRoot.getElementById("coinSelectionMenu") + + coinSelectionMenu.addEventListener('change', function () { + _this.setForeignCoin(coinSelectionMenu.value,false) + }) + + _this.setForeignCoin(coinSelectionMenu.value,true) + }) + parentEpml.imReady() + this.btcTradebook() + this.ltcTradebook() + this.dogeTradebook() + this.dgbTradebook() + this.rvnTradebook() + this.arrrTradebook() + } + + changeTheme() { + const checkTheme = localStorage.getItem('qortalTheme') + this.theme = (checkTheme === 'dark') ? 'dark' : 'light' + document.querySelector('html').setAttribute('theme', this.theme); + } + + changeLanguage() { + const checkLanguage = localStorage.getItem('qortalLanguage') + + if (checkLanguage === null || checkLanguage.length === 0) { + localStorage.setItem('qortalLanguage', 'us') + use('us') + } else { + use(checkLanguage) + } + } + + renderFetchText() { + return html`${translate("walletpage.wchange1")}` + } + + renderWarning() { + return html`${translate("tradepage.tchange48")} ${this.listedCoins.get(this.selectedCoin).coinCode}` + } + + renderBotWarning() { + return html`${translate("walletpage.wchange1")}` + } + + showAutoBuyGrid() { + switch(this.listedCoins.get(this.selectedCoin).coinCode) { + case "BTC": + return html`${this.tradeBotBTCTemplate()}` + break + case "LTC": + return html`${this.tradeBotLTCTemplate()}` + break + case "DOGE": + return html`${this.tradeBotDOGETemplate()}` + break + case "DGB": + return html`${this.tradeBotDGBTemplate()}` + break + case "RVN": + return html`${this.tradeBotRVNTemplate()}` + break + case "ARRR": + return html`${this.tradeBotARRRTemplate()}` + break + default: + break + } + } + + exchangeRateQort() { + switch(this.listedCoins.get(this.selectedCoin).coinCode) { + case "BTC": + this.qortRatio = this.qortbtc + break + case "LTC": + this.qortRatio = this.qortltc + break + case "DOGE": + this.qortRatio = this.qortdoge + break + case "DGB": + this.qortRatio = this.qortdgb + break + case "RVN": + this.qortRatio = this.qortrvn + break + case "ARRR": + this.qortRatio = this.qortarrr + break + default: + break + } + return html`${this.qortRatio}` + } + + exchangeRateForeign() { + if (this.listedCoins.get(this.selectedCoin).coinCode === "BTC") { + parentEpml.request('apiCall', { + url: `/crosschain/price/BITCOIN?inverse=false` + }).then((res) => { + this.btcqort = (Number(res) / 1e8).toFixed(8) + }) + return html`${this.btcqort}` + } else if (this.listedCoins.get(this.selectedCoin).coinCode === "LTC") { + parentEpml.request('apiCall', { + url: `/crosschain/price/LITECOIN?inverse=false` + }).then((res) => { + this.ltcqort = (Number(res) / 1e8).toFixed(8) + }) + return html`${this.ltcqort}` + } else if (this.listedCoins.get(this.selectedCoin).coinCode === "DOGE") { + parentEpml.request('apiCall', { + url: `/crosschain/price/DOGECOIN?inverse=false` + }).then((res) => { + this.dogeqort = (Number(res) / 1e8).toFixed(8) + }) + return html`${this.dogeqort}` + } else if (this.listedCoins.get(this.selectedCoin).coinCode === "DGB") { + parentEpml.request('apiCall', { + url: `/crosschain/price/DIGIBYTE?inverse=false` + }).then((res) => { + this.dgbqort = (Number(res) / 1e8).toFixed(8) + }) + return html`${this.dgbqort}` + } else if (this.listedCoins.get(this.selectedCoin).coinCode === "RVN") { + parentEpml.request('apiCall', { + url: `/crosschain/price/RAVENCOIN?inverse=false` + }).then((res) => { + this.rvnqort = (Number(res) / 1e8).toFixed(8) + }) + return html`${this.rvnqort}` + } else if (this.listedCoins.get(this.selectedCoin).coinCode === "ARRR") { + parentEpml.request('apiCall', { + url: `/crosschain/price/PIRATECHAIN?inverse=false` + }).then((res) => { + this.arrrqort = (Number(res) / 1e8).toFixed(8) + }) + return html`${this.arrrqort}` + } + } + + async updateWalletBalance() { + let _url = `` + let _body = null + + switch (this.selectedCoin) { + case 'BITCOIN': + _url = `/crosschain/btc/walletbalance?apiKey=${this.getApiKey()}` + _body = window.parent.reduxStore.getState().app.selectedAddress.btcWallet.derivedMasterPublicKey + break + case 'LITECOIN': + _url = `/crosschain/ltc/walletbalance?apiKey=${this.getApiKey()}` + _body = window.parent.reduxStore.getState().app.selectedAddress.ltcWallet.derivedMasterPublicKey + break + case 'DOGECOIN': + _url = `/crosschain/doge/walletbalance?apiKey=${this.getApiKey()}` + _body = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet.derivedMasterPublicKey + break + case 'DIGIBYTE': + _url = `/crosschain/dgb/walletbalance?apiKey=${this.getApiKey()}` + _body = window.parent.reduxStore.getState().app.selectedAddress.dgbWallet.derivedMasterPublicKey + break + case 'RAVENCOIN': + _url = `/crosschain/rvn/walletbalance?apiKey=${this.getApiKey()}` + _body = window.parent.reduxStore.getState().app.selectedAddress.rvnWallet.derivedMasterPublicKey + break + case 'PIRATECHAIN': + _url = `/crosschain/arrr/walletbalance?apiKey=${this.getApiKey()}` + _body = window.parent.reduxStore.getState().app.selectedAddress.arrrWallet.seed58 + break + default: + break + } + + this.showGetWalletBance = true + this.showAddAutoBuy = false + + await parentEpml.request('apiCall', { + url: _url, + method: 'POST', + body: _body, + }).then((res) => { + if (isNaN(Number(res))) { + let snack1string = get("tradepage.tchange30") + parentEpml.request('showSnackBar', `${snack1string}`) + } else { + this.listedCoins.get(this.selectedCoin).balance = (Number(res) / 1e8).toFixed(8) + } + }) + + this.showGetWalletBance = false + this.showAddAutoBuy = true + } + + async fetchWalletAddress(coin) { + switch (coin) { + case 'PIRATECHAIN': + let res = await parentEpml.request('apiCall', { + url: `/crosschain/arrr/walletaddress?apiKey=${this.getApiKey()}`, + method: 'POST', + body: `${window.parent.reduxStore.getState().app.selectedAddress.arrrWallet.seed58}`, + }) + if (res != null && res.error != 1201) { + this.arrrWalletAddress = res + } + break + + default: + // Not used for other coins yet + break + } + } + + async getDoneTrades() { + const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] + const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port + const myAddress = window.parent.reduxStore.getState().app.selectedAddress.address + switch (this.selectedCoin) { + case 'BITCOIN': + this.isLoadingDoneTrades = true + const doneBtcQortalUrl = `${nodeUrl}/crosschain/trades?foreignBlockchain=BITCOIN&minimumTimestamp=1597310000000&limit=0&reverse=true` + + const doneBtcQortal = await fetch(doneBtcQortalUrl).then(response => { + return response.json() + }) + + this.listedCoins.get(this.selectedCoin).myGridBoughtItems = doneBtcQortal.map(item => { + const searchBtcAddress = item.buyerReceivingAddress + if (searchBtcAddress == myAddress) { + return { + timestamp: item.tradeTimestamp, + foreignAmount: item.foreignAmount, + qortAmount: item.qortAmount + } + } + }).filter(item => !!item) + + this.isLoadingDoneTrades = false + break + case 'LITECOIN': + this.isLoadingDoneTrades = true + const doneLtcQortalUrl = `${nodeUrl}/crosschain/trades?foreignBlockchain=LITECOIN&minimumTimestamp=1597310000000&limit=0&reverse=true` + + const doneLtcQortal = await fetch(doneLtcQortalUrl).then(response => { + return response.json() + }) + + this.listedCoins.get(this.selectedCoin).myGridBoughtItems = doneLtcQortal.map(item => { + const searchLtcAddress = item.buyerReceivingAddress + if (searchLtcAddress == myAddress) { + return { + timestamp: item.tradeTimestamp, + foreignAmount: item.foreignAmount, + qortAmount: item.qortAmount + } + } + }).filter(item => !!item) + + this.isLoadingDoneTrades = false + break + case 'DOGECOIN': + this.isLoadingDoneTrades = true + const doneDogeQortalUrl = `${nodeUrl}/crosschain/trades?foreignBlockchain=DOGECOIN&minimumTimestamp=1597310000000&limit=0&reverse=true` + + const doneDogeQortal = await fetch(doneDogeQortalUrl).then(response => { + return response.json() + }) + + this.listedCoins.get(this.selectedCoin).myGridBoughtItems = doneDogeQortal.map(item => { + const searchDogeAddress = item.buyerReceivingAddress + if (searchDogeAddress == myAddress) { + return { + timestamp: item.tradeTimestamp, + foreignAmount: item.foreignAmount, + qortAmount: item.qortAmount + } + } + }).filter(item => !!item) + + this.isLoadingDoneTrades = false + break + case 'DIGIBYTE': + this.isLoadingDoneTrades = true + const doneDgbQortalUrl = `${nodeUrl}/crosschain/trades?foreignBlockchain=DIGIBYTE&minimumTimestamp=1597310000000&limit=0&reverse=true` + + const doneDgbQortal = await fetch(doneDgbQortalUrl).then(response => { + return response.json() + }) + + this.listedCoins.get(this.selectedCoin).myGridBoughtItems = doneDgbQortal.map(item => { + const searchDgbAddress = item.buyerReceivingAddress + if (searchDgbAddress == myAddress) { + return { + timestamp: item.tradeTimestamp, + foreignAmount: item.foreignAmount, + qortAmount: item.qortAmount + } + } + }).filter(item => !!item) + + this.isLoadingDoneTrades = false + break + case 'RAVENCOIN': + this.isLoadingDoneTrades = true + const doneRvnQortalUrl = `${nodeUrl}/crosschain/trades?foreignBlockchain=RAVENCOIN&minimumTimestamp=1597310000000&limit=0&reverse=true` + + const doneRvnQortal = await fetch(doneRvnQortalUrl).then(response => { + return response.json() + }) + + this.listedCoins.get(this.selectedCoin).myGridBoughtItems = doneRvnQortal.map(item => { + const searchRvnAddress = item.buyerReceivingAddress + if (searchRvnAddress == myAddress) { + return { + timestamp: item.tradeTimestamp, + foreignAmount: item.foreignAmount, + qortAmount: item.qortAmount + } + } + }).filter(item => !!item) + + this.isLoadingDoneTrades = false + break + case 'PIRATECHAIN': + this.isLoadingDoneTrades = true + const doneArrrQortalUrl = `${nodeUrl}/crosschain/trades?foreignBlockchain=PIRATECHAIN&minimumTimestamp=1597310000000&limit=0&reverse=true` + + const doneArrrQortal = await fetch(doneArrrQortalUrl).then(response => { + return response.json() + }) + + this.listedCoins.get(this.selectedCoin).myGridBoughtItems = doneArrrQortal.map(item => { + const searchArrrAddress = item.buyerReceivingAddress + if (searchArrrAddress == myAddress) { + return { + timestamp: item.tradeTimestamp, + foreignAmount: item.foreignAmount, + qortAmount: item.qortAmount + } + } + }).filter(item => !!item) + + this.isLoadingDoneTrades = false + break + default: + break + } + } + + btcTradebook() { + if (localStorage.getItem(this.btcWallet) === null) { + localStorage.setItem(this.btcWallet, "") + } else { + this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]") + } + } + + addToBTCTradebook() { + const addBotBtcQortAmount = this.shadowRoot.getElementById('autoBuyBTCQortAmountInput').value + const addBotBtcPrice = this.shadowRoot.getElementById('autoBuyBTCPriceInput').value + const addBtcQortAmount = this.round(parseFloat(addBotBtcQortAmount)) + const addBtcPrice = this.round(parseFloat(addBotBtcPrice)) + + var oldBtcTradebook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]") + + const newBtcTradebookItem = { + botBtcQortAmount: addBtcQortAmount, + botBtcPrice: addBtcPrice + } + + oldBtcTradebook.push(newBtcTradebookItem) + + localStorage.setItem(this.btcWallet, JSON.stringify(oldBtcTradebook)) + + let btctradebookstring = get("tradepage.tchange44") + parentEpml.request('showSnackBar', `${btctradebookstring}`) + + this.closeBTCTradebookDialog() + this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]") + } + + closeBTCTradebookDialog() { + this.shadowRoot.querySelector('#tradeBotBTCAddDialog').close() + this.clearTradeBotForm() + } + + removeBTCTradebook() { + localStorage.removeItem(this.btcWallet) + localStorage.setItem(this.btcWallet, "") + this.tradeBotBtcBook = JSON.parse(localStorage.getItem(this.btcWallet) || "[]") + + this.autoBuyBotDisable = false + + let btcstring = get("tradepage.tchange41") + parentEpml.request('showSnackBar', `${btcstring}`) + } + + ltcTradebook() { + if (localStorage.getItem(this.ltcWallet) === null) { + localStorage.setItem(this.ltcWallet, "") + } else { + this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]") + } + } + + addToLTCTradebook() { + const addBotLtcQortAmount = this.shadowRoot.getElementById('autoBuyLTCQortAmountInput').value + const addBotLtcPrice = this.shadowRoot.getElementById('autoBuyLTCPriceInput').value + const addLtcQortAmount = this.round(parseFloat(addBotLtcQortAmount)) + const addLtcPrice = this.round(parseFloat(addBotLtcPrice)) + + var oldLtcTradebook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]") + + const newLtcTradebookItem = { + botLtcQortAmount: addLtcQortAmount, + botLtcPrice: addLtcPrice + } + + oldLtcTradebook.push(newLtcTradebookItem) + + localStorage.setItem(this.ltcWallet, JSON.stringify(oldLtcTradebook)) + + let ltctradebookstring = get("tradepage.tchange44") + parentEpml.request('showSnackBar', `${ltctradebookstring}`) + + this.closeLTCTradebookDialog() + this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]") + } + + closeLTCTradebookDialog() { + this.shadowRoot.querySelector('#tradeBotLTCAddDialog').close() + this.clearTradeBotForm() + } + + removeLTCTradebook() { + localStorage.removeItem(this.ltcWallet) + localStorage.setItem(this.ltcWallet, "") + this.tradeBotLtcBook = JSON.parse(localStorage.getItem(this.ltcWallet) || "[]") + + this.autoBuyBotDisable = false + + let ltcstring = get("tradepage.tchange41") + parentEpml.request('showSnackBar', `${ltcstring}`) + } + + dogeTradebook() { + if (localStorage.getItem(this.dogeWallet) === null) { + localStorage.setItem(this.dogeWallet, "") + } else { + this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.dogeWallet) || "[]") + } + } + + addToDOGETradebook() { + const addBotDogeQortAmount = this.shadowRoot.getElementById('autoBuyDOGEQortAmountInput').value + const addBotDogePrice = this.shadowRoot.getElementById('autoBuyDOGEPriceInput').value + const addDogeQortAmount = this.round(parseFloat(addBotDogeQortAmount)) + const addDogePrice = this.round(parseFloat(addBotDogePrice)) + + var oldDogeTradebook = JSON.parse(localStorage.getItem(this.dogeWallet) || "[]") + + const newDogeTradebookItem = { + botDogeQortAmount: addDogeQortAmount, + botDogePrice: addDogePrice + } + + oldDogeTradebook.push(newDogeTradebookItem) + + localStorage.setItem(this.dogeWallet, JSON.stringify(oldDogeTradebook)) + + let dogetradebookstring = get("tradepage.tchange44") + parentEpml.request('showSnackBar', `${dogetradebookstring}`) + + this.closeDOGETradebookDialog() + this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.dogeWallet) || "[]") + } + + closeDOGETradebookDialog() { + this.shadowRoot.querySelector('#tradeBotDOGEAddDialog').close() + this.clearTradeBotForm() + } + + removeDOGETradebook() { + localStorage.removeItem(this.dogeWallet) + localStorage.setItem(this.dogeWallet, "") + this.tradeBotDogeBook = JSON.parse(localStorage.getItem(this.dogeWallet) || "[]") + + this.autoBuyBotDisable = false + + let dogestring = get("tradepage.tchange41") + parentEpml.request('showSnackBar', `${dogestring}`) + } + + dgbTradebook() { + if (localStorage.getItem(this.dgbWallet) === null) { + localStorage.setItem(this.dgbWallet, "") + } else { + this.tradeBotDgbBook = JSON.parse(localStorage.getItem(this.dgbWallet) || "[]") + } + } + + addToDGBTradebook() { + const addBotDgbQortAmount = this.shadowRoot.getElementById('autoBuyDGBQortAmountInput').value + const addBotDgbPrice = this.shadowRoot.getElementById('autoBuyDGBPriceInput').value + const addDgbQortAmount = this.round(parseFloat(addBotDgbQortAmount)) + const addDgbPrice = this.round(parseFloat(addBotDgbPrice)) + + var oldDgbTradebook = JSON.parse(localStorage.getItem(this.dgbWallet) || "[]") + + const newDgbTradebookItem = { + botDgbQortAmount: addDgbQortAmount, + botDgbPrice: addDgbPrice + } + + oldDgbTradebook.push(newDgbTradebookItem) + + localStorage.setItem(this.dgbWallet, JSON.stringify(oldDgbTradebook)) + + let dgbtradebookstring = get("tradepage.tchange44") + parentEpml.request('showSnackBar', `${dgbtradebookstring}`) + + this.closeDGBTradebookDialog() + this.tradeBotDgbBook = JSON.parse(localStorage.getItem(this.dgbWallet) || "[]") + } + + closeDGBTradebookDialog() { + this.shadowRoot.querySelector('#tradeBotDGBAddDialog').close() + this.clearTradeBotForm() + } + + removeDGBTradebook() { + localStorage.removeItem(this.dgbWallet) + localStorage.setItem(this.dgbWallet, "") + this.tradeBotDgbBook = JSON.parse(localStorage.getItem(this.dgbWallet) || "[]") + + this.autoBuyBotDisable = false + + let dgbstring = get("tradepage.tchange41") + parentEpml.request('showSnackBar', `${dgbstring}`) + } + + rvnTradebook() { + if (localStorage.getItem(this.rvnWallet) === null) { + localStorage.setItem(this.rvnWallet, "") + } else { + this.tradeBotRvnBook = JSON.parse(localStorage.getItem(this.rvnWallet) || "[]") + } + } + + addToRVNTradebook() { + const addBotRvnQortAmount = this.shadowRoot.getElementById('autoBuyRVNQortAmountInput').value + const addBotRvnPrice = this.shadowRoot.getElementById('autoBuyRVNPriceInput').value + const addRvnQortAmount = this.round(parseFloat(addBotRvnQortAmount)) + const addRvnPrice = this.round(parseFloat(addBotRvnPrice)) + + var oldRvnTradebook = JSON.parse(localStorage.getItem(this.rvnWallet) || "[]") + + const newRvnTradebookItem = { + botRvnQortAmount: addRvnQortAmount, + botRvnPrice: addRvnPrice + } + + oldRvnTradebook.push(newRvnTradebookItem) + + localStorage.setItem(this.rvnWallet, JSON.stringify(oldRvnTradebook)) + + let rvntradebookstring = get("tradepage.tchange44") + parentEpml.request('showSnackBar', `${rvntradebookstring}`) + + this.closeRVNTradebookDialog() + this.tradeBotRvnBook = JSON.parse(localStorage.getItem(this.rvnWallet) || "[]") + } + + closeRVNTradebookDialog() { + this.shadowRoot.querySelector('#tradeBotRVNAddDialog').close() + this.clearTradeBotForm() + } + + removeRVNTradebook() { + localStorage.removeItem(this.rvnWallet) + localStorage.setItem(this.rvnWallet, "") + this.tradeBotRvnBook = JSON.parse(localStorage.getItem(this.rvnWallet) || "[]") + + this.autoBuyBotDisable = false + + let rvnstring = get("tradepage.tchange41") + parentEpml.request('showSnackBar', `${rvnstring}`) + } + + arrrTradebook() { + if (localStorage.getItem(this.arrrWallet) === null) { + localStorage.setItem(this.arrrWallet, "") + } else { + this.tradeBotArrrBook = JSON.parse(localStorage.getItem(this.arrrWallet) || "[]") + } + } + + addToARRRTradebook() { + const addBotArrrQortAmount = this.shadowRoot.getElementById('autoBuyARRRQortAmountInput').value + const addBotArrrPrice = this.shadowRoot.getElementById('autoBuyARRRPriceInput').value + const addArrrQortAmount = this.round(parseFloat(addBotArrrQortAmount)) + const addArrrPrice = this.round(parseFloat(addBotArrrPrice)) + + var oldArrrTradebook = JSON.parse(localStorage.getItem(this.arrrWallet) || "[]") + + const newArrrTradebookItem = { + botArrrQortAmount: addArrrQortAmount, + botArrrPrice: addArrrPrice + } + + oldArrrTradebook.push(newArrrTradebookItem) + + localStorage.setItem(this.arrrWallet, JSON.stringify(oldArrrTradebook)) + + let arrrtradebookstring = get("tradepage.tchange44") + parentEpml.request('showSnackBar', `${arrrtradebookstring}`) + + this.closeARRRTradebookDialog() + this.tradeBotArrrBook = JSON.parse(localStorage.getItem(this.arrrWallet) || "[]") + } + + closeARRRTradebookDialog() { + this.shadowRoot.querySelector('#tradeBotARRRAddDialog').close() + this.clearTradeBotForm() + } + + removeARRRTradebook() { + localStorage.removeItem(this.arrrWallet) + localStorage.setItem(this.arrrWallet, "") + this.tradeBotArrrBook = JSON.parse(localStorage.getItem(this.arrrWallet) || "[]") + + this.autoBuyBotDisable = false + + let arrrstring = get("tradepage.tchange41") + parentEpml.request('showSnackBar', `${arrrstring}`) + } + + async setForeignCoin(coin,beingInitialized) { + let _this = this + this.selectedCoin = coin + + let coinSelectionMenu=this.shadowRoot.getElementById("coinSelectionMenu") + + if(beingInitialized){ + coinSelectionMenu.shadowRoot.querySelector('.mdc-select--outlined .mdc-select__anchor').setAttribute('style', 'padding-left: 60px;') + let pairIconContainer = document.createElement("span") + let pairicon = (_this.listedCoins.get(_this.selectedCoin).coinCode).toLowerCase() + pairIconContainer.setAttribute("class","pairIconContainer") + pairIconContainer.setAttribute('style', 'left: 10px;top: 50%;transform: translate(0, -50%);height: 26px;width: 45px;position: absolute;background-repeat: no-repeat;background-size: cover;background-image: url(/img/qort'+pairicon+'.png);') + coinSelectionMenu.shadowRoot.querySelector('.mdc-select--outlined .mdc-select__anchor').appendChild(pairIconContainer) + }else{ + let pairIconContainer = coinSelectionMenu.shadowRoot.querySelector(".mdc-select--outlined .mdc-select__anchor span.pairIconContainer") + let pairicon = (_this.listedCoins.get(_this.selectedCoin).coinCode).toLowerCase() + pairIconContainer.style.backgroundImage='url(/img/qort'+pairicon+'.png)' + } + + this.isLoadingOpenTrades = true + this.createConnection() + this._openOrdersGrid.querySelector('#priceColumn').headerRenderer = function (root) { + const priceString2 = get("tradepage.tchange9") + root.innerHTML = '' + priceString2 + ' (' + _this.listedCoins.get(_this.selectedCoin).coinCode + ')' + } + this.clearTradeBotForm() + clearTimeout(this.updateDoneTradesTimeout) + await this.getDoneTrades() + this.updateDoneTradesTimeout = setTimeout(() => this.getDoneTrades(), 180000) + await this.updateWalletBalance() + this.fetchWalletAddress(coin) + + } + + async reRenderOpenFilteredOrders() { + this.requestUpdate() + await this.updateComplete + this.isLoadingOpenTrades = false + } + + async reRenderMyOpenOrders() { + this.requestUpdate() + await this.updateComplete + this.isLoadingMyOpenOrders = false + } + + addAutoBuyAction() { + this.autoBuyWarning = false + this.clearTradeBotForm() + this.shadowRoot.querySelector('#tradeBot' + this.listedCoins.get(this.selectedCoin).coinCode + 'AddDialog').show() + } + + checkTradeBotValues() { + const checkTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value + const checkTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value + const checkAmount = this.round(parseFloat(checkTradeBotAmountInput)) + const checkPrice = this.round(parseFloat(checkTradeBotPriceInput)) + + if (Number(checkAmount) === 0) { + let amountString = get("tradepage.tchange34") + parentEpml.request('showSnackBar', `${amountString}`) + } else if (Number(checkPrice) === 0) { + let priceString = get("tradepage.tchange35") + parentEpml.request('showSnackBar', `${priceString}`) + } else { + this.showAddToAutoBuyStore() + } + } + + showAddToAutoBuyStore() { + switch(this.listedCoins.get(this.selectedCoin).coinCode) { + case "BTC": + this.addToBTCTradebook() + break + case "LTC": + this.addToLTCTradebook() + break + case "DOGE": + this.addToDOGETradebook() + break + case "DGB": + this.addToDGBTradebook() + break + case "RVN": + this.addToRVNTradebook() + break + case "ARRR": + this.addToARRRTradebook() + break + default: + break + } + } + + processOfferingTrade(offer) { + try { + if(this.listedCoins.get(offer.foreignBlockchain).name!='') { + const offerItem = { + ...offer, + qortAmount: parseFloat(offer.qortAmount), + price: parseFloat(offer.foreignAmount) / parseFloat(offer.qortAmount), + } + const addOffer = () => { + this.listedCoins.get(offer.foreignBlockchain).openOrders.unshift(offerItem) + } + const initOffer = () => { + this.listedCoins.get(offer.foreignBlockchain).openOrders.push(offerItem) + } + this.listedCoins.get(offer.foreignBlockchain).openOrders.length === 0 ? initOffer() : addOffer() + this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._openOrdersGrid.clearCache() : null + } + } catch(e) { + console.log("Error adding offer from "+offer.foreignBlockchain) + } + } + + processRedeemedTrade(offer) { + try { + if (this.listedCoins.get(offer.foreignBlockchain).name!='') { + + if (offer.qortalCreator === this.selectedAddress.address) { + if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { + this.updateWalletBalance() + } + const offerItem = { + ...offer, + mode: 'SOLD', + } + this._myHistoricTradesGrid.items.unshift(offerItem) + this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null + } else if (offer.partnerQortalReceivingAddress === this.selectedAddress.address) { + if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { + this.updateWalletBalance() + } + const offerItem = { + ...offer, + mode: 'BOUGHT', + } + this._myHistoricTradesGrid.items.unshift(offerItem) + this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null + } + const addNewHistoricTrade = () => { + this._historicTradesGrid.items.unshift(offer) + this._historicTradesGrid.clearCache() + } + this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? addNewHistoricTrade() : null + + } + } catch(e) { + console.log("Error processing redeemed trade offer from "+offer.foreignBlockchain) + } + } + + processTradingTrade(offer) { + try { + if (this.listedCoins.get(offer.foreignBlockchain).name!='') { + + if (offer.qortalCreator === this.selectedAddress.address && this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { + this.updateWalletBalance() + } + this._openOrdersGrid.items.forEach((item, index) => { + if (item.qortalAtAddress === offer.qortalAtAddress) { + this._openOrdersGrid.items.splice(index, 1) + this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._openOrdersGrid.clearCache() : null + } + }) + this.listedCoins.get(offer.foreignBlockchain).openOrders = this.listedCoins.get(offer.foreignBlockchain).openOrders.filter((order) => order.qortalAtAddress !== offer.qortalAtAddress) + } + } catch(e) { + console.log("Error processing trading trade offer from "+offer.foreignBlockchain) + } + } + + processRefundedTrade(offer) { + try { + if (this.listedCoins.get(offer.foreignBlockchain).name!='') { + + if (offer.qortalCreator === this.selectedAddress.address) { + if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { + this.updateWalletBalance() + } + this._myHistoricTradesGrid.items.unshift(offer) + this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null + } + + } + } catch(e) { + console.log("Error processing refunded trade offer from "+offer.foreignBlockchain) + } + } + + processCancelledTrade(offer) { + try { + if (this.listedCoins.get(offer.foreignBlockchain).name!='') { + + if (offer.qortalCreator === this.selectedAddress.address) { + if (this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1) { + this.updateWalletBalance() + } + this._myHistoricTradesGrid.items.unshift(offer) + this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._myHistoricTradesGrid.clearCache() : null + } + this._openOrdersGrid.items.forEach((item, index) => { + if (item.qortalAtAddress === offer.qortalAtAddress) { + this._openOrdersGrid.items.splice(index, 1) + this.listedCoins.get(offer.foreignBlockchain).tradeOffersSocketCounter > 1 ? this._openOrdersGrid.clearCache() : null + } + }) + this.listedCoins.get(offer.foreignBlockchain).openOrders = this.listedCoins.get(offer.foreignBlockchain).openOrders.filter((order) => order.qortalAtAddress !== offer.qortalAtAddress) + this._stuckOrdersGrid.items.forEach((item, index) => { + if (item.qortalAtAddress === offer.qortalAtAddress) { + this._stuckOrdersGrid.items.splice(index, 1) + this._stuckOrdersGrid.clearCache() + } + }) + } + } catch(e) { + console.log("Error processing cancelled trade offer from "+offer.foreignBlockchain) + } + } + + processTradeOffers(offers) { + offers.forEach((offer) => { + if (offer.mode === 'OFFERING') { + this.processOfferingTrade(offer) + } + }) + } + + processTradeBotStates(tradeStates) { + + const BitcoinACCTv1 = (states) => { + states.reverse() + states.forEach((state) => { + if (state.creatorAddress === this.selectedAddress.address) { + if (state.tradeState == 'ALICE_WAITING_FOR_AT_LOCK') { + this.changeTradeBotState(state, 'BUYING') + } else if (state.tradeState == 'ALICE_DONE') { + this.handleCompletedState(state) + } else if (state.tradeState == 'ALICE_REFUNDING_A') { + this.changeTradeBotState(state, 'REFUNDING') + } else if (state.tradeState == 'ALICE_REFUNDED') { + this.handleCompletedState(state) + } + } + }) + } + + const LitecoinACCTv1 = (states) => { + states.reverse() + states.forEach((state) => { + if (state.creatorAddress === this.selectedAddress.address) { + if (state.tradeState == 'ALICE_WAITING_FOR_AT_LOCK') { + this.changeTradeBotState(state, 'BUYING') + } else if (state.tradeState == 'ALICE_DONE') { + this.handleCompletedState(state) + } else if (state.tradeState == 'ALICE_REFUNDING_A') { + this.changeTradeBotState(state, 'REFUNDING') + } else if (state.tradeState == 'ALICE_REFUNDED') { + this.handleCompletedState(state) + } + } + }) + } + + const DogecoinACCTv1 = (states) => { + states.reverse() + states.forEach((state) => { + if (state.creatorAddress === this.selectedAddress.address) { + if (state.tradeState == 'ALICE_WAITING_FOR_AT_LOCK') { + this.changeTradeBotState(state, 'BUYING') + } else if (state.tradeState == 'ALICE_DONE') { + this.handleCompletedState(state) + } else if (state.tradeState == 'ALICE_REFUNDING_A') { + this.changeTradeBotState(state, 'REFUNDING') + } else if (state.tradeState == 'ALICE_REFUNDED') { + this.handleCompletedState(state) + } + } + }) + } + + const DigibyteACCTv1 = (states) => { + states.reverse() + states.forEach((state) => { + if (state.creatorAddress === this.selectedAddress.address) { + if (state.tradeState == 'ALICE_WAITING_FOR_AT_LOCK') { + this.changeTradeBotState(state, 'BUYING') + } else if (state.tradeState == 'ALICE_DONE') { + this.handleCompletedState(state) + } else if (state.tradeState == 'ALICE_REFUNDING_A') { + this.changeTradeBotState(state, 'REFUNDING') + } else if (state.tradeState == 'ALICE_REFUNDED') { + this.handleCompletedState(state) + } + } + }) + } + + const RavencoinACCTv1 = (states) => { + states.reverse() + states.forEach((state) => { + if (state.creatorAddress === this.selectedAddress.address) { + if (state.tradeState == 'ALICE_WAITING_FOR_AT_LOCK') { + this.changeTradeBotState(state, 'BUYING') + } else if (state.tradeState == 'ALICE_DONE') { + this.handleCompletedState(state) + } else if (state.tradeState == 'ALICE_REFUNDING_A') { + this.changeTradeBotState(state, 'REFUNDING') + } else if (state.tradeState == 'ALICE_REFUNDED') { + this.handleCompletedState(state) + } + } + }) + } + + const PirateChainACCTv1 = (states) => { + states.reverse() + states.forEach((state) => { + if (state.creatorAddress === this.selectedAddress.address) { + if (state.tradeState == 'ALICE_WAITING_FOR_AT_LOCK') { + this.changeTradeBotState(state, 'BUYING') + } else if (state.tradeState == 'ALICE_DONE') { + this.handleCompletedState(state) + } else if (state.tradeState == 'ALICE_REFUNDING_A') { + this.changeTradeBotState(state, 'REFUNDING') + } else if (state.tradeState == 'ALICE_REFUNDED') { + this.handleCompletedState(state) + } + } + }) + } + + switch (this.selectedCoin) { + case 'BITCOIN': + BitcoinACCTv1(tradeStates) + break + case 'LITECOIN': + LitecoinACCTv1(tradeStates) + break + case 'DOGECOIN': + DogecoinACCTv1(tradeStates) + break + case 'DIGIBYTE': + DigibyteACCTv1(tradeStates) + break + case 'RAVENCOIN': + RavencoinACCTv1(tradeStates) + break + case 'PIRATECHAIN': + PirateChainACCTv1(tradeStates) + break + default: + break + } + } + + changeTradeBotState(state, tradeState) { + this.isLoadingMyOpenOrders = true + const stateItem = { + ...state, + _tradeState: tradeState, + } + const item = this._myOrdersGrid.querySelector(`#${state.atAddress}`) + const addStateItem = () => { + this.reRenderMyOpenOrders() + this._myOrdersGrid.items.unshift(stateItem) + this._myOrdersGrid.clearCache() + } + const updateStateItem = () => { + this._myOrdersGrid.items.forEach((item, index) => { + if (item.atAddress === state.atAddress) { + this.reRenderMyOpenOrders() + this._myOrdersGrid.items.splice(index, 1) + this._myOrdersGrid.items.unshift(stateItem) + this._myOrdersGrid.clearCache() + } + }) + } + item ? updateStateItem() : addStateItem() + } + + handleCompletedState(state) { + this._myOrdersGrid.items.forEach((item, index) => { + if (item.atAddress === state.atAddress) { + this.reRenderMyOpenOrders() + this._myOrdersGrid.items.splice(index, 1) + this._myOrdersGrid.clearCache() + } + }) + } + + initSocket() { + let _relatedCoin = "" + let tradePresenceTxns = null + let offeringTrades = null + + self.addEventListener('message', function (event) { + switch (event.data.type) { + case 'open_orders': + offeringTrades = event.data.content + processOffersWithPresence() + break + case 'set_coin': + _relatedCoin = event.data.content + break + default: + break + } + }) + + const lessThanThirtyMinsAgo = (timestamp) => { + const THIRTYMINS = 1000 * 60 * 30 + const thirtyMinsAgo = Date.now() - THIRTYMINS + return timestamp > thirtyMinsAgo + } + + const filterOffersUsingTradePresence = (offeringTrade) => { + return offeringTrade.tradePresenceExpiry > Date.now(); + } + + const processOffersWithPresence = () => { + if (offeringTrades === null) return + + async function asyncForEach(array, callback) { + for (let index = 0; index < array.length; index++) { + await callback(array[index], index, array) + } + } + + const startOfferPresenceMapping = async () => { + + if (tradePresenceTxns !== null) { + await asyncForEach(tradePresenceTxns, async (tradePresence) => { + let offerIndex = offeringTrades.findIndex((offeringTrade) => offeringTrade.qortalCreatorTradeAddress === tradePresence.tradeAddress) + offerIndex !== -1 ? (offeringTrades[offerIndex].tradePresenceExpiry = tradePresence.timestamp) : null + }) + } + + let filteredOffers = offeringTrades.filter((offeringTrade) => filterOffersUsingTradePresence(offeringTrade)) + self.postMessage({ type: 'PRESENCE', data: { offers: offeringTrades, filteredOffers: filteredOffers, relatedCoin: _relatedCoin } }) + } + + startOfferPresenceMapping() + } + + const initTradeOffersWebSocket = (restarted = false) => { + let tradeOffersSocketCounter = 0 + let socketTimeout + let socketLink = `ws://NODEURL/websockets/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN&includeHistoric=true` + const socket = new WebSocket(socketLink) + socket.onopen = () => { + setTimeout(pingSocket, 50) + tradeOffersSocketCounter += 1 + } + socket.onmessage = (e) => { + e.relatedCoin = _relatedCoin + self.postMessage({ + type: 'TRADE_OFFERS', + data: e.data, + counter: tradeOffersSocketCounter, + isRestarted: restarted, + }) + tradeOffersSocketCounter += 1 + restarted = false + } + socket.onclose = () => { + clearTimeout(socketTimeout) + restartTradeOffersWebSocket() + } + socket.onerror = (e) => { + clearTimeout(socketTimeout) + } + const pingSocket = () => { + socket.send('ping') + socketTimeout = setTimeout(pingSocket, 295000) + } + } + + const initTradeBotWebSocket = (restarted = false) => { + let socketTimeout + let socketLink = `ws://NODEURL/websockets/crosschain/tradebot?foreignBlockchain=FOREIGN_BLOCKCHAIN` + const socket = new WebSocket(socketLink) + socket.onopen = () => { + setTimeout(pingSocket, 50) + } + socket.onmessage = (e) => { + e.relatedCoin = _relatedCoin + self.postMessage({ + type: 'TRADE_BOT', + data: e.data, + isRestarted: restarted, + }) + restarted = false + } + socket.onclose = () => { + clearTimeout(socketTimeout) + restartTradeBotWebSocket() + } + socket.onerror = (e) => { + clearTimeout(socketTimeout) + } + const pingSocket = () => { + socket.send('ping') + socketTimeout = setTimeout(pingSocket, 295000) + } + } + + const initTradePresenceWebSocket = (restarted = false) => { + let socketTimeout + let socketLink = `ws://NODEURL/websockets/crosschain/tradepresence` + const socket = new WebSocket(socketLink) + socket.onopen = () => { + setTimeout(pingSocket, 50) + } + socket.onmessage = (e) => { + tradePresenceTxns = JSON.parse(e.data) + processOffersWithPresence() + restarted = false + } + socket.onclose = () => { + clearTimeout(socketTimeout) + restartTradePresenceWebSocket() + } + socket.onerror = (e) => { + clearTimeout(socketTimeout) + } + const pingSocket = () => { + socket.send('ping') + socketTimeout = setTimeout(pingSocket, 295000) + } + } + + const restartTradePresenceWebSocket = () => { + setTimeout(() => initTradePresenceWebSocket(true), 50) + } + + const restartTradeOffersWebSocket = () => { + setTimeout(() => initTradeOffersWebSocket(true), 50) + } + + const restartTradeBotWebSocket = () => { + setTimeout(() => initTradeBotWebSocket(true), 50) + } + + initTradeOffersWebSocket() + initTradePresenceWebSocket() + initTradeBotWebSocket() + } + + updateAccountBalance() { + clearTimeout(this.updateAccountBalanceTimeout) + parentEpml.request('apiCall', { + url: `/addresses/balance/${this.selectedAddress.address}?apiKey=${this.getApiKey()}`, + }) + .then((res) => { + this.listedCoins.get("QORTAL").balance = res + this.updateAccountBalanceTimeout = setTimeout(() => this.updateAccountBalance(), 10000) + }) + } + + _checkBuyAmount(e) { + const targetAmount = e.target.value + const target = e.target + + if (targetAmount.length === 0) { + this.isValidAmount = false + this.sellBtnDisable = true + e.target.blur() + e.target.focus() + e.target.invalid = true + } else { + this.buyBtnDisable = false + } + + e.target.blur() + e.target.focus() + + e.target.validityTransform = (newValue, nativeValidity) => { + if (newValue.includes('-') === true) { + this.buyBtnDisable = true + return { + valid: false, + } + } else if (!nativeValidity.valid) { + if (newValue.includes('.') === true) { + let myAmount = newValue.split('.') + if (myAmount[1].length > 8) { + this.buyBtnDisable = true + } else { + this.buyBtnDisable = false + return { + valid: true, + } + } + } + } else { + this.buyBtnDisable = false + } + } + } + + checkTradeBotAmount(e) { + const targetAmount = e.target.value + const target = e.target + this.autoBuyWarning = false + + if (targetAmount.length === 0) { + this.isValidAmount = false + this.autoBuyBtnDisable = true + this.autoBuyWarning = false + e.target.blur() + e.target.focus() + e.target.invalid = true + } else { + const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value + const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value + const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) + const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) + if (Number(myFunds) > Number(checkFunds)) { + this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) + this.autoBuyBtnDisable = false + this.autoBuyWarning = false + } else { + this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) + this.autoBuyBtnDisable = true + this.autoBuyWarning = true + } + } + + e.target.blur() + e.target.focus() + + e.target.validityTransform = (newValue, nativeValidity) => { + if (newValue.includes('-') === true) { + this.autoBuyBtnDisable = true + this.autoBuyWarning = false + return { + valid: false, + } + } else if (!nativeValidity.valid) { + if (newValue.includes('.') === true) { + let myAmount = newValue.split('.') + if (myAmount[1].length > 8) { + this.autoBuyBtnDisable = true + this.autoBuyWarning = false + } else { + const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value + const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value + const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) + const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) + if (Number(myFunds) > Number(checkFunds)) { + this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) + this.autoBuyBtnDisable = false + this.autoBuyWarning = false + } else { + this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) + this.autoBuyBtnDisable = true + this.autoBuyWarning = true + } + return { + valid: true, + } + } + } + } else { + const buyTradeBotAmountInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value + const buyTradeBotPriceInput = this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value + const checkFunds = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) + const myFunds = this.round(parseFloat(this.listedCoins.get(this.selectedCoin).balance)) + if (Number(myFunds) > Number(checkFunds)) { + this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) + this.autoBuyBtnDisable = false + this.autoBuyWarning = false + } else { + this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.round(parseFloat(buyTradeBotAmountInput) * parseFloat(buyTradeBotPriceInput)) + this.autoBuyBtnDisable = true + this.autoBuyWarning = true + } + } + } + } + + getApiKey() { + const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]; + let apiKey = myNode.apiKey; + return apiKey; + } + + clearSelection() { + window.getSelection().removeAllRanges() + window.parent.getSelection().removeAllRanges() + } + + _textMenu(event) { + const getSelectedText = () => { + var text = '' + if (typeof window.getSelection != 'undefined') { + text = window.getSelection().toString() + } else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') { + text = this.shadowRoot.selection.createRange().text + } + return text + } + + const checkSelectedTextAndShowMenu = () => { + let selectedText = getSelectedText() + if (selectedText && typeof selectedText === 'string') { + let _eve = { + pageX: event.pageX, + pageY: event.pageY, + clientX: event.clientX, + clientY: event.clientY, + } + let textMenuObject = { + selectedText: selectedText, + eventObject: _eve, + isFrame: true, + } + parentEpml.request('openCopyTextMenu', textMenuObject) + } + } + checkSelectedTextAndShowMenu() + } + + clearTradeBotForm() { + this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'QortAmountInput').value = this.initialAmount + this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'PriceInput').value = this.initialAmount + this.shadowRoot.getElementById('autoBuy' + this.listedCoins.get(this.selectedCoin).coinCode + 'TotalInput').value = this.initialAmount + this.autoBuyBtnDisable = true + } + + isEmptyArray(arr) { + if (!arr) { + return true + } + return arr.length === 0 + } + + round(number) { + let result = (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8) + return result + } + + inlineWorker(passedFunction, modifiers) { + let parsedFunction = `` + + modifiers.forEach((modifier) => { + let regex = new RegExp(modifier.searchValue, 'g') + parsedFunction = parsedFunction.length === 0 ? `(function ${passedFunction.toString().trim().replace(regex, modifier.replaceValue)})()` : parsedFunction.toString().trim().replace(regex, modifier.replaceValue) + }) + + const workerUrl = URL.createObjectURL(new Blob([parsedFunction], { type: 'text/javascript' })) + const worker = new Worker(workerUrl) + URL.revokeObjectURL(workerUrl) + return worker + } + + clearPaneCache() { + this._openOrdersGrid.clearCache() + this._myOrdersGrid.clearCache() + } + + createConnection() { + if (workers.get(this.selectedCoin).tradesConnectedWorker !== null) { + this.isLoadingHistoricTrades = false + this.isLoadingOpenTrades = false + return + } + + const handleMessage = (message) => { + switch (message.type) { + case 'TRADE_OFFERS': + if (!message.isRestarted) { + this.listedCoins.get(this.selectedCoin).tradeOffersSocketCounter = message.counter + this.processTradeOffers(JSON.parse(message.data)) + this.listedCoins.get(this.selectedCoin).tradeOffersSocketCounter === 1 ? this.clearPaneCache() : null + workers.get(this.selectedCoin).tradesConnectedWorker.postMessage(this.listedCoins.get(this.selectedCoin).openOrders) + workers.get(this.selectedCoin).tradesConnectedWorker.postMessage({ type: "open_orders", content: this.listedCoins.get(this.selectedCoin).openOrders }) + } + return null + case 'TRADE_BOT': + if (!message.isRestarted) this.processTradeBotStates(JSON.parse(message.data)) + return null + case 'PRESENCE': + this.listedCoins.get(message.data.relatedCoin).openOrders = message.data.offers + this.listedCoins.get(message.data.relatedCoin).openFilteredOrders = message.data.filteredOffers + this.reRenderOpenFilteredOrders() + return null + default: + break + } + } + + let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node] + let nodeUrl = myNode.domain + ':' + myNode.port + + const modifiers = [ + { searchValue: 'NODEURL', replaceValue: nodeUrl }, + { searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin }, + ] + + workers.get(this.selectedCoin).tradesConnectedWorker = this.inlineWorker(this.initSocket, modifiers) + + workers.get(this.selectedCoin).tradesConnectedWorker.addEventListener('message', function (event) { handleMessage(event.data) }, { passive: true }) + + workers.get(this.selectedCoin).tradesConnectedWorker.postMessage({ type: "set_coin", content: this.selectedCoin }) + } +} + +window.customElements.define('trade-bot-portal', TradeBotPortal) \ No newline at end of file