Skip to content

Commit 5414b94

Browse files
authored
Merge pull request #7 from turbo-eth/feat/etherscan
Add Support for Etherscan
2 parents e1072a4 + 43c3646 commit 5414b94

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1102
-115
lines changed

.env.example

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,14 @@
1-
NEXT_PUBLIC_API_URL=
2-
NEXT_PUBLIC_ALCHEMY_API_KEY=
1+
# Public ---------------------------
2+
NEXTAUTH_SECRET=
3+
4+
# Blockchain RPC Providers
5+
NEXT_PUBLIC_ALCHEMY_API_KEY=
6+
7+
# Private --------------------------
8+
ETHERSCAN_API_KEY=
9+
ETHERSCAN_API_KEY_OPTIMISM=
10+
ETHERSCAN_API_KEY_ARBITRUM=
11+
ETHERSCAN_API_KEY_POLYGON=
12+
13+
# Generate one here: https://generate-secret.vercel.app/32
14+
NEXTAUTH_SECRET=

components/TransactionsTable.tsx

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import React from 'react'
2+
3+
import { Address, Balance } from '@turbo-eth/core-wagmi'
4+
import { formatEther } from 'ethers/lib/utils.js'
5+
import Link from 'next/link'
6+
7+
import TableCore from './table/TableCore'
8+
import TimeFromEpoch from './time/TimeFromEpoch'
9+
10+
/*
11+
{
12+
"blockNumber": "15204742",
13+
"timeStamp": "1658658027",
14+
"hash": "0x3aa360849f6985569d3946508cbec462a8051cdcbcb03fd41658dcef800c9b65",
15+
"nonce": "2681446",
16+
"blockHash": "0x600cc1f0a66a5ada08b2c944d5366b54a7e151e26b4d839652e7af21cc3c230e",
17+
"transactionIndex": "50",
18+
"from": "0x267be1c1d684f78cb4f6a176c4911b741e4ffdc0",
19+
"to": "0x761d584f1c2d43cbc3f42ecd739701a36dffaa31",
20+
"value": "771500000000000000",
21+
"gas": "21000",
22+
"gasPrice": "7555699848",
23+
"isError": "0",
24+
"txreceipt_status": "1",
25+
"input": "0x",
26+
"contractAddress": "",
27+
"cumulativeGasUsed": "3987451",
28+
"gasUsed": "21000",
29+
"confirmations": "1200526",
30+
"methodId": "0x",
31+
"functionName": ""
32+
}
33+
*/
34+
35+
function TransactionsTable({ data }: any) {
36+
const columns = React.useMemo(
37+
() => [
38+
{
39+
Header: 'From',
40+
accessor: 'from',
41+
Cell: (props: any) => <Address address={props.value} truncate className="text-sm font-medium" />,
42+
},
43+
{
44+
Header: 'To',
45+
accessor: 'to',
46+
Cell: (props: any) => <Address address={props.value} truncate className="text-sm font-medium" />,
47+
},
48+
{
49+
Header: 'Created',
50+
accessor: 'timeStamp',
51+
Cell: (props: any) => <TimeFromEpoch epoch={props.value || 0} />,
52+
},
53+
{
54+
Header: 'Sent',
55+
accessor: 'value',
56+
Cell: (props: any) => <span className="">{formatEther(props.value)}</span>,
57+
},
58+
{
59+
Header: () => null,
60+
id: 'actions',
61+
accessor: 'hash',
62+
Cell: (props: any) => (
63+
<div className="flex items-center justify-end gap-2">
64+
<Link href={`/dashboard/transaction/${props.value}`}>
65+
<span className="text-xs">View</span>
66+
</Link>
67+
</div>
68+
),
69+
},
70+
],
71+
[]
72+
)
73+
if (!data) return null
74+
return <TableCore columns={columns} data={data} className="w-full overflow-hidden rounded-xl" />
75+
}
76+
77+
export default TransactionsTable

