mirror of
https://github.com/acid-info/logos-ordinals-dashboard.git
synced 2025-02-05 10:04:28 +00:00
feat: implement wallet connect dropdown
This commit is contained in:
parent
e9cd02826d
commit
5e75d92dbb
@ -1,4 +1,3 @@
|
||||
import { Collapse } from '@/components/common/Collapse'
|
||||
import { breakpoints } from '@/configs/ui.configs'
|
||||
import { truncateString } from '@/utils/general.utils'
|
||||
import styled from '@emotion/styled'
|
||||
@ -9,33 +8,33 @@ import useGetPillars from '../../../../apis/general/useGetPillars'
|
||||
|
||||
interface OperatorPanelProps {}
|
||||
|
||||
const TEMP_BADGES = [
|
||||
{
|
||||
id: 1,
|
||||
image: '/dashboard/badges/1-year-streak.svg',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
image: '/dashboard/badges/10-day-streak.svg',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
image: '/dashboard/badges/100-days-streak.svg',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
image: '/dashboard/badges/badege-placeholder.svg',
|
||||
},
|
||||
]
|
||||
// const TEMP_BADGES = [
|
||||
// {
|
||||
// id: 1,
|
||||
// image: '/dashboard/badges/1-year-streak.svg',
|
||||
// },
|
||||
// {
|
||||
// id: 2,
|
||||
// image: '/dashboard/badges/10-day-streak.svg',
|
||||
// },
|
||||
// {
|
||||
// id: 3,
|
||||
// image: '/dashboard/badges/100-days-streak.svg',
|
||||
// },
|
||||
// {
|
||||
// id: 4,
|
||||
// image: '/dashboard/badges/badege-placeholder.svg',
|
||||
// },
|
||||
// ]
|
||||
|
||||
const OperatorPanel: React.FC<OperatorPanelProps> = () => {
|
||||
const { data: currentBlock } = useGetCurrentBTCBlock()
|
||||
const { data: epochs } = useGetEpochs()
|
||||
const { data: pillars } = useGetPillars()
|
||||
|
||||
console.log('currentBlock', currentBlock)
|
||||
console.log('epochs', epochs)
|
||||
console.log('pillars', pillars)
|
||||
// console.log('currentBlock', currentBlock)
|
||||
// console.log('epochs', epochs)
|
||||
// console.log('pillars', pillars)
|
||||
|
||||
return (
|
||||
<StyledPanel>
|
||||
@ -79,7 +78,7 @@ const OperatorPanel: React.FC<OperatorPanelProps> = () => {
|
||||
</InfoRow>
|
||||
</CallSignContainer>
|
||||
|
||||
<ProfileInfo>
|
||||
{/* <ProfileInfo>
|
||||
<BadgesSection>
|
||||
<BadgeTitle>
|
||||
<Label>Badges</Label>
|
||||
@ -95,12 +94,12 @@ const OperatorPanel: React.FC<OperatorPanelProps> = () => {
|
||||
))}
|
||||
</BadgeList>
|
||||
</BadgesSection>
|
||||
</ProfileInfo>
|
||||
</ProfileInfo> */}
|
||||
|
||||
<Collapse
|
||||
{/* <Collapse
|
||||
header="Refer Operators +100 XP"
|
||||
content={truncateString('445f5slk1as4645sdf54')}
|
||||
/>
|
||||
/> */}
|
||||
</StyledPanel>
|
||||
)
|
||||
}
|
||||
@ -159,11 +158,11 @@ const InfoRow = styled.div`
|
||||
background-color: var(--grey-900);
|
||||
`
|
||||
|
||||
const ProfileInfo = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
`
|
||||
// const ProfileInfo = styled.div`
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// gap: 2px;
|
||||
// `
|
||||
|
||||
const CallSignContainer = styled.div`
|
||||
margin-top: 24px;
|
||||
@ -187,38 +186,38 @@ const Value = styled.span`
|
||||
}
|
||||
`
|
||||
|
||||
const BadgesSection = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: var(--grey-900);
|
||||
padding: 16px 8px;
|
||||
`
|
||||
// const BadgesSection = styled.div`
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// background-color: var(--grey-900);
|
||||
// padding: 16px 8px;
|
||||
// `
|
||||
|
||||
const BadgeTitle = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
width: 100%;
|
||||
`
|
||||
// const BadgeTitle = styled.div`
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// margin-bottom: 16px;
|
||||
// width: 100%;
|
||||
// `
|
||||
|
||||
const BadgeIcon = styled.img`
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
// const BadgeIcon = styled.img`
|
||||
// width: 14px;
|
||||
// height: 14px;
|
||||
|
||||
margin-left: auto;
|
||||
`
|
||||
// margin-left: auto;
|
||||
// `
|
||||
|
||||
const BadgeList = styled.div`
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
`
|
||||
// const BadgeList = styled.div`
|
||||
// display: flex;
|
||||
// flex-wrap: wrap;
|
||||
// gap: 16px;
|
||||
// `
|
||||
|
||||
const Badge = styled.img`
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
object-fit: contain;
|
||||
`
|
||||
// const Badge = styled.img`
|
||||
// width: 52px;
|
||||
// height: 52px;
|
||||
// object-fit: contain;
|
||||
// `
|
||||
|
||||
const ActionButton = styled.button`
|
||||
display: flex;
|
||||
|
@ -1,11 +1,9 @@
|
||||
import HamburguerMenu from '@/components/HamburgerMenu/HamburgerMenu'
|
||||
import { WalletConnect } from '@/components/WalletConnect'
|
||||
import { breakpoints } from '@/configs/ui.configs'
|
||||
import { truncateString } from '@/utils/general.utils'
|
||||
import styled from '@emotion/styled'
|
||||
import Link from 'next/link'
|
||||
import React, { useState } from 'react'
|
||||
import { api } from '../../../../common/api'
|
||||
import { WALLET_SIGN_MESSAGE_REQUEST } from '../../../../constants/wallet'
|
||||
import React from 'react'
|
||||
import { Navbar } from '../Navbar'
|
||||
|
||||
declare global {
|
||||
@ -18,42 +16,6 @@ declare global {
|
||||
interface NavbarProps {}
|
||||
|
||||
const Header: React.FC<NavbarProps> = () => {
|
||||
const [walletAddress, setWalletAddress] = useState<string | null>(null)
|
||||
|
||||
const connectWallet = async () => {
|
||||
try {
|
||||
if (walletAddress) {
|
||||
setWalletAddress(null)
|
||||
alert('Wallet disconnected.')
|
||||
} else {
|
||||
if (window.okxwallet) {
|
||||
// DOCS: https://www.okx.com/web3/build/docs/sdks/chains/bitcoin/provider#connect
|
||||
const result = await window.okxwallet.bitcoin.connect()
|
||||
const address = result.address
|
||||
|
||||
setWalletAddress(address)
|
||||
|
||||
// Docs: https://www.okx.com/web3/build/docs/sdks/chains/bitcoin/provider#signmessage
|
||||
const signature = await window.okxwallet.bitcoin.signMessage(
|
||||
WALLET_SIGN_MESSAGE_REQUEST,
|
||||
'bip322-simple',
|
||||
)
|
||||
|
||||
const response = await api.post('/token/pair', {
|
||||
address,
|
||||
signature,
|
||||
})
|
||||
|
||||
console.log('Token pair response:', response)
|
||||
} else {
|
||||
alert('No Bitcoin wallet found. Please install OKX Wallet.')
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to connect or disconnect wallet:', error)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Link href="/">
|
||||
@ -72,7 +34,7 @@ const Header: React.FC<NavbarProps> = () => {
|
||||
<span>Gitbook</span>
|
||||
</GitbookButton>
|
||||
</Link>
|
||||
<Link
|
||||
{/* <Link
|
||||
href="https://discord.com/invite/logosnetwork"
|
||||
passHref
|
||||
target="_blank"
|
||||
@ -81,18 +43,9 @@ const Header: React.FC<NavbarProps> = () => {
|
||||
<span>Join our Discord</span>
|
||||
<Icon src="/icons/discord-white.svg" alt="Discord" />
|
||||
</SocialButton>
|
||||
</Link>
|
||||
</Link> */}
|
||||
<WalletConnect />
|
||||
<HamburguerMenu />
|
||||
<WalletButton onClick={connectWallet}>
|
||||
<WalletAddress>
|
||||
{walletAddress ? truncateString(walletAddress) : 'Connect'}
|
||||
</WalletAddress>
|
||||
{/* <Icon src="/assets/btc.svg" alt="Wallet icon" /> */}
|
||||
</WalletButton>
|
||||
{/* <PointsButton>
|
||||
<PointsValue>4,278</PointsValue>
|
||||
<Icon src="/assets/star.png" alt="Points icon" />
|
||||
</PointsButton> */}
|
||||
</UserActions>
|
||||
</Container>
|
||||
)
|
||||
@ -129,30 +82,15 @@ const UserActions = styled.div`
|
||||
}
|
||||
`
|
||||
|
||||
const Button = styled.button`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 12px;
|
||||
height: 28px;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
border: 1px solid rgb(var(--lsd-border-primary));
|
||||
background: transparent;
|
||||
color: rgb(var(--lsd-text-primary));
|
||||
cursor: pointer;
|
||||
`
|
||||
// const SocialButton = styled(Button)`
|
||||
// width: 142px;
|
||||
// box-sizing: border-box;
|
||||
// gap: 12px;
|
||||
|
||||
const SocialButton = styled(Button)`
|
||||
width: 142px;
|
||||
box-sizing: border-box;
|
||||
gap: 12px;
|
||||
|
||||
span {
|
||||
white-space: nowrap;
|
||||
}
|
||||
`
|
||||
// span {
|
||||
// white-space: nowrap;
|
||||
// }
|
||||
// `
|
||||
|
||||
const DesktopNavbar = styled.div`
|
||||
position: absolute;
|
||||
@ -164,26 +102,6 @@ const DesktopNavbar = styled.div`
|
||||
}
|
||||
`
|
||||
|
||||
const WalletButton = styled(Button)`
|
||||
width: fit-content;
|
||||
`
|
||||
|
||||
const WalletAddress = styled.span`
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
`
|
||||
|
||||
// const PointsButton = styled(Button)`
|
||||
// width: 83px;
|
||||
// `
|
||||
|
||||
// const PointsValue = styled.span``
|
||||
|
||||
const Icon = styled.img`
|
||||
padding: 0;
|
||||
`
|
||||
|
||||
const GitbookButton = styled.button`
|
||||
display: flex;
|
||||
padding: 6px 12px;
|
||||
|
215
src/components/WalletConnect/WalletConnect.tsx
Normal file
215
src/components/WalletConnect/WalletConnect.tsx
Normal file
@ -0,0 +1,215 @@
|
||||
import { truncateString } from '@/utils/general.utils'
|
||||
import styled from '@emotion/styled'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import { api } from '../../../common/api'
|
||||
import { WALLET_SIGN_MESSAGE_REQUEST } from '../../../constants/wallet'
|
||||
|
||||
const options = [
|
||||
{ label: 'Multiplass', value: 'multiplass' },
|
||||
{ label: 'Unisat', value: 'unisat' },
|
||||
{ label: 'Magic Eden', value: 'magic-eden' },
|
||||
{ label: 'Phantom', value: 'phantom' },
|
||||
{ label: 'OKX', value: 'okx' },
|
||||
]
|
||||
|
||||
const Dropdown: React.FC = () => {
|
||||
const [isExpanded, setIsExpanded] = useState(false)
|
||||
const [walletAddress, setWalletAddress] = useState<string | null>(null)
|
||||
|
||||
const connectWallet = async (wallet: string) => {
|
||||
try {
|
||||
if (walletAddress) {
|
||||
setWalletAddress(null)
|
||||
alert('Wallet disconnected.')
|
||||
} else {
|
||||
if (wallet === 'okx' && window.okxwallet) {
|
||||
// Docs: https://www.okx.com/web3/build/docs/sdks/chains/bitcoin/provider#connect
|
||||
const result = await window.okxwallet.bitcoin.connect()
|
||||
const address = result.address
|
||||
|
||||
setWalletAddress(address)
|
||||
|
||||
// Docs: https://www.okx.com/web3/build/docs/sdks/chains/bitcoin/provider#signmessage
|
||||
const signature = await window.okxwallet.bitcoin.signMessage(
|
||||
WALLET_SIGN_MESSAGE_REQUEST,
|
||||
'bip322-simple',
|
||||
)
|
||||
|
||||
const response = await api.post('/token/pair', {
|
||||
address,
|
||||
signature,
|
||||
})
|
||||
|
||||
console.log('Token pair response:', response)
|
||||
} else {
|
||||
alert('Only OKX wallet is supported for now.')
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to connect or disconnect wallet:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const dropdownRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const toggleDropdown = () => {
|
||||
setIsExpanded(!isExpanded)
|
||||
}
|
||||
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (
|
||||
dropdownRef.current &&
|
||||
!dropdownRef.current.contains(event.target as Node)
|
||||
) {
|
||||
setIsExpanded(false)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isExpanded) {
|
||||
document.addEventListener('mousedown', handleClickOutside)
|
||||
} else {
|
||||
document.removeEventListener('mousedown', handleClickOutside)
|
||||
}
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside)
|
||||
}
|
||||
}, [isExpanded])
|
||||
|
||||
return (
|
||||
<DropdownContainer ref={dropdownRef}>
|
||||
<DropdownHeader onClick={toggleDropdown} isExpanded={isExpanded}>
|
||||
<div>
|
||||
<WalletButton>
|
||||
<WalletAddress>
|
||||
{walletAddress ? truncateString(walletAddress) : 'Connect Wallet'}
|
||||
</WalletAddress>
|
||||
<Icon src="/assets/chevron-down.svg" alt="Wallet icon" />
|
||||
</WalletButton>
|
||||
{isExpanded && (
|
||||
<DropdownContent>
|
||||
<ScrollDiv>
|
||||
{options.map((option, index) => (
|
||||
<WalletName
|
||||
onClick={() => connectWallet(option.value)}
|
||||
key={'wallet-' + index}
|
||||
>
|
||||
{option.label}
|
||||
</WalletName>
|
||||
))}
|
||||
</ScrollDiv>
|
||||
</DropdownContent>
|
||||
)}
|
||||
</div>
|
||||
{walletAddress && (
|
||||
<PointsButton>
|
||||
<PointsValue>4,278 XP</PointsValue>
|
||||
</PointsButton>
|
||||
)}
|
||||
</DropdownHeader>
|
||||
</DropdownContainer>
|
||||
)
|
||||
}
|
||||
|
||||
const DropdownContainer = styled.div`
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
width: 100%;
|
||||
}
|
||||
`
|
||||
|
||||
const DropdownHeader = styled.div<{ isExpanded: boolean }>`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
`
|
||||
|
||||
const ScrollDiv = styled.div`
|
||||
box-sizing: border-box;
|
||||
`
|
||||
|
||||
const WalletName = styled.div`
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
border-bottom: 1px solid rgb(var(--lsd-border-primary));
|
||||
display: flex;
|
||||
padding: 6px 10px 6px 12px;
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
cursor: pointer;
|
||||
|
||||
&:last-of-type {
|
||||
border-bottom: none;
|
||||
}
|
||||
`
|
||||
|
||||
const WalletButton = styled.button`
|
||||
width: fit-content;
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 12px;
|
||||
height: 28px;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
border: 1px solid rgb(var(--lsd-border-primary));
|
||||
background: transparent;
|
||||
color: rgb(var(--lsd-text-primary));
|
||||
cursor: pointer;
|
||||
`
|
||||
|
||||
const WalletAddress = styled.span`
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
min-width: 90px;
|
||||
`
|
||||
|
||||
const Icon = styled.img`
|
||||
padding: 0;
|
||||
margin-left: 10px;
|
||||
`
|
||||
|
||||
const DropdownContent = styled.div`
|
||||
position: absolute;
|
||||
top: 28px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background-color: black;
|
||||
border: 1px solid white;
|
||||
border-top: none;
|
||||
z-index: 10;
|
||||
|
||||
box-sizing: border-box;
|
||||
`
|
||||
|
||||
const PointsButton = styled.button`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
position: absolute;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
height: 28px;
|
||||
border: 1px solid rgb(var(--lsd-border-primary));
|
||||
padding: 8px 12px;
|
||||
top: 36px;
|
||||
right: 0;
|
||||
`
|
||||
|
||||
const PointsValue = styled.span`
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
white-space: nowrap;
|
||||
color: white;
|
||||
`
|
||||
|
||||
export default Dropdown
|
1
src/components/WalletConnect/index.ts
Normal file
1
src/components/WalletConnect/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default as WalletConnect } from './WalletConnect'
|
Loading…
x
Reference in New Issue
Block a user