From f8ceaa56c51eb376b539b29d6e7c15e9bae53558 Mon Sep 17 00:00:00 2001
From: AlphaX-Projects <77661270+AlphaX-Projects@users.noreply.github.com>
Date: Mon, 9 Jan 2023 15:03:59 +0100
Subject: [PATCH] Add chart js files
---
.../core/trade-portal/charts/arrr-charts.js | 214 +++++++++++++++++
.../core/trade-portal/charts/btc-charts.js | 215 ++++++++++++++++++
.../core/trade-portal/charts/dgb-charts.js | 214 +++++++++++++++++
.../core/trade-portal/charts/doge-charts.js | 214 +++++++++++++++++
.../core/trade-portal/charts/ltc-charts.js | 214 +++++++++++++++++
.../core/trade-portal/charts/rvn-charts.js | 214 +++++++++++++++++
6 files changed, 1285 insertions(+)
create mode 100644 qortal-ui-plugins/plugins/core/trade-portal/charts/arrr-charts.js
create mode 100644 qortal-ui-plugins/plugins/core/trade-portal/charts/btc-charts.js
create mode 100644 qortal-ui-plugins/plugins/core/trade-portal/charts/dgb-charts.js
create mode 100644 qortal-ui-plugins/plugins/core/trade-portal/charts/doge-charts.js
create mode 100644 qortal-ui-plugins/plugins/core/trade-portal/charts/ltc-charts.js
create mode 100644 qortal-ui-plugins/plugins/core/trade-portal/charts/rvn-charts.js
diff --git a/qortal-ui-plugins/plugins/core/trade-portal/charts/arrr-charts.js b/qortal-ui-plugins/plugins/core/trade-portal/charts/arrr-charts.js
new file mode 100644
index 00000000..561cd9df
--- /dev/null
+++ b/qortal-ui-plugins/plugins/core/trade-portal/charts/arrr-charts.js
@@ -0,0 +1,214 @@
+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 '@polymer/paper-dialog/paper-dialog.js'
+import * as Highcharts from 'highcharts'
+import Exporting from 'highcharts/modules/exporting'
+Exporting(Highcharts)
+import StockChart from 'highcharts/modules/stock'
+StockChart(Highcharts)
+import 'highcharts/highcharts-more.js'
+import 'highcharts/modules/accessibility.js'
+import 'highcharts/modules/boost.js'
+import 'highcharts/modules/data.js'
+import 'highcharts/modules/export-data.js'
+import 'highcharts/modules/offline-exporting.js'
+
+let arrrChartDialog
+
+const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
+
+class ArrrCharts extends LitElement {
+ static get properties() {
+ return {
+ isLoadingTradesChart: { type: Boolean },
+ arrrTrades: { type: Array },
+ arrrPrice: { type: Array }
+ }
+ }
+
+ static get styles() {
+ return css`
+ .loadingContainer {
+ height: 100%;
+ width: 100%;
+ }
+
+ .trades-chart {
+ color: var(--black);
+ background: var(--white);
+ border: 1px solid var(--black);
+ border-radius: 25px;
+ padding: 15px;
+ }
+
+ .chart-container {
+ margin: auto;
+ color: var(--black);
+ text-align: center;
+ padding: 15px;
+ height: 30vh;
+ width: 80vw;
+ }
+
+ .chart-info-wrapper {
+ background: transparent;
+ height: 38vh;
+ width: 83vw;
+ overflow: auto;
+ }
+
+ .chart-loading-wrapper {
+ color: var(--black);
+ background: var(--white);
+ border: 1px solid var(--black);
+ border-radius: 15px;
+ }
+ `
+ }
+
+ constructor() {
+ super()
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
+ this.isLoadingTradesChart = false
+ this.arrrTrades = []
+ this.arrrPrice = []
+ }
+
+ render() {
+ return html`
+
+
+ ${translate("login.loading")}
+
+
+
+
+
+ `
+ }
+
+ async firstUpdated() {
+ this.changeTheme()
+ this.changeLanguage()
+
+ 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)
+ })
+ }
+
+ async loadTradesChart() {
+ this.isLoadingTradesChart = true
+ this.shadowRoot.getElementById('loadChartDialog').open()
+ await this.getArrrTrades()
+ this.isLoadingTradesChart = false
+ this.shadowRoot.getElementById('loadChartDialog').close()
+ this.enableArrrStockPriceChart()
+ }
+
+ async getArrrTrades() {
+ let currentArrrTimestamp = Date.now()
+ const monthBackArrr = currentArrrTimestamp - 31556952000
+ await parentEpml.request("apiCall", { url: `/crosschain/trades?foreignBlockchain=PIRATECHAIN&minimumTimestamp=${monthBackArrr}&limit=0&reverse=false` }).then((res) => {
+ this.arrrTrades = res
+ })
+ this.arrrPrice = this.arrrTrades.map(item => {
+ const arrrSellPrice = this.round(parseFloat(item.foreignAmount) / parseFloat(item.qortAmount))
+ return [item.tradeTimestamp, parseFloat(arrrSellPrice)]
+ }).filter(item => !!item)
+ }
+
+ enableArrrStockPriceChart() {
+ const arrrStockPriceData = this.arrrPrice
+ const header = 'QORT / ARRR ' + get("tradepage.tchange49")
+ Highcharts.stockChart(this.shadowRoot.querySelector('#arrrStockPriceContainer'), {
+ accessibility: {
+ enabled: false
+ },
+ credits: {
+ enabled: false
+ },
+ rangeSelector: {
+ selected: 1,
+ labelStyle: {color: 'var(--black)'},
+ inputStyle: {color: '#03a9f4'}
+ },
+ chart: {
+ backgroundColor: 'transparent'
+ },
+ title: {
+ text: header,
+ style: {color: 'var(--black)'}
+ },
+ xAxis: {
+ labels: {
+ style: {
+ color: '#03a9f4'
+ }
+ }
+ },
+ yAxis: {
+ labels: {
+ style: {
+ color: '#03a9f4'
+ }
+ }
+ },
+ series: [{
+ name: 'QORT / ARRR',
+ data: arrrStockPriceData,
+ tooltip: {
+ valueDecimals: 8
+ }
+ }]
+ })
+ }
+
+ async open() {
+ await this.loadTradesChart()
+ this.shadowRoot.getElementById('arrrChartDialog').open()
+ }
+
+ 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)
+ }
+ }
+
+ round(number) {
+ let result = (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8)
+ return result
+ }
+}
+
+window.customElements.define('arrr-charts', ArrrCharts)
+
+const chartsarrr = document.createElement('arrr-charts')
+arrrChartDialog = document.body.appendChild(chartsarrr)
+
+export default arrrChartDialog
\ No newline at end of file
diff --git a/qortal-ui-plugins/plugins/core/trade-portal/charts/btc-charts.js b/qortal-ui-plugins/plugins/core/trade-portal/charts/btc-charts.js
new file mode 100644
index 00000000..c31d272b
--- /dev/null
+++ b/qortal-ui-plugins/plugins/core/trade-portal/charts/btc-charts.js
@@ -0,0 +1,215 @@
+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 '@polymer/paper-dialog/paper-dialog.js'
+import * as Highcharts from 'highcharts'
+import Exporting from 'highcharts/modules/exporting'
+Exporting(Highcharts)
+import StockChart from 'highcharts/modules/stock'
+StockChart(Highcharts)
+import 'highcharts/highcharts-more.js'
+import 'highcharts/modules/accessibility.js'
+import 'highcharts/modules/boost.js'
+import 'highcharts/modules/data.js'
+import 'highcharts/modules/export-data.js'
+import 'highcharts/modules/offline-exporting.js'
+
+let btcChartDialog
+
+const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
+
+class BtcCharts extends LitElement {
+ static get properties() {
+ return {
+ isLoadingTradesChart: { type: Boolean },
+ btcTrades: { type: Array },
+ btcPrice: { type: Array }
+ }
+ }
+
+ static get styles() {
+ return css`
+ .loadingContainer {
+ height: 100%;
+ width: 100%;
+ }
+
+ .trades-chart {
+ color: var(--black);
+ background: var(--white);
+ border: 1px solid var(--black);
+ border-radius: 25px;
+ padding: 15px;
+ }
+
+ .chart-container {
+ margin: auto;
+ color: var(--black);
+ text-align: center;
+ padding: 15px;
+ height: 30vh;
+ width: 80vw;
+ }
+
+ .chart-info-wrapper {
+ background: transparent;
+ height: 38vh;
+ width: 83vw;
+ overflow: auto;
+ }
+
+ .chart-loading-wrapper {
+ color: var(--black);
+ background: var(--white);
+ border: 1px solid var(--black);
+ border-radius: 15px;
+ }
+ `
+ }
+
+ constructor() {
+ super()
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
+ this.isLoadingTradesChart = false
+ this.btcTrades = []
+ this.btcPrice = []
+ }
+
+ render() {
+ return html`
+
+
+ ${translate("login.loading")}
+
+
+
+
+
+ `
+ }
+
+ async firstUpdated() {
+ this.changeTheme()
+ this.changeLanguage()
+
+ 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)
+ })
+ }
+
+ async loadTradesChart() {
+ this.isLoadingTradesChart = true
+ this.shadowRoot.getElementById('loadChartDialog').open()
+ await this.getBtcTrades()
+ this.isLoadingTradesChart = false
+ this.shadowRoot.getElementById('loadChartDialog').close()
+ this.enableBtcStockPriceChart()
+ }
+
+ async getBtcTrades() {
+ let currentBtcTimestamp = Date.now()
+ const monthBackBtc = currentBtcTimestamp - 31556952000
+ await parentEpml.request("apiCall", { url: `/crosschain/trades?foreignBlockchain=BITCOIN&minimumTimestamp=${monthBackBtc}&limit=0&reverse=false` }).then((res) => {
+ this.btcTrades = res
+ })
+
+ this.btcPrice = this.btcTrades.map(item => {
+ const btcSellPrice = this.round(parseFloat(item.foreignAmount) / parseFloat(item.qortAmount))
+ return [item.tradeTimestamp, parseFloat(btcSellPrice)]
+ }).filter(item => !!item)
+ }
+
+ enableBtcStockPriceChart() {
+ const btcStockPriceData = this.btcPrice
+ const header = 'QORT / BTC ' + get("tradepage.tchange49")
+ Highcharts.stockChart(this.shadowRoot.querySelector('#btcStockPriceContainer'), {
+ accessibility: {
+ enabled: false
+ },
+ credits: {
+ enabled: false
+ },
+ rangeSelector: {
+ selected: 1,
+ labelStyle: {color: 'var(--black)'},
+ inputStyle: {color: '#03a9f4'}
+ },
+ chart: {
+ backgroundColor: 'transparent'
+ },
+ title: {
+ text: header,
+ style: {color: 'var(--black)'}
+ },
+ xAxis: {
+ labels: {
+ style: {
+ color: '#03a9f4'
+ }
+ }
+ },
+ yAxis: {
+ labels: {
+ style: {
+ color: '#03a9f4'
+ }
+ }
+ },
+ series: [{
+ name: 'QORT / BTC',
+ data: btcStockPriceData,
+ tooltip: {
+ valueDecimals: 8
+ }
+ }]
+ })
+ }
+
+ async open() {
+ await this.loadTradesChart()
+ this.shadowRoot.getElementById('btcChartDialog').open()
+ }
+
+ 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)
+ }
+ }
+
+ round(number) {
+ let result = (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8)
+ return result
+ }
+}
+
+window.customElements.define('btc-charts', BtcCharts)
+
+const chartsbtc = document.createElement('btc-charts')
+btcChartDialog = document.body.appendChild(chartsbtc)
+
+export default btcChartDialog
\ No newline at end of file
diff --git a/qortal-ui-plugins/plugins/core/trade-portal/charts/dgb-charts.js b/qortal-ui-plugins/plugins/core/trade-portal/charts/dgb-charts.js
new file mode 100644
index 00000000..5e57aad7
--- /dev/null
+++ b/qortal-ui-plugins/plugins/core/trade-portal/charts/dgb-charts.js
@@ -0,0 +1,214 @@
+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 '@polymer/paper-dialog/paper-dialog.js'
+import * as Highcharts from 'highcharts'
+import Exporting from 'highcharts/modules/exporting'
+Exporting(Highcharts)
+import StockChart from 'highcharts/modules/stock'
+StockChart(Highcharts)
+import 'highcharts/highcharts-more.js'
+import 'highcharts/modules/accessibility.js'
+import 'highcharts/modules/boost.js'
+import 'highcharts/modules/data.js'
+import 'highcharts/modules/export-data.js'
+import 'highcharts/modules/offline-exporting.js'
+
+let dgbChartDialog
+
+const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
+
+class DgbCharts extends LitElement {
+ static get properties() {
+ return {
+ isLoadingTradesChart: { type: Boolean },
+ dgbTrades: { type: Array },
+ dgbPrice: { type: Array }
+ }
+ }
+
+ static get styles() {
+ return css`
+ .loadingContainer {
+ height: 100%;
+ width: 100%;
+ }
+
+ .trades-chart {
+ color: var(--black);
+ background: var(--white);
+ border: 1px solid var(--black);
+ border-radius: 25px;
+ padding: 15px;
+ }
+
+ .chart-container {
+ margin: auto;
+ color: var(--black);
+ text-align: center;
+ padding: 15px;
+ height: 30vh;
+ width: 80vw;
+ }
+
+ .chart-info-wrapper {
+ background: transparent;
+ height: 38vh;
+ width: 83vw;
+ overflow: auto;
+ }
+
+ .chart-loading-wrapper {
+ color: var(--black);
+ background: var(--white);
+ border: 1px solid var(--black);
+ border-radius: 15px;
+ }
+ `
+ }
+
+ constructor() {
+ super()
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
+ this.isLoadingTradesChart = false
+ this.dgbTrades = []
+ this.dgbPrice = []
+ }
+
+ render() {
+ return html`
+
+
+ ${translate("login.loading")}
+
+
+
+
+
+ `
+ }
+
+ async firstUpdated() {
+ this.changeTheme()
+ this.changeLanguage()
+
+ 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)
+ })
+ }
+
+ async loadTradesChart() {
+ this.isLoadingTradesChart = true
+ this.shadowRoot.getElementById('loadChartDialog').open()
+ await this.getDgbTrades()
+ this.isLoadingTradesChart = false
+ this.shadowRoot.getElementById('loadChartDialog').close()
+ this.enableDgbStockPriceChart()
+ }
+
+ async getDgbTrades() {
+ let currentDgbTimestamp = Date.now()
+ const monthBackDgb = currentDgbTimestamp - 31556952000
+ await parentEpml.request("apiCall", { url: `/crosschain/trades?foreignBlockchain=DIGIBYTE&minimumTimestamp=${monthBackDgb}&limit=0&reverse=false` }).then((res) => {
+ this.dgbTrades = res
+ })
+ this.dgbPrice = this.dgbTrades.map(item => {
+ const dgbSellPrice = this.round(parseFloat(item.foreignAmount) / parseFloat(item.qortAmount))
+ return [item.tradeTimestamp, parseFloat(dgbSellPrice)]
+ }).filter(item => !!item)
+ }
+
+ enableDgbStockPriceChart() {
+ const dgbStockPriceData = this.dgbPrice
+ const header = 'QORT / DGB ' + get("tradepage.tchange49")
+ Highcharts.stockChart(this.shadowRoot.querySelector('#dgbStockPriceContainer'), {
+ accessibility: {
+ enabled: false
+ },
+ credits: {
+ enabled: false
+ },
+ rangeSelector: {
+ selected: 1,
+ labelStyle: {color: 'var(--black)'},
+ inputStyle: {color: '#03a9f4'}
+ },
+ chart: {
+ backgroundColor: 'transparent'
+ },
+ title: {
+ text: header,
+ style: {color: 'var(--black)'}
+ },
+ xAxis: {
+ labels: {
+ style: {
+ color: '#03a9f4'
+ }
+ }
+ },
+ yAxis: {
+ labels: {
+ style: {
+ color: '#03a9f4'
+ }
+ }
+ },
+ series: [{
+ name: 'QORT / DGB',
+ data: dgbStockPriceData,
+ tooltip: {
+ valueDecimals: 8
+ }
+ }]
+ })
+ }
+
+ async open() {
+ await this.loadTradesChart()
+ this.shadowRoot.getElementById('dgbChartDialog').open()
+ }
+
+ 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)
+ }
+ }
+
+ round(number) {
+ let result = (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8)
+ return result
+ }
+}
+
+window.customElements.define('dgb-charts', DgbCharts)
+
+const chartsdgb = document.createElement('dgb-charts')
+dgbChartDialog = document.body.appendChild(chartsdgb)
+
+export default dgbChartDialog
\ No newline at end of file
diff --git a/qortal-ui-plugins/plugins/core/trade-portal/charts/doge-charts.js b/qortal-ui-plugins/plugins/core/trade-portal/charts/doge-charts.js
new file mode 100644
index 00000000..a4267361
--- /dev/null
+++ b/qortal-ui-plugins/plugins/core/trade-portal/charts/doge-charts.js
@@ -0,0 +1,214 @@
+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 '@polymer/paper-dialog/paper-dialog.js'
+import * as Highcharts from 'highcharts'
+import Exporting from 'highcharts/modules/exporting'
+Exporting(Highcharts)
+import StockChart from 'highcharts/modules/stock'
+StockChart(Highcharts)
+import 'highcharts/highcharts-more.js'
+import 'highcharts/modules/accessibility.js'
+import 'highcharts/modules/boost.js'
+import 'highcharts/modules/data.js'
+import 'highcharts/modules/export-data.js'
+import 'highcharts/modules/offline-exporting.js'
+
+let dogeChartDialog
+
+const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
+
+class DogeCharts extends LitElement {
+ static get properties() {
+ return {
+ isLoadingTradesChart: { type: Boolean },
+ dogeTrades: { type: Array },
+ dogePrice: { type: Array }
+ }
+ }
+
+ static get styles() {
+ return css`
+ .loadingContainer {
+ height: 100%;
+ width: 100%;
+ }
+
+ .trades-chart {
+ color: var(--black);
+ background: var(--white);
+ border: 1px solid var(--black);
+ border-radius: 25px;
+ padding: 15px;
+ }
+
+ .chart-container {
+ margin: auto;
+ color: var(--black);
+ text-align: center;
+ padding: 15px;
+ height: 30vh;
+ width: 80vw;
+ }
+
+ .chart-info-wrapper {
+ background: transparent;
+ height: 38vh;
+ width: 83vw;
+ overflow: auto;
+ }
+
+ .chart-loading-wrapper {
+ color: var(--black);
+ background: var(--white);
+ border: 1px solid var(--black);
+ border-radius: 15px;
+ }
+ `
+ }
+
+ constructor() {
+ super()
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
+ this.isLoadingTradesChart = false
+ this.dogeTrades = []
+ this.dogePrice = []
+ }
+
+ render() {
+ return html`
+
+
+ ${translate("login.loading")}
+
+
+
+
+
+ `
+ }
+
+ async firstUpdated() {
+ this.changeTheme()
+ this.changeLanguage()
+
+ 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)
+ })
+ }
+
+ async loadTradesChart() {
+ this.isLoadingTradesChart = true
+ this.shadowRoot.getElementById('loadChartDialog').open()
+ await this.getDogeTrades()
+ this.isLoadingTradesChart = false
+ this.shadowRoot.getElementById('loadChartDialog').close()
+ this.enableDogeStockPriceChart()
+ }
+
+ async getDogeTrades() {
+ let currentDogeTimestamp = Date.now()
+ const monthBackDoge = currentDogeTimestamp - 31556952000
+ await parentEpml.request("apiCall", { url: `/crosschain/trades?foreignBlockchain=DOGECOIN&minimumTimestamp=${monthBackDoge}&limit=0&reverse=false` }).then((res) => {
+ this.dogeTrades = res
+ })
+ this.dogePrice = this.dogeTrades.map(item => {
+ const dogeSellPrice = this.round(parseFloat(item.foreignAmount) / parseFloat(item.qortAmount))
+ return [item.tradeTimestamp, parseFloat(dogeSellPrice)]
+ }).filter(item => !!item)
+ }
+
+ enableDogeStockPriceChart() {
+ const dogeStockPriceData = this.dogePrice
+ const header = 'QORT / DOGE ' + get("tradepage.tchange49")
+ Highcharts.stockChart(this.shadowRoot.querySelector('#dogeStockPriceContainer'), {
+ accessibility: {
+ enabled: false
+ },
+ credits: {
+ enabled: false
+ },
+ rangeSelector: {
+ selected: 1,
+ labelStyle: {color: 'var(--black)'},
+ inputStyle: {color: '#03a9f4'}
+ },
+ chart: {
+ backgroundColor: 'transparent'
+ },
+ title: {
+ text: header,
+ style: {color: 'var(--black)'}
+ },
+ xAxis: {
+ labels: {
+ style: {
+ color: '#03a9f4'
+ }
+ }
+ },
+ yAxis: {
+ labels: {
+ style: {
+ color: '#03a9f4'
+ }
+ }
+ },
+ series: [{
+ name: 'QORT / DOGE',
+ data: dogeStockPriceData,
+ tooltip: {
+ valueDecimals: 8
+ }
+ }]
+ })
+ }
+
+ async open() {
+ await this.loadTradesChart()
+ this.shadowRoot.getElementById('dogeChartDialog').open()
+ }
+
+ 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)
+ }
+ }
+
+ round(number) {
+ let result = (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8)
+ return result
+ }
+}
+
+window.customElements.define('doge-charts', DogeCharts)
+
+const chartsdoge = document.createElement('doge-charts')
+dogeChartDialog = document.body.appendChild(chartsdoge)
+
+export default dogeChartDialog
\ No newline at end of file
diff --git a/qortal-ui-plugins/plugins/core/trade-portal/charts/ltc-charts.js b/qortal-ui-plugins/plugins/core/trade-portal/charts/ltc-charts.js
new file mode 100644
index 00000000..08ffd339
--- /dev/null
+++ b/qortal-ui-plugins/plugins/core/trade-portal/charts/ltc-charts.js
@@ -0,0 +1,214 @@
+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 '@polymer/paper-dialog/paper-dialog.js'
+import * as Highcharts from 'highcharts'
+import Exporting from 'highcharts/modules/exporting'
+Exporting(Highcharts)
+import StockChart from 'highcharts/modules/stock'
+StockChart(Highcharts)
+import 'highcharts/highcharts-more.js'
+import 'highcharts/modules/accessibility.js'
+import 'highcharts/modules/boost.js'
+import 'highcharts/modules/data.js'
+import 'highcharts/modules/export-data.js'
+import 'highcharts/modules/offline-exporting.js'
+
+let ltcChartDialog
+
+const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
+
+class LtcCharts extends LitElement {
+ static get properties() {
+ return {
+ isLoadingTradesChart: { type: Boolean },
+ ltcTrades: { type: Array },
+ ltcPrice: { type: Array }
+ }
+ }
+
+ static get styles() {
+ return css`
+ .loadingContainer {
+ height: 100%;
+ width: 100%;
+ }
+
+ .trades-chart {
+ color: var(--black);
+ background: var(--white);
+ border: 1px solid var(--black);
+ border-radius: 25px;
+ padding: 15px;
+ }
+
+ .chart-container {
+ margin: auto;
+ color: var(--black);
+ text-align: center;
+ padding: 15px;
+ height: 30vh;
+ width: 80vw;
+ }
+
+ .chart-info-wrapper {
+ background: transparent;
+ height: 38vh;
+ width: 83vw;
+ overflow: auto;
+ }
+
+ .chart-loading-wrapper {
+ color: var(--black);
+ background: var(--white);
+ border: 1px solid var(--black);
+ border-radius: 15px;
+ }
+ `
+ }
+
+ constructor() {
+ super()
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
+ this.isLoadingTradesChart = false
+ this.ltcTrades = []
+ this.ltcPrice = []
+ }
+
+ render() {
+ return html`
+
+
+ ${translate("login.loading")}
+
+
+
+
+
+ `
+ }
+
+ async firstUpdated() {
+ this.changeTheme()
+ this.changeLanguage()
+
+ 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)
+ })
+ }
+
+ async loadTradesChart() {
+ this.isLoadingTradesChart = true
+ this.shadowRoot.getElementById('loadChartDialog').open()
+ await this.getLtcTrades()
+ this.isLoadingTradesChart = false
+ this.shadowRoot.getElementById('loadChartDialog').close()
+ this.enableLtcStockPriceChart()
+ }
+
+ async getLtcTrades() {
+ let currentLtcTimestamp = Date.now()
+ const monthBackLtc = currentLtcTimestamp - 31556952000
+ await parentEpml.request("apiCall", { url: `/crosschain/trades?foreignBlockchain=LITECOIN&minimumTimestamp=${monthBackLtc}&limit=0&reverse=false` }).then((res) => {
+ this.ltcTrades = res
+ })
+ this.ltcPrice = this.ltcTrades.map(item => {
+ const ltcSellPrice = this.round(parseFloat(item.foreignAmount) / parseFloat(item.qortAmount))
+ return [item.tradeTimestamp, parseFloat(ltcSellPrice)]
+ }).filter(item => !!item)
+ }
+
+ enableLtcStockPriceChart() {
+ const ltcStockPriceData = this.ltcPrice
+ const header = 'QORT / LTC ' + get("tradepage.tchange49")
+ Highcharts.stockChart(this.shadowRoot.querySelector('#ltcStockPriceContainer'), {
+ accessibility: {
+ enabled: false
+ },
+ credits: {
+ enabled: false
+ },
+ rangeSelector: {
+ selected: 1,
+ labelStyle: {color: 'var(--black)'},
+ inputStyle: {color: '#03a9f4'}
+ },
+ chart: {
+ backgroundColor: 'transparent'
+ },
+ title: {
+ text: header,
+ style: {color: 'var(--black)'}
+ },
+ xAxis: {
+ labels: {
+ style: {
+ color: '#03a9f4'
+ }
+ }
+ },
+ yAxis: {
+ labels: {
+ style: {
+ color: '#03a9f4'
+ }
+ }
+ },
+ series: [{
+ name: 'QORT / LTC',
+ data: ltcStockPriceData,
+ tooltip: {
+ valueDecimals: 8
+ }
+ }]
+ })
+ }
+
+ async open() {
+ await this.loadTradesChart()
+ this.shadowRoot.getElementById('ltcChartDialog').open()
+ }
+
+ 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)
+ }
+ }
+
+ round(number) {
+ let result = (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8)
+ return result
+ }
+}
+
+window.customElements.define('ltc-charts', LtcCharts)
+
+const chartsltc = document.createElement('ltc-charts')
+ltcChartDialog = document.body.appendChild(chartsltc)
+
+export default ltcChartDialog
\ No newline at end of file
diff --git a/qortal-ui-plugins/plugins/core/trade-portal/charts/rvn-charts.js b/qortal-ui-plugins/plugins/core/trade-portal/charts/rvn-charts.js
new file mode 100644
index 00000000..1110bdfc
--- /dev/null
+++ b/qortal-ui-plugins/plugins/core/trade-portal/charts/rvn-charts.js
@@ -0,0 +1,214 @@
+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 '@polymer/paper-dialog/paper-dialog.js'
+import * as Highcharts from 'highcharts'
+import Exporting from 'highcharts/modules/exporting'
+Exporting(Highcharts)
+import StockChart from 'highcharts/modules/stock'
+StockChart(Highcharts)
+import 'highcharts/highcharts-more.js'
+import 'highcharts/modules/accessibility.js'
+import 'highcharts/modules/boost.js'
+import 'highcharts/modules/data.js'
+import 'highcharts/modules/export-data.js'
+import 'highcharts/modules/offline-exporting.js'
+
+let rvnChartDialog
+
+const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
+
+class RvnCharts extends LitElement {
+ static get properties() {
+ return {
+ isLoadingTradesChart: { type: Boolean },
+ rvnTrades: { type: Array },
+ rvnPrice: { type: Array }
+ }
+ }
+
+ static get styles() {
+ return css`
+ .loadingContainer {
+ height: 100%;
+ width: 100%;
+ }
+
+ .trades-chart {
+ color: var(--black);
+ background: var(--white);
+ border: 1px solid var(--black);
+ border-radius: 25px;
+ padding: 15px;
+ }
+
+ .chart-container {
+ margin: auto;
+ color: var(--black);
+ text-align: center;
+ padding: 15px;
+ height: 30vh;
+ width: 80vw;
+ }
+
+ .chart-info-wrapper {
+ background: transparent;
+ height: 38vh;
+ width: 83vw;
+ overflow: auto;
+ }
+
+ .chart-loading-wrapper {
+ color: var(--black);
+ background: var(--white);
+ border: 1px solid var(--black);
+ border-radius: 15px;
+ }
+ `
+ }
+
+ constructor() {
+ super()
+ this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
+ this.isLoadingTradesChart = false
+ this.rvnTrades = []
+ this.rvnPrice = []
+ }
+
+ render() {
+ return html`
+
+
+ ${translate("login.loading")}
+
+
+
+
+
+ `
+ }
+
+ async firstUpdated() {
+ this.changeTheme()
+ this.changeLanguage()
+
+ 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)
+ })
+ }
+
+ async loadTradesChart() {
+ this.isLoadingTradesChart = true
+ this.shadowRoot.getElementById('loadChartDialog').open()
+ await this.getRvnTrades()
+ this.isLoadingTradesChart = false
+ this.shadowRoot.getElementById('loadChartDialog').close()
+ this.enableRvnStockPriceChart()
+ }
+
+ async getRvnTrades() {
+ let currentRvnTimestamp = Date.now()
+ const monthBackRvn = currentRvnTimestamp - 31556952000
+ await parentEpml.request("apiCall", { url: `/crosschain/trades?foreignBlockchain=RAVENCOIN&minimumTimestamp=${monthBackRvn}&limit=0&reverse=false` }).then((res) => {
+ this.rvnTrades = res
+ })
+ this.rvnPrice = this.rvnTrades.map(item => {
+ const rvnSellPrice = this.round(parseFloat(item.foreignAmount) / parseFloat(item.qortAmount))
+ return [item.tradeTimestamp, parseFloat(rvnSellPrice)]
+ }).filter(item => !!item)
+ }
+
+ enableRvnStockPriceChart() {
+ const rvnStockPriceData = this.rvnPrice
+ const header = 'QORT / RVN ' + get("tradepage.tchange49")
+ Highcharts.stockChart(this.shadowRoot.querySelector('#rvnStockPriceContainer'), {
+ accessibility: {
+ enabled: false
+ },
+ credits: {
+ enabled: false
+ },
+ rangeSelector: {
+ selected: 1,
+ labelStyle: {color: 'var(--black)'},
+ inputStyle: {color: '#03a9f4'}
+ },
+ chart: {
+ backgroundColor: 'transparent'
+ },
+ title: {
+ text: header,
+ style: {color: 'var(--black)'}
+ },
+ xAxis: {
+ labels: {
+ style: {
+ color: '#03a9f4'
+ }
+ }
+ },
+ yAxis: {
+ labels: {
+ style: {
+ color: '#03a9f4'
+ }
+ }
+ },
+ series: [{
+ name: 'QORT / RVN',
+ data: rvnStockPriceData,
+ tooltip: {
+ valueDecimals: 8
+ }
+ }]
+ })
+ }
+
+ async open() {
+ await this.loadTradesChart()
+ this.shadowRoot.getElementById('rvnChartDialog').open()
+ }
+
+ 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)
+ }
+ }
+
+ round(number) {
+ let result = (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8)
+ return result
+ }
+}
+
+window.customElements.define('rvn-charts', RvnCharts)
+
+const chartsrvn = document.createElement('rvn-charts')
+rvnChartDialog = document.body.appendChild(chartsrvn)
+
+export default rvnChartDialog
\ No newline at end of file