create-stylus 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +31 -5
- package/dist/cli.js.map +1 -1
- package/package.json +11 -2
- package/src/main.ts +11 -2
- package/src/tasks/config-to-sepolia.ts +25 -0
- package/src/tasks/copy-template-files.ts +7 -4
- package/src/tasks/index.ts +1 -0
- package/src/utils/prompt-for-missing-options.ts +1 -1
- package/templates/base/package.json +10 -1
- package/templates/base/packages/nextjs/app/debug/_components/DebugContracts.tsx +15 -5
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractInput.tsx +3 -3
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractUI.tsx +104 -28
- package/templates/base/packages/nextjs/app/debug/_components/contract/DisplayVariable.tsx +15 -2
- package/templates/base/packages/nextjs/app/debug/_components/contract/ReadOnlyFunctionForm.tsx +11 -4
- package/templates/base/packages/nextjs/app/debug/_components/contract/TxReceipt.tsx +37 -21
- package/templates/base/packages/nextjs/app/debug/_components/contract/WriteOnlyFunctionForm.tsx +26 -20
- package/templates/base/packages/nextjs/app/layout.tsx +10 -4
- package/templates/base/packages/nextjs/components/AngularBorder.tsx +41 -0
- package/templates/base/packages/nextjs/components/Footer.tsx +153 -44
- package/templates/base/packages/nextjs/components/Header.tsx +73 -10
- package/templates/base/packages/nextjs/components/SwitchTheme.tsx +34 -3
- package/templates/base/packages/nextjs/components/scaffold-eth/Faucet.tsx +40 -5
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/AddressInput.tsx +1 -9
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/InputBase.tsx +1 -1
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/IntegerInput.tsx +35 -25
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/AddressInfoDropdown.tsx +138 -24
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/RevealBurnerPKModal.tsx +59 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/index.tsx +2 -0
- package/templates/base/packages/nextjs/contracts/deployedContracts.ts +117 -1
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldEventHistory.ts +107 -28
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldWriteContract.ts +5 -1
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useTransactor.tsx +7 -5
- package/templates/base/packages/nextjs/icons/EthIcon.tsx +28 -0
- package/templates/base/packages/nextjs/icons/LightBugAntIcon.tsx +7 -7
- package/templates/base/packages/nextjs/package.json +13 -5
- package/templates/base/packages/nextjs/public/logo.svg +20 -7
- package/templates/base/packages/nextjs/services/web3/wagmiConnectors.tsx +1 -0
- package/templates/base/packages/nextjs/styles/globals.css +339 -2
- package/templates/base/packages/nextjs/tailwind.config.js +2 -1
- package/templates/base/packages/nextjs/utils/scaffold-eth/contract.ts +74 -2
- package/templates/base/packages/nextjs/utils/scaffold-stylus/supportedChains.ts +1 -1
- package/templates/base/packages/stylus/package.json +9 -0
- package/templates/base/packages/stylus/scripts/deploy.ts +0 -8
- package/templates/base/packages/stylus/scripts/deploy_contract.ts +1 -0
- package/templates/base/packages/stylus/scripts/test_network.ts +6 -7
- package/templates/base/packages/stylus/scripts/utils/contract.ts +6 -2
- package/templates/base/packages/stylus/scripts/utils/deployment.ts +1 -0
- package/templates/base/packages/stylus/scripts/utils/network.ts +23 -5
- package/templates/base/packages/stylus/your-contract/Cargo.lock +4 -4
- package/templates/base/packages/stylus/your-contract/Cargo.toml +1 -1
- package/templates/base/packages/stylus/your-contract/src/lib.rs +3 -7
- package/templates/base/readme.md +55 -169
- package/templates/base/yarn.lock +1058 -1128
- package/templates/base/packages/stylus/counter/.cargo/config.toml +0 -18
- package/templates/base/packages/stylus/counter/Cargo.lock +0 -5788
- package/templates/base/packages/stylus/counter/Cargo.toml +0 -46
- package/templates/base/packages/stylus/counter/rust-toolchain.toml +0 -2
- package/templates/base/packages/stylus/counter/src/lib.rs +0 -121
- package/templates/base/packages/stylus/counter/src/main.rs +0 -10
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import React, { useCallback, useRef, useState } from "react";
|
|
3
|
+
import React, { useCallback, useRef, useState, useMemo } from "react";
|
|
4
4
|
import Image from "next/image";
|
|
5
5
|
import Link from "next/link";
|
|
6
6
|
import { usePathname } from "next/navigation";
|
|
7
|
+
import { useTheme } from "next-themes";
|
|
7
8
|
import { SwitchTheme } from "./SwitchTheme";
|
|
8
|
-
import { Bars3Icon
|
|
9
|
+
import { Bars3Icon } from "@heroicons/react/24/outline";
|
|
9
10
|
import { RainbowKitCustomConnectButton } from "~~/components/scaffold-eth";
|
|
10
11
|
import { useOutsideClick, useTargetNetwork } from "~~/hooks/scaffold-eth";
|
|
11
12
|
import { arbitrumNitro } from "~~/utils/scaffold-stylus/supportedChains";
|
|
@@ -24,25 +25,46 @@ export const menuLinks: HeaderMenuLink[] = [
|
|
|
24
25
|
{
|
|
25
26
|
label: "Debug Contracts",
|
|
26
27
|
href: "/debug",
|
|
27
|
-
icon: <BugAntIcon className="h-4 w-4" />,
|
|
28
|
+
// icon: <BugAntIcon className="h-4 w-4" />,
|
|
28
29
|
},
|
|
29
30
|
];
|
|
30
31
|
|
|
31
32
|
export const HeaderMenuLinks = () => {
|
|
32
33
|
const pathname = usePathname();
|
|
34
|
+
const { resolvedTheme } = useTheme();
|
|
35
|
+
const isDarkMode = useMemo(() => resolvedTheme === "dark", [resolvedTheme]);
|
|
33
36
|
|
|
34
37
|
return (
|
|
35
38
|
<>
|
|
36
39
|
{menuLinks.map(({ label, href, icon }) => {
|
|
37
40
|
const isActive = pathname === href;
|
|
41
|
+
|
|
38
42
|
return (
|
|
39
43
|
<li key={href}>
|
|
40
44
|
<Link
|
|
41
45
|
href={href}
|
|
42
46
|
passHref
|
|
43
47
|
className={`${
|
|
44
|
-
isActive ? "
|
|
48
|
+
isActive ? "shadow-md" : ""
|
|
45
49
|
} hover:bg-secondary hover:shadow-md focus:!bg-secondary active:!text-neutral py-1.5 px-3 text-sm rounded-full gap-2 grid grid-flow-col`}
|
|
50
|
+
style={{
|
|
51
|
+
color: isActive
|
|
52
|
+
? isDarkMode
|
|
53
|
+
? "#2B2B2B"
|
|
54
|
+
: "black"
|
|
55
|
+
: isDarkMode
|
|
56
|
+
? "var(--text-sub-600, rgba(255, 255, 255, 0.60))"
|
|
57
|
+
: "black",
|
|
58
|
+
fontFamily: "Orbitron, sans-serif",
|
|
59
|
+
fontSize: "14px",
|
|
60
|
+
fontWeight: 700,
|
|
61
|
+
letterSpacing: "-0.28px",
|
|
62
|
+
textTransform: "uppercase",
|
|
63
|
+
background: isActive ? "linear-gradient(180deg, #FFF 18.79%, #D5D5D5 100%)" : undefined,
|
|
64
|
+
borderBottom: isActive ? "2px solid #ABABAB" : undefined,
|
|
65
|
+
borderRadius: isActive ? "8px" : undefined,
|
|
66
|
+
padding: isActive ? "8px 16px" : undefined,
|
|
67
|
+
}}
|
|
46
68
|
>
|
|
47
69
|
{icon}
|
|
48
70
|
<span>{label}</span>
|
|
@@ -61,6 +83,8 @@ export const Header = () => {
|
|
|
61
83
|
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
|
62
84
|
const burgerMenuRef = useRef<HTMLDivElement>(null);
|
|
63
85
|
const { targetNetwork } = useTargetNetwork();
|
|
86
|
+
const { resolvedTheme } = useTheme();
|
|
87
|
+
const isDarkMode = useMemo(() => resolvedTheme === "dark", [resolvedTheme]);
|
|
64
88
|
const isLocalNetwork = targetNetwork?.id === arbitrumNitro.id;
|
|
65
89
|
useOutsideClick(
|
|
66
90
|
burgerMenuRef,
|
|
@@ -68,7 +92,18 @@ export const Header = () => {
|
|
|
68
92
|
);
|
|
69
93
|
|
|
70
94
|
return (
|
|
71
|
-
<div
|
|
95
|
+
<div
|
|
96
|
+
className="sticky lg:static top-0 navbar min-h-0 flex-shrink-0 justify-between z-20 px-0 sm:px-2"
|
|
97
|
+
style={{
|
|
98
|
+
display: "flex",
|
|
99
|
+
// height: "46px",
|
|
100
|
+
padding: "12px var(--spacing-2xl, 16px)",
|
|
101
|
+
justifyContent: "center",
|
|
102
|
+
alignItems: "center",
|
|
103
|
+
gap: "var(--spacing-md, 8px)",
|
|
104
|
+
alignSelf: "stretch",
|
|
105
|
+
}}
|
|
106
|
+
>
|
|
72
107
|
<div className="navbar-start w-auto lg:w-1/2">
|
|
73
108
|
<div className="lg:hidden dropdown" ref={burgerMenuRef}>
|
|
74
109
|
<label
|
|
@@ -93,20 +128,48 @@ export const Header = () => {
|
|
|
93
128
|
)}
|
|
94
129
|
</div>
|
|
95
130
|
<Link href="/" passHref className="hidden lg:flex items-center gap-2 ml-4 mr-6 shrink-0">
|
|
96
|
-
<div className="flex relative w-
|
|
97
|
-
<Image alt="
|
|
131
|
+
<div className="flex relative w-12 h-12">
|
|
132
|
+
<Image alt="Scaffold Stylus logo" className="cursor-pointer" fill src="/logo.svg" />
|
|
98
133
|
</div>
|
|
99
134
|
<div className="flex flex-col">
|
|
100
|
-
<span
|
|
101
|
-
|
|
135
|
+
<span
|
|
136
|
+
style={{
|
|
137
|
+
color: isDarkMode ? "#FFF" : "black",
|
|
138
|
+
fontFamily: "Orbitron, sans-serif",
|
|
139
|
+
fontSize: "16px",
|
|
140
|
+
fontWeight: 700,
|
|
141
|
+
lineHeight: "normal",
|
|
142
|
+
letterSpacing: "-0.32px",
|
|
143
|
+
textTransform: "uppercase",
|
|
144
|
+
}}
|
|
145
|
+
>
|
|
146
|
+
SCAFFOLD STYLUS
|
|
147
|
+
</span>
|
|
148
|
+
<span
|
|
149
|
+
style={{
|
|
150
|
+
color: isDarkMode ? "#FFF" : "black",
|
|
151
|
+
fontFamily: "Inter, sans-serif",
|
|
152
|
+
fontSize: "12px",
|
|
153
|
+
fontWeight: 600,
|
|
154
|
+
lineHeight: "20px",
|
|
155
|
+
}}
|
|
156
|
+
>
|
|
157
|
+
Arbitrum dev stack
|
|
158
|
+
</span>
|
|
102
159
|
</div>
|
|
103
160
|
</Link>
|
|
104
161
|
<ul className="hidden lg:flex lg:flex-nowrap menu menu-horizontal px-1 gap-2">
|
|
105
162
|
<HeaderMenuLinks />
|
|
106
163
|
</ul>
|
|
107
164
|
</div>
|
|
108
|
-
<div className="flex gap-4 navbar-end flex-grow mr-4">
|
|
165
|
+
<div className="flex items-center gap-4 navbar-end flex-grow mr-4">
|
|
109
166
|
<RainbowKitCustomConnectButton />
|
|
167
|
+
<div
|
|
168
|
+
className="h-6 w-px opacity-20"
|
|
169
|
+
style={{
|
|
170
|
+
backgroundColor: isDarkMode ? "white" : "black",
|
|
171
|
+
}}
|
|
172
|
+
></div>
|
|
110
173
|
<SwitchTheme className={`pointer-events-auto ${isLocalNetwork ? "self-end md:self-auto" : ""}`} />
|
|
111
174
|
</div>
|
|
112
175
|
</div>
|
|
@@ -25,15 +25,46 @@ export const SwitchTheme = ({ className }: { className?: string }) => {
|
|
|
25
25
|
if (!mounted) return null;
|
|
26
26
|
|
|
27
27
|
return (
|
|
28
|
-
<div className={`flex space-x-2 h-5 items-center justify-center text-sm
|
|
28
|
+
<div className={`flex space-x-2 h-5 items-center justify-center text-sm px-4 ${className}`}>
|
|
29
29
|
{
|
|
30
30
|
<label
|
|
31
31
|
htmlFor="theme-toggle"
|
|
32
32
|
className={`swap swap-rotate ${!isDarkMode ? "swap-active" : ""}`}
|
|
33
33
|
onClick={handleToggle}
|
|
34
|
+
style={{
|
|
35
|
+
width: "44px",
|
|
36
|
+
height: "44px",
|
|
37
|
+
aspectRatio: "1/1",
|
|
38
|
+
display: "flex",
|
|
39
|
+
alignItems: "center",
|
|
40
|
+
justifyContent: "center",
|
|
41
|
+
cursor: "pointer",
|
|
42
|
+
borderRadius: "50%",
|
|
43
|
+
background: isDarkMode ? "rgba(25, 144, 196, 0.30)" : "rgba(227, 6, 110, 0.30)",
|
|
44
|
+
border: isDarkMode ? "1px solid #30B4ED" : "1px solid rgba(227, 6, 110, 1)",
|
|
45
|
+
position: "relative",
|
|
46
|
+
}}
|
|
34
47
|
>
|
|
35
|
-
<SunIcon
|
|
36
|
-
|
|
48
|
+
<SunIcon
|
|
49
|
+
className="swap-on h-5 w-5"
|
|
50
|
+
style={{
|
|
51
|
+
color: isDarkMode ? "#30B4ED" : "rgba(227, 6, 110, 1)",
|
|
52
|
+
position: "absolute",
|
|
53
|
+
top: "50%",
|
|
54
|
+
left: "50%",
|
|
55
|
+
transform: "translate(-50%, -50%)",
|
|
56
|
+
}}
|
|
57
|
+
/>
|
|
58
|
+
<MoonIcon
|
|
59
|
+
className="swap-off h-5 w-5"
|
|
60
|
+
style={{
|
|
61
|
+
color: "#30B4ED",
|
|
62
|
+
position: "absolute",
|
|
63
|
+
top: "50%",
|
|
64
|
+
left: "50%",
|
|
65
|
+
transform: "translate(-50%, -50%)",
|
|
66
|
+
}}
|
|
67
|
+
/>
|
|
37
68
|
</label>
|
|
38
69
|
}
|
|
39
70
|
</div>
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useEffect, useState } from "react";
|
|
3
|
+
import { useEffect, useState, useMemo } from "react";
|
|
4
4
|
import { Address as AddressType, createWalletClient, http, parseEther } from "viem";
|
|
5
5
|
import { privateKeyToAccount } from "viem/accounts";
|
|
6
6
|
import { useAccount } from "wagmi";
|
|
7
|
+
import { useTheme } from "next-themes";
|
|
7
8
|
import { BanknotesIcon } from "@heroicons/react/24/outline";
|
|
9
|
+
import { AngularBorder } from "~~/components/AngularBorder";
|
|
8
10
|
import { Address, AddressInput, Balance, EtherInput } from "~~/components/scaffold-eth";
|
|
9
11
|
import { useTransactor } from "~~/hooks/scaffold-eth";
|
|
10
12
|
import { notification } from "~~/utils/scaffold-eth";
|
|
@@ -29,6 +31,11 @@ export const Faucet = () => {
|
|
|
29
31
|
const [sendValue, setSendValue] = useState("");
|
|
30
32
|
|
|
31
33
|
const { chain: ConnectedChain } = useAccount();
|
|
34
|
+
const { resolvedTheme } = useTheme();
|
|
35
|
+
|
|
36
|
+
const isDarkMode = useMemo(() => {
|
|
37
|
+
return resolvedTheme === "dark";
|
|
38
|
+
}, [resolvedTheme]);
|
|
32
39
|
|
|
33
40
|
const faucetTxn = useTransactor(localWalletClient);
|
|
34
41
|
|
|
@@ -83,10 +90,38 @@ export const Faucet = () => {
|
|
|
83
90
|
|
|
84
91
|
return (
|
|
85
92
|
<div>
|
|
86
|
-
<
|
|
87
|
-
<
|
|
88
|
-
<
|
|
89
|
-
|
|
93
|
+
<div className="relative">
|
|
94
|
+
<AngularBorder width={130} height={40} color="rgba(227, 6, 110, 1)" />
|
|
95
|
+
<label
|
|
96
|
+
htmlFor="faucet-modal"
|
|
97
|
+
className="flex items-center gap-2 px-4 py-2 cursor-pointer rounded-lg"
|
|
98
|
+
style={{
|
|
99
|
+
width: "130px",
|
|
100
|
+
height: "40px",
|
|
101
|
+
display: "flex",
|
|
102
|
+
alignItems: "flex-start",
|
|
103
|
+
paddingTop: "8px",
|
|
104
|
+
position: "relative",
|
|
105
|
+
zIndex: 1,
|
|
106
|
+
}}
|
|
107
|
+
>
|
|
108
|
+
<BanknotesIcon className="h-4 w-4" style={{ color: "rgba(227, 6, 110, 1)" }} />
|
|
109
|
+
<span
|
|
110
|
+
style={{
|
|
111
|
+
color: isDarkMode ? "#FFF" : "black",
|
|
112
|
+
fontFamily: "Orbitron, sans-serif",
|
|
113
|
+
fontSize: "14px",
|
|
114
|
+
fontWeight: 700,
|
|
115
|
+
textTransform: "uppercase",
|
|
116
|
+
whiteSpace: "nowrap",
|
|
117
|
+
overflow: "hidden",
|
|
118
|
+
textOverflow: "ellipsis",
|
|
119
|
+
}}
|
|
120
|
+
>
|
|
121
|
+
Faucet
|
|
122
|
+
</span>
|
|
123
|
+
</label>
|
|
124
|
+
</div>
|
|
90
125
|
<input type="checkbox" id="faucet-modal" className="modal-toggle" />
|
|
91
126
|
<label htmlFor="faucet-modal" className="modal cursor-pointer">
|
|
92
127
|
<label className="modal-box relative">
|
|
@@ -23,7 +23,6 @@ export const AddressInput = ({ value, name, placeholder, onChange, disabled }: C
|
|
|
23
23
|
data: ensAddress,
|
|
24
24
|
isLoading: isEnsAddressLoading,
|
|
25
25
|
isError: isEnsAddressError,
|
|
26
|
-
isSuccess: isEnsAddressSuccess,
|
|
27
26
|
} = useEnsAddress({
|
|
28
27
|
name: settledValue,
|
|
29
28
|
chainId: 1,
|
|
@@ -38,7 +37,6 @@ export const AddressInput = ({ value, name, placeholder, onChange, disabled }: C
|
|
|
38
37
|
data: ensName,
|
|
39
38
|
isLoading: isEnsNameLoading,
|
|
40
39
|
isError: isEnsNameError,
|
|
41
|
-
isSuccess: isEnsNameSuccess,
|
|
42
40
|
} = useEnsName({
|
|
43
41
|
address: settledValue as Address,
|
|
44
42
|
chainId: 1,
|
|
@@ -70,13 +68,7 @@ export const AddressInput = ({ value, name, placeholder, onChange, disabled }: C
|
|
|
70
68
|
setEnteredEnsName(undefined);
|
|
71
69
|
}, [value]);
|
|
72
70
|
|
|
73
|
-
const reFocus =
|
|
74
|
-
isEnsAddressError ||
|
|
75
|
-
isEnsNameError ||
|
|
76
|
-
isEnsNameSuccess ||
|
|
77
|
-
isEnsAddressSuccess ||
|
|
78
|
-
ensName === null ||
|
|
79
|
-
ensAddress === null;
|
|
71
|
+
const reFocus = isEnsAddressError || isEnsNameError || ensName === null || ensAddress === null;
|
|
80
72
|
|
|
81
73
|
return (
|
|
82
74
|
<InputBase<Address>
|
|
@@ -47,7 +47,7 @@ export const InputBase = <T extends { toString: () => string } | undefined = str
|
|
|
47
47
|
}, [reFocus]);
|
|
48
48
|
|
|
49
49
|
return (
|
|
50
|
-
<div className={`flex
|
|
50
|
+
<div className={`flex text-accent ${modifier}`}>
|
|
51
51
|
{prefix}
|
|
52
52
|
<input
|
|
53
53
|
className="input input-ghost focus-within:border-transparent focus:outline-hidden focus:bg-transparent h-[2.2rem] min-h-[2.2rem] px-4 border w-full font-medium placeholder:text-accent/70 text-base-content/70 focus:text-base-content/70"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from "react";
|
|
2
2
|
import { parseEther } from "viem";
|
|
3
|
+
import { useTheme } from "next-themes";
|
|
3
4
|
import { CommonInputProps, InputBase, IntegerVariant, isValidInteger } from "~~/components/scaffold-eth";
|
|
4
5
|
|
|
5
6
|
type IntegerInputProps = CommonInputProps<string> & {
|
|
@@ -16,6 +17,8 @@ export const IntegerInput = ({
|
|
|
16
17
|
variant = IntegerVariant.UINT256,
|
|
17
18
|
disableMultiplyBy1e18 = false,
|
|
18
19
|
}: IntegerInputProps) => {
|
|
20
|
+
const { resolvedTheme } = useTheme();
|
|
21
|
+
const isDarkMode = resolvedTheme === "dark";
|
|
19
22
|
const [inputError, setInputError] = useState(false);
|
|
20
23
|
const multiplyBy1e18 = useCallback(() => {
|
|
21
24
|
if (!value) {
|
|
@@ -33,31 +36,38 @@ export const IntegerInput = ({
|
|
|
33
36
|
}, [value, variant]);
|
|
34
37
|
|
|
35
38
|
return (
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
39
|
+
<div
|
|
40
|
+
className="integer-input-wrapper input-container"
|
|
41
|
+
style={{
|
|
42
|
+
padding: "12px 16px",
|
|
43
|
+
}}
|
|
44
|
+
>
|
|
45
|
+
<InputBase
|
|
46
|
+
name={name}
|
|
47
|
+
value={value}
|
|
48
|
+
placeholder={placeholder}
|
|
49
|
+
error={inputError}
|
|
50
|
+
onChange={onChange}
|
|
51
|
+
disabled={disabled}
|
|
52
|
+
suffix={
|
|
53
|
+
!inputError &&
|
|
54
|
+
!disableMultiplyBy1e18 && (
|
|
55
|
+
<div
|
|
56
|
+
className="space-x-4 flex tooltip tooltip-top tooltip-secondary before:content-[attr(data-tip)] before:right-[-10px] before:left-auto before:transform-none"
|
|
57
|
+
data-tip="Multiply by 1e18 (wei)"
|
|
55
58
|
>
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
<button
|
|
60
|
+
className={`${disabled ? "cursor-not-allowed" : "cursor-pointer"} font-semibold px-4 text-accent`}
|
|
61
|
+
onClick={multiplyBy1e18}
|
|
62
|
+
disabled={disabled}
|
|
63
|
+
type="button"
|
|
64
|
+
>
|
|
65
|
+
∗
|
|
66
|
+
</button>
|
|
67
|
+
</div>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
/>
|
|
71
|
+
</div>
|
|
62
72
|
);
|
|
63
73
|
};
|
|
@@ -2,13 +2,14 @@ import { useRef, useState } from "react";
|
|
|
2
2
|
import { NetworkOptions } from "./NetworkOptions";
|
|
3
3
|
import { getAddress } from "viem";
|
|
4
4
|
import { Address } from "viem";
|
|
5
|
-
import { useDisconnect } from "wagmi";
|
|
5
|
+
import { useAccount, useDisconnect } from "wagmi";
|
|
6
6
|
import {
|
|
7
7
|
ArrowLeftEndOnRectangleIcon,
|
|
8
8
|
ArrowsRightLeftIcon,
|
|
9
9
|
CheckCircleIcon,
|
|
10
10
|
ChevronDownIcon,
|
|
11
11
|
DocumentDuplicateIcon,
|
|
12
|
+
EyeIcon,
|
|
12
13
|
QrCodeIcon,
|
|
13
14
|
UserCircleIcon,
|
|
14
15
|
} from "@heroicons/react/24/outline";
|
|
@@ -16,6 +17,9 @@ import { BlockieAvatar, isENS } from "~~/components/scaffold-eth";
|
|
|
16
17
|
import { useCopyToClipboard, useOutsideClick } from "~~/hooks/scaffold-eth";
|
|
17
18
|
import { getTargetNetworks } from "~~/utils/scaffold-stylus";
|
|
18
19
|
import { arbitrumNitro } from "~~/utils/scaffold-stylus/supportedChains";
|
|
20
|
+
import { useTheme } from "next-themes";
|
|
21
|
+
|
|
22
|
+
const BURNER_WALLET_ID = "burnerWallet";
|
|
19
23
|
|
|
20
24
|
const allowedNetworks = getTargetNetworks();
|
|
21
25
|
|
|
@@ -28,7 +32,10 @@ type AddressInfoDropdownProps = {
|
|
|
28
32
|
|
|
29
33
|
export const AddressInfoDropdown = ({ address, ensAvatar, displayName, onSwitchAccount }: AddressInfoDropdownProps) => {
|
|
30
34
|
const { disconnect } = useDisconnect();
|
|
35
|
+
const { connector } = useAccount();
|
|
31
36
|
const checkSumAddress = getAddress(address);
|
|
37
|
+
const { resolvedTheme } = useTheme();
|
|
38
|
+
const isDarkMode = resolvedTheme === "dark";
|
|
32
39
|
|
|
33
40
|
const { copyToClipboard: copyAddressToClipboard, isCopiedToClipboard: isAddressCopiedToClipboard } =
|
|
34
41
|
useCopyToClipboard();
|
|
@@ -44,74 +51,181 @@ export const AddressInfoDropdown = ({ address, ensAvatar, displayName, onSwitchA
|
|
|
44
51
|
|
|
45
52
|
return (
|
|
46
53
|
<>
|
|
47
|
-
<details ref={dropdownRef} className="
|
|
54
|
+
<details ref={dropdownRef} className="dropdown dropdown-end leading-3">
|
|
48
55
|
<summary
|
|
49
56
|
tabIndex={0}
|
|
50
|
-
className="
|
|
57
|
+
className="dropdown-toggle gap-0 !h-auto"
|
|
58
|
+
style={{
|
|
59
|
+
position: "relative",
|
|
60
|
+
width: "220px",
|
|
61
|
+
height: "46px",
|
|
62
|
+
display: "flex",
|
|
63
|
+
alignItems: "center",
|
|
64
|
+
padding: "0 20px",
|
|
65
|
+
cursor: "pointer",
|
|
66
|
+
alignSelf: "center",
|
|
67
|
+
}}
|
|
51
68
|
>
|
|
52
|
-
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
69
|
+
{/* Angular border SVG */}
|
|
70
|
+
<svg
|
|
71
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
72
|
+
width="220"
|
|
73
|
+
height="46"
|
|
74
|
+
viewBox="0 0 220 46"
|
|
75
|
+
fill="none"
|
|
76
|
+
style={{
|
|
77
|
+
position: "absolute",
|
|
78
|
+
top: "-7px",
|
|
79
|
+
left: 0,
|
|
80
|
+
pointerEvents: "none",
|
|
81
|
+
}}
|
|
82
|
+
>
|
|
83
|
+
<path
|
|
84
|
+
d="M196.132 0.5L219.5 23.2109V45.5H24.0811L0.5 22.7871V0.5H196.132Z"
|
|
85
|
+
stroke="#30B4ED"
|
|
86
|
+
strokeWidth="1"
|
|
87
|
+
/>
|
|
88
|
+
</svg>
|
|
89
|
+
|
|
90
|
+
{/* Content */}
|
|
91
|
+
<div
|
|
92
|
+
style={{
|
|
93
|
+
display: "flex",
|
|
94
|
+
alignItems: "center",
|
|
95
|
+
gap: "8px",
|
|
96
|
+
width: "100%",
|
|
97
|
+
height: "100%",
|
|
98
|
+
zIndex: 1,
|
|
99
|
+
position: "relative",
|
|
100
|
+
}}
|
|
101
|
+
>
|
|
102
|
+
<BlockieAvatar address={checkSumAddress} size={30} ensImage={ensAvatar} />
|
|
103
|
+
<span
|
|
104
|
+
style={{
|
|
105
|
+
color: isDarkMode ? "#FFF" : "black",
|
|
106
|
+
fontFamily: "Orbitron, sans-serif",
|
|
107
|
+
fontSize: "14px",
|
|
108
|
+
fontWeight: 700,
|
|
109
|
+
lineHeight: "1",
|
|
110
|
+
textTransform: "uppercase",
|
|
111
|
+
display: "flex",
|
|
112
|
+
alignItems: "center",
|
|
113
|
+
height: "30px",
|
|
114
|
+
whiteSpace: "nowrap",
|
|
115
|
+
minWidth: 0,
|
|
116
|
+
}}
|
|
117
|
+
>
|
|
118
|
+
{isENS(displayName) ? displayName : checkSumAddress?.slice(0, 6) + "..." + checkSumAddress?.slice(-4)}
|
|
119
|
+
</span>
|
|
120
|
+
<ChevronDownIcon
|
|
121
|
+
className="h-4 w-4"
|
|
122
|
+
style={{
|
|
123
|
+
color: isDarkMode ? "#FFF" : "black",
|
|
124
|
+
height: "16px",
|
|
125
|
+
width: "16px",
|
|
126
|
+
}}
|
|
127
|
+
/>
|
|
128
|
+
</div>
|
|
57
129
|
</summary>
|
|
58
130
|
<ul
|
|
59
131
|
tabIndex={0}
|
|
60
|
-
className="dropdown-content menu z-[2] p-2 mt-
|
|
132
|
+
className="dropdown-content menu z-[2] p-2 mt-4 gap-1"
|
|
133
|
+
style={{
|
|
134
|
+
borderRadius: "8px",
|
|
135
|
+
border: isDarkMode ? "1px solid rgba(255, 255, 255, 0.20)" : "1px solid rgba(0, 0, 0, 0.1)",
|
|
136
|
+
background: isDarkMode ? "rgba(2, 2, 2, 0.20)" : "rgba(255, 255, 255, 0.20)",
|
|
137
|
+
backdropFilter: "blur(25px)",
|
|
138
|
+
}}
|
|
61
139
|
>
|
|
62
140
|
<NetworkOptions hidden={!selectingNetwork} />
|
|
63
141
|
<li className={selectingNetwork ? "hidden" : ""}>
|
|
64
142
|
<div
|
|
65
|
-
className="
|
|
143
|
+
className="flex gap-3 py-3 px-3 cursor-pointer rounded-lg transition-all duration-200 hover:bg-gradient-to-r hover:from-[rgba(48,180,237,0.16)] hover:to-[rgba(227,6,110,0.16)]"
|
|
66
144
|
onClick={() => copyAddressToClipboard(checkSumAddress)}
|
|
67
145
|
>
|
|
68
146
|
{isAddressCopiedToClipboard ? (
|
|
69
147
|
<>
|
|
70
|
-
<CheckCircleIcon
|
|
71
|
-
|
|
148
|
+
<CheckCircleIcon
|
|
149
|
+
className="h-5 w-5"
|
|
150
|
+
style={{ color: isDarkMode ? "white" : "black" }}
|
|
151
|
+
aria-hidden="true"
|
|
152
|
+
/>
|
|
153
|
+
<span className="whitespace-nowrap" style={{ color: isDarkMode ? "white" : "black" }}>
|
|
154
|
+
Copied!
|
|
155
|
+
</span>
|
|
72
156
|
</>
|
|
73
157
|
) : (
|
|
74
158
|
<>
|
|
75
|
-
<DocumentDuplicateIcon
|
|
76
|
-
|
|
159
|
+
<DocumentDuplicateIcon
|
|
160
|
+
className="h-5 w-5"
|
|
161
|
+
style={{ color: isDarkMode ? "white" : "black" }}
|
|
162
|
+
aria-hidden="true"
|
|
163
|
+
/>
|
|
164
|
+
<span className="whitespace-nowrap" style={{ color: isDarkMode ? "white" : "black" }}>
|
|
165
|
+
Copy address
|
|
166
|
+
</span>
|
|
77
167
|
</>
|
|
78
168
|
)}
|
|
79
169
|
</div>
|
|
80
170
|
</li>
|
|
81
171
|
<li className={selectingNetwork ? "hidden" : ""}>
|
|
82
|
-
<label
|
|
83
|
-
|
|
84
|
-
|
|
172
|
+
<label
|
|
173
|
+
htmlFor="qrcode-modal"
|
|
174
|
+
className="flex gap-3 py-3 px-3 cursor-pointer rounded-lg transition-all duration-200 hover:bg-gradient-to-r hover:from-[rgba(48,180,237,0.16)] hover:to-[rgba(227,6,110,0.16)]"
|
|
175
|
+
>
|
|
176
|
+
<QrCodeIcon className="h-5 w-5" style={{ color: isDarkMode ? "white" : "black" }} />
|
|
177
|
+
<span className="whitespace-nowrap" style={{ color: isDarkMode ? "white" : "black" }}>
|
|
178
|
+
View QR Code
|
|
179
|
+
</span>
|
|
85
180
|
</label>
|
|
86
181
|
</li>
|
|
87
182
|
{allowedNetworks.some(network => network.id === arbitrumNitro.id) && (
|
|
88
183
|
<li className={selectingNetwork ? "hidden" : ""}>
|
|
89
|
-
<button
|
|
90
|
-
|
|
91
|
-
|
|
184
|
+
<button
|
|
185
|
+
className="flex gap-3 py-3 px-3 cursor-pointer rounded-lg transition-all duration-200 hover:bg-gradient-to-r hover:from-[rgba(48,180,237,0.16)] hover:to-[rgba(227,6,110,0.16)] w-full text-left"
|
|
186
|
+
type="button"
|
|
187
|
+
onClick={onSwitchAccount}
|
|
188
|
+
>
|
|
189
|
+
<UserCircleIcon className="h-5 w-5" style={{ color: isDarkMode ? "white" : "black" }} />
|
|
190
|
+
<span className="whitespace-nowrap" style={{ color: isDarkMode ? "white" : "black" }}>
|
|
191
|
+
Switch account
|
|
192
|
+
</span>
|
|
92
193
|
</button>
|
|
93
194
|
</li>
|
|
94
195
|
)}
|
|
95
196
|
{allowedNetworks.length > 1 ? (
|
|
96
197
|
<li className={selectingNetwork ? "hidden" : ""}>
|
|
97
198
|
<button
|
|
98
|
-
className="
|
|
199
|
+
className="flex gap-3 py-3 px-3 cursor-pointer rounded-lg transition-all duration-200 hover:bg-gradient-to-r hover:from-[rgba(48,180,237,0.16)] hover:to-[rgba(227,6,110,0.16)] w-full text-left"
|
|
99
200
|
type="button"
|
|
100
201
|
onClick={() => {
|
|
101
202
|
setSelectingNetwork(true);
|
|
102
203
|
}}
|
|
103
204
|
>
|
|
104
|
-
<ArrowsRightLeftIcon className="h-
|
|
205
|
+
<ArrowsRightLeftIcon className="h-5 w-5" style={{ color: isDarkMode ? "white" : "black" }} />
|
|
206
|
+
<span style={{ color: isDarkMode ? "white" : "black" }}>Switch Network</span>
|
|
105
207
|
</button>
|
|
106
208
|
</li>
|
|
107
209
|
) : null}
|
|
210
|
+
{connector?.id === BURNER_WALLET_ID ? (
|
|
211
|
+
<li>
|
|
212
|
+
<label
|
|
213
|
+
htmlFor="reveal-burner-pk-modal"
|
|
214
|
+
className="flex gap-3 py-3 px-3 cursor-pointer rounded-lg transition-all duration-200 hover:bg-gradient-to-r hover:from-[rgba(48,180,237,0.16)] hover:to-[rgba(227,6,110,0.16)]"
|
|
215
|
+
>
|
|
216
|
+
<EyeIcon className="h-5 w-5" style={{ color: isDarkMode ? "white" : "black" }} />
|
|
217
|
+
<span style={{ color: isDarkMode ? "white" : "black" }}>Reveal Private Key</span>
|
|
218
|
+
</label>
|
|
219
|
+
</li>
|
|
220
|
+
) : null}
|
|
108
221
|
<li className={selectingNetwork ? "hidden" : ""}>
|
|
109
222
|
<button
|
|
110
|
-
className="
|
|
223
|
+
className="flex gap-3 py-3 px-3 cursor-pointer rounded-lg transition-all duration-200 hover:bg-gradient-to-r hover:from-[rgba(48,180,237,0.16)] hover:to-[rgba(227,6,110,0.16)] w-full text-left"
|
|
111
224
|
type="button"
|
|
112
225
|
onClick={() => disconnect()}
|
|
113
226
|
>
|
|
114
|
-
<ArrowLeftEndOnRectangleIcon className="h-
|
|
227
|
+
<ArrowLeftEndOnRectangleIcon className="h-5 w-5" style={{ color: "#FB3748" }} />
|
|
228
|
+
<span style={{ color: "#FB3748" }}>Disconnect</span>
|
|
115
229
|
</button>
|
|
116
230
|
</li>
|
|
117
231
|
</ul>
|