components/app/ImageColorMode.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from 'react'
2+
3+
import Image from 'next/image'
4+
5+
import { useColorMode } from '@/lib/state'
6+
7+
export function ImageColorMode({ src, srcDark, ...props }: any) {
8+
const [colorMode] = useColorMode()
9+
10+
return colorMode === 'light' ? <Image alt="logo" src={src} {...props} /> : <Image alt="logo" src={srcDark} {...props} />
11+
}

components/app/ThemeSwitcher.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,28 @@ import MoonIcon from 'public/icons/MoonIcon.svg?icon'
55
// @ts-ignore
66
import SunIcon from 'public/icons/SunIcon.svg?icon'
77

8+
import { useColorMode } from '@/lib/state'
9+
810
export function ThemeSwitcher() {
911
const classes = 'cursor-pointer'
10-
const [colorMode, setColorMode] = React.useState<'light' | 'dark'>('light')
12+
const [colorMode, toggleMode, setMode] = useColorMode()
1113

1214
useEffect(() => {
1315
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
14-
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
16+
if (localStorage.colorMode === 'dark' || (!('colorMode' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
1517
document.documentElement.classList.add('dark')
1618
document.documentElement.classList.remove('light')
17-
setColorMode('dark')
19+
setMode('dark')
1820
} else {
1921
document.documentElement.classList.add('light')
2022
document.documentElement.classList.remove('dark')
21-
setColorMode('light')
23+
setMode('light')
2224
}
2325
}, [])
2426

2527
const handleToggle = (_e: any) => {
2628
document.documentElement.classList.toggle('dark')
27-
setColorMode(colorMode === 'dark' ? 'light' : 'dark')
29+
toggleMode()
2830
}
2931

3032
return (
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { useColorMode } from '@/lib/state'
2+
3+
export function BranchColorMode({ children }: any) {
4+
const [colorMode] = useColorMode()
5+
6+
return colorMode === 'light' ? children[0] : children[1]
7+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import * as React from 'react'
2+
3+
import classNames from 'classnames'
4+
5+
interface DashboardSidebarProps {
6+
className?: string
7+
}
8+
9+
import { LayoutDashboardIcon, NetworkIcon, Wallet } from 'lucide-react'
10+
import Link from 'next/link'
11+
import { useRouter } from 'next/router'
12+
13+
export const DashboardSidebar = ({ className }: DashboardSidebarProps) => {
14+
const cx = classNames(className, 'flex flex-col gap-1', 'DashboardSidebar')
15+
16+
const router = useRouter()
17+
return (
18+
<div className={cx}>
19+
<Item currentPath={router.pathname} className="menu-item my-2" href="/dashboard">
20+
<LayoutDashboardIcon width={22} />
21+
<span className="">Dashboard</span>
22+
</Item>
23+
<Item currentPath={router.pathname} className="menu-item my-2" href="/dashboard/account">
24+
<Wallet width={22} />
25+
<span className="">Account</span>
26+
</Item>
27+
<Item currentPath={router.pathname} className="menu-item my-2" href="/dashboard/transactions">
28+
<NetworkIcon width={22} />
29+
<span className="">Transactions</span>
30+
</Item>
31+
</div>
32+
)
33+
}
34+
35+
const Item = ({ children, href, currentPath }: any) => {
36+
const cx = classNames('menu-item my-2', 'DashboardSidebar', {
37+
active: currentPath === href,
38+
})
39+
40+
return (
41+
<Link className={cx} href={href}>
42+
{children[0]}
43+
{children[1]}
44+
</Link>
45+
)
46+
}
47+
48+
export default DashboardSidebar

components/layout/Header.tsx

Lines changed: 27 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import React from 'react'
22

3-
import { ConnectButton } from '@rainbow-me/rainbowkit'
43
import classNames from 'classnames'
4+
import Image from 'next/image'
55

66
import { SITE_EMOJI, SITE_NAME } from '@/lib/constants'
77
import useScroll from '@/lib/hooks/useScroll'
88

99
import { LinkComponent } from '../app/LinkComponent'
1010
import { ThemeSwitcher } from '../app/ThemeSwitcher'
11+
import { BranchColorMode } from '../branch/BranchColorMode'
1112
import BranchIsAuthenticated from '../branch/BranchIsAuthenticated'
1213
import BranchIsWalletConnected from '../branch/BranchIsWalletConnected'
1314
import ResponsiveMobileAndDesktop from '../responsive/ResponsiveMobileAndDesktop'
1415
import ButtonSIWELogin from '../siwe/ButtonSIWELogin'
15-
import MenuMobile from './MenuMobile'
1616
import UserDropdown from './UserDropdown'
1717

1818
interface Props {
@@ -25,7 +25,7 @@ export function Header(props: Props) {
2525
props.className,
2626
'Header',
2727
'fixed top-0 w-full',
28-
' px-10 py-3 mb-8 flex items-center',
28+
'px-6 lg:px-10 py-3 mb-8 flex items-center',
2929
{
3030
'border-b border-gray-200 bg-white/50 backdrop-blur-xl dark:bg-black/50 dark:border-gray-800': scrolled,
3131
},
@@ -34,47 +34,31 @@ export function Header(props: Props) {
3434
return (
3535
<header className={classes}>
3636
<ResponsiveMobileAndDesktop>
37-
<>
38-
<LinkComponent href="/" className="flex flex-1 items-center">
39-
<span className="mr-1 text-3xl">{SITE_EMOJI}</span>
40-
</LinkComponent>
41-
<div className="flex items-center gap-4">
42-
<ThemeSwitcher />
43-
<ConnectButton
44-
showBalance={false}
45-
accountStatus={{
46-
smallScreen: 'avatar',
47-
largeScreen: 'avatar',
48-
}}
49-
chainStatus={{
50-
smallScreen: 'icon',
51-
largeScreen: 'icon',
52-
}}
53-
/>
54-
<MenuMobile>
55-
<div className="btn btn-light btn-sm">MENU</div>
56-
</MenuMobile>
57-
</div>
58-
</>
59-
<>
60-
<LinkComponent className="flex items-center" href="/">
61-
<span className="mr-1">{SITE_EMOJI}</span>
62-
<h1 className="text-2xl font-bold">{SITE_NAME}</h1>
63-
</LinkComponent>
64-
65-
<div className="flex-1" />
66-
67-
<div className="flex items-center gap-4">
68-
<BranchIsWalletConnected>
69-
<BranchIsAuthenticated>
70-
<UserDropdown />
71-
<ButtonSIWELogin />
72-
</BranchIsAuthenticated>
73-
</BranchIsWalletConnected>
74-
<ThemeSwitcher />
75-
</div>
76-
</>
37+
<LinkComponent href="/" className="flex flex-1 items-center ">
38+
<BranchColorMode>
39+
<Image alt="Logo" src="/logo-dark.png" width={32} height={32} />
40+
<Image alt="Logo" src="/logo-white.png" width={32} height={32} />
41+
</BranchColorMode>
42+
</LinkComponent>
43+
<LinkComponent className="flex items-center" href="/">
44+
<BranchColorMode>
45+
<Image alt="Logo" src="/logo-dark.png" width={32} height={32} />
46+
<Image alt="Logo" src="/logo-white.png" width={32} height={32} />
47+
</BranchColorMode>
48+
<h1 className="text-gradient-sand ml-2 text-2xl font-bold">{SITE_NAME}</h1>
49+
</LinkComponent>
7750
</ResponsiveMobileAndDesktop>
51+
<div className="flex-1" />
52+
53+
<div className="flex items-center gap-4">
54+
<BranchIsWalletConnected>
55+
<BranchIsAuthenticated>
56+
<UserDropdown />
57+
<ButtonSIWELogin />
58+
</BranchIsAuthenticated>
59+
</BranchIsWalletConnected>
60+
<ThemeSwitcher />
61+
</div>
7862
</header>
7963
)
8064
}

components/layout/UserDropdown.tsx

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,16 @@ export default function UserDropdown() {
1818
<Popover
1919
content={
2020
<div className="bg-card w-full rounded-md p-2 sm:w-56">
21-
<Link
22-
className="relative flex w-full items-center justify-start space-x-2 rounded-md p-2 text-left text-sm transition-all duration-75 hover:bg-gray-100"
23-
href="/account">
21+
<Link className="user-dropdown-menu-item" href="/account">
2422
<PersonStanding className="h-4 w-4" />
2523
<p className="text-sm">Account</p>
2624
</Link>
27-
<Link
28-
className="relative flex w-full items-center justify-start space-x-2 rounded-md p-2 text-left text-sm transition-all duration-75 hover:bg-gray-100"
29-
href="/dashboard">
25+
<Link className="user-dropdown-menu-item " href="/dashboard">
3026
<LayoutDashboard className="h-4 w-4" />
3127
<p className="text-sm">Dashboard</p>
3228
</Link>
3329

34-
<ButtonSIWELogout className="relative flex w-full items-center justify-start space-x-2 rounded-md p-2 text-left text-sm transition-all duration-75 hover:bg-gray-100">
30+
<ButtonSIWELogout className="user-dropdown-menu-item">
3531
<>
3632
<LogOutIcon className="h-4 w-4" />
3733
<p className="text-sm">Logout</p>
@@ -44,8 +40,8 @@ export default function UserDropdown() {
4440
setOpenPopover={setOpenPopover}>
4541
<button
4642
onClick={() => setOpenPopover(!openPopover)}
47-
className="bg-card flex items-center justify-center overflow-hidden rounded-full border border-gray-300 p-2 px-4 transition-all duration-75 hover:bg-neutral-100 focus:outline-none active:scale-95 dark:border-neutral-600">
48-
<WalletAddress truncate className="font-raleway font-semibold leading-4 tracking-[0.08em]" />
43+
className="bg-card flex items-center justify-center overflow-hidden rounded-full p-2 px-4 transition-all duration-75 hover:bg-neutral-100 focus:outline-none active:scale-95 ">
44+
<WalletAddress truncate className="font-raleway font-semibold leading-4 tracking-[0.08em]" />
4945
<Wallet className="ml-3 h-6 w-6" />
5046
</button>
5147
</Popover>

components/shared/popover.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,17 @@ export default function Popover({
5454
onDragEnd={handleDragEnd}
5555
dragElastic={{ top: 0, bottom: 1 }}
5656
dragConstraints={{ top: 0, bottom: 0 }}>
57-
<div className={`rounded-t-4xl -mb-1 flex h-7 w-full items-center justify-center border-t border-gray-200 bg-white`}>
57+
<div className={`rounded-t-4xl -mb-1 flex h-7 w-full items-center justify-center bg-white dark:bg-neutral-700 `}>
5858
<div className="-mr-1 h-1 w-6 rounded-full bg-gray-300 transition-all group-active:rotate-12" />
5959
<div className="h-1 w-6 rounded-full bg-gray-300 transition-all group-active:-rotate-12" />
6060
</div>
61-
<div className="flex min-h-[150px] w-full items-center justify-center overflow-hidden bg-white align-middle shadow-xl">{content}</div>
61+
<div className="flex min-h-[150px] w-full items-center justify-center overflow-hidden bg-white align-middle shadow-xl dark:bg-neutral-800">
62+
{content}
63+
</div>
6264
</motion.div>
6365
<motion.div
6466
key="mobile-tooltip-backdrop"
65-
className="fixed inset-0 z-30 bg-gray-100 bg-opacity-10 backdrop-blur md:hidden"
67+
className="dakr:bg-neutral-700 fixed inset-0 z-30 bg-gray-100 bg-opacity-10 backdrop-blur md:hidden"
6668
initial={{ opacity: 0 }}
6769
animate={{ opacity: 1 }}
6870
exit={{ opacity: 0 }}
@@ -78,7 +80,7 @@ export default function Popover({
7880
<PopoverPrimitive.Content
7981
sideOffset={4}
8082
align={align}
81-
className="z-20 hidden animate-slide-up-fade items-center rounded-md border border-gray-200 bg-white shadow-md md:block">
83+
className="z-20 hidden animate-slide-up-fade items-center rounded-md bg-white shadow-md dark:border-gray-800 dark:bg-neutral-800 md:block">
8284
{content}
8385
</PopoverPrimitive.Content>
8486
</PopoverPrimitive.Root>

0 commit comments

Comments
 (0)