diff --git a/package.json b/package.json
index 00f12cd..e97fe03 100644
--- a/package.json
+++ b/package.json
@@ -58,5 +58,11 @@
">0.2%",
"not dead",
"not op_mini all"
- ]
+ ],
+ "resolutions": {
+ "react-error-overlay": "6.0.9"
+ },
+ "devDependencies": {
+ "react-error-overlay": "6.0.9"
+ }
}
diff --git a/src/components/Body/AddressInput.tsx b/src/components/Body/AddressInput.tsx
deleted file mode 100644
index 2e34ec6..0000000
--- a/src/components/Body/AddressInput.tsx
+++ /dev/null
@@ -1,83 +0,0 @@
-import {
- FormControl,
- FormLabel,
- InputGroup,
- Input,
- InputRightElement,
- Button,
-} from "@chakra-ui/react";
-import { DeleteIcon } from "@chakra-ui/icons";
-
-interface AddressInputParams {
- showAddress: string;
- setShowAddress: (value: string) => void;
- setAddress: (value: string) => void;
- setIsAddressValid: (value: boolean) => void;
- bg: string;
- isAddressValid: boolean;
- selectedTabIndex: number;
- isConnected: boolean;
- appUrl: string | undefined;
- isIFrameLoading: boolean;
- updateAddress: () => void;
-}
-
-function AddressInput({
- showAddress,
- setShowAddress,
- setAddress,
- setIsAddressValid,
- bg,
- isAddressValid,
- selectedTabIndex,
- isConnected,
- appUrl,
- isIFrameLoading,
- updateAddress,
-}: AddressInputParams) {
- return (
-
- Enter Address or ENS to Impersonate
-
- {
- const _showAddress = e.target.value;
- setShowAddress(_showAddress);
- setAddress(_showAddress);
- setIsAddressValid(true); // remove inValid warning when user types again
- }}
- bg={bg}
- isInvalid={!isAddressValid}
- />
- {(selectedTabIndex === 0 && isConnected) ||
- (selectedTabIndex === 1 && appUrl && !isIFrameLoading) ? (
-
-
-
- ) : (
- showAddress && (
-
-
-
- )
- )}
-
-
- );
-}
-
-export default AddressInput;
diff --git a/src/components/Body/AddressInput/AddressBook/index.tsx b/src/components/Body/AddressInput/AddressBook/index.tsx
new file mode 100644
index 0000000..2a4e587
--- /dev/null
+++ b/src/components/Body/AddressInput/AddressBook/index.tsx
@@ -0,0 +1,160 @@
+import { useState, useEffect } from "react";
+import {
+ Modal,
+ ModalOverlay,
+ ModalContent,
+ ModalHeader,
+ HStack,
+ ModalCloseButton,
+ ModalBody,
+ Text,
+ Input,
+ Center,
+ Button,
+ Box,
+} from "@chakra-ui/react";
+import { DeleteIcon } from "@chakra-ui/icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faSave } from "@fortawesome/free-solid-svg-icons";
+import { slicedText } from "../../TransactionRequests";
+
+const STORAGE_KEY = "address-book";
+
+interface SavedAddressInfo {
+ address: string;
+ label: string;
+}
+
+interface AddressBookParams {
+ isAddressBookOpen: boolean;
+ closeAddressBook: () => void;
+ showAddress: string;
+ setShowAddress: (value: string) => void;
+ setAddress: (value: string) => void;
+}
+
+function AddressBook({
+ isAddressBookOpen,
+ closeAddressBook,
+ showAddress,
+ setShowAddress,
+ setAddress,
+}: AddressBookParams) {
+ const [newAddressInput, setNewAddressInput] = useState("");
+ const [newLableInput, setNewLabelInput] = useState("");
+ const [savedAddresses, setSavedAddresses] = useState([]);
+
+ useEffect(() => {
+ setSavedAddresses(JSON.parse(localStorage.getItem(STORAGE_KEY) ?? "[]"));
+ }, []);
+
+ useEffect(() => {
+ setNewAddressInput(showAddress);
+ }, [showAddress]);
+
+ useEffect(() => {
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(savedAddresses));
+ }, [savedAddresses]);
+
+ // reset label when modal is reopened
+ useEffect(() => {
+ setNewLabelInput("");
+ }, [isAddressBookOpen]);
+
+ return (
+
+
+
+ Address Book
+
+
+
+ setNewAddressInput(e.target.value)}
+ />
+ setNewLabelInput(e.target.value)}
+ />
+
+
+
+
+ {savedAddresses.length > 0 && (
+
+ Select from saved addresses:
+
+ {savedAddresses.map(({ address, label }, i) => (
+
+
+
+
+ ))}
+
+
+ )}
+
+
+
+ );
+}
+
+export default AddressBook;
diff --git a/src/components/Body/AddressInput/index.tsx b/src/components/Body/AddressInput/index.tsx
new file mode 100644
index 0000000..3142624
--- /dev/null
+++ b/src/components/Body/AddressInput/index.tsx
@@ -0,0 +1,106 @@
+import {
+ FormControl,
+ FormLabel,
+ InputGroup,
+ Input,
+ InputRightElement,
+ Button,
+ HStack,
+ useDisclosure,
+} from "@chakra-ui/react";
+import { DeleteIcon } from "@chakra-ui/icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faBook } from "@fortawesome/free-solid-svg-icons";
+import AddressBook from "./AddressBook";
+
+interface AddressInputParams {
+ showAddress: string;
+ setShowAddress: (value: string) => void;
+ setAddress: (value: string) => void;
+ setIsAddressValid: (value: boolean) => void;
+ bg: string;
+ isAddressValid: boolean;
+ selectedTabIndex: number;
+ isConnected: boolean;
+ appUrl: string | undefined;
+ isIFrameLoading: boolean;
+ updateAddress: () => void;
+}
+
+function AddressInput({
+ showAddress,
+ setShowAddress,
+ setAddress,
+ setIsAddressValid,
+ bg,
+ isAddressValid,
+ selectedTabIndex,
+ isConnected,
+ appUrl,
+ isIFrameLoading,
+ updateAddress,
+}: AddressInputParams) {
+ const {
+ isOpen: isAddressBookOpen,
+ onOpen: openAddressBook,
+ onClose: closeAddressBook,
+ } = useDisclosure();
+
+ return (
+
+ Enter Address or ENS to Impersonate
+
+
+ {
+ const _showAddress = e.target.value;
+ setShowAddress(_showAddress);
+ setAddress(_showAddress);
+ setIsAddressValid(true); // remove inValid warning when user types again
+ }}
+ bg={bg}
+ isInvalid={!isAddressValid}
+ />
+ {(selectedTabIndex === 0 && isConnected) ||
+ (selectedTabIndex === 1 && appUrl && !isIFrameLoading) ? (
+
+
+
+ ) : (
+ showAddress && (
+
+
+
+ )
+ )}
+
+
+
+
+
+ );
+}
+
+export default AddressInput;
diff --git a/src/components/Body/TransactionRequests.tsx b/src/components/Body/TransactionRequests.tsx
index a58225f..65131e5 100644
--- a/src/components/Body/TransactionRequests.tsx
+++ b/src/components/Body/TransactionRequests.tsx
@@ -26,7 +26,7 @@ import {
import CopyToClipboard from "./CopyToClipboard";
import { TxnDataType } from "../../types";
-const slicedText = (txt: string) => {
+export const slicedText = (txt: string) => {
return txt.length > 6
? `${txt.slice(0, 4)}...${txt.slice(txt.length - 2, txt.length)}`
: txt;
diff --git a/yarn.lock b/yarn.lock
index bf08ef0..a8b75a1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -11492,10 +11492,10 @@ react-dom@^17.0.2:
object-assign "^4.1.1"
scheduler "^0.20.2"
-react-error-overlay@^6.0.9:
- version "6.0.11"
- resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb"
- integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==
+react-error-overlay@6.0.9, react-error-overlay@^6.0.9:
+ version "6.0.9"
+ resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a"
+ integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==
react-fast-compare@3.2.0:
version "3.2.0"