diff --git a/packages/app-extension/src/components/Unlocked/Balances/TokensWidget/AddressSelector.tsx b/packages/app-extension/src/components/Unlocked/Balances/TokensWidget/AddressSelector.tsx index 629f27350..47fe45255 100644 --- a/packages/app-extension/src/components/Unlocked/Balances/TokensWidget/AddressSelector.tsx +++ b/packages/app-extension/src/components/Unlocked/Balances/TokensWidget/AddressSelector.tsx @@ -40,6 +40,14 @@ import { useIsValidAddress } from "./Send"; let debouncedTimer = 0; +export interface SendData { + address: string; + username?: string; + image?: string; + uuid?: string; + walletName?: string; +} + const useStyles = makeStyles((theme: any) => createStyles({ hoverParent: { @@ -84,21 +92,25 @@ const useStyles = makeStyles((theme: any) => type AddressSelectorContext = { blockchain: Blockchain; - token: TokenDataWithPrice; + name: string; + onSelect: (sendData: SendData) => void; }; const AddressSelectorContext = React.createContext(null); + export function AddressSelectorProvider(props: { blockchain: Blockchain; - token: TokenDataWithPrice; + name: string; + onSelect: (sendData: SendData) => void; children: any; }) { return ( {props.children} @@ -127,6 +139,7 @@ export const AddressSelectorLoader = ({ // (rather than aggregate mode). const activePublicKey = useActiveWallet().publicKey; const publicKeyStr = publicKey ?? activePublicKey; + const { push } = useNavigation(); const [token] = useLoader( blockchainTokenData({ publicKey: publicKeyStr, @@ -136,15 +149,63 @@ export const AddressSelectorLoader = ({ null ); if (!token) return null; - return ; + return ( + { + push("send", { + blockchain, + token, + to: sendData, + }); + }} + /> + ); +}; + +export const TokenAddressSelector = (props: any) => { + const { push } = useNavigation(); + + return ( + { + push("send", { + blockchain: props.blockchain, + token: props.token, + to: sendData, + }); + }} + /> + ); +}; + +export const NftAddressSelector = (props: any) => { + const { push } = useNavigation(); + + return ( + { + push("send", { + blockchain: props.blockchain, + token: props.token, + to: sendData, + }); + }} + /> + ); }; export const AddressSelector = ({ blockchain, - token, + name, + onSelect, }: { blockchain: Blockchain; - token: TokenDataWithPrice; + name: string; + onSelect: (sendData: SendData) => void; }) => { const classes = useStyles(); const nav = useNavigationEphemeral(); @@ -152,7 +213,6 @@ export const AddressSelector = ({ const { provider: solanaProvider } = useAnchorContext(); const ethereumCtx = useEthereumCtx(); const [searchResults, setSearchResults] = useState([]); - const { push } = useNavigation(); const { isValidAddress, normalizedAddress } = useIsValidAddress( blockchain, inputContent, @@ -162,14 +222,18 @@ export const AddressSelector = ({ useEffect(() => { const prev = nav.title; - nav.setOptions({ headerTitle: `Send ${token.ticker}` }); + nav.setOptions({ headerTitle: `Send ${name}` }); return () => { nav.setOptions({ headerTitle: prev }); }; }, []); return ( - +
result.publicKey === inputContent ) ); - push("send", { - blockchain, - token, - to: { - address: normalizedAddress || inputContent, - username: user?.username, - image: user?.image, - uuid: user?.id, - }, + onSelect({ + address: normalizedAddress || inputContent, + username: user?.username, + image: user?.image, + uuid: user?.id, }); }} disabled={!isValidAddress} @@ -504,8 +564,7 @@ const AddressListItem = ({ }) => { const theme = useCustomTheme(); const classes = useStyles(); - const { push } = useNavigation(); - const { blockchain, token } = useAddressSelectorContext(); + const { onSelect } = useAddressSelectorContext(); return ( , + component: (props: any) => , title: "", }, { diff --git a/packages/app-extension/src/components/Unlocked/Nfts/Detail.tsx b/packages/app-extension/src/components/Unlocked/Nfts/Detail.tsx index 5290676c4..88c71fd50 100644 --- a/packages/app-extension/src/components/Unlocked/Nfts/Detail.tsx +++ b/packages/app-extension/src/components/Unlocked/Nfts/Detail.tsx @@ -1,4 +1,4 @@ -import { type CSSProperties, useEffect, useState } from "react"; +import React, { type CSSProperties, useEffect, useState } from "react"; import type { Nft } from "@coral-xyz/common"; import { AVATAR_BASE_URL, @@ -41,7 +41,7 @@ import { useSolanaExplorer, useUser, } from "@coral-xyz/recoil"; -import { useCustomTheme } from "@coral-xyz/themes"; +import { styles, useCustomTheme } from "@coral-xyz/themes"; import { Whatshot } from "@mui/icons-material"; import MoreHorizIcon from "@mui/icons-material/MoreHoriz"; import { Button, IconButton, Typography } from "@mui/material"; @@ -54,6 +54,7 @@ import { } from "recoil"; import { ApproveTransactionDrawer } from "../../common/ApproveTransactionDrawer"; +import { CopyablePublicKey } from "../../common/CopyablePublicKey"; import { CloseButton, useDrawerContext, @@ -62,8 +63,11 @@ import { import { NavStackEphemeral, NavStackScreen, + useNavigation as useNavigationEphemeral, } from "../../common/Layout/NavStack"; import PopoverMenu from "../../common/PopoverMenu"; +import type { SendData } from "../Balances/TokensWidget/AddressSelector"; +import { AddressSelector } from "../Balances/TokensWidget/AddressSelector"; import { SendEthereumConfirmationCard } from "../Balances/TokensWidget/Ethereum"; import { Error as ErrorConfirmation, @@ -381,7 +385,7 @@ function SendButton({
({ title: nft.name ? `${nft.name} / Send` : "Send", })} @@ -389,7 +393,12 @@ function SendButton({ > } + component={(props) => } + /> + + } />
@@ -398,12 +407,38 @@ function SendButton({ ); } -function SendScreen({ nft }: { nft: any }) { +function NftAddressSelector({ nft }: { nft: any }) { + const { push } = useNavigationEphemeral(); + + return ( +
+ { + push("send", { + to: sendData, + }); + }} + blockchain={nft.blockchain} + name={nft.name} + /> +
+ ); +} + +const useStyles = styles((theme) => ({ + horizontalCenter: { + display: "flex", + justifyContent: "center", + }, +})); + +function SendScreen({ nft, to }: { nft: any; to: SendData }) { const background = useBackgroundClient(); const { close } = useDrawerContext(); const { provider: solanaProvider } = useAnchorContext(); + const classes = useStyles(); const ethereumCtx = useEthereumCtx(); - const [destinationAddress, setDestinationAddress] = useState(""); + const destinationAddress = to.address; const [openConfirm, setOpenConfirm] = useState(false); const [wasSent, setWasSent] = useState(false); const { isValidAddress, isErrorAddress } = useIsValidAddress( @@ -446,16 +481,12 @@ function SendScreen({ nft }: { nft: any }) { >
- setDestinationAddress(e.target.value)} - error={isErrorAddress} - inputProps={{ - name: "to", - }} - /> +
+ Sending to +
+
+ +
["destinationUser"] + } destinationAddress={destinationAddress} amount={BigNumber.from(1)} onComplete={() => setWasSent(true)} @@ -505,6 +543,13 @@ function SendScreen({ nft }: { nft: any }) { address: nft.contractAddress, tokenId: nft.tokenId, }} + destinationUser={ + (to && to.uuid && to.username && to.image + ? to + : undefined) as React.ComponentProps< + typeof SendEthereumConfirmationCard + >["destinationUser"] + } destinationAddress={destinationAddress} amount={BigNumber.from(1)} onComplete={() => setWasSent(true)}