Compare commits
10 Commits
7c3e2a5c89
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 226cff721c | |||
| e4ef99e19d | |||
| 6ffc2e9780 | |||
| ddabcb0a73 | |||
| 5ffda01a3e | |||
| c08b4cc281 | |||
| 3da72b1fb3 | |||
| 44e29f5bca | |||
| ab4ca23351 | |||
| b9a0948b2c |
@@ -4,10 +4,19 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/bitcoin.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="google-site-verification" content="ouaN13NvEutq1CGQ2iALjnFFP3naSQH9u2zElneZgk0" />
|
||||
<title>Bitcoin Average</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
<!-- Google tag (gtag.js) -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-TW05X9PC25"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-TW05X9PC25');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
4380
package-lock.json
generated
@@ -15,6 +15,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^4.5.0",
|
||||
"vite": "^5.0.0"
|
||||
"vite": "^5.0.0",
|
||||
"vite-plugin-pwa": "^0.17.4"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
public/pwa/apple-icon-180.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
public/pwa/apple-splash-1125-2436.jpg
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
public/pwa/apple-splash-1136-640.jpg
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
public/pwa/apple-splash-1170-2532.jpg
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
public/pwa/apple-splash-1179-2556.jpg
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
public/pwa/apple-splash-1242-2208.jpg
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
public/pwa/apple-splash-1242-2688.jpg
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
public/pwa/apple-splash-1284-2778.jpg
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
public/pwa/apple-splash-1290-2796.jpg
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
public/pwa/apple-splash-1334-750.jpg
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/pwa/apple-splash-1536-2048.jpg
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
public/pwa/apple-splash-1620-2160.jpg
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
public/pwa/apple-splash-1668-2224.jpg
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
public/pwa/apple-splash-1668-2388.jpg
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
public/pwa/apple-splash-1792-828.jpg
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
public/pwa/apple-splash-2048-1536.jpg
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
public/pwa/apple-splash-2048-2732.jpg
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
public/pwa/apple-splash-2160-1620.jpg
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
public/pwa/apple-splash-2208-1242.jpg
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
public/pwa/apple-splash-2224-1668.jpg
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
public/pwa/apple-splash-2388-1668.jpg
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
public/pwa/apple-splash-2436-1125.jpg
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
public/pwa/apple-splash-2532-1170.jpg
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
public/pwa/apple-splash-2556-1179.jpg
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
public/pwa/apple-splash-2688-1242.jpg
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
public/pwa/apple-splash-2732-2048.jpg
Normal file
|
After Width: | Height: | Size: 97 KiB |
BIN
public/pwa/apple-splash-2778-1284.jpg
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
public/pwa/apple-splash-2796-1290.jpg
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
public/pwa/apple-splash-640-1136.jpg
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
public/pwa/apple-splash-750-1334.jpg
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
public/pwa/apple-splash-828-1792.jpg
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
public/pwa/manifest-icon-192.maskable.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
public/pwa/manifest-icon-512.maskable.png
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
@@ -24,7 +24,6 @@ onMounted(updateBackground);
|
||||
window.addEventListener('resize', event => {
|
||||
const newWidth = round(event.target.innerWidth);
|
||||
const newHeight = round(event.target.innerHeight);
|
||||
console.log(newWidth, width.value);
|
||||
if (newWidth === width.value && newHeight === height.value) return;
|
||||
width.value = newWidth;
|
||||
height.value = newHeight;
|
||||
@@ -40,11 +39,14 @@ window.addEventListener('resize', event => {
|
||||
|
||||
<style scoped>
|
||||
.background {
|
||||
overflow: hidden;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
.background svg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: -1;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { ref, onMounted } from 'vue';
|
||||
|
||||
const TIMEOUT = 15e3;
|
||||
|
||||
@@ -34,12 +34,18 @@ const dataSources = [
|
||||
pick: res => +res.result.XXBTZUSD.a[0],
|
||||
asset: 'USD',
|
||||
},
|
||||
// {
|
||||
// name: 'bitstamp',
|
||||
// url: 'https://www.bitstamp.net/api/v2/ticker/btcusd',
|
||||
// pick: res => +res.last,
|
||||
// asset: 'USD',
|
||||
// },
|
||||
{
|
||||
name: 'bitstamp',
|
||||
url: 'https://www.bitstamp.net/api/v2/ticker/btcusd',
|
||||
pick: res => +res.last,
|
||||
asset: 'USD',
|
||||
},
|
||||
{
|
||||
name: 'kucoin',
|
||||
url: 'https://api.kucoin.com/api/v1/market/orderbook/level1?symbol=BTC-USDT',
|
||||
pick: res => +res.data.price,
|
||||
asset: 'USDT',
|
||||
},
|
||||
{
|
||||
name: 'coingecko',
|
||||
url: 'https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd',
|
||||
@@ -77,16 +83,28 @@ const recalc = () => {
|
||||
calcStdev();
|
||||
};
|
||||
|
||||
const format = (price, precision = 2) => {
|
||||
const num = (price ?? 0);
|
||||
return (Number.isNaN(num) ? 0 : num).toFixed(precision);
|
||||
const vibrate = () => {
|
||||
navigator?.vibrate([30,20,20]);
|
||||
};
|
||||
|
||||
const format = (price, precision = 2, split = false) => {
|
||||
const num = (price ?? 0);
|
||||
const str = (Number.isNaN(num) ? 0 : num).toFixed(precision);
|
||||
if (!split) return str;
|
||||
return (str.match(/(^\d{1,2}(?=(\d{3})*$)|\d{3})/g) || []).join(' ');
|
||||
};
|
||||
|
||||
const dataSourcesEl = ref(null);
|
||||
const dataSourcesHeight = ref('100%');
|
||||
const average = ref();
|
||||
const prices = ref([]);
|
||||
const stdev = ref();
|
||||
const showSources = ref(true);
|
||||
|
||||
onMounted(() => {
|
||||
dataSourcesHeight.value = `${dataSourcesEl.value.offsetHeight}px`;
|
||||
});
|
||||
|
||||
(() => {
|
||||
let idx = -1;
|
||||
const loop = async () => {
|
||||
@@ -111,17 +129,18 @@ const showSources = ref(true);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="box" @click="showSources = !showSources">
|
||||
<p class="average">1 BTC = <span class="nobr">{{ format(average, 0) }} USD</span></p>
|
||||
<div class="box" @click="showSources = !showSources; vibrate()">
|
||||
<p class="average"><span class="nobr">1 BTC</span> = <span class="nobr">{{ format(average, 0, true) }} USD</span></p>
|
||||
<Transition>
|
||||
<div v-show="showSources">
|
||||
<p>Data Sources:</p>
|
||||
<div v-show="showSources" ref="dataSourcesEl">
|
||||
<p class="vert-margin">Data Sources:</p>
|
||||
<ul>
|
||||
<li v-for="(val, i) in dataSources">
|
||||
{{ val.name }}: {{ format(prices[i]) }}
|
||||
<div class="li-name">{{ val.name }}:</div>
|
||||
<div class="li-price">{{ format(prices[i]) }}</div>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Standard Deviation: {{ format(stdev) }} ({{ format(stdev/average*100, 4) }}%)</p>
|
||||
<p class="vert-margin">St. Deviation: {{ format(stdev) }} ({{ format(stdev/average*100, 4) }}%)</p>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
@@ -130,16 +149,19 @@ const showSources = ref(true);
|
||||
<style scoped>
|
||||
.v-enter-active,
|
||||
.v-leave-active {
|
||||
transition: opacity 0.2s ease;
|
||||
overflow: hidden;
|
||||
transition: all 80ms ease-in-out;
|
||||
height: v-bind(dataSourcesHeight);
|
||||
}
|
||||
|
||||
.v-enter-from,
|
||||
.v-leave-to {
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.box {
|
||||
cursor: pointer;
|
||||
/* cursor: pointer;*/
|
||||
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
@@ -163,4 +185,26 @@ const showSources = ref(true);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.box ul li {
|
||||
display: flex;
|
||||
flex-basis: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.box ul li div {
|
||||
flex-basis: 0;
|
||||
padding: 0 4px;
|
||||
}
|
||||
.li-name {
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
text-align: right;
|
||||
flex-grow: 7;
|
||||
}
|
||||
.li-price {
|
||||
text-align: left;
|
||||
flex-grow: 5;
|
||||
}
|
||||
.vert-margin {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1 +1,9 @@
|
||||
@import 'reset-css';
|
||||
|
||||
body {
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-o-user-select: none;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,46 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import { defineConfig } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import { VitePWA } from 'vite-plugin-pwa';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
})
|
||||
plugins: [
|
||||
vue(),
|
||||
VitePWA({
|
||||
registerType: 'autoUpdate',
|
||||
injectRegister: 'auto',
|
||||
manifest: {
|
||||
name: 'Bitcoin Average',
|
||||
short_name: 'BtcAvg',
|
||||
description: 'Display bitcoin average price',
|
||||
theme_color: '#f7931d',
|
||||
icons: [
|
||||
{
|
||||
src: 'pwa/manifest-icon-192.maskable.png',
|
||||
sizes: '192x192',
|
||||
type: 'image/png',
|
||||
purpose: 'any'
|
||||
},
|
||||
{
|
||||
src: 'pwa/manifest-icon-192.maskable.png',
|
||||
sizes: '192x192',
|
||||
type: 'image/png',
|
||||
purpose: 'maskable'
|
||||
},
|
||||
{
|
||||
src: 'pwa/manifest-icon-512.maskable.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
purpose: 'any'
|
||||
},
|
||||
{
|
||||
src: 'pwa/manifest-icon-512.maskable.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
purpose: 'maskable'
|
||||
}
|
||||
],
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||