-
Notifications
You must be signed in to change notification settings - Fork 66
Expand file tree
/
Copy pathpeer-maddr.tsx
More file actions
169 lines (149 loc) · 5.73 KB
/
peer-maddr.tsx
File metadata and controls
169 lines (149 loc) · 5.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import { useLibp2pContext } from '@/context/ctx'
import { multiaddr } from '@multiformats/multiaddr'
import { useState } from 'react'
import Spinner from '@/components/spinner'
import { connectToMultiaddr } from '../lib/libp2p'
import type { PeerId } from '@libp2p/interface'
interface PeerMaddrListProps {
resolvedMultiaddrs: string[]
setResolvedMultiaddrs: (addrs: string[]) => void
setError: (error: string | null) => void
}
export default function PeerMaddrList({ resolvedMultiaddrs, setResolvedMultiaddrs, setError }: PeerMaddrListProps) {
if (resolvedMultiaddrs.length === 0) return null
return (
<div className="mt-6 w-full">
<h4 className="text-lg font-semibold text-gray-900 mb-3">Found {resolvedMultiaddrs.length} addresses:</h4>
<ul className="p-4 border rounded-lg bg-gray-50 shadow-sm space-y-3">
{resolvedMultiaddrs.map((addr, index) => (
<MaddrItem key={index} addr={addr} setResolvedMultiaddrs={setResolvedMultiaddrs} setError={setError} />
))}
</ul>
</div>
)
}
interface MaddrItemProps {
addr: string
setResolvedMultiaddrs: (addrs: string[]) => void
setError: (error: string | null) => void
}
function MaddrItem({ addr, setResolvedMultiaddrs, setError }: MaddrItemProps) {
const [loading, setLoading] = useState(false)
const { libp2p, connections, setConnections } = useLibp2pContext()
// Helper to check if address is external
const isExternalAddress = (addr: string) => {
return !addr.includes('127.0.0.1') && !addr.includes('localhost') && !addr.includes('::1')
}
// Helper to validate transport stack
const hasValidTransportStack = (addr: string) => {
const hasWebTransport = addr.includes('webtransport') && addr.includes('certhash')
const hasWebRTC = addr.includes('webrtc') && addr.includes('certhash')
const hasQuic = addr.includes('quic-v1')
return hasWebTransport || (hasWebRTC && hasQuic)
}
const handleConnect = async () => {
setLoading(true)
try {
const maddr = multiaddr(addr)
const peerId = maddr.getPeerId()
if (!peerId) {
throw new Error('No peer ID found in multiaddr')
}
if (!isExternalAddress(addr)) {
console.warn('⚠️ Attempting to connect to local address, this might fail:', addr)
}
if (!hasValidTransportStack(addr)) {
throw new Error('Invalid or incomplete transport protocol stack')
}
console.log(`🔌 Attempting to connect to ${addr}`)
// Ensure the multiaddr includes the peer ID
const fullAddr = addr.includes(`/p2p/${peerId}`) ? addr : `${addr}/p2p/${peerId}`
const fullMaddr = multiaddr(fullAddr)
// Attempt connection
await connectToMultiaddr(libp2p)(fullMaddr)
console.log('✅ Successfully connected via:', fullAddr)
if (connections && !connections.find((conn) => conn.remotePeer.toString() === peerId)) {
const newConnections = [...connections]
const peerConnections = libp2p.getConnections(peerId as unknown as PeerId)
if (peerConnections.length > 0) {
newConnections.push(peerConnections[0])
setConnections(newConnections)
}
}
setError('✅ Successfully connected to peer!')
setResolvedMultiaddrs([])
} catch (err: unknown) {
const errorMessage = err instanceof Error ? err.message : String(err)
console.error('❌ Connection failed:', errorMessage)
setError(`❌ Failed to connect: ${errorMessage}`)
} finally {
setLoading(false)
}
}
// Only show valid multiaddrs that can be used for connection
const isValidMultiaddr = () => {
try {
const maddr = multiaddr(addr)
return !!maddr.getPeerId() // Only show if it has a peer ID
} catch {
return false
}
}
// Only show promising connection candidates
const getConnectionPriority = () => {
if (!isValidMultiaddr()) return 0
let priority = 1
if (isExternalAddress(addr)) priority += 2
if (addr.includes('webtransport')) priority += 3
if (addr.includes('webrtc')) priority += 2
return priority
}
// Don't render if priority is 0 (invalid)
if (getConnectionPriority() === 0) {
return null
}
return (
<li className="flex justify-between gap-x-6 py-3">
<div className="flex min-w-0 gap-x-4">
<div className="min-w-0 flex-auto">
<p className="text-sm font-semibold leading-6 text-gray-900 break-all">
<span
className={`inline-block px-2 py-1 text-xs rounded-full mr-2
${
addr.includes('webtransport')
? 'bg-green-100 text-green-800'
: addr.includes('webrtc')
? 'bg-blue-100 text-blue-800'
: 'bg-purple-100 text-purple-800'
}`}
>
{addr.includes('webtransport') ? '🌐 WebTransport' : addr.includes('webrtc') ? '🔌 WebRTC' : '🚀 QUIC'}
{!isExternalAddress(addr) && ' (Local)'}
</span>
{addr}
</p>
</div>
</div>
<div className="hidden sm:flex sm:flex-col sm:items-end">
<button
onClick={handleConnect}
className={`font-bold py-2 px-4 rounded flex flex-row items-center
${
loading
? 'bg-gray-400 cursor-not-allowed'
: getConnectionPriority() > 3
? 'bg-green-600 hover:bg-green-700'
: 'bg-yellow-600 hover:bg-yellow-700'
}
text-white disabled:opacity-70`}
disabled={loading}
>
{loading && <Spinner />}
<span className="pl-1">
{loading ? 'Connecting...' : getConnectionPriority() > 3 ? 'Connect (Recommended)' : 'Connect'}
</span>
</button>
</div>
</li>
)
}