Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert frontend to use /api/wallets route #206

Merged
merged 1 commit into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 10 additions & 13 deletions components/GetWalletCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,19 @@ import {
HStack,
Image,
Stack,
Tag,
Text,
Link,
} from '@chakra-ui/react'
import { Service } from '../types'
import NextLink from 'next/link'
import { Wallet } from '../data/wallets'

type Props = {
icon: string
name: string
service: Service
wallet: Wallet
}

export default function GetWalletCard({ icon, name, service }: Props) {
const isExtensionService = isExtension(service)
const isExtensionServiceInstalled = Boolean(service?.provider?.is_installed)
export default function GetWalletCard({ wallet }: Props) {
const extensionService = wallet.services.find(isExtension)
const isExtensionService = !!extensionService
const isExtensionServiceInstalled = extensionService?.provider?.is_installed

return (
<Card size="md" variant="unstyled">
Expand All @@ -31,8 +28,8 @@ export default function GetWalletCard({ icon, name, service }: Props) {
<Flex alignItems="center" justifyContent="space-between">
<HStack>
<Image
src={icon}
alt={name}
src={wallet.icon}
alt={wallet.name}
borderRadius="lg"
borderWidth="1px"
borderColor="gray.200"
Expand All @@ -43,7 +40,7 @@ export default function GetWalletCard({ icon, name, service }: Props) {
/>
<Flex direction="column" textAlign="left">
<Text fontSize="lg" as="b">
{name}
{wallet.name}
</Text>

{isExtensionService && !isExtensionServiceInstalled ? (
Expand All @@ -58,7 +55,7 @@ export default function GetWalletCard({ icon, name, service }: Props) {

{/* TODO: Needs to link to install page, will be addressed in future PR */}
<Button
href={service.provider.install_link || service.provider.website}
href={wallet.website}
target="_blank"
as={NextLink}
variant="outline"
Expand Down
11 changes: 2 additions & 9 deletions components/GetWalletList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,8 @@ export default function GetWalletList() {

return (
<Stack spacing={4}>
{wallets.map((wallet, index) => {
return (
<GetWalletCard
key={wallet.provider.address ?? index}
service={wallet}
name={wallet?.provider?.name ?? ''}
icon={wallet?.provider?.icon ?? ''}
/>
)
{wallets.map(wallet => {
return <GetWalletCard key={wallet.uid} wallet={wallet} />
})}
</Stack>
)
Expand Down
53 changes: 11 additions & 42 deletions components/ServiceCard.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import { WalletUtils } from '@onflow/fcl'
import { SUPPORTED_VERSIONS } from '../helpers/constants'
import { isExtension } from '../helpers/services'
import { isGreaterThanOrEqualToVersion } from '../helpers/version'
import {
Card,
CardBody,
Expand All @@ -12,47 +9,19 @@ import {
Tag,
Text,
} from '@chakra-ui/react'
import { Service } from '../types'
import { useConfig } from '../contexts/ConfigContext'
import { useLastUsedState } from '../hooks/useLastUsedState'
import { Wallet } from '../data/wallets'

type Props = {
icon: string
name: string
service: Service
interface ServiceCardProps {
wallet: Wallet
}

export default function ServiceCard({ icon, name, service }: Props) {
const { appVersion } = useConfig()

const installLink = service?.provider?.install_link
const isExtensionService = isExtension(service)
const isExtensionServiceInstalled = Boolean(service?.provider?.is_installed)

const { setLastUsed } = useLastUsedState()
export default function ServiceCard({ wallet }: ServiceCardProps) {
const extensionService = wallet.services.find(isExtension)
const isExtensionService = !!extensionService
const isExtensionServiceInstalled = extensionService?.provider?.is_installed

const onSelect = () => {
if (!service) return

setLastUsed(service?.provider?.address)

if (isExtensionService && !isExtensionServiceInstalled) {
if (installLink) {
// Extensions require reload of page to inject script into dapp with data
// Redirecting dapp to install page forces page to be refreshed when returning
window.parent.location.href = installLink
}
return
}

if (
appVersion &&
isGreaterThanOrEqualToVersion(appVersion, SUPPORTED_VERSIONS.EXTENSIONS)
) {
WalletUtils.redirect(service)
} else {
window.location.href = `${service.endpoint}${window.location.search}`
}
// TODO: implement connect wallet logic, future PR
}

return (
Expand All @@ -73,8 +42,8 @@ export default function ServiceCard({ icon, name, service }: Props) {
<Flex alignItems="center" justifyContent="space-between">
<HStack>
<Image
src={icon}
alt={name}
src={wallet.icon}
alt={wallet.name}
borderRadius="lg"
borderWidth="1px"
borderColor="gray.200"
Expand All @@ -85,7 +54,7 @@ export default function ServiceCard({ icon, name, service }: Props) {
/>
<Flex direction="column" textAlign="left">
<Text fontSize="lg" as="b">
{name}
{wallet.name}
</Text>

{isExtensionService && !isExtensionServiceInstalled ? (
Expand Down
20 changes: 6 additions & 14 deletions components/ServiceGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { Flex, Stack, Text } from '@chakra-ui/react'
import { Service } from '../types'
import { Stack, Text } from '@chakra-ui/react'
import ServiceCard from './ServiceCard'
import { Wallet } from '../data/wallets'

interface ServiceGroupProps {
title: string
services: Service[]
wallets: Wallet[]
titleProps?: React.ComponentProps<typeof Text>
cardProps?: React.ComponentProps<typeof ServiceCard>
}

export default function ServiceGroup({
title,
services,
wallets,
titleProps,
cardProps,
}: ServiceGroupProps) {
Expand All @@ -21,16 +21,8 @@ export default function ServiceGroup({
{title}
</Text>
<Stack spacing={2}>
{services.map((service, index) => {
return (
<ServiceCard
key={service?.provider?.address ?? index}
service={service}
name={service?.provider?.name ?? ''}
icon={service?.provider?.icon ?? ''}
{...cardProps}
/>
)
{wallets.map(wallet => {
return <ServiceCard key={wallet.uid} wallet={wallet} {...cardProps} />
})}
</Stack>
</Stack>
Expand Down
49 changes: 26 additions & 23 deletions components/ServiceList.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,60 @@
import { Stack } from '@chakra-ui/react'
import ServiceGroup from './ServiceGroup'
import { useLastUsedState } from '../hooks/useLastUsedState'
import { Service } from '../types'
import { useMemo } from 'react'
import { Wallet } from '../data/wallets'
import { isExtension } from '../helpers/services'
import { useWalletHistory } from '../hooks/useWalletHistory'

interface ServiceListProps {
services: Service[]
wallets: Wallet[]
}

export default function ServiceList({ services }: ServiceListProps) {
const { lastUsed: lastUsedAddr } = useLastUsedState()
export default function ServiceList({ wallets }: ServiceListProps) {
const { isLastUsed } = useWalletHistory()

// Get the last used service, installed services, and recommended services
const { lastUsedService, installedServices, recommendedServices } = useMemo(
const { lastUsedWallet, installedWallets, recommendedWallets } = useMemo(
() =>
services.reduce(
(acc, service) => {
if (service.provider.address === lastUsedAddr && lastUsedAddr) {
acc.lastUsedService = service
} else if (service.provider.is_installed) {
acc.installedServices.push(service)
wallets.reduce(
(acc, wallet) => {
const extensionService = wallet.services.find(isExtension)

if (isLastUsed(wallet)) {
acc.lastUsedWallet = wallet
} else if (extensionService?.provider?.is_installed) {
acc.installedWallets.push(wallet)
} else {
acc.recommendedServices.push(service)
acc.recommendedWallets.push(wallet)
}
return acc
},
{
lastUsedService: null,
installedServices: [] as Service[],
recommendedServices: [] as Service[],
lastUsedWallet: null as Wallet | null,
installedWallets: [] as Wallet[],
recommendedWallets: [] as Wallet[],
}
),
[services, lastUsedAddr]
[wallets, isLastUsed]
)

return (
<Stack spacing={4}>
{lastUsedService && (
{lastUsedWallet && (
<ServiceGroup
title="Last Used"
services={[lastUsedService]}
wallets={[lastUsedWallet]}
titleProps={{
color: 'blue.400',
}}
/>
)}

{installedServices.length > 0 && (
<ServiceGroup title="Installed" services={installedServices} />
{installedWallets.length > 0 && (
<ServiceGroup title="Installed" wallets={installedWallets} />
)}

{recommendedServices.length > 0 && (
<ServiceGroup title="Recommended" services={recommendedServices} />
{recommendedWallets.length > 0 && (
<ServiceGroup title="Recommended" wallets={recommendedWallets} />
)}
</Stack>
)
Expand Down
2 changes: 1 addition & 1 deletion components/views/WalletSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default function WalletSelection({ onSwitchToLearnMore }: Props) {
<Stack overflow="scroll" px={8} pb={6} flexGrow={1}>
{/* TODO: replace this in future PR with Filter Bar */}
{/*isFeaturesSupported && <Features />*/}
<ServiceList services={wallets} />
<ServiceList wallets={wallets} />
</Stack>

<Divider color="gray.300" />
Expand Down
9 changes: 0 additions & 9 deletions hooks/useLastUsedState.tsx

This file was deleted.

26 changes: 26 additions & 0 deletions hooks/useWalletHistory.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useCallback } from 'react'
import { Wallet } from '../data/wallets'
import { LOCAL_STORAGE_KEYS } from '../helpers/constants'
import { useLocalStorage } from './useLocalStorage'

export function useWalletHistory() {
const [, setLastUsedState] = useLocalStorage(
LOCAL_STORAGE_KEYS.LAST_USED,
null
)
const [lastUsedUid] = useLocalStorage(LOCAL_STORAGE_KEYS.LAST_USED, null)

const setLastUsed = useCallback(
(wallet: Wallet) => {
setLastUsedState(wallet.uid)
},
[setLastUsedState]
)

const isLastUsed = useCallback(
(wallet: Wallet) => wallet.uid === lastUsedUid,
[lastUsedUid]
)

return { isLastUsed, setLastUsed, lastUsedUid }
}
7 changes: 3 additions & 4 deletions hooks/useWallets.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import useSWR from 'swr'
import { PATHS } from '../helpers/constants'
import { useConfig } from '../contexts/ConfigContext'
import { getUserAgent } from '../helpers/platform'
import { Service } from '../types'
import { Wallet } from '../data/wallets'

const genKey = (url: string, opts: any) => [url, JSON.stringify(opts)]

Expand All @@ -27,7 +26,7 @@ export function useWallets() {
port,
} = useConfig()

const requestUrl = `/api${PATHS[network.toUpperCase()]}?discoveryType=UI`
const requestUrl = `/api/${network.toLowerCase()}/wallets?discoveryType=UI`
const body = {
type: ['authn'],
fclVersion: appVersion,
Expand All @@ -43,7 +42,7 @@ export function useWallets() {
}

const { data: wallets, error } = useSWR(genKey(requestUrl, body), url =>
fetcher<Service[]>(url, body)
fetcher<Wallet[]>(url, body)
)

return { wallets, error, isLoading: !wallets && !error }
Expand Down
Loading