diff --git a/__tests__/app/networkPages.test.tsx b/__tests__/app/networkPages.test.tsx index 40da9c416d..8962fcab65 100644 --- a/__tests__/app/networkPages.test.tsx +++ b/__tests__/app/networkPages.test.tsx @@ -1,9 +1,12 @@ +import DefinitionsPage, { + generateMetadata as generateDefinitionsMetadata, +} from "@/app/network/definitions/page"; import GroupsPage, { generateMetadata as generateGroupsMetadata, } from "@/app/network/groups/page"; -import CommunityMetricsPage, { - generateMetadata as generateMetricsMetadata, -} from "@/app/network/metrics/page"; +import TDHPage, { + generateMetadata as generateTDHMetadata, +} from "@/app/network/tdh/page"; import { AuthContext } from "@/components/auth/Auth"; import { render, screen } from "@testing-library/react"; import React from "react"; @@ -64,17 +67,26 @@ describe("network pages render", () => { expect(screen.getByTestId("groups-component")).toBeInTheDocument(); }); - it("renders Community Metrics page", () => { - renderWithAuth(); - expect(screen.getByText("Network")).toBeInTheDocument(); - expect(screen.getByText("Metrics")).toBeInTheDocument(); - expect(screen.getByText(/Background/i)).toBeInTheDocument(); - expect(screen.getByText(/Metrics Definitions/i)).toBeInTheDocument(); + it("renders TDH page", () => { + renderWithAuth(); + expect( + screen.getByRole("heading", { level: 1, name: /^TDH$/ }) + ).toBeInTheDocument(); + expect(screen.getByText(/How TDH is computed/i)).toBeInTheDocument(); + expect(screen.getByText(/TDH 1.4/i)).toBeInTheDocument(); }); - it("displays TDH calculation details in metrics page", () => { - renderWithAuth(); + it("displays TDH calculation details", () => { + renderWithAuth(); expect(screen.getByText(/Total Days Held/i)).toBeInTheDocument(); + expect(screen.getByText(/Additional Set Boost/i)).toBeInTheDocument(); + }); + + it("renders Definitions page", () => { + renderWithAuth(); + expect( + screen.getByRole("heading", { level: 1, name: /^Definitions$/ }) + ).toBeInTheDocument(); expect(screen.getByText(/Cards Collected/i)).toBeInTheDocument(); expect(screen.getByText(/Unique Memes/i)).toBeInTheDocument(); }); @@ -85,9 +97,15 @@ describe("network pages render", () => { expect(metadata.description).toEqual("Network | 6529.io"); }); - it("generates metadata for Metrics page", async () => { - const metadata = await generateMetricsMetadata(); - expect(metadata.title).toEqual("Metrics"); + it("generates metadata for TDH page", async () => { + const metadata = await generateTDHMetadata(); + expect(metadata.title).toEqual("TDH"); + expect(metadata.description).toEqual("Network | 6529.io"); + }); + + it("generates metadata for Definitions page", async () => { + const metadata = await generateDefinitionsMetadata(); + expect(metadata.title).toEqual("Definitions"); expect(metadata.description).toEqual("Network | 6529.io"); }); }); diff --git a/app/network/definitions/page.client.tsx b/app/network/definitions/page.client.tsx new file mode 100644 index 0000000000..8aa2736884 --- /dev/null +++ b/app/network/definitions/page.client.tsx @@ -0,0 +1,113 @@ +"use client"; + +import { useSetTitle } from "@/contexts/TitleContext"; +import Link from "next/link"; +import { Col, Container, Row } from "react-bootstrap"; + +const NAV_LINKS = [ + { href: "/network/tdh", label: "TDH" }, + { href: "/network/tdh/historic-boosts", label: "TDH Historic Boosts" }, + { href: "/network/stats", label: "Network Stats" }, + { href: "/network/levels", label: "Levels" }, +] as const; + +const BUTTON_LINK_CLASSES = + "tw-flex-1 tw-min-w-[150px] tw-text-center tw-inline-block tw-rounded-md tw-bg-[#eee] tw-text-black tw-font-medium hover:tw-bg-[#ddd] hover:tw-text-black tw-border-solid tw-border-[#222] tw-px-4 tw-py-2 tw-no-underline tw-w-full sm:tw-w-auto sm:tw-whitespace-nowrap"; + +export default function DefinitionsClient() { + useSetTitle("Definitions | Network"); + + return ( + + + +

Definitions

+ +
+

+ + Cards Collected: + {" "} + Total number of The Memes NFTs owned. +

+

+ + Unique Memes: + {" "} + Total number of unique Meme NFTs owned. +

+

+ + Meme Sets: + {" "} + Number of complete sets of The Memes (all SZNs or a specific SZN). +

+

+ + Meme Sets -1 / -2: + {" "} + Complete sets missing 1 or 2 cards respectively. +

+

+ + Genesis Sets: + {" "} + Complete set of the first three Meme NFTs. +

+

+ + Purchases / Sales: + {" "} + Count of bought/sold NFTs (Memes or Gradients). +

+

+ + Purchases (ETH) / Sales (ETH): + {" "} + ETH spent/received for those NFTs. +

+

+ + Transfers In / Out: + {" "} + NFTs moved into/out of an address. +

+

+ + TDH (unweighted): + {" "} + "Total Days Held" — each NFT contributes one unit per day held, + summed across NFTs, calculated daily at 00:00 UTC. +

+

+ + TDH (unboosted): + {" "} + TDH weighted by edition size (FirstGM 3,941 = 1.0 baseline). +

+

+ + TDH: + {" "} + TDH (unboosted) × boosters. For the current rules, see{" "} + + TDH + + . +

+
+ +
+ {NAV_LINKS.map(({ href, label }) => ( + + {label} + + ))} +
+ +
+
+ ); +} diff --git a/app/network/definitions/page.tsx b/app/network/definitions/page.tsx new file mode 100644 index 0000000000..d95f566f20 --- /dev/null +++ b/app/network/definitions/page.tsx @@ -0,0 +1,13 @@ +import { getAppMetadata } from "@/components/providers/metadata"; +import DefinitionsClient from "./page.client"; + +export default function Definitions() { + return ; +} + +export const generateMetadata = async () => { + return getAppMetadata({ + title: "Definitions", + description: "Network", + }); +}; diff --git a/app/network/metrics/page.client.tsx b/app/network/metrics/page.client.tsx deleted file mode 100644 index a87770143d..0000000000 --- a/app/network/metrics/page.client.tsx +++ /dev/null @@ -1,403 +0,0 @@ -"use client"; - -import styles from "@/styles/Home.module.scss"; -import { Container, Row, Col } from "react-bootstrap"; -import { useSetTitle } from "@/contexts/TitleContext"; - -export default function CommunityMetricsClient() { - useSetTitle("Metrics | Network"); - return ( - - - - - - -

- Network Metrics -

- -
- - -

- - Background - -

-

- One of our mental models is that NFT collections are publicly - readable databases of people with similar interests. For - example, we believe that, statistically, people who own The - Memes NFTs might be more likely to be interested in the - principles of decentralization than average. -

-

- We further believe that by seeing collector behavior on-chain, - we can further delineate different profiles. In other words, - someone who bought a few Meme Cards early and then just held - them is likely a different psychological profile than an - active buyer and seller. -

-

- We calculate and make available community wide (all of them - directly from public blockchain data) and we expect to add - more metrics over time. These metrics may be used from time to - time by us for allowlists, by others for their own allowlists - or by anyone for any purpose whatsoever. -

-

- No metric is the 'correct' metric. They are just - different ways to look at the community. We expect to continue - to add (but not subtract) metrics over time, in the hope that - some might be useful to others. -

-

- Our current view is that we can consolidate metrics for up to - 3 addresses via an on-chain delegation tool. This is something - we will review in a future release of these metrics. -

-

- Note that there is no provision (or planned provision) for - staking or locking NFTs. We suggest that people use their NFTs - in the normal way they like and the metrics will just reflect - their actual actions. -

-

- - Metrics Definitions - -

-

- Cards Collected: This is the total number of The Memes - NFTs owned by an address -

-

- Unique Memes: The total number of unique The Meme NFTs - owned by an address -

-

- Meme Sets: The total number of complete - "sets" of The Memes NFTs owned by an address, either - for all SZNs or a specific SZN -

-

- Meme Sets -1: The total number of complete - "sets" of The Memes NFTs owned by an address, - excluding 1 card -

-

- Meme Sets -2: The total number of complete - "sets" of The Memes NFTs owned by an address, - excluding 2 cards -

-

- Genesis Sets: The total number of complete - "sets" of the first three Meme NFTs owned by an - address -

-

- Purchases: Number of NFTs (Memes or Gradient) bought by - an address -

-

- Purchases (ETH): Amount of ETH spent on those NFTs by - an address -

-

- Sales: Number of NFTs (Memes or Gradient) sold by an - address -

-

- Sales (ETH): Amount of ETH received by an address from - the NFT sales -

-

- Transfers In: The number of NFTs (Memes or Gradient) - transferred into an address -

-

- Transfers Out: The number of NFTs (Memes or Gradient) - transferred out of an address -

-

- TDH (unweighted): "Total Days Held" - The - total number of days that the NFTs (Memes or Gradients) held - in an address have been held by that address. Each NFT-day - counts as one. This figured is calculated daily at 00:00 - Coordinated Universal Time (UTC). -

-

- TDH (unboosted): The TDH calculation above weighted by - the size of the card edition, with FirstGM edition size - (3,941) being weighted as 1. -

-

- So for the purposes of this calculation, SeizingJPG with an - edition size of 1,000 is weighted as 3.941 (3,941/1,000), - Nakamoto Freedom is weighted as 13.136 (3,941/300) and - Gradients are weighted as 39.020 (3,941/101) -

-

- TDH: "TDH (unboosted)" multiplied by a fun - qualitative factor based on which NFTS were collected. The - boosters are as follows: -

-
- - TDH 1.3 (March 29, 2024 - present) - -
-
-

- Higher of Category A and Category B Boosters, plus Category C - Boosters -

-

- Category A -

-
    -
  1. A complete set of all Meme Cards: 1.55x
  2. -
  3. - Additional complete set of Meme Cards: 1.02x (up to a - maximum of 2 additional sets) -
  4. -
-

- Category B -

- These boosts are applied to the total TDH, not just to that - SZN's TDH -
    -
  1. - SZN1: -
      -
    1. Complete Set: 1.05x or
    2. -
    3. Genesis Set: 1.01x and
    4. -
    5. Nakamoto Freedom: 1.01x
    6. -
    -
  2. -
  3. SZN2: Complete Set: 1.05x
  4. -
  5. SZN3: Complete Set: 1.05x
  6. -
  7. SZN4: Complete Set: 1.05x
  8. -
  9. SZN5: Complete Set: 1.05x
  10. -
  11. SZN6: Complete Set: 1.05x
  12. -
  13. SZN7: Complete Set: 1.05x
  14. -
  15. SZN8: Complete Set: 1.05x
  16. -
  17. SZN9: Complete Set: 1.05x
  18. -
  19. SZN10: Complete Set: 1.05x
  20. -
  21. SZN11: Complete Set: 1.05x
  22. -
-

- Category C -

-
    -
  1. - Gradient: 1.02x per Gradient (up to a maximum of 3 - Gradients) -
  2. -
-
- - TDH 1.2 (December 30, 2023 - March 28, 2024) - -
-
-

- Higher of Category A and Category B Boosters, plus Category C - Boosters -

-

- Category A -

-
    -
  1. A complete set of all Meme Cards: 1.25x
  2. -
  3. - Additional complete set of Meme Cards: 1.02x (up to a - maximum of 2 additional sets) -
  4. -
-

- Category B -

- These boosts are applied to the total TDH, not just to that - SZN's TDH -
    -
  1. - SZN1: -
      -
    1. Complete Set: 1.05x or
    2. -
    3. Genesis Set: 1.01x and
    4. -
    5. Nakamoto Freedom: 1.01x
    6. -
    -
  2. -
  3. SZN2: Complete Set: 1.05x
  4. -
  5. SZN3: Complete Set: 1.05x
  6. -
  7. SZN4: Complete Set: 1.05x
  8. -
  9. SZN5: Complete Set: 1.05x
  10. -
-

- Category C -

-
    -
  1. - Gradient: 1.02x per Gradient (up to a maximum of 3 - Gradients) -
  2. -
  3. - Identity: Boosts can be earned for both a) and b) - below: -
      -
    1. - 1.03x on any address that is part of an active Seize - profile -
    2. -
    3. - 1.01x for having an ENS domain/subdomain active on all - addresses in a consolidation -
    4. -
    -
  4. -
-
- - TDH 1.1 (July 14, 2023 - December 29, 2023) - -
-
-

- Higher of Category A and Category B Boosters, plus Category C - Boosters -

-

- Category A -

-
    -
  1. A complete set of all Meme Cards: 1.20x
  2. -
  3. - Additional complete set of Meme Cards: 1.02x (up to a - maximum of 2 additional sets) -
  4. -
-

- Category B -

-
    -
  1. - SZN1: -
      -
    1. Complete Set: 1.05x or
    2. -
    3. Genesis Set: 1.01x and
    4. -
    5. Nakamoto Freedom: 1.01x
    6. -
    -
  2. -
  3. SZN2: Complete Set: 1.05x
  4. -
  5. SZN3: Complete Set: 1.05x
  6. -
  7. SZN4: Complete Set: 1.05x
  8. -
-

- Category C -

-
    -
  1. - Gradient: 1.02x per Gradient (up to a maximum of 3 - Gradients) -
  2. -
  3. - 1.02x for having an ENS domain/subdomain active on all - addresses in a consolidation. The purpose of this boost is - to improve legibility of the collector profiles. The ENS - domain can be anonymous or pseudo. -
  4. -
-
-
-
- - TDH 1.0 (January 30, 2023 - July 13, 2023) - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(1)
A complete set of Meme Cards1.20x
+ 0.02x for each additional Meme Card set
and
+ 0.02x for each Gradient
with a max of 1.30x
- or -
(2)
A complete set of Meme Cards - 11.05x
A complete set of Meme Cards - 21.04x
A complete set of Meme Cards - 31.03x
A complete set of Meme Cards - 41.02x
A complete set of Meme Cards - 51.01x
A complete set of genesis cards (cards 1 to 3)1.02x
- or -
(3)
A complete set of genesis cards (cards 1 to 3):1.02x
-

- Each address uses the highest value that it is eligible for - from #1, #2 or #3 -

- -
-
- -
-
- ); -} diff --git a/app/network/metrics/page.tsx b/app/network/metrics/page.tsx deleted file mode 100644 index 1fb5e615c5..0000000000 --- a/app/network/metrics/page.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import styles from "@/styles/Home.module.scss"; -import { getAppMetadata } from "@/components/providers/metadata"; -import CommunityMetricsClient from "./page.client"; - -export default function CommunityMetrics() { - return ( -
- -
- ); -} - -export const generateMetadata = async () => { - return getAppMetadata({ - title: "Metrics", - description: "Network", - }); -}; diff --git a/app/network/stats/page.tsx b/app/network/stats/page.tsx index 115cb95aa3..4156d2ed8a 100644 --- a/app/network/stats/page.tsx +++ b/app/network/stats/page.tsx @@ -1,11 +1,11 @@ -import styles from "@/styles/Home.module.scss"; -import { Container, Row, Col } from "react-bootstrap"; import CommunityStatsComponent from "@/components/communityStats/CommunityStats"; import { getAppMetadata } from "@/components/providers/metadata"; +import styles from "@/styles/Home.module.scss"; +import { Col, Container, Row } from "react-bootstrap"; export default function CommunityStatsPage() { return ( -
+
diff --git a/app/network/tdh/historic-boosts/page.client.tsx b/app/network/tdh/historic-boosts/page.client.tsx new file mode 100644 index 0000000000..ce3b7fa899 --- /dev/null +++ b/app/network/tdh/historic-boosts/page.client.tsx @@ -0,0 +1,195 @@ +"use client"; + +import { useSetTitle } from "@/contexts/TitleContext"; +import Link from "next/link"; +import type { PropsWithChildren, ReactNode } from "react"; +import { Col, Container, Row } from "react-bootstrap"; + +function DetailsCard(props: Readonly<{ title: string; children: ReactNode }>) { + return ( +
+ +
{props.title}
+
+
{props.children}
+
+ ); +} + +function CategoryAList( + props: Readonly<{ + // heading element differences between 1.1 (h3) and others (p) + headingVariant: "p" | "h3"; + completeSetMultiplier: string; // "1.55x" | "1.25x" | "1.20x" + }> +) { + const Heading = (props.headingVariant === "h3" ? "h3" : "p") as any; + const headingClass = + props.headingVariant === "h3" + ? "tw-mt-3 tw-font-medium" + : "tw-font-medium tw-text-lg tw-mb-2"; + + return ( + <> + Category A +
    +
  • + A complete set of all Meme Cards:{" "} + + {props.completeSetMultiplier} + +
  • +
  • + Additional complete set:{" "} + 1.02x (up to a + maximum of 2 additional sets) +
  • +
+ + ); +} + +function Szn1Sublist() { + return ( +
    +
  • + Complete Set: 1.05x{" "} + or +
  • +
  • + Genesis Set: 1.01x{" "} + and +
  • +
  • + Nakamoto Set: 1.01x +
  • +
+ ); +} + +function CategoryBList( + props: Readonly<{ + maxSeason: number; // 4, 5, 11 + includeAppliedNote?: boolean; // only for 1.3 + }> +) { + const seasons = Array.from({ length: props.maxSeason }, (_, i) => i + 1); + + return ( + <> +

Category B

+ {props.includeAppliedNote ? ( +

+ Applied to total TDH (not just that SZN's TDH) +

+ ) : null} +
    +
  • + SZN1: + +
  • + {seasons + .filter((n) => n >= 2) // SZN2..max + .map((n) => ( +
  • + SZN{n}: 1.05x +
  • + ))} +
+ + ); +} + +function CategoryCList() { + return ( + <> +

Category C

+
    +
  • + Gradient: 1.02x{" "} + per Gradient (up to a maximum of 3) +
  • +
+ + ); +} + +function IntroLine(props: PropsWithChildren) { + return

{props.children}

; +} + +const NAV_LINKS = [ + { href: "/network/tdh", label: "TDH" }, + { href: "/network/definitions", label: "Definitions" }, + { href: "/network/stats", label: "Network Stats" }, + { href: "/network/levels", label: "Levels" }, +] as const; + +export default function TDHHistoricBoostsPage() { + useSetTitle("TDH Historic Boosts | Network"); + + return ( + + + +

TDH — Historic Boosts

+

+ Previous TDH versions are archived here for reference. +

+ +
+ {/* 1.3 */} + + + Higher of Category A and Category B Boosters, plus{" "} + Category C Boosters + + + + + + + + {/* 1.2 */} + + + Higher of Category A and Category B boosters, plus{" "} + Category C boosters + + + + + + + + {/* 1.1 */} + + + Higher of Category A and Category B Boosters, plus{" "} + Category C Boosters + + + + + + +
+ +
+ {NAV_LINKS.map(({ href, label }) => ( + + {label} + + ))} +
+ +
+
+ ); +} diff --git a/app/network/tdh/historic-boosts/page.tsx b/app/network/tdh/historic-boosts/page.tsx new file mode 100644 index 0000000000..f52dd0886b --- /dev/null +++ b/app/network/tdh/historic-boosts/page.tsx @@ -0,0 +1,13 @@ +import { getAppMetadata } from "@/components/providers/metadata"; +import TDHHistoricBoostsPage from "./page.client"; + +export default function TDHHistory() { + return ; +} + +export const generateMetadata = async () => { + return getAppMetadata({ + title: "TDH Historic Boosts", + description: "Network", + }); +}; diff --git a/app/network/tdh/page.client.tsx b/app/network/tdh/page.client.tsx new file mode 100644 index 0000000000..4404f72854 --- /dev/null +++ b/app/network/tdh/page.client.tsx @@ -0,0 +1,244 @@ +"use client"; + +import { useSetTitle } from "@/contexts/TitleContext"; +import Link from "next/link"; +import { Col, Container, Row } from "react-bootstrap"; + +const BUTTON_LINK_CLASSES = + "tw-inline-block tw-rounded-md tw-bg-[#eee] tw-text-black tw-font-medium tw-border-solid tw-border-[#222] hover:tw-bg-[#ddd] hover:tw-text-black tw-px-4 tw-py-2 tw-no-underline"; + +export default function TDHMainPage() { + useSetTitle("TDH | Network"); + + return ( + + + +

TDH

+

+ TDH (Total Days Held) is our time-weighted holding metric. Each NFT + you hold contributes its days-held to your total. We then multiply + by edition-size weights and apply collection "boosters" based on + what you hold. +

+ +
+

How TDH is computed

+
    +
  1. + Unweighted days: each + NFT contributes 1 per day it's held. +
  2. +
  3. + Edition weighting: we + scale by edition size with FirstGM (3,941) as 1. +
    + Examples: +
      +
    • SeizingJPG (Edition Size 1,000) = 3.941
    • +
    • Nakamoto Freedom (Edition Size 300) = 13.136
    • +
    • Gradients (Edition Size 101) = 39.020
    • +
    +
  4. +
  5. + Boosts: we multiply by + the higher of Category A + or B, then add Category C. (Details below.) +
  6. +
+

* Calculated daily at 00:00 UTC.

+
+ + {/* TDH 1.4 */} +
+

TDH 1.4 (October 8, 2025 — present)

+

+ Higher of Category A and Category B boosters, plus{" "} + Category C boosters. +

+ +
+

Category A

+
    +
  • + A complete set of all Meme Cards:{" "} + 1.60x +
  • +
+ +

+ Additional complete sets add to the total TDH (no cap): +

+

+ Additional Set Boost ={" "} + + 0.05 × (0.6529)(n-1) + +

+
+

Examples:

+
    +
  • + 1st additional set:{" "} + 0.05 +
  • +
  • + 2nd additional set:{" "} + + 0.05 × 0.6529 = 0.032645 + +
  • +
  • + 3rd additional set:{" "} + + 0.05 × 0.65292 = 0.021314 + +
  • +
  • + 5th additional set:{" "} + + 0.05 × 0.65294 = 0.009086 + +
  • +
  • + 10th additional set:{" "} + + 0.05 × 0.65299 = 0.001078 + +
  • +
+
+

+ Maximum theoretical Category A boost (infinite sets):{" "} + + {"0.60 + 0.05 / (1 - 0.6529) = 0.744051"} + +

+
+ +
+

Category B

+

+ Applied to the total TDH, not just that season's TDH: +

+
    +
  • + SZN1: +
      +
    • + Complete Set:{" "} + 1.05x{" "} + or +
    • +
    • + Genesis Set:{" "} + 1.01x{" "} + and +
    • +
    • + Nakamoto Set:{" "} + 1.01x +
    • +
    +
  • +
  • + SZN2:{" "} + 1.05x +
  • +
  • + SZN3:{" "} + 1.05x +
  • +
  • + SZN4:{" "} + 1.05x +
  • +
  • + SZN5:{" "} + 1.05x +
  • +
  • + SZN6:{" "} + 1.05x +
  • +
  • + SZN7:{" "} + 1.05x +
  • +
  • + SZN8:{" "} + 1.05x +
  • +
  • + SZN9:{" "} + 1.05x +
  • +
  • + SZN10:{" "} + 1.05x +
  • +
  • + SZN11:{" "} + 1.05x +
  • +
  • + SZN12:{" "} + 1.05x +
  • +
+
+ +
+

Category C

+
    +
  • + Gradient:{" "} + 1.02x per + Gradient (up to a maximum of{" "} + 5) +
  • +
+
+ +
+ + View Historic Boosts + + + Definitions + +
+
+ + {/* Cross-links */} +
+
+

Network Stats

+

+ Aggregate community activity, holdings, trading, and time-based + metrics across the network. +

+ + View Network Stats + +
+
+

Levels

+

+ Our integrated progression that combines TDH with{" "} + Rep (peer-given reputation points). +

+ + View Levels + +
+
+ +
+
+ ); +} diff --git a/app/network/tdh/page.tsx b/app/network/tdh/page.tsx new file mode 100644 index 0000000000..5f80abd011 --- /dev/null +++ b/app/network/tdh/page.tsx @@ -0,0 +1,13 @@ +import { getAppMetadata } from "@/components/providers/metadata"; +import TDHMainPage from "./page.client"; + +export default function TDH() { + return ; +} + +export const generateMetadata = async () => { + return getAppMetadata({ + title: "TDH", + description: "Network", + }); +}; diff --git a/components/about/AboutMinting.tsx b/components/about/AboutMinting.tsx index 30ac67aa74..6d4731c3ff 100644 --- a/components/about/AboutMinting.tsx +++ b/components/about/AboutMinting.tsx @@ -537,12 +537,12 @@ export default function AboutMinting() {
  • - For our full analysis of our Network Metrics, go here:{" "} + For our full analysis of our Network Definitions, go here:{" "} - 6529.io/network/metrics + 6529.io/network/definitions
  • diff --git a/components/brain/my-stream/MyStreamWaveFAQ.tsx b/components/brain/my-stream/MyStreamWaveFAQ.tsx index 035ec7479a..8ccdd1a302 100644 --- a/components/brain/my-stream/MyStreamWaveFAQ.tsx +++ b/components/brain/my-stream/MyStreamWaveFAQ.tsx @@ -437,7 +437,7 @@ const MyStreamWaveFAQ: React.FC = ({ wave }) => { /> diff --git a/components/header/AppSidebar.tsx b/components/header/AppSidebar.tsx index 8da18154e2..649118ee47 100644 --- a/components/header/AppSidebar.tsx +++ b/components/header/AppSidebar.tsx @@ -79,8 +79,9 @@ const MENU = [ { label: "Groups", path: "/network/groups" }, { label: "NFT Activity", path: "/nft-activity" }, { label: "Memes Calendar", path: "/meme-calendar" }, + { label: "TDH", path: "/network/tdh" }, { label: "Metrics", section: true }, - { label: "Definitions", path: "/network/metrics" }, + { label: "Definitions", path: "/network/definitions" }, { label: "Network Stats", path: "/network/stats" }, { label: "Levels", path: "/network/levels" }, ], diff --git a/components/header/Header.module.scss b/components/header/Header.module.scss index aa7f58fc2b..f9b3dfdad5 100644 --- a/components/header/Header.module.scss +++ b/components/header/Header.module.scss @@ -372,7 +372,8 @@ top: 0; display: none; background-color: black; - padding: 0.5rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; z-index: 1050; min-width: 160px; } diff --git a/components/header/HeaderMobileMenu.tsx b/components/header/HeaderMobileMenu.tsx index c0e9eb0d03..7d0803ced6 100644 --- a/components/header/HeaderMobileMenu.tsx +++ b/components/header/HeaderMobileMenu.tsx @@ -215,9 +215,10 @@ export default function HeaderMobileMenu({ {printMobileRow("Groups", "/network/groups")} {printMobileRow("NFT Activity", "/nft-activity")} {printMobileRow("Memes Calendar", "/meme-calendar")} + {printMobileRow("TDH", "/network/tdh")} {printMobileHr()} {printMobileSubheader("Metrics")} - {printMobileRow("Definitions", "/network/metrics")} + {printMobileRow("Definitions", "/network/definitions")} {printMobileRow("Network Stats", "/network/stats")} {printMobileRow("Levels", "/network/levels")} {printMobileHr()} diff --git a/components/header/HeaderNavConfig.ts b/components/header/HeaderNavConfig.ts index e84c367c48..e4e89e40db 100644 --- a/components/header/HeaderNavConfig.ts +++ b/components/header/HeaderNavConfig.ts @@ -57,12 +57,13 @@ export function getDesktopNavigation(_context: NavContext): NavDropdown[] { { name: "Groups", path: "/network/groups" }, { name: "NFT Activity", path: "/nft-activity" }, { name: "Memes Calendar", path: "/meme-calendar" }, + { name: "TDH", path: "/network/tdh" }, ], sections: [ { name: "Metrics", items: [ - { name: "Definitions", path: "/network/metrics" }, + { name: "Definitions", path: "/network/definitions" }, { name: "Network Stats", path: "/network/stats" }, { name: "Levels", path: "/network/levels" }, ], diff --git a/components/user/stats/UserPageStatsBoostBreakdown.tsx b/components/user/stats/UserPageStatsBoostBreakdown.tsx index 2bdb07ebbf..7a0350632d 100644 --- a/components/user/stats/UserPageStatsBoostBreakdown.tsx +++ b/components/user/stats/UserPageStatsBoostBreakdown.tsx @@ -45,42 +45,48 @@ export default function UserPageStatsBoostBreakdown({ } function getMemesRows() { - let rows = []; - rows.push( + const headerRow = ( Memes ); - if (tdh?.boost_breakdown) { - rows.push( - getMemeRow("Full Collection Set", tdh.boost_breakdown?.memes_card_sets) - ); - if (tdh.boost_breakdown?.memes_card_sets?.acquired === 0) { - rows.push(getMemeRow("SZN1", tdh.boost_breakdown?.memes_szn1)); - if (!tdh.boost_breakdown?.memes_szn1?.acquired) { - rows.push( - getMemeRow("Genesis Set", tdh.boost_breakdown?.memes_genesis) - ); - rows.push( - getMemeRow("Nakamoto", tdh.boost_breakdown?.memes_nakamoto) - ); - } - rows.push(getMemeRow("SZN2", tdh.boost_breakdown?.memes_szn2)); - rows.push(getMemeRow("SZN3", tdh.boost_breakdown?.memes_szn3)); - rows.push(getMemeRow("SZN4", tdh.boost_breakdown?.memes_szn4)); - rows.push(getMemeRow("SZN5", tdh.boost_breakdown?.memes_szn5)); - rows.push(getMemeRow("SZN6", tdh.boost_breakdown?.memes_szn6)); - rows.push(getMemeRow("SZN7", tdh.boost_breakdown?.memes_szn7)); - rows.push(getMemeRow("SZN8", tdh.boost_breakdown?.memes_szn8)); - rows.push(getMemeRow("SZN9", tdh.boost_breakdown?.memes_szn9)); - rows.push(getMemeRow("SZN10", tdh.boost_breakdown?.memes_szn10)); - rows.push(getMemeRow("SZN11", tdh.boost_breakdown?.memes_szn11)); - } + + const bb = tdh?.boost_breakdown; + if (!bb) return [headerRow]; + + const baseRows = [ + headerRow, + getMemeRow("Full Collection Set", bb.memes_card_sets), + ]; + + if (bb.memes_card_sets?.acquired !== 0) { + return baseRows; } - return rows; + const extraRows = [ + getMemeRow("SZN1", bb.memes_szn1), + ...(bb.memes_szn1?.acquired + ? [] + : [ + getMemeRow("Genesis Set", bb.memes_genesis), + getMemeRow("Nakamoto", bb.memes_nakamoto), + ]), + getMemeRow("SZN2", bb.memes_szn2), + getMemeRow("SZN3", bb.memes_szn3), + getMemeRow("SZN4", bb.memes_szn4), + getMemeRow("SZN5", bb.memes_szn5), + getMemeRow("SZN6", bb.memes_szn6), + getMemeRow("SZN7", bb.memes_szn7), + getMemeRow("SZN8", bb.memes_szn8), + getMemeRow("SZN9", bb.memes_szn9), + getMemeRow("SZN10", bb.memes_szn10), + getMemeRow("SZN11", bb.memes_szn11), + getMemeRow("SZN12", bb.memes_szn12), + ]; + + return [...baseRows, ...extraRows]; } function getBaseBoostRow(name: string, breakdown?: TDHBoostBreakdown) { @@ -125,9 +131,9 @@ export default function UserPageStatsBoostBreakdown({ - TDH Version: 1.3 + TDH Version: 1.4 diff --git a/entities/ITDH.ts b/entities/ITDH.ts index 38d2d52e44..ee622bc4a2 100644 --- a/entities/ITDH.ts +++ b/entities/ITDH.ts @@ -24,6 +24,7 @@ interface BaseTDH { memes_szn9: TDHBoostBreakdown; memes_szn10: TDHBoostBreakdown; memes_szn11: TDHBoostBreakdown; + memes_szn12: TDHBoostBreakdown; memes_genesis: TDHBoostBreakdown; memes_nakamoto: TDHBoostBreakdown; gradients: TDHBoostBreakdown; diff --git a/hooks/useBreadcrumbs.ts b/hooks/useBreadcrumbs.ts index bcae4f1523..53247abfdd 100644 --- a/hooks/useBreadcrumbs.ts +++ b/hooks/useBreadcrumbs.ts @@ -1,9 +1,9 @@ "use client"; +import { Crumb } from "@/components/breadcrumb/Breadcrumb"; import { useQuery } from "@tanstack/react-query"; import { usePathname, useSearchParams } from "next/navigation"; import { useEffect, useMemo, useState } from "react"; -import { Crumb } from "@/components/breadcrumb/Breadcrumb"; import { DYNAMIC_ROUTE_CONFIGS, DeterminedRouteInfo, @@ -140,6 +140,8 @@ export const useBreadcrumbs = (): Crumb[] => { // 1) Special caps if (disp === "api") c = { ...c, display: "API" }; + if (disp === "tdh") c = { ...c, display: "TDH" }; + if (disp === "tdh history") c = { ...c, display: "TDH History" }; // 2) Force non-link for "Tools" if (disp === "tools") { diff --git a/styles/Home.module.scss b/styles/Home.module.scss index e3aaba3a86..bf1bc007ba 100644 --- a/styles/Home.module.scss +++ b/styles/Home.module.scss @@ -41,13 +41,6 @@ background-color: transparent; } -.tdhMain { - h3, - h4 { - float: none; - } -} - .tdhFormula { line-height: 75px; color: lightblue; diff --git a/tests/pages/network-metrics.spec.ts b/tests/pages/network-metrics.spec.ts deleted file mode 100644 index 16e46fc220..0000000000 --- a/tests/pages/network-metrics.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { test, expect } from '../testHelpers'; - -test.describe("Network Metrics Page", () => { - test.beforeEach(async ({ page }, testInfo) => { - await page.goto("/network/metrics"); - }); - - test("should load with correct title and heading", async ({ page }) => { - await expect(page).toHaveTitle("Metrics | Network"); - - const heading = page.locator("h1"); - await expect(heading).toContainText("Network Metrics"); - await expect(heading).toBeVisible(); - }); -});