Adds current Eth gas price widget

This commit is contained in:
Alicia Sykes 2022-01-02 23:09:31 +00:00
parent 65ffa0efc4
commit 7b030d8e5b
4 changed files with 265 additions and 1 deletions

View File

@ -21,6 +21,7 @@ Dashy has support for displaying dynamic content in the form of widgets. There a
- [Public Holidays](#public-holidays)
- [TFL Status](#tfl-status)
- [Stock Price History](#stock-price-history)
- [ETH Gas Prices](#eth-gas-prices)
- [Joke of the Day](#joke)
- [XKCD Comics](#xkcd-comics)
- [News Headlines](#news-headlines)
@ -129,7 +130,7 @@ Displays the weather (temperature and conditions) for the next few days for a gi
**Field** | **Type** | **Required** | **Description**
--- | --- | --- | ---
**`apiKey`** | `string` | Required | Your OpenWeatherMap API key. You can get one for free at [openweathermap.org](https://openweathermap.org/)
**`apiKey`** | `string` | Required | Your OpenWeatherMap API key. You can get one at [openweathermap.org](https://openweathermap.org/) or for free via the [OWM Student Plan](https://home.openweathermap.org/students)
**`city`** | `string` | Required | A city name to use for fetching weather. This can also be a state code or country code, following the ISO-3166 format
**`numDays`** | `number` | _Optional_ | The number of days to display of forecast info to display. Defaults to `4`, max `16` days
**`units`** | `string` | _Optional_ | The units to use for displaying data, can be either `metric` or `imperial`. Defaults to `metric`
@ -526,6 +527,31 @@ Shows recent price history for a given publicly-traded stock or share
---
### ETH Gas Prices
Renders the current Gas cost of transactions on the Ethereum network (in both GWEI and USD), along with recent historical prices. Useful for spotting a good time to transact. Uses data from [ethgas.watch](https://ethgas.watch/)
<p align="center"><img width="400" src="https://i.ibb.co/LhHfQyp/eth-gas-prices.png" /></p>
##### Options
_No config options._
##### Example
```yaml
- type: eth-gas-prices
```
##### Info
- **CORS**: 🟢 Enabled
- **Auth**: 🟢 Not Required
- **Price**: 🟢 Free
- **Host**: Managed Instance or Self-Hosted (see [wslyvh/ethgaswatch](https://github.com/wslyvh/ethgaswatch))
- **Privacy**: ⚫ No Policy Available
---
### Joke
Renders a programming or generic joke. Data is fetched from the [JokesAPI](https://github.com/Sv443/JokeAPI) by @Sv443. All fields are optional.

View File

@ -0,0 +1,228 @@
<template>
<div class="eth-gas-wrapper" v-if="gasCosts">
<!-- Current Prices -->
<p class="current-label">Current Gas Prices</p>
<div v-for="gasCost in gasCosts" :key="gasCost.name" class="gas-row">
<p class="time-name">{{ gasCost.name }}</p>
<div class="cost">
<span class="usd">${{ gasCost.usd }}</span>
<span class="gwei">{{ gasCost.gwei }} GWEI</span>
</div>
</div>
<!-- Current ETH Price -->
<div class="current-price">
<span class="label">Current ETH Price:</span>
<span class="price">{{ gasInfo.ethPrice }}</span>
</div>
<!-- Historical Chart -->
<p class="time-frame-label">Historical Gas Prices</p>
<div class="time-frame-selector">
<span
v-for="time in timeOptions"
:key="time.value"
@click="updateTimeFrame(time.value)"
:class="time.value === selectedTimeFrame ? 'selected' : ''"
>
{{ time.label }}
</span>
</div>
<div :id="chartId"></div>
<!-- Meta Info -->
<div v-if="gasInfo" class="gas-info">
<p>Last Updated: {{ gasInfo.lastUpdated }}</p>
<div class="sources">
Sources:
<a
v-for="source in gasInfo.sources"
:key="source.name"
:href="source.source"
v-tooltip="tooltip(`Average: ${source.standard || '[UNKNOWN]'} GWEI`)"
>{{ source.name }}</a>
</div>
</div>
</div>
</template>
<script>
import WidgetMixin from '@/mixins/WidgetMixin';
import ChartingMixin from '@/mixins/ChartingMixin';
import { widgetApiEndpoints } from '@/utils/defaults';
import { timestampToTime, roundPrice, putCommasInBigNum } from '@/utils/MiscHelpers';
export default {
mixins: [WidgetMixin, ChartingMixin],
computed: {
numHours() {
return this.options.numHours || 24;
},
endpoint() {
const numHours = this.selectedTimeFrame || this.numHours;
return `${widgetApiEndpoints.ethGasHistory}?hours=${numHours}`;
},
},
data() {
return {
gasInfo: null,
gasCosts: null,
timeOptions: [
{ label: '6 hours', value: 6 },
{ label: '1 Day', value: 24 },
{ label: '1 Week', value: 168 },
{ label: '2 Weeks', value: 220 },
],
selectedTimeFrame: null,
};
},
methods: {
/* Make GET request to CoinGecko API endpoint */
fetchData() {
this.makeRequest(widgetApiEndpoints.ethGasPrices).then(this.processPriceInfo);
this.makeRequest(this.endpoint).then(this.processHistoryData);
},
processPriceInfo(data) {
this.gasCosts = [
{ name: 'Slow', gwei: data.slow.gwei, usd: data.slow.usd },
{ name: 'Normal', gwei: data.normal.gwei, usd: data.normal.usd },
{ name: 'Fast', gwei: data.fast.gwei, usd: data.fast.usd },
{ name: 'Instant', gwei: data.instant.gwei, usd: data.instant.usd },
];
const sources = [];
data.sources.forEach((sourceInfo) => {
const { name, source, standard } = sourceInfo;
sources.push({ name, source, standard });
});
this.gasInfo = {
lastUpdated: timestampToTime(data.lastUpdated),
ethPrice: `$${putCommasInBigNum(roundPrice(data.ethPrice))}`,
sources,
};
},
processHistoryData(data) {
const chartData = {
labels: data.labels,
datasets: [
{ name: 'Slow', type: 'bar', values: data.slow },
{ name: 'Normal', type: 'bar', values: data.normal },
{ name: 'Fast', type: 'bar', values: data.fast },
{ name: 'Instant', type: 'bar', values: data.instant },
],
};
return new this.Chart(`#${this.chartId}`, {
title: 'Historical Transaction Costs',
data: chartData,
type: 'axis-mixed',
height: this.chartHeight,
colors: ['#ef476f', '#ffd166', '#118ab2', '#06d6a0'],
truncateLegends: true,
lineOptions: {
hideDots: 1,
},
axisOptions: {
xIsSeries: true,
xAxisMode: 'tick',
},
tooltipOptions: {
formatTooltipY: d => `${d} GWEI`,
},
});
},
updateTimeFrame(newNumHours) {
this.startLoading();
this.selectedTimeFrame = newNumHours;
this.fetchData();
},
},
mounted() {
this.selectedTimeFrame = this.numHours;
},
};
</script>
<style scoped lang="scss">
.eth-gas-wrapper {
p.current-label {
margin: 0.25rem 0;
opacity: var(--dimming-factor);
color: var(--widget-text-color);
}
.gas-row {
display: flex;
vertical-align: middle;
justify-content: space-between;
color: var(--widget-text-color);
p.time-name {
margin: 0.25rem 0;
font-weight: bold;
font-size: 1.1rem;
}
.cost {
display: flex;
min-width: 10rem;
justify-content: space-between;
span {
font-family: var(--font-monospace);
margin: 0.5rem;
&.usd {
opacity: var(--dimming-factor);
}
}
}
&:not(:last-child) { border-bottom: 1px dashed var(--widget-text-color); }
}
.current-price {
color: var(--widget-text-color);
margin: 1rem 0 0.5rem;
span.label {
font-weight: bold;
margin-right: 0.5rem;
}
span.price {
font-family: var(--font-monospace);
}
}
.gas-info {
p, .sources {
margin: 0.5rem 0;
font-size: 0.8rem;
opacity: var(--dimming-factor);
color: var(--widget-text-color);
font-family: var(--font-monospace);
}
.sources a {
color: var(--widget-text-color);
margin: 0 0.15rem;
}
}
p.time-frame-label {
display: inline-block;
color: var(--widget-text-color);
opacity: var(--dimming-factor);
margin: 1rem 0.5rem 0.25rem 0;
font-size: 0.9rem;
}
.time-frame-selector {
display: inline-block;
margin: 0 0 0.25rem;
max-width: 20rem;
vertical-align: middle;
justify-content: space-evenly;
color: var(--widget-text-color);
font-size: 0.9rem;
span {
cursor: pointer;
padding: 0.1rem 0.25rem;
margin: 0 0.15rem;
border: 1px solid transparent;
border-radius: var(--curve-factor);
&.selected {
background: var(--widget-text-color);
color: var(--widget-background-color);
}
&:hover {
border: 1px solid var(--widget-text-color);
}
}
}
}
</style>

View File

@ -67,6 +67,13 @@
@error="handleError"
:ref="widgetRef"
/>
<EthGasPrices
v-else-if="widgetType === 'eth-gas-prices'"
:options="widgetOptions"
@loading="setLoaderState"
@error="handleError"
:ref="widgetRef"
/>
<ExchangeRates
v-else-if="widgetType === 'exchange-rates'"
:options="widgetOptions"
@ -272,6 +279,7 @@ export default {
CryptoWatchList: () => import('@/components/Widgets/CryptoWatchList.vue'),
CveVulnerabilities: () => import('@/components/Widgets/CveVulnerabilities.vue'),
EmbedWidget: () => import('@/components/Widgets/EmbedWidget.vue'),
EthGasPrices: () => import('@/components/Widgets/EthGasPrices.vue'),
ExchangeRates: () => import('@/components/Widgets/ExchangeRates.vue'),
Flights: () => import('@/components/Widgets/Flights.vue'),
GitHubTrending: () => import('@/components/Widgets/GitHubTrending.vue'),

View File

@ -213,6 +213,8 @@ module.exports = {
cryptoPrices: 'https://api.coingecko.com/api/v3/coins/',
cryptoWatchList: 'https://api.coingecko.com/api/v3/coins/markets/',
cveVulnerabilities: 'https://www.cvedetails.com/json-feed.php',
ethGasPrices: 'https://ethgas.watch/api/gas',
ethGasHistory: 'https://ethgas.watch/api/gas/trend',
exchangeRates: 'https://v6.exchangerate-api.com/v6/',
flights: 'https://aerodatabox.p.rapidapi.com/flights/airports/icao/',
githubTrending: 'https://gh-trending-repos.herokuapp.com/',