Skip to content
Merged

Staging #15970

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e1f25ba
fix: return fallback config if not production
wackerow Jul 22, 2025
154255f
fix: user test group assignment distribution
wackerow Jul 22, 2025
54a0806
Merge pull request #15927 from ethereum/hot-matomo-ab
corwintines Jul 25, 2025
2a4a16b
fix 10 year date
corwintines Jul 28, 2025
fe967e5
Merge pull request #15949 from ethereum/10yeardate
wackerow Jul 28, 2025
38708f7
10y ui
pettinarip Jul 23, 2025
b4b7485
fix genesis block datetimes
pettinarip Jul 29, 2025
ecc43eb
livestream
pettinarip Jul 29, 2025
292f840
remove card to submit events
pettinarip Jul 29, 2025
5d850c5
update mainnet data
pettinarip Jul 29, 2025
44e747c
Merge pull request #15955 from ethereum/10y-new
minimalsm Jul 29, 2025
da87cd8
set maxresdefault to youtube component
pettinarip Jul 29, 2025
aeb8e4a
replace torchbearers external data call with static local data
pettinarip Jul 29, 2025
3d31b40
display gas price indicator when the user connects
pettinarip Jul 29, 2025
0c16591
fix: keep mint success ui after rerender
pettinarip Jul 29, 2025
4530323
Merge pull request #15956 from ethereum/hotfix-10y-livestream
pettinarip Jul 29, 2025
f76c08d
Merge branch 'master' into hotfix-10y-torchbearers
pettinarip Jul 29, 2025
22156f3
Merge pull request #15957 from ethereum/hotfix-10y-torchbearers
pettinarip Jul 29, 2025
b117431
Merge pull request #15958 from ethereum/fix-gasprice-calls
pettinarip Jul 29, 2025
5085005
Merge pull request #15959 from ethereum/fix-perisist-success
pettinarip Jul 29, 2025
c4a78dc
Merge pull request #15969 from ethereum/master
corwintines Jul 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,3 @@ ANALYZE=false
# Use mock data for development. Set to "false" to use live data but you must have the
# environment variables set to make api requests
USE_MOCK_DATA=true

# Google Sheet ID for torch holders
GOOGLE_SHEET_ID_TORCH_HOLDERS=
136 changes: 76 additions & 60 deletions app/[locale]/10years/_components/CountDown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ interface CountDownProps {
className?: string
timeLeftLabels: TimeLeftLabels
expiredLabel: string
dateTime: string
hideZeroUnits?: boolean
onExpired?: () => void
}

