From 2938c5f5a589785c64c808bdaa2e0268e45d360a Mon Sep 17 00:00:00 2001 From: Lucas Meier Date: Tue, 22 Oct 2024 16:02:49 -0700 Subject: [PATCH] Display shielded pool changes --- app/routes/_index.tsx | 154 ++++++++++++++++++++++++++++++++++++++++-- package-lock.json | 18 +++-- package.json | 1 + 3 files changed, 163 insertions(+), 10 deletions(-) diff --git a/app/routes/_index.tsx b/app/routes/_index.tsx index a315a3a..9ce760f 100644 --- a/app/routes/_index.tsx +++ b/app/routes/_index.tsx @@ -2,7 +2,7 @@ import { Table } from "@penumbra-zone/ui/Table"; import type { MetaFunction } from "@remix-run/node"; import { Database, db, Schema } from "backend/database"; import { QueryCreator } from "kysely"; -import { splitLoHi } from "@penumbra-zone/types/lo-hi"; +import { joinLoHi, splitLoHi } from "@penumbra-zone/types/lo-hi"; import { AssetId, Metadata, @@ -13,7 +13,11 @@ import { Amount } from "@penumbra-zone/protobuf/penumbra/core/num/v1/num_pb"; import { useLoaderData } from "@remix-run/react"; import { Jsonified } from "@penumbra-zone/types/jsonified"; import { ChainRegistryClient, Registry } from "@penumbra-labs/registry"; -import { multiplyAmountByNumber } from "@penumbra-zone/types/amount"; +import { + joinLoHiAmount, + multiplyAmountByNumber, + subtractAmounts, +} from "@penumbra-zone/types/amount"; import { PenumbraUIProvider } from "@penumbra-zone/ui/PenumbraUIProvider"; import { ValueViewComponent } from "@penumbra-zone/ui/ValueViewComponent"; import { Grid } from "@penumbra-zone/ui/Grid"; @@ -21,6 +25,10 @@ import { Card } from "@penumbra-zone/ui/Card"; import { Density } from "@penumbra-zone/ui/Density"; import { getFormattedAmtFromValueView } from "@penumbra-zone/types/value-view"; import { Display } from "@penumbra-zone/ui/Display"; +import { TediousRequest } from "kysely"; +import { DropdownMenu } from "@penumbra-zone/ui/DropdownMenu"; +import { Button } from "@penumbra-zone/ui/Button"; +import { useState } from "react"; function knownValueView(metadata: Metadata, amount: Amount): ValueView { return new ValueView({ @@ -247,11 +255,13 @@ const ShowSupply = ({ supply }: { supply: Supply }) => { {"price"} - {supply.price} + ${supply.price.toLocaleString("en-us")} {"market_cap"} - {supply.market_cap} + + ${(supply.market_cap / 1000).toLocaleString("en-us")} + @@ -259,6 +269,42 @@ const ShowSupply = ({ supply }: { supply: Supply }) => { ); }; +const ValueViewChange = ({ + then, + now, + foo, +}: { + then: ValueView; + now: ValueView; + foo: string; +}) => { + const thenValue = then.valueView.value; + const nowValue = now.valueView.value; + if (!thenValue || !nowValue) { + throw new Error("cannot display values"); + } + const thenAmount = joinLoHiAmount(thenValue.amount!); + const nowAmount = joinLoHiAmount(nowValue.amount!); + const positive = nowAmount >= thenAmount; + const change = positive ? nowAmount - thenAmount : thenAmount - nowAmount; + const changeAmount = new Amount(splitLoHi(change)); + const newValue = new ValueView({ valueView: now.valueView }).clone(); + newValue.valueView.value!.amount = changeAmount; + const formatted = getFormattedAmtFromValueView(newValue, true); + const sign = positive ? "+" : "-"; + return ( + {`${sign}${formatted}`} + ); +}; + const ShowShielded = ({ shielded, }: { @@ -270,13 +316,79 @@ const ShowShielded = ({ : b.now.priority - a.now.priority, ); + const [changeWindow, setChangeWindow] = useState("24h"); + const [depositorsWindow, setDepositorsWindow] = useState("∞"); + + const getDepositors = (x: ShieldedPoolTimedSnapshots) => { + const now = x.now.unique_depositors; + if (depositorsWindow === "24h") { + return now - x.h24.unique_depositors; + } + if (depositorsWindow === "7d") { + return now - x.d7.unique_depositors; + } + if (depositorsWindow === "30d") { + return now - x.d30.unique_depositors; + } + return now; + }; + const getChange = (x: ShieldedPoolTimedSnapshots) => { + if (changeWindow === "24h") { + return x.h24; + } + if (changeWindow === "7d") { + return x.d7; + } + if (changeWindow === "30d") { + return x.d30; + } + throw new Error(`impossible changeWindow: ${changeWindow}`); + }; + return ( total / current - depositors + + + + + + + + {["24h", "7d", "30d"].map((x) => ( + + {x} + + ))} + + + + + + + + + + + + {["∞", "24h", "7d", "30d"].map((x) => ( + + {x} + + ))} + + + + @@ -288,7 +400,21 @@ const ShowShielded = ({ - {x.now.unique_depositors} + +
+ + +
+
+ {getDepositors(x)} ))}
@@ -304,6 +430,22 @@ export const meta: MetaFunction = () => { export default function Index() { const raw = useLoaderData>(); const data = Data.fromJson(raw); + console.log( + JSON.stringify( + data.shieldedPool + .filter( + (x) => + x.now.current.valueView.case === "knownAssetId" && + x.now.current.valueView.value.metadata!.symbol === "USDC", + ) + .map((x) => [ + x.now.current.valueView.value?.amount, + x.h24.current.valueView.value?.amount, + x.d7.current.valueView.value?.amount, + x.d30.current.valueView.value?.amount, + ]), + ), + ); return ( diff --git a/package-lock.json b/package-lock.json index 63ddf2f..833992b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@remix-run/serve": "^2.12.1", "isbot": "^4.1.0", "kysely": "^0.27.4", + "lucide-react": "^0.453.0", "pg": "^8.13.0", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -2016,6 +2017,15 @@ "tailwindcss": "^3.4.3" } }, + "node_modules/@penumbra-zone/ui/node_modules/lucide-react": { + "version": "0.378.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.378.0.tgz", + "integrity": "sha512-u6EPU8juLUk9ytRcyapkWI18epAv3RU+6+TC23ivjR0e+glWKBobFeSgRwOIJihzktILQuy6E0E80P2jVTDR5g==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/@penumbra-zone/wasm": { "version": "29.1.0", "resolved": "https://registry.npmjs.org/@penumbra-zone/wasm/-/wasm-29.1.0.tgz", @@ -10789,12 +10799,12 @@ } }, "node_modules/lucide-react": { - "version": "0.378.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.378.0.tgz", - "integrity": "sha512-u6EPU8juLUk9ytRcyapkWI18epAv3RU+6+TC23ivjR0e+glWKBobFeSgRwOIJihzktILQuy6E0E80P2jVTDR5g==", + "version": "0.453.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.453.0.tgz", + "integrity": "sha512-kL+RGZCcJi9BvJtzg2kshO192Ddy9hv3ij+cPrVPWSRzgCWCVazoQJxOjAwgK53NomL07HB7GPHW120FimjNhQ==", "license": "ISC", "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0" + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" } }, "node_modules/markdown-extensions": { diff --git a/package.json b/package.json index 99f5a63..c517695 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@remix-run/serve": "^2.12.1", "isbot": "^4.1.0", "kysely": "^0.27.4", + "lucide-react": "^0.453.0", "pg": "^8.13.0", "react": "^18.2.0", "react-dom": "^18.2.0",