diff --git a/CHANGELOG.md b/CHANGELOG.md index fe18b932c..09a897112 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,22 +11,24 @@ - Value destroyed - Value created - Spent Output Profit Ratio (SOPR) - - Market Price to Realized Price - - Market Price to Realized Price Ratio - - Market Price to Realized Price Ratio 1 Week SMA - - Market Price to Realized Price Ratio 1 Month SMA - - Market Price to Realized Price Ratio 1 Year SMA - - Market Price to Realized Price Ratio 99th Percentile - - Market Price to Realized Price Ratio 99.5th Percentile - - Market Price to Realized Price Ratio 99.9th Percentile - - Market Price to Realized Price Ratio 1st Percentile - - Market Price to Realized Price Ratio 0.5th Percentile - - Realized Price 0.1th Percentile - - Realized Price 99.5th Percentile - - Realized Price 99.9th Percentile - - Realized Price 1st Percentile - - Realized Price 0.5th Percentile - - Realized Price 0.1th Percentile + - Added the following datasets to all realized prices, price moving averages and cointime prices: + - Market Price to {X} + - Market Price to {X} Ratio + - Market Price to {X} Ratio 1 Week SMA + - Market Price to {X} Ratio 1 Month SMA + - Market Price to {X} Ratio 1 Year SMA + - Market Price to {X} Ratio 1 Year SMA Momentum Oscillator + - Market Price to {X} Ratio 99th Percentile + - Market Price to {X} Ratio 99.5th Percentile + - Market Price to {X} Ratio 99.9th Percentile + - Market Price to {X} Ratio 1st Percentile + - Market Price to {X} Ratio 0.5th Percentile + - {X} 1% Top Probability + - {X} 0.5% Top Probability + - {X} 0.1% Top Probability + - {X} 1% Bottom Probability + - {X} 0.5% Bottom Probability + - {X} 0.1% Bottom Probability - Price - Improved error message when price cannot be found diff --git a/app/package.json b/app/package.json index a45a5662b..4608008b4 100644 --- a/app/package.json +++ b/app/package.json @@ -34,7 +34,7 @@ "prettier-plugin-tailwindcss": "^0.6.5", "pwa-asset-generator": "^6.3.1", "rollup-plugin-visualizer": "^5.12.0", - "tailwindcss": "^3.4.5", + "tailwindcss": "^3.4.6", "typescript": "^5.5.3", "unplugin-auto-import": "^0.18.0", "unplugin-icons": "^0.19.0", @@ -42,6 +42,6 @@ "vite-plugin-pwa": "^0.20.0", "vite-plugin-solid": "^2.10.2", "workbox-window": "^7.1.0", - "wrangler": "^3.64.0" + "wrangler": "^3.65.0" } } diff --git a/app/pnpm-lock.yaml b/app/pnpm-lock.yaml index c93d72cf8..34e5008ce 100644 --- a/app/pnpm-lock.yaml +++ b/app/pnpm-lock.yaml @@ -36,7 +36,7 @@ devDependencies: version: 1.1.117 '@tailwindcss/container-queries': specifier: ^0.1.1 - version: 0.1.1(tailwindcss@3.4.5) + version: 0.1.1(tailwindcss@3.4.6) autoprefixer: specifier: ^10.4.19 version: 10.4.19(postcss@8.4.39) @@ -56,8 +56,8 @@ devDependencies: specifier: ^5.12.0 version: 5.12.0(rollup@2.79.1) tailwindcss: - specifier: ^3.4.5 - version: 3.4.5 + specifier: ^3.4.6 + version: 3.4.6 typescript: specifier: ^5.5.3 version: 5.5.3 @@ -80,8 +80,8 @@ devDependencies: specifier: ^7.1.0 version: 7.1.0 wrangler: - specifier: ^3.64.0 - version: 3.64.0 + specifier: ^3.65.0 + version: 3.65.0 packages: @@ -146,7 +146,7 @@ packages: dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.24.7 - '@babel/generator': 7.24.9 + '@babel/generator': 7.24.10 '@babel/helper-compilation-targets': 7.24.8 '@babel/helper-module-transforms': 7.24.9(@babel/core@7.24.9) '@babel/helpers': 7.24.8 @@ -163,8 +163,8 @@ packages: - supports-color dev: true - /@babel/generator@7.24.9: - resolution: {integrity: sha512-G8v3jRg+z8IwY1jHFxvCNhOPYPterE4XljNgdGTYfSTtzzwjIswIzIaSPSLs3R7yFuqnqNeay5rjICfqVr+/6A==} + /@babel/generator@7.24.10: + resolution: {integrity: sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.24.9 @@ -1358,7 +1358,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.24.7 - '@babel/generator': 7.24.9 + '@babel/generator': 7.24.10 '@babel/helper-environment-visitor': 7.24.7 '@babel/helper-function-name': 7.24.7 '@babel/helper-hoist-variables': 7.24.7 @@ -1387,8 +1387,8 @@ packages: mime: 3.0.0 dev: true - /@cloudflare/workerd-darwin-64@1.20240701.0: - resolution: {integrity: sha512-XAZa4ZP+qyTn6JQQACCPH09hGZXP2lTnWKkmg5mPwT8EyRzCKLkczAf98vPP5bq7JZD/zORdFWRY0dOTap8zTQ==} + /@cloudflare/workerd-darwin-64@1.20240712.0: + resolution: {integrity: sha512-KB1vbOhr62BCAwVr3VaRcngzPeSCQ7zPA9VGrfwYXIxo0Y4zlW1z0EVtcewFSz5XXKr3BtNnJXxdjDPUNkguQw==} engines: {node: '>=16'} cpu: [x64] os: [darwin] @@ -1396,8 +1396,8 @@ packages: dev: true optional: true - /@cloudflare/workerd-darwin-arm64@1.20240701.0: - resolution: {integrity: sha512-w80ZVAgfH4UwTz7fXZtk7KmS2FzlXniuQm4ku4+cIgRTilBAuKqjpOjwUCbx5g13Gqcm9NuiHce+IDGtobRTIQ==} + /@cloudflare/workerd-darwin-arm64@1.20240712.0: + resolution: {integrity: sha512-UDwFnCfQGFVCNxOeHxKNEc1ANQk/3OIiFWpVsxgZqJqU/22XM88JHxJW+YcBKsaUGUlpLyImaYUn2/rG+i+9UQ==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] @@ -1405,8 +1405,8 @@ packages: dev: true optional: true - /@cloudflare/workerd-linux-64@1.20240701.0: - resolution: {integrity: sha512-UWLr/Anxwwe/25nGv451MNd2jhREmPt/ws17DJJqTLAx6JxwGWA15MeitAIzl0dbxRFAJa+0+R8ag2WR3F/D6g==} + /@cloudflare/workerd-linux-64@1.20240712.0: + resolution: {integrity: sha512-MxpMHSJcZRUL66TO7BEnEim9WgZ8wJEVOB1Rq7a/IF2hI4/8f+N+02PChh62NkBlWxDfTXAtZy0tyQMm0EGjHg==} engines: {node: '>=16'} cpu: [x64] os: [linux] @@ -1414,8 +1414,8 @@ packages: dev: true optional: true - /@cloudflare/workerd-linux-arm64@1.20240701.0: - resolution: {integrity: sha512-3kCnF9kYgov1ggpuWbgpXt4stPOIYtVmPCa7MO2xhhA0TWP6JDUHRUOsnmIgKrvDjXuXqlK16cdg3v+EWsaPJg==} + /@cloudflare/workerd-linux-arm64@1.20240712.0: + resolution: {integrity: sha512-DtLYZsFFFAMgn+6YCHoQS6nYY4nbdAtcAFa4PhWTjLJDbvQEn3IoK9Bi4ajCL7xG36FeuBdZliSbBiiv7CJjfQ==} engines: {node: '>=16'} cpu: [arm64] os: [linux] @@ -1423,8 +1423,8 @@ packages: dev: true optional: true - /@cloudflare/workerd-windows-64@1.20240701.0: - resolution: {integrity: sha512-6IPGITRAeS67j3BH1rN4iwYWDt47SqJG7KlZJ5bB4UaNAia4mvMBSy/p2p4vA89bbXoDRjMtEvRu7Robu6O7hQ==} + /@cloudflare/workerd-windows-64@1.20240712.0: + resolution: {integrity: sha512-u8zoT9PQiiwxuz9npquLBFWrC/RlBWGGZ1aylarZNFlM4sFrRm+bRr6i+KtS+fltHIVXj3teuoKYytA1ppf9Yw==} engines: {node: '>=16'} cpu: [x64] os: [win32] @@ -1877,7 +1877,7 @@ packages: optional: true dependencies: '@babel/core': 7.24.9 - '@babel/generator': 7.24.9 + '@babel/generator': 7.24.10 '@babel/parser': 7.24.8 '@babel/traverse': 7.24.8 '@babel/types': 7.24.9 @@ -2072,7 +2072,7 @@ packages: rollup: 2.79.1 serialize-javascript: 6.0.2 smob: 1.5.0 - terser: 5.31.2 + terser: 5.31.3 dev: true /@rollup/pluginutils@3.1.0(rollup@2.79.1): @@ -2295,12 +2295,12 @@ packages: string.prototype.matchall: 4.0.11 dev: true - /@tailwindcss/container-queries@0.1.1(tailwindcss@3.4.5): + /@tailwindcss/container-queries@0.1.1(tailwindcss@3.4.6): resolution: {integrity: sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA==} peerDependencies: tailwindcss: '>=3.2.0' dependencies: - tailwindcss: 3.4.5 + tailwindcss: 3.4.6 dev: true /@types/babel__core@7.20.5: @@ -2347,11 +2347,11 @@ packages: /@types/node-forge@1.3.11: resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} dependencies: - '@types/node': 20.14.10 + '@types/node': 20.14.11 dev: true - /@types/node@20.14.10: - resolution: {integrity: sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==} + /@types/node@20.14.11: + resolution: {integrity: sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==} dependencies: undici-types: 5.26.5 dev: true @@ -2372,7 +2372,7 @@ packages: resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} requiresBuild: true dependencies: - '@types/node': 20.14.10 + '@types/node': 20.14.11 dev: true optional: true @@ -2772,7 +2772,7 @@ packages: engines: {node: '>=12.13.0'} hasBin: true dependencies: - '@types/node': 20.14.10 + '@types/node': 20.14.11 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -4256,8 +4256,8 @@ packages: engines: {node: '>=4'} dev: true - /miniflare@3.20240701.0: - resolution: {integrity: sha512-m9+I+7JNyqDGftCMKp9cK9pCZkK72hAL2mM9IWwhct+ZmucLBA8Uu6+rHQqA5iod86cpwOkrB2PrPA3wx9YNgw==} + /miniflare@3.20240712.0: + resolution: {integrity: sha512-zVbsMX2phvJS1uTPmjK6CvVBq4ON2UkmvTw9IMfNPACsWJmHEdsBDxsYEG1vKAduJdI5gULLuJf7qpFxByDhGw==} engines: {node: '>=16.13'} hasBin: true dependencies: @@ -4269,7 +4269,7 @@ packages: glob-to-regexp: 0.4.1 stoppable: 1.1.0 undici: 5.28.4 - workerd: 1.20240701.0 + workerd: 1.20240712.0 ws: 8.18.0 youch: 3.3.3 zod: 3.23.8 @@ -4330,7 +4330,7 @@ packages: acorn: 8.12.1 pathe: 1.1.2 pkg-types: 1.1.3 - ufo: 1.5.3 + ufo: 1.5.4 dev: true /ms@2.0.0: @@ -5224,7 +5224,7 @@ packages: peerDependencies: solid-js: ^1.3 dependencies: - '@babel/generator': 7.24.9 + '@babel/generator': 7.24.10 '@babel/helper-module-imports': 7.24.7 '@babel/types': 7.24.9 solid-js: 1.8.18 @@ -5453,8 +5453,8 @@ packages: engines: {node: '>= 0.4'} dev: true - /tailwindcss@3.4.5: - resolution: {integrity: sha512-DlTxttYcogpDfx3tf/8jfnma1nfAYi2cBUYV2YNoPPecwmO3YGiFlOX9D8tGAu+EDF38ryBzvrDKU/BLMsUwbw==} + /tailwindcss@3.4.6: + resolution: {integrity: sha512-1uRHzPB+Vzu57ocybfZ4jh5Q3SdlH7XW23J5sQoM9LhE9eIOlzxer/3XPSsycvih3rboRsvt0QCmzSrqyOYUIA==} engines: {node: '>=14.0.0'} hasBin: true dependencies: @@ -5519,8 +5519,8 @@ packages: unique-string: 2.0.0 dev: true - /terser@5.31.2: - resolution: {integrity: sha512-LGyRZVFm/QElZHy/CPr/O4eNZOZIzsrQ92y4v9UJe/pFJjypje2yI3C2FmPtvUEnhadlSbmG2nXtdcjHOjCfxw==} + /terser@5.31.3: + resolution: {integrity: sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==} engines: {node: '>=10'} hasBin: true dependencies: @@ -5657,8 +5657,8 @@ packages: hasBin: true dev: true - /ufo@1.5.3: - resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} + /ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} dev: true /unbox-primitive@1.0.2: @@ -5696,7 +5696,7 @@ packages: mime: 3.0.0 node-fetch-native: 1.6.4 pathe: 1.1.2 - ufo: 1.5.3 + ufo: 1.5.4 dev: true /unicode-canonical-property-names-ecmascript@2.0.0: @@ -5722,8 +5722,8 @@ packages: engines: {node: '>=4'} dev: true - /unimport@3.7.2(rollup@2.79.1): - resolution: {integrity: sha512-91mxcZTadgXyj3lFWmrGT8GyoRHWuE5fqPOjg5RVtF6vj+OfM5G6WCzXjuYtSgELE5ggB34RY4oiCSEP8I3AHw==} + /unimport@3.8.0(rollup@2.79.1): + resolution: {integrity: sha512-leq5bfNxyytAer8cYPi0dR0L6p8ZnZ8NxR9TKsSIbJM47TOxC5qURJXQZ8xuBGqLakUqYO6CvVtf3lWKo9k+8A==} dependencies: '@rollup/pluginutils': 5.1.0(rollup@2.79.1) acorn: 8.12.1 @@ -5772,7 +5772,7 @@ packages: local-pkg: 0.5.0 magic-string: 0.30.10 minimatch: 9.0.5 - unimport: 3.7.2(rollup@2.79.1) + unimport: 3.8.0(rollup@2.79.1) unplugin: 1.11.0 transitivePeerDependencies: - rollup @@ -6147,25 +6147,25 @@ packages: workbox-core: 7.1.0 dev: true - /workerd@1.20240701.0: - resolution: {integrity: sha512-qSgNVqauqzNCij9MaJLF2c2ko3AnFioVSIxMSryGbRK+LvtGr9BKBt6JOxCb24DoJASoJDx3pe3DJHBVydUiBg==} + /workerd@1.20240712.0: + resolution: {integrity: sha512-hdIHZif82hBDy9YnMtcmDGgbLU5f2P2aGpi/X8EKhTSLDppVUGrkY3XB536J4jGjA2D5dS0FUEXCl5bAJEed8Q==} engines: {node: '>=16'} hasBin: true requiresBuild: true optionalDependencies: - '@cloudflare/workerd-darwin-64': 1.20240701.0 - '@cloudflare/workerd-darwin-arm64': 1.20240701.0 - '@cloudflare/workerd-linux-64': 1.20240701.0 - '@cloudflare/workerd-linux-arm64': 1.20240701.0 - '@cloudflare/workerd-windows-64': 1.20240701.0 + '@cloudflare/workerd-darwin-64': 1.20240712.0 + '@cloudflare/workerd-darwin-arm64': 1.20240712.0 + '@cloudflare/workerd-linux-64': 1.20240712.0 + '@cloudflare/workerd-linux-arm64': 1.20240712.0 + '@cloudflare/workerd-windows-64': 1.20240712.0 dev: true - /wrangler@3.64.0: - resolution: {integrity: sha512-q2VQADJXzuOkXs9KIfPSx7UCZHBoxsqSNbJDLkc2pHpGmsyNQXsJRqjMoTg/Kls7O3K9A7EGnzGr7+Io2vE6AQ==} + /wrangler@3.65.0: + resolution: {integrity: sha512-IDy4ttyJZssazAd5CXHw4NWeZFGxngdNF5m2ogltdT3CV7uHfCvPVdMcr4uNMpRZd0toHmAE3LtQeXxDFFp88A==} engines: {node: '>=16.17.0'} hasBin: true peerDependencies: - '@cloudflare/workers-types': ^4.20240620.0 + '@cloudflare/workers-types': ^4.20240712.0 peerDependenciesMeta: '@cloudflare/workers-types': optional: true @@ -6177,7 +6177,7 @@ packages: chokidar: 3.6.0 date-fns: 3.6.0 esbuild: 0.17.19 - miniflare: 3.20240701.0 + miniflare: 3.20240712.0 nanoid: 3.3.7 path-to-regexp: 6.2.2 resolve: 1.22.8 diff --git a/app/src/scripts/presets/blocks/index.ts b/app/src/scripts/presets/blocks/index.ts index 67b9d73fb..07ab30861 100644 --- a/app/src/scripts/presets/blocks/index.ts +++ b/app/src/scripts/presets/blocks/index.ts @@ -1,144 +1,203 @@ import { colors } from "../../utils/colors"; -export function createPresets() { - const scale: ResourceScale = "date"; - +export function createPresets(scale: ResourceScale) { return { name: "Blocks", tree: [ - { - scale, - icon: IconTablerWall, - name: "Height", - title: "Block Height", - description: "", - bottom: [ - { - title: "Height", - color: colors.bitcoin, - datasetPath: `/date-to-last-height`, - }, - ], - }, - { - scale, - name: "Mined", - tree: [ - { - scale, - icon: IconTablerCube, - name: "Daily Sum", - title: "Daily Sum Of Blocks Mined", - description: "", - bottom: [ - { - title: "Target", - color: colors.white, - datasetPath: `/date-to-blocks-mined-1d-target`, - options: { - lineStyle: 3, + ...((scale === "date" + ? [ + { + scale, + icon: IconTablerWall, + name: "Height", + title: "Block Height", + description: "", + bottom: [ + { + title: "Height", + color: colors.bitcoin, + datasetPath: `/date-to-last-height`, }, - }, - { - title: "1W Avg.", - color: colors.momentumYellow, - datasetPath: `/date-to-blocks-mined-1w-sma`, - defaultVisible: false, - }, - { - title: "1M Avg.", - color: colors.bitcoin, - datasetPath: `/date-to-blocks-mined-1m-sma`, - }, - { - title: "Mined", - color: colors.darkBitcoin, - datasetPath: `/date-to-blocks-mined`, - }, - ], - }, - { - scale, - icon: IconTablerLetterW, - name: "Weekly Sum", - title: "Weekly Sum Of Blocks Mined", - description: "", - bottom: [ - { - title: "Target", - color: colors.white, - datasetPath: `/date-to-blocks-mined-1w-target`, - options: { - lineStyle: 3, + ], + }, + { + scale, + name: "Mined", + tree: [ + { + scale, + icon: IconTablerCube, + name: "Daily Sum", + title: "Daily Sum Of Blocks Mined", + description: "", + bottom: [ + { + title: "Target", + color: colors.white, + datasetPath: `/date-to-blocks-mined-1d-target`, + options: { + lineStyle: 3, + }, + }, + { + title: "1W Avg.", + color: colors.momentumYellow, + datasetPath: `/date-to-blocks-mined-1w-sma`, + defaultVisible: false, + }, + { + title: "1M Avg.", + color: colors.bitcoin, + datasetPath: `/date-to-blocks-mined-1m-sma`, + }, + { + title: "Mined", + color: colors.darkBitcoin, + datasetPath: `/date-to-blocks-mined`, + }, + ], }, - }, - { - title: "Sum Mined", - color: colors.bitcoin, - datasetPath: `/date-to-blocks-mined-1w-sum`, - }, - ], - }, - { - scale, - icon: IconTablerLetterM, - name: "Monthly Sum", - title: "Monthly Sum Of Blocks Mined", - description: "", - bottom: [ - { - title: "Target", - color: colors.white, - datasetPath: `/date-to-blocks-mined-1m-target`, - options: { - lineStyle: 3, + { + scale, + icon: IconTablerLetterW, + name: "Weekly Sum", + title: "Weekly Sum Of Blocks Mined", + description: "", + bottom: [ + { + title: "Target", + color: colors.white, + datasetPath: `/date-to-blocks-mined-1w-target`, + options: { + lineStyle: 3, + }, + }, + { + title: "Sum Mined", + color: colors.bitcoin, + datasetPath: `/date-to-blocks-mined-1w-sum`, + }, + ], }, - }, - { - title: "Sum Mined", - color: colors.bitcoin, - datasetPath: `/date-to-blocks-mined-1m-sum`, - }, - ], - }, - { - scale, - icon: IconTablerLetterY, - name: "Yearly Sum", - title: "Yearly Sum Of Blocks Mined", - description: "", - bottom: [ - { - title: "Target", - color: colors.white, - datasetPath: `/date-to-blocks-mined-1y-target`, - options: { - lineStyle: 3, + { + scale, + icon: IconTablerLetterM, + name: "Monthly Sum", + title: "Monthly Sum Of Blocks Mined", + description: "", + bottom: [ + { + title: "Target", + color: colors.white, + datasetPath: `/date-to-blocks-mined-1m-target`, + options: { + lineStyle: 3, + }, + }, + { + title: "Sum Mined", + color: colors.bitcoin, + datasetPath: `/date-to-blocks-mined-1m-sum`, + }, + ], }, - }, - { - title: "Sum Mined", - color: colors.bitcoin, - datasetPath: `/date-to-blocks-mined-1y-sum`, - }, - ], - }, - { - scale, - icon: IconTablerWall, - name: "Total", - title: "Total Blocks Mined", - description: "", - bottom: [ - { - title: "Mined", - color: colors.bitcoin, - datasetPath: `/date-to-total-blocks-mined`, - }, - ], - }, - ], - }, + { + scale, + icon: IconTablerLetterY, + name: "Yearly Sum", + title: "Yearly Sum Of Blocks Mined", + description: "", + bottom: [ + { + title: "Target", + color: colors.white, + datasetPath: `/date-to-blocks-mined-1y-target`, + options: { + lineStyle: 3, + }, + }, + { + title: "Sum Mined", + color: colors.bitcoin, + datasetPath: `/date-to-blocks-mined-1y-sum`, + }, + ], + }, + { + scale, + icon: IconTablerWall, + name: "Total", + title: "Total Blocks Mined", + description: "", + bottom: [ + { + title: "Mined", + color: colors.bitcoin, + datasetPath: `/date-to-total-blocks-mined`, + }, + ], + }, + ], + }, + ] + : [ + { + scale, + icon: IconTablerMaximize, + name: "Size", + title: "Block Size", + description: "", + bottom: [ + { + title: "Size (MB)", + color: colors.darkWhite, + datasetPath: `/height-to-block-size`, + }, + ], + }, + { + scale, + icon: IconTablerWeight, + name: "Weight", + title: "Block Weight", + description: "", + bottom: [ + { + title: "Weight (MB)", + color: colors.darkWhite, + datasetPath: `/height-to-block-weight`, + }, + ], + }, + { + scale, + icon: IconTablerBinary, + name: "VBytes", + title: "Block VBytes", + description: "", + bottom: [ + { + title: "VBytes", + color: colors.darkWhite, + datasetPath: `/height-to-block-vbytes`, + }, + ], + }, + { + scale, + icon: IconTablerAlarm, + name: "Interval", + title: "Block Interval", + description: "", + bottom: [ + { + title: "Interval (s)", + color: colors.darkWhite, + datasetPath: `/height-to-block-interval`, + }, + ], + }, + ]) satisfies PartialPresetTree), { scale, icon: IconTablerStack3, @@ -149,7 +208,7 @@ export function createPresets() { { title: "Size (MB)", color: colors.darkWhite, - datasetPath: `/date-to-cumulative-block-size`, + datasetPath: `/${scale}-to-cumulative-block-size`, }, ], }, diff --git a/app/src/scripts/presets/index.ts b/app/src/scripts/presets/index.ts index 988393a4e..ca0a465ff 100644 --- a/app/src/scripts/presets/index.ts +++ b/app/src/scripts/presets/index.ts @@ -36,7 +36,7 @@ export function createPresets(): Presets { name: "By Block Date", tree: [ createMarketPresets("date"), - createBlocksPresets(), + createBlocksPresets("date"), createMinersPresets("date"), createTransactionsPresets("date"), ...createCohortPresetList({ @@ -62,6 +62,7 @@ export function createPresets(): Presets { tree: !phone ? [ createMarketPresets("height"), + createBlocksPresets("height"), createMinersPresets("height"), createTransactionsPresets("height"), ...createCohortPresetList({ diff --git a/app/src/scripts/presets/market/averages/index.ts b/app/src/scripts/presets/market/averages/index.ts index a8d45665e..bb409e617 100644 --- a/app/src/scripts/presets/market/averages/index.ts +++ b/app/src/scripts/presets/market/averages/index.ts @@ -12,7 +12,7 @@ export function createPresets(scale: ResourceScale): PartialPresetFolder { scale, icon: IconTablerMathAvg, name: "All", - title: "All Averages", + title: "All Moving Averages", description: "", top: averages.map((average) => ({ title: average.key.toUpperCase(), @@ -25,6 +25,7 @@ export function createPresets(scale: ResourceScale): PartialPresetFolder { scale, color: colors[`_${key}`], name, + title: `${name} Market Price Moving Average`, key, }), ), @@ -36,11 +37,13 @@ function createPresetFolder({ scale, color, name, + title, key, }: { scale: ResourceScale; color: Color; name: string; + title: string; key: AverageName; }) { return { @@ -51,7 +54,7 @@ function createPresetFolder({ name: "Average", description: "", icon: IconTablerMathAvg, - title: `${name} Moving Average`, + title, top: [ { title: `SMA`, @@ -60,255 +63,12 @@ function createPresetFolder({ }, ], }, - // { - // name: "Ratio", - // tree: [ - // { - // scale, - // name: "Basic", - // description: "", - // icon: IconTablerMathXDivideY, - // title: `Market Price To ${name} Moving Average Ratio`, - // top: [ - // { - // title: `SMA`, - // color, - // datasetPath: `/${scale}-to-price-${key}-sma`, - // }, - // ], - // bottom: [ - // { - // title: `Ratio`, - // seriesType: SeriesType.Based, - // datasetPath: `/${scale}-to-market-price-to-price-${key}-sma-ratio`, - // options: { - // base: 1, - // }, - // }, - // { - // title: `Even`, - // color: colors.white, - // datasetPath: `/${scale}-to-1`, - // options: { - // lineStyle: 3, - // lastValueVisible: false, - // }, - // }, - // ], - // }, - // { - // scale, - // name: "Averages", - // description: "", - // icon: IconTablerMathAvg, - // title: `Market Price To ${name} Moving Average Ratio Averages`, - // top: [ - // { - // title: `SMA`, - // color, - // datasetPath: `/${scale}-to-price-${key}-sma`, - // }, - // ], - // bottom: [ - // { - // title: `1Y`, - // color: colors._1y, - // datasetPath: `/${scale}-to-market-price-to-price-${key}-sma-ratio-1y-sma`, - // }, - // { - // title: `1M`, - // color: colors._1m, - // datasetPath: `/${scale}-to-market-price-to-price-${key}-sma-ratio-1m-sma`, - // }, - // { - // title: `1W`, - // color: colors._1w, - // datasetPath: `/${scale}-to-market-price-to-price-${key}-sma-ratio-1w-sma`, - // }, - // { - // title: `Raw`, - // color: colors.white, - // datasetPath: `/${scale}-to-market-price-to-price-${key}-sma-ratio`, - // options: { - // base: 1, - // }, - // }, - // { - // title: `Even`, - // color: colors.gray, - // datasetPath: `/${scale}-to-1`, - // options: { - // lineStyle: 3, - // lastValueVisible: false, - // }, - // }, - // ], - // }, - // { - // scale, - // name: "Momentum Oscillator", - // description: "", - // icon: IconTablerWaveSine, - // title: `Market Price To ${name} Moving Average Ratio 1Y SMA Momentum Oscillator`, - // top: [ - // { - // title: `SMA`, - // color, - // datasetPath: `/${scale}-to-price-${key}-sma`, - // }, - // ], - // bottom: [ - // { - // title: `Momentum`, - // seriesType: SeriesType.Based, - // datasetPath: `/${scale}-to-market-price-to-price-${key}-sma-ratio-1y-sma-momentum-oscillator`, - // }, - // { - // title: `Base`, - // color: colors.white, - // datasetPath: `/${scale}-to-0`, - // options: { - // lineStyle: 3, - // lastValueVisible: false, - // }, - // }, - // ], - // }, - // { - // scale, - // name: "Top Percentiles", - // description: "", - // icon: IconTablerFlame, - // title: `Market Price To ${name} Moving Average Ratio Top Percentiles`, - // top: [ - // { - // title: `SMA`, - // color, - // datasetPath: `/${scale}-to-price-${key}-sma`, - // }, - // ], - // bottom: [ - // { - // title: `99.9%`, - // color: colors.extremeMax, - // datasetPath: `/${scale}-to-market-price-to-price-${key}-sma-ratio-99-9p`, - // }, - // { - // title: `99.5%`, - // color: colors.extremeMiddle, - // datasetPath: `/${scale}-to-market-price-to-price-${key}-sma-ratio-99-5p`, - // }, - // { - // title: `99%`, - // color: colors.extremeMin, - // datasetPath: `/${scale}-to-market-price-to-price-${key}-sma-ratio-99p`, - // }, - // { - // title: `Raw`, - // color: colors.white, - // datasetPath: `/${scale}-to-market-price-to-price-${key}-sma-ratio`, - // options: { - // base: 1, - // }, - // }, - // ], - // }, - // { - // scale, - // name: "Bottom Percentiles", - // description: "", - // icon: IconTablerIceCream, - // title: `Market Price To ${name} Moving Average Ratio Bottom Percentiles`, - // top: [ - // { - // title: `SMA`, - // color, - // datasetPath: `/${scale}-to-price-${key}-sma`, - // }, - // ], - // bottom: [ - // { - // title: `1%`, - // color: colors.extremeMin, - // datasetPath: `/${scale}-to-market-price-to-price-${key}-sma-ratio-1p`, - // }, - // { - // title: `0.5%`, - // color: colors.extremeMiddle, - // datasetPath: `/${scale}-to-market-price-to-price-${key}-sma-ratio-0-5p`, - // }, - // { - // title: `0.1%`, - // color: colors.extremeMax, - // datasetPath: `/${scale}-to-market-price-to-price-${key}-sma-ratio-0-1p`, - // }, - // { - // title: `Raw`, - // color: colors.white, - // datasetPath: `/${scale}-to-market-price-to-price-${key}-sma-ratio`, - // options: { - // base: 1, - // }, - // }, - // ], - // }, - // { - // scale, - // name: "Extreme Tops", - // description: "", - // icon: IconTablerRocket, - // title: `${name} Moving Average Extreme Tops`, - // top: [ - // { - // title: `99.9%`, - // color: colors.extremeMax, - // datasetPath: `/${scale}-to-price-${key}-sma-99-9p`, - // }, - // { - // title: `99.5%`, - // color: colors.extremeMiddle, - // datasetPath: `/${scale}-to-price-${key}-sma-99-5p`, - // }, - // { - // title: `99%`, - // color: colors.extremeMin, - // datasetPath: `/${scale}-to-price-${key}-sma-99p`, - // }, - // ], - // }, - // { - // scale, - // name: "Extreme Bottoms", - // description: "", - // icon: IconTablerSubmarine, - // title: `${name} Moving Average Extreme Bottoms`, - // top: [ - // { - // title: `0.1%`, - // color: colors.extremeMax, - // datasetPath: `/${scale}-to-price-${key}-sma-0-1p`, - // }, - // { - // title: `0.5%`, - // color: colors.extremeMiddle, - // datasetPath: `/${scale}-to-price-${key}-sma-0-5p`, - // }, - // { - // title: `1%`, - // color: colors.extremeMin, - // datasetPath: `/${scale}-to-price-${key}-sma-1p`, - // }, - // ], - // }, - // ], - // }, - createRatioFolder({ scale, color, ratioDatasetPath: `/${scale}-to-market-price-to-price-${key}-sma-ratio`, valueDatasetPath: `/${scale}-to-price-${key}-sma`, - title: `${name} Moving Average`, + title, }), ], } satisfies PartialPresetFolder; diff --git a/app/src/scripts/presets/templates/ratio.ts b/app/src/scripts/presets/templates/ratio.ts index 7af61d58e..af7d67972 100644 --- a/app/src/scripts/presets/templates/ratio.ts +++ b/app/src/scripts/presets/templates/ratio.ts @@ -142,17 +142,17 @@ export function createRatioFolder({ bottom: [ { title: `99.9%`, - color: colors.extremeMax, + color: colors.probability0_1p, datasetPath: `${ratioDatasetPath}-99-9p` as any, }, { title: `99.5%`, - color: colors.extremeMiddle, + color: colors.probability0_5p, datasetPath: `${ratioDatasetPath}-99-5p` as any, }, { title: `99%`, - color: colors.extremeMin, + color: colors.probability1p, datasetPath: `${ratioDatasetPath}-99p` as any, }, { @@ -178,17 +178,17 @@ export function createRatioFolder({ bottom: [ { title: `1%`, - color: colors.extremeMin, + color: colors.probability1p, datasetPath: `${ratioDatasetPath}-1p` as any, }, { title: `0.5%`, - color: colors.extremeMiddle, + color: colors.probability0_5p, datasetPath: `${ratioDatasetPath}-0-5p` as any, }, { title: `0.1%`, - color: colors.extremeMax, + color: colors.probability0_1p, datasetPath: `${ratioDatasetPath}-0-1p` as any, }, { @@ -200,48 +200,48 @@ export function createRatioFolder({ }, { scale, - name: "Extreme Tops", + name: "Top Probabilities", description: "", icon: IconTablerRocket, - title: `${title} Extreme Tops`, + title: `${title} Top Probabilities`, top: [ { - title: `99.9%`, - color: colors.extremeMax, + title: `0.1%`, + color: colors.probability0_1p, datasetPath: `${valueDatasetPath}-99-9p` as any, }, { - title: `99.5%`, - color: colors.extremeMiddle, + title: `0.5%`, + color: colors.probability0_5p, datasetPath: `${valueDatasetPath}-99-5p` as any, }, { - title: `99%`, - color: colors.extremeMin, + title: `1%`, + color: colors.probability1p, datasetPath: `${valueDatasetPath}-99p` as any, }, ], }, { scale, - name: "Extreme Bottoms", + name: "Bottom Probabilities", description: "", icon: IconTablerSubmarine, - title: `${title} Extreme Bottoms`, + title: `${title} Bottom Probabilities`, top: [ { title: `0.1%`, - color: colors.extremeMax, + color: colors.probability0_1p, datasetPath: `${valueDatasetPath}-0-1p` as any, }, { title: `0.5%`, - color: colors.extremeMiddle, + color: colors.probability0_5p, datasetPath: `${valueDatasetPath}-0-5p` as any, }, { title: `1%`, - color: colors.extremeMin, + color: colors.probability1p, datasetPath: `${valueDatasetPath}-1p` as any, }, ], diff --git a/app/src/scripts/utils/colors.ts b/app/src/scripts/utils/colors.ts index 03b811f07..d08e7dba9 100644 --- a/app/src/scripts/utils/colors.ts +++ b/app/src/scripts/utils/colors.ts @@ -306,9 +306,9 @@ export const colors = { momentumGreen: green, momentumYellow: yellow, momentumRed: red, - extremeMax: red, - extremeMiddle: orange, - extremeMin: yellow, + probability0_1p: red, + probability0_5p: orange, + probability1p: yellow, year_2009: yellow, year_2010: yellow, year_2011: yellow, diff --git a/app/src/types/auto-imports.d.ts b/app/src/types/auto-imports.d.ts index 3cee5c993..8154b4672 100644 --- a/app/src/types/auto-imports.d.ts +++ b/app/src/types/auto-imports.d.ts @@ -34,6 +34,7 @@ declare global { const IconTablerAsterisk: typeof import('~icons/tabler/asterisk.jsx')['default'] const IconTablerAt: (typeof import("~icons/tabler/at.jsx"))["default"] const IconTablerBalance: (typeof import("~icons/tabler/balance.jsx"))["default"] + const IconTablerBinary: typeof import('~icons/tabler/binary.jsx')['default'] const IconTablerBitcoin: typeof import('~icons/tabler/bitcoin.jsx')['default'] const IconTablerBitcoinCoin: typeof import('~icons/tabler/bitcoin-coin.jsx')['default'] const IconTablerBolt: (typeof import("~icons/tabler/bolt.jsx"))["default"] diff --git a/parser/src/actions/parse.rs b/parser/src/actions/parse.rs index ae47f3160..695df3819 100644 --- a/parser/src/actions/parse.rs +++ b/parser/src/actions/parse.rs @@ -92,8 +92,13 @@ pub fn parse( let block_size = block.total_size(); let block_weight = block.weight().to_wu(); let block_vbytes = block.weight().to_vbytes_floor(); - let block_interval = - previous_timestamp.map_or(0, |previous_timestamp| timestamp - previous_timestamp); + let block_interval = previous_timestamp.map_or(0, |previous_timestamp| { + if previous_timestamp <= timestamp { + 0 + } else { + timestamp - previous_timestamp + } + }); states .date_data_vec diff --git a/parser/src/datasets/mining.rs b/parser/src/datasets/mining.rs index c6d8c78b1..17b217e99 100644 --- a/parser/src/datasets/mining.rs +++ b/parser/src/datasets/mining.rs @@ -51,7 +51,7 @@ pub struct MiningDataset { pub block_size: HeightMap, // in MB pub block_weight: HeightMap, // in MB pub block_vbytes: HeightMap, - pub block_interval: HeightMap, // in ms + pub block_interval: HeightMap, // in s // Computed pub annualized_issuance: BiMap, // Same as subsidy_1y_sum @@ -88,10 +88,14 @@ pub struct MiningDataset { pub hash_price: DateMap, pub difficulty_adjustment: DateMap, pub puell_multiple: DateMap, - // pub average_block_size: DateMap, // in MB - // pub average_block_weight: DateMap, // in MB - // pub average_block_vbytes: DateMap, - // pub average_block_interval: DateMap, // in ms + // pub block_size_1d_sma: DateMap, // in MB + // pub block_weight_1d_sma: DateMap, // in MB + // pub block_vbytes_1d_sma: DateMap, + // pub block_interval_1d_sma: DateMap, // in s + // pub block_size_1d_median: DateMap, // in MB + // pub block_weight_1d_median: DateMap, // in MB + // pub block_vbytes_1d_median: DateMap, + // pub block_interval_1d_median: DateMap, // pub blocks_size: DateMap, // pub average_block_size: DateMap, // pub median_block_size: DateMap, @@ -167,11 +171,19 @@ impl MiningDataset { difficulty: BiMap::new_bin(1, &f("difficulty")), difficulty_adjustment: DateMap::new_bin(1, &f("difficulty_adjustment")), block_size: HeightMap::new_bin(1, &f("block_size")), + // + // block_size_1d_sma: HeightMap::new_bin(1, &f("block_size")), + // block_size_1d_median: HeightMap::new_bin(1, &f("block_size")), + // cumulative_block_size: BiMap::new_bin(1, &f("cumulative_block_size")), block_weight: HeightMap::new_bin(1, &f("block_weight")), + // + // block_weight_1d_sma: HeightMap::new_bin(1, &f("block_weight")), block_vbytes: HeightMap::new_bin(1, &f("block_vbytes")), - block_interval: HeightMap::new_bin(1, &f("block_interval")), - + // block_vbytes_1d_sma: HeightMap::new_bin(1, &f("block_vbytes")), + block_interval: HeightMap::new_bin(2, &f("block_interval")), + // block_interval_1d_sma: HeightMap::new_bin(2, &f("block_interval")), + // hash_rate: DateMap::new_bin(1, &f("hash_rate")), hash_rate_1w_sma: DateMap::new_bin(1, &f("hash_rate_1w_sma")), hash_rate_1m_sma: DateMap::new_bin(1, &f("hash_rate_1m_sma")), diff --git a/parser/src/datasets/subs/capitalization.rs b/parser/src/datasets/subs/capitalization.rs index 0eed9e7e7..c8f114729 100644 --- a/parser/src/datasets/subs/capitalization.rs +++ b/parser/src/datasets/subs/capitalization.rs @@ -57,8 +57,8 @@ impl CapitalizationDataset { &mut self, &InsertData { height, - is_date_last_block, date, + is_date_last_block, .. }: &InsertData, state: &CapitalizationState, diff --git a/parser/src/datasets/subs/mod.rs b/parser/src/datasets/subs/mod.rs index 9b60d4232..f5a62ca2b 100644 --- a/parser/src/datasets/subs/mod.rs +++ b/parser/src/datasets/subs/mod.rs @@ -2,20 +2,20 @@ use allocative::Allocative; mod capitalization; mod input; -mod ratio; -// mod output; mod price_paid; +mod ratio; mod realized; +// mod recap; mod supply; mod unrealized; mod utxo; pub use capitalization::*; pub use input::*; -pub use ratio::*; -// pub use output::*; pub use price_paid::*; +pub use ratio::*; pub use realized::*; +// pub use recap::*; pub use supply::*; pub use unrealized::*; pub use utxo::*; diff --git a/parser/src/datasets/subs/recap.rs b/parser/src/datasets/subs/recap.rs new file mode 100644 index 000000000..a0d0602d1 --- /dev/null +++ b/parser/src/datasets/subs/recap.rs @@ -0,0 +1,237 @@ +use allocative::Allocative; + +use crate::{ + datasets::{AnyDataset, ComputeData, MinInitialStates}, + structs::{AnyDateMap, MapValue}, + DateMap, HeightMap, +}; + +#[derive(Default, Allocative)] +pub struct RecapDataset { + min_initial_states: MinInitialStates, + + // Computed + min: Option>, + max: Option>, + median: Option>, + average: Option>, + sum: Option>, + _90p: Option>, + _75p: Option>, + _25p: Option>, + _10p: Option>, +} + +#[derive(Default)] +struct RecapOptions { + min: bool, + max: bool, + median: bool, + average: bool, + sum: bool, + _90p: bool, + _75p: bool, + _25p: bool, + _10p: bool, +} + +impl RecapOptions { + pub fn add_min(&mut self) { + self.min = true; + } + + pub fn add_max(&mut self) { + self.max = true; + } + + pub fn add_median(&mut self) { + self.median = true; + } + + pub fn add_average(&mut self) { + self.average = true; + } + + pub fn add_sum(&mut self) { + self.sum = true; + } + + pub fn add_90p(&mut self) { + self._90p = true; + } + + pub fn add_75p(&mut self) { + self._75p = true; + } + + pub fn add_25p(&mut self) { + self._25p = true; + } + + pub fn add_10p(&mut self) { + self._10p = true; + } +} + +impl RecapDataset +where + T: MapValue, +{ + pub fn import(parent_path: &str, options: RecapOptions) -> color_eyre::Result { + let f = |s: &str| format!("{parent_path}/{s}"); + + let mut s = Self { + min_initial_states: MinInitialStates::default(), + + min: options.min.then(|| DateMap::new_bin(1, &f("min"))), + max: options.max.then(|| DateMap::new_bin(1, &f("max"))), + median: options.median.then(|| DateMap::new_bin(1, &f("median"))), + average: options.average.then(|| DateMap::new_bin(1, &f("average"))), + sum: options.sum.then(|| DateMap::new_bin(1, &f("sum"))), + _90p: options._90p.then(|| DateMap::new_bin(1, &f("90p"))), + _75p: options._75p.then(|| DateMap::new_bin(1, &f("75p"))), + _25p: options._25p.then(|| DateMap::new_bin(1, &f("25p"))), + _10p: options._10p.then(|| DateMap::new_bin(1, &f("10p"))), + }; + + s.min_initial_states + .consume(MinInitialStates::compute_from_dataset(&s)); + + Ok(s) + } + + pub fn compute( + &mut self, + &ComputeData { heights, dates }: &ComputeData, + source: &mut HeightMap, + ) { + if let Some(min) = self.min.as_ref() { + // v.push(min); + } + + if let Some(max) = self.max.as_ref() { + // v.push(max); + } + + if let Some(median) = self.median.as_ref() { + // v.push(median); + } + + if let Some(average) = self.average.as_ref() { + // v.push(average); + } + + if let Some(sum) = self.sum.as_ref() { + // v.push(sum); + } + + if let Some(_90p) = self._90p.as_ref() { + // v.push(_90p); + } + + if let Some(_75p) = self._75p.as_ref() { + // v.push(_75p); + } + + if let Some(_25p) = self._25p.as_ref() { + // v.push(_25p); + } + + if let Some(_10p) = self._10p.as_ref() { + // v.push(_10p); + } + } +} + +impl AnyDataset for RecapDataset +where + T: MapValue, +{ + fn get_min_initial_states(&self) -> &MinInitialStates { + &self.min_initial_states + } + + fn to_computed_date_map_vec(&self) -> Vec<&(dyn AnyDateMap + Send + Sync)> { + let mut v: Vec<&(dyn AnyDateMap + Send + Sync)> = vec![]; + + if let Some(min) = self.min.as_ref() { + v.push(min); + } + + if let Some(max) = self.max.as_ref() { + v.push(max); + } + + if let Some(median) = self.median.as_ref() { + v.push(median); + } + + if let Some(average) = self.average.as_ref() { + v.push(average); + } + + if let Some(sum) = self.sum.as_ref() { + v.push(sum); + } + + if let Some(_90p) = self._90p.as_ref() { + v.push(_90p); + } + + if let Some(_75p) = self._75p.as_ref() { + v.push(_75p); + } + + if let Some(_25p) = self._25p.as_ref() { + v.push(_25p); + } + + if let Some(_10p) = self._10p.as_ref() { + v.push(_10p); + } + + v + } + + fn to_computed_mut_date_map_vec(&mut self) -> Vec<&mut dyn AnyDateMap> { + let mut v: Vec<&mut dyn AnyDateMap> = vec![]; + + if let Some(min) = self.min.as_mut() { + v.push(min); + } + + if let Some(max) = self.max.as_mut() { + v.push(max); + } + + if let Some(median) = self.median.as_mut() { + v.push(median); + } + + if let Some(average) = self.average.as_mut() { + v.push(average); + } + + if let Some(sum) = self.sum.as_mut() { + v.push(sum); + } + + if let Some(_90p) = self._90p.as_mut() { + v.push(_90p); + } + + if let Some(_75p) = self._75p.as_mut() { + v.push(_75p); + } + + if let Some(_25p) = self._25p.as_mut() { + v.push(_25p); + } + + if let Some(_10p) = self._10p.as_mut() { + v.push(_10p); + } + + v + } +}