const CountDown = ({
className,
timeLeftLabels,
expiredLabel,
dateTime,
hideZeroUnits = false,
onExpired,
}: CountDownProps) => {
const [timeLeft, setTimeLeft] = useState({
days: 0,
Expand All @@ -26,7 +32,7 @@ const CountDown = ({
const [isExpired, setIsExpired] = useState(false)

useEffect(() => {
const targetDate = new Date("2025-07-30T15:44:00Z")
const targetDate = new Date(dateTime)

const calculateTimeLeft = () => {
const now = new Date()
Expand All @@ -41,7 +47,10 @@ const CountDown = ({
seconds: Math.floor((difference / 1000) % 60),
})
} else {
setIsExpired(true)
if (!isExpired) {
setIsExpired(true)
onExpired?.()
}
}
}

Expand All @@ -51,74 +60,81 @@ const CountDown = ({
const timer = setInterval(calculateTimeLeft, 1000)

return () => clearInterval(timer)
}, [])
}, [isExpired, onExpired, dateTime])

if (isExpired) {
return <div className="text-center text-2xl font-bold">{expiredLabel}</div>
}

return (
<div className="flex items-center justify-center gap-10">
<div
className={cn(
"flex h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold text-accent-a">
{timeLeft.days}
<div className="flex items-center justify-center gap-10 text-accent-a">
{(!hideZeroUnits || timeLeft.days > 0) && (
<div
className={cn(
"flex h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold">{timeLeft.days}</div>
<div className="font-mono text-xs">
{timeLeft.days === 1
? timeLeftLabels.days.singular
: timeLeftLabels.days.plural}
</div>
</div>
<div className="font-mono text-xs text-accent-a">
{timeLeft.days === 1
? timeLeftLabels.days.singular
: timeLeftLabels.days.plural}
)}
{(!hideZeroUnits || timeLeft.days > 0 || timeLeft.hours > 0) && (
<div
className={cn(
"flex h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold">{timeLeft.hours}</div>
<div className="font-mono text-xs">
{timeLeft.hours === 1
? timeLeftLabels.hours.singular
: timeLeftLabels.hours.plural}
</div>
</div>
</div>
<div
className={cn(
"flex h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold text-accent-a">
{timeLeft.hours}
)}
{(!hideZeroUnits ||
timeLeft.days > 0 ||
timeLeft.hours > 0 ||
timeLeft.minutes > 0) && (
<div
className={cn(
"flex h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold">{timeLeft.minutes}</div>
<div className="font-mono text-xs">
{timeLeft.minutes === 1
? timeLeftLabels.minutes.singular
: timeLeftLabels.minutes.plural}
</div>
</div>
<div className="font-mono text-xs text-accent-a">
{timeLeft.hours === 1
? timeLeftLabels.hours.singular
: timeLeftLabels.hours.plural}
)}
{(!hideZeroUnits ||
timeLeft.days > 0 ||
timeLeft.hours > 0 ||
timeLeft.minutes > 0 ||
timeLeft.seconds > 0) && (
<div
className={cn(
"hidden h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] lg:flex dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold">{timeLeft.seconds}</div>
<div className="font-mono text-xs">
{timeLeft.seconds === 1
? timeLeftLabels.seconds.singular
: timeLeftLabels.seconds.plural}
</div>
</div>
</div>
<div
className={cn(
"flex h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold text-accent-a">
{timeLeft.minutes}
</div>
<div className="font-mono text-xs text-accent-a">
{timeLeft.minutes === 1
? timeLeftLabels.minutes.singular
: timeLeftLabels.minutes.plural}
</div>
</div>
<div
className={cn(
"hidden h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] lg:flex dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold text-accent-a">
{timeLeft.seconds}
</div>
<div className="font-mono text-xs text-accent-a">
{timeLeft.seconds === 1
? timeLeftLabels.seconds.singular
: timeLeftLabels.seconds.plural}
</div>
</div>
)}
</div>
)
}
Expand Down
77 changes: 77 additions & 0 deletions app/[locale]/10years/_components/NFTMintCard/Connected.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Address } from "viem"
import { useDisconnect, useSwitchChain } from "wagmi"

import { Avatar } from "@/components/ui/avatar"
import { Button } from "@/components/ui/buttons/Button"

import { useNetworkContract } from "@/hooks/useNetworkContract"
import {
formatAddress,
getAddressEtherscanUrl,
getBlockieImage,
} from "@/lib/torch"

export default function Connected({
address,
ensName,
}: {
address: Address
ensName?: string | null
}) {
const { disconnect } = useDisconnect()
const { isSupportedNetwork, networkName, chainId } = useNetworkContract()
const { switchChain, isPending } = useSwitchChain()

const handleSwitchNetwork = () => {
switchChain({ chainId })
}

return (
<div className="flex flex-col items-center justify-between space-y-2">
{/* Wallet Info */}
<div className="flex items-center gap-4">
<Avatar
className="h-6 w-6 !shadow-none"
src={getBlockieImage(address)}
href={getAddressEtherscanUrl(address)}
name={ensName || formatAddress(address)}
/>
<div>{ensName || formatAddress(address)}</div>
</div>

{/* Network Status */}
<div className="text-center">
{isSupportedNetwork ? (
<div className="flex items-center gap-2 text-sm text-success">
<div className="h-2 w-2 rounded-full bg-success"></div>
<span>Connected to {networkName}</span>
</div>
) : (
<div className="flex flex-col items-center gap-2">
<div className="flex items-center gap-2 text-sm text-error">
<div className="h-2 w-2 rounded-full bg-error"></div>
<span>Unsupported Network</span>
</div>
<Button
size="sm"
onClick={handleSwitchNetwork}
disabled={isPending}
>
{isPending ? "Switching..." : `Switch to ${networkName}`}
</Button>
</div>
)}
</div>

{/* Disconnect Button */}
<Button
variant="link"
size="sm"
onClick={() => disconnect()}
className="text-body-medium"
>
disconnect
</Button>
</div>
)
}
14 changes: 14 additions & 0 deletions app/[locale]/10years/_components/NFTMintCard/Connection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useAccount } from "wagmi"

import MintConnect from "./views/MintConnect"
import Prechecks from "./Prechecks"

export default function Connection() {
const { address, isConnected } = useAccount()

if (!isConnected || !address) {
return <MintConnect />
}

return <Prechecks address={address} />
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Info } from "lucide-react"

import {
Alert,
AlertContent,
AlertDescription,
AlertTitle,
} from "@/components/ui/alert"

const GasFeeInformation = () => {
return (
<Alert variant="warning" className="w-full rounded-none border-none">
<Info className="h-5 w-5 !text-yellow-600" />
<AlertContent>
<AlertTitle className="!text-yellow-800">About Network Fees</AlertTitle>
<AlertDescription className="text-sm text-yellow-700">
While the NFT is free, you&apos;ll need to pay Ethereum network fees
to complete the transaction. Network fees vary throughout the day -
consider waiting for lower network fees periods to save on costs.
</AlertDescription>
</AlertContent>
</Alert>
)
}

export default GasFeeInformation
Loading
Loading