1 |
|
2 |
|
3 | const codec = require('./codec')
|
4 | const protocols = require('./protocols-table')
|
5 | const varint = require('varint')
|
6 | const { CID } = require('multiformats/cid')
|
7 | const { base58btc } = require('multiformats/bases/base58')
|
8 | const errCode = require('err-code')
|
9 | const inspect = Symbol.for('nodejs.util.inspect.custom')
|
10 | const { toString: uint8ArrayToString } = require('uint8arrays/to-string')
|
11 | const { equals: uint8ArrayEquals } = require('uint8arrays/equals')
|
12 |
|
13 | /**
|
14 | * @typedef {(addr: Multiaddr) => Promise<string[]>} Resolver
|
15 | * @typedef {string | Multiaddr | Uint8Array | null} MultiaddrInput
|
16 | * @typedef {import('./types').MultiaddrObject} MultiaddrObject
|
17 | * @typedef {import('./types').Protocol} Protocol
|
18 | */
|
19 |
|
20 | /** @type {Map<string, Resolver>} */
|
21 | const resolvers = new Map()
|
22 | const symbol = Symbol.for('@multiformats/js-multiaddr/multiaddr')
|
23 |
|
24 | /**
|
25 | * Creates a [multiaddr](https://github.com/multiformats/multiaddr) from
|
26 | * a Uint8Array, String or another Multiaddr instance
|
27 | * public key.
|
28 | *
|
29 | */
|
30 | class Multiaddr {
|
31 | /**
|
32 | * @example
|
33 | * ```js
|
34 | * new Multiaddr('/ip4/127.0.0.1/tcp/4001')
|
35 | * // <Multiaddr 047f000001060fa1 - /ip4/127.0.0.1/tcp/4001>
|
36 | * ```
|
37 | *
|
38 | * @param {MultiaddrInput} [addr] - If String or Uint8Array, needs to adhere to the address format of a [multiaddr](https://github.com/multiformats/multiaddr#string-format)
|
39 | */
|
40 | constructor (addr) {
|
41 | // default
|
42 | if (addr == null) {
|
43 | addr = ''
|
44 | }
|
45 |
|
46 | // Define symbol
|
47 | Object.defineProperty(this, symbol, { value: true })
|
48 |
|
49 | if (addr instanceof Uint8Array) {
|
50 | /** @type {Uint8Array} - The raw bytes representing this multiaddress */
|
51 | this.bytes = codec.fromBytes(addr)
|
52 | } else if (typeof addr === 'string') {
|
53 | if (addr.length > 0 && addr.charAt(0) !== '/') {
|
54 | throw new Error(`multiaddr "${addr}" must start with a "/"`)
|
55 | }
|
56 | this.bytes = codec.fromString(addr)
|
57 | } else if (Multiaddr.isMultiaddr(addr)) { // Multiaddr
|
58 | this.bytes = codec.fromBytes(addr.bytes) // validate + copy buffer
|
59 | } else {
|
60 | throw new Error('addr must be a string, Buffer, or another Multiaddr')
|
61 | }
|
62 | }
|
63 |
|
64 | /**
|
65 | * Returns Multiaddr as a String
|
66 | *
|
67 | * @example
|
68 | * ```js
|
69 | * new Multiaddr('/ip4/127.0.0.1/tcp/4001').toString()
|
70 | * // '/ip4/127.0.0.1/tcp/4001'
|
71 | * ```
|
72 | */
|
73 | toString () {
|
74 | return codec.bytesToString(this.bytes)
|
75 | }
|
76 |
|
77 | /**
|
78 | * Returns Multiaddr as a JSON encoded object
|
79 | *
|
80 | * @example
|
81 | * ```js
|
82 | * JSON.stringify(new Multiaddr('/ip4/127.0.0.1/tcp/4001'))
|
83 | * // '/ip4/127.0.0.1/tcp/4001'
|
84 | * ```
|
85 | */
|
86 | toJSON () {
|
87 | return this.toString()
|
88 | }
|
89 |
|
90 | /**
|
91 | * Returns Multiaddr as a convinient options object to be used with net.createConnection
|
92 | *
|
93 | * @example
|
94 | * ```js
|
95 | * new Multiaddr('/ip4/127.0.0.1/tcp/4001').toOptions()
|
96 | * // { family: 4, host: '127.0.0.1', transport: 'tcp', port: 4001 }
|
97 | * ```
|
98 | */
|
99 | toOptions () {
|
100 | /** @type {MultiaddrObject} */
|
101 | const opts = {}
|
102 | const parsed = this.toString().split('/')
|
103 | opts.family = parsed[1] === 'ip4' ? 4 : 6
|
104 | opts.host = parsed[2]
|
105 | opts.transport = parsed[3]
|
106 | opts.port = parseInt(parsed[4])
|
107 | return opts
|
108 | }
|
109 |
|
110 | /**
|
111 | * Returns the protocols the Multiaddr is defined with, as an array of objects, in
|
112 | * left-to-right order. Each object contains the protocol code, protocol name,
|
113 | * and the size of its address space in bits.
|
114 | * [See list of protocols](https://github.com/multiformats/multiaddr/blob/master/protocols.csv)
|
115 | *
|
116 | * @example
|
117 | * ```js
|
118 | * new Multiaddr('/ip4/127.0.0.1/tcp/4001').protos()
|
119 | * // [ { code: 4, size: 32, name: 'ip4' },
|
120 | * // { code: 6, size: 16, name: 'tcp' } ]
|
121 | * ```
|
122 | *
|
123 | * @returns {Protocol[]} protocols - All the protocols the address is composed of
|
124 | */
|
125 | protos () {
|
126 | return this.protoCodes().map(code => Object.assign({}, protocols(code)))
|
127 | }
|
128 |
|
129 | /**
|
130 | * Returns the codes of the protocols in left-to-right order.
|
131 | * [See list of protocols](https://github.com/multiformats/multiaddr/blob/master/protocols.csv)
|
132 | *
|
133 | * @example
|
134 | * ```js
|
135 | * Multiaddr('/ip4/127.0.0.1/tcp/4001').protoCodes()
|
136 | * // [ 4, 6 ]
|
137 | * ```
|
138 | *
|
139 | * @returns {number[]} protocol codes
|
140 | */
|
141 | protoCodes () {
|
142 | const codes = []
|
143 | const buf = this.bytes
|
144 | let i = 0
|
145 | while (i < buf.length) {
|
146 | const code = varint.decode(buf, i)
|
147 | const n = varint.decode.bytes
|
148 |
|
149 | const p = protocols(code)
|
150 | const size = codec.sizeForAddr(p, buf.slice(i + n))
|
151 |
|
152 | i += (size + n)
|
153 | codes.push(code)
|
154 | }
|
155 |
|
156 | return codes
|
157 | }
|
158 |
|
159 | /**
|
160 | * Returns the names of the protocols in left-to-right order.
|
161 | * [See list of protocols](https://github.com/multiformats/multiaddr/blob/master/protocols.csv)
|
162 | *
|
163 | * @example
|
164 | * ```js
|
165 | * new Multiaddr('/ip4/127.0.0.1/tcp/4001').protoNames()
|
166 | * // [ 'ip4', 'tcp' ]
|
167 | * ```
|
168 | *
|
169 | * @returns {string[]} protocol names
|
170 | */
|
171 | protoNames () {
|
172 | return this.protos().map(proto => proto.name)
|
173 | }
|
174 |
|
175 | /**
|
176 | * Returns a tuple of parts
|
177 | *
|
178 | * @example
|
179 | * ```js
|
180 | * new Multiaddr("/ip4/127.0.0.1/tcp/4001").tuples()
|
181 | * // [ [ 4, <Buffer 7f 00 00 01> ], [ 6, <Buffer 0f a1> ] ]
|
182 | * ```
|
183 | */
|
184 | tuples () {
|
185 | return codec.bytesToTuples(this.bytes)
|
186 | }
|
187 |
|
188 | /**
|
189 | * Returns a tuple of string/number parts
|
190 | * - tuples[][0] = code of protocol
|
191 | * - tuples[][1] = contents of address
|
192 | *
|
193 | * @example
|
194 | * ```js
|
195 | * new Multiaddr("/ip4/127.0.0.1/tcp/4001").stringTuples()
|
196 | * // [ [ 4, '127.0.0.1' ], [ 6, '4001' ] ]
|
197 | * ```
|
198 | */
|
199 | stringTuples () {
|
200 | const t = codec.bytesToTuples(this.bytes)
|
201 | return codec.tuplesToStringTuples(t)
|
202 | }
|
203 |
|
204 | /**
|
205 | * Encapsulates a Multiaddr in another Multiaddr
|
206 | *
|
207 | * @example
|
208 | * ```js
|
209 | * const mh1 = new Multiaddr('/ip4/8.8.8.8/tcp/1080')
|
210 | * // <Multiaddr 0408080808060438 - /ip4/8.8.8.8/tcp/1080>
|
211 | *
|
212 | * const mh2 = new Multiaddr('/ip4/127.0.0.1/tcp/4001')
|
213 | * // <Multiaddr 047f000001060fa1 - /ip4/127.0.0.1/tcp/4001>
|
214 | *
|
215 | * const mh3 = mh1.encapsulate(mh2)
|
216 | * // <Multiaddr 0408080808060438047f000001060fa1 - /ip4/8.8.8.8/tcp/1080/ip4/127.0.0.1/tcp/4001>
|
217 | *
|
218 | * mh3.toString()
|
219 | * // '/ip4/8.8.8.8/tcp/1080/ip4/127.0.0.1/tcp/4001'
|
220 | * ```
|
221 | *
|
222 | * @param {MultiaddrInput} addr - Multiaddr to add into this Multiaddr
|
223 | */
|
224 | encapsulate (addr) {
|
225 | addr = new Multiaddr(addr)
|
226 | return new Multiaddr(this.toString() + addr.toString())
|
227 | }
|
228 |
|
229 | /**
|
230 | * Decapsulates a Multiaddr from another Multiaddr
|
231 | *
|
232 | * @example
|
233 | * ```js
|
234 | * const mh1 = new Multiaddr('/ip4/8.8.8.8/tcp/1080')
|
235 | * // <Multiaddr 0408080808060438 - /ip4/8.8.8.8/tcp/1080>
|
236 | *
|
237 | * const mh2 = new Multiaddr('/ip4/127.0.0.1/tcp/4001')
|
238 | * // <Multiaddr 047f000001060fa1 - /ip4/127.0.0.1/tcp/4001>
|
239 | *
|
240 | * const mh3 = mh1.encapsulate(mh2)
|
241 | * // <Multiaddr 0408080808060438047f000001060fa1 - /ip4/8.8.8.8/tcp/1080/ip4/127.0.0.1/tcp/4001>
|
242 | *
|
243 | * mh3.decapsulate(mh2).toString()
|
244 | * // '/ip4/8.8.8.8/tcp/1080'
|
245 | * ```
|
246 | *
|
247 | * @param {Multiaddr | string} addr - Multiaddr to remove from this Multiaddr
|
248 | * @returns {Multiaddr}
|
249 | */
|
250 | decapsulate (addr) {
|
251 | const addrString = addr.toString()
|
252 | const s = this.toString()
|
253 | const i = s.lastIndexOf(addrString)
|
254 | if (i < 0) {
|
255 | throw new Error('Address ' + this + ' does not contain subaddress: ' + addr)
|
256 | }
|
257 | return new Multiaddr(s.slice(0, i))
|
258 | }
|
259 |
|
260 | /**
|
261 | * A more reliable version of `decapsulate` if you are targeting a
|
262 | * specific code, such as 421 (the `p2p` protocol code). The last index of the code
|
263 | * will be removed from the `Multiaddr`, and a new instance will be returned.
|
264 | * If the code is not present, the original `Multiaddr` is returned.
|
265 | *
|
266 | * @example
|
267 | * ```js
|
268 | * const addr = new Multiaddr('/ip4/0.0.0.0/tcp/8080/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC')
|
269 | * // <Multiaddr 0400... - /ip4/0.0.0.0/tcp/8080/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC>
|
270 | *
|
271 | * addr.decapsulateCode(421).toString()
|
272 | * // '/ip4/0.0.0.0/tcp/8080'
|
273 | *
|
274 | * new Multiaddr('/ip4/127.0.0.1/tcp/8080').decapsulateCode(421).toString()
|
275 | * // '/ip4/127.0.0.1/tcp/8080'
|
276 | * ```
|
277 | *
|
278 | * @param {number} code - The code of the protocol to decapsulate from this Multiaddr
|
279 | * @returns {Multiaddr}
|
280 | */
|
281 | decapsulateCode (code) {
|
282 | const tuples = this.tuples()
|
283 | for (let i = tuples.length - 1; i >= 0; i--) {
|
284 | if (tuples[i][0] === code) {
|
285 | return new Multiaddr(codec.tuplesToBytes(tuples.slice(0, i)))
|
286 | }
|
287 | }
|
288 | return this
|
289 | }
|
290 |
|
291 | /**
|
292 | * Extract the peerId if the multiaddr contains one
|
293 | *
|
294 | * @example
|
295 | * ```js
|
296 | * const mh1 = new Multiaddr('/ip4/8.8.8.8/tcp/1080/ipfs/QmValidBase58string')
|
297 | * // <Multiaddr 0408080808060438 - /ip4/8.8.8.8/tcp/1080/ipfs/QmValidBase58string>
|
298 | *
|
299 | * // should return QmValidBase58string or null if the id is missing or invalid
|
300 | * const peerId = mh1.getPeerId()
|
301 | * ```
|
302 | *
|
303 | * @returns {string | null} peerId - The id of the peer or null if invalid or missing from the ma
|
304 | */
|
305 | getPeerId () {
|
306 | try {
|
307 | const tuples = this.stringTuples().filter((tuple) => {
|
308 | if (tuple[0] === protocols.names.ipfs.code) {
|
309 | return true
|
310 | }
|
311 | return false
|
312 | })
|
313 |
|
314 | // Get the last ipfs tuple ['ipfs', 'peerid string']
|
315 | const tuple = tuples.pop()
|
316 | if (tuple && tuple[1]) {
|
317 | const peerIdStr = tuple[1]
|
318 |
|
319 | // peer id is base58btc encoded string but not multibase encoded so add the `z`
|
320 | // prefix so we can validate that it is correctly encoded
|
321 | if (peerIdStr[0] === 'Q' || peerIdStr[0] === '1') {
|
322 | return uint8ArrayToString(base58btc.decode(`z${peerIdStr}`), 'base58btc')
|
323 | }
|
324 |
|
325 | // try to parse peer id as CID
|
326 | return uint8ArrayToString(CID.parse(peerIdStr).multihash.bytes, 'base58btc')
|
327 | }
|
328 |
|
329 | return null
|
330 | } catch (e) {
|
331 | return null
|
332 | }
|
333 | }
|
334 |
|
335 | /**
|
336 | * Extract the path if the multiaddr contains one
|
337 | *
|
338 | * @example
|
339 | * ```js
|
340 | * const mh1 = new Multiaddr('/ip4/8.8.8.8/tcp/1080/unix/tmp/p2p.sock')
|
341 | * // <Multiaddr 0408080808060438 - /ip4/8.8.8.8/tcp/1080/unix/tmp/p2p.sock>
|
342 | *
|
343 | * // should return utf8 string or null if the id is missing or invalid
|
344 | * const path = mh1.getPath()
|
345 | * ```js
|
346 | *
|
347 | * @returns {string | null} path - The path of the multiaddr, or null if no path protocol is present
|
348 | */
|
349 | getPath () {
|
350 | let path = null
|
351 | try {
|
352 | path = this.stringTuples().filter((tuple) => {
|
353 | const proto = protocols(tuple[0])
|
354 | if (proto.path) {
|
355 | return true
|
356 | }
|
357 | return false
|
358 | })[0][1]
|
359 |
|
360 | if (!path) {
|
361 | path = null
|
362 | }
|
363 | } catch (e) {
|
364 | path = null
|
365 | }
|
366 | return path
|
367 | }
|
368 |
|
369 | /**
|
370 | * Checks if two Multiaddrs are the same
|
371 | *
|
372 | * @example
|
373 | * ```js
|
374 | * const mh1 = new Multiaddr('/ip4/8.8.8.8/tcp/1080')
|
375 | * // <Multiaddr 0408080808060438 - /ip4/8.8.8.8/tcp/1080>
|
376 | *
|
377 | * const mh2 = new Multiaddr('/ip4/127.0.0.1/tcp/4001')
|
378 | * // <Multiaddr 047f000001060fa1 - /ip4/127.0.0.1/tcp/4001>
|
379 | *
|
380 | * mh1.equals(mh1)
|
381 | * // true
|
382 | *
|
383 | * mh1.equals(mh2)
|
384 | * // false
|
385 | * ```
|
386 | *
|
387 | * @param {Multiaddr} addr
|
388 | * @returns {boolean}
|
389 | */
|
390 | equals (addr) {
|
391 | return uint8ArrayEquals(this.bytes, addr.bytes)
|
392 | }
|
393 |
|
394 | /**
|
395 | * Resolve multiaddr if containing resolvable hostname.
|
396 | *
|
397 | * @example
|
398 | * ```js
|
399 | * Multiaddr.resolvers.set('dnsaddr', resolverFunction)
|
400 | * const mh1 = new Multiaddr('/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb')
|
401 | * const resolvedMultiaddrs = await mh1.resolve()
|
402 | * // [
|
403 | * // <Multiaddr 04934b5353060fa1a503221220c10f9319dac35c270a6b74cd644cb3acfc1f6efc8c821f8eb282599fd1814f64 - /ip4/147.75.83.83/tcp/4001/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb>,
|
404 | * // <Multiaddr 04934b53530601bbde03a503221220c10f9319dac35c270a6b74cd644cb3acfc1f6efc8c821f8eb282599fd1814f64 - /ip4/147.75.83.83/tcp/443/wss/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb>,
|
405 | * // <Multiaddr 04934b535391020fa1cc03a503221220c10f9319dac35c270a6b74cd644cb3acfc1f6efc8c821f8eb282599fd1814f64 - /ip4/147.75.83.83/udp/4001/quic/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb>
|
406 | * // ]
|
407 | * ```
|
408 | *
|
409 | * @returns {Promise<Array<Multiaddr>>}
|
410 | */
|
411 | async resolve () {
|
412 | const resolvableProto = this.protos().find((p) => p.resolvable)
|
413 |
|
414 | // Multiaddr is not resolvable?
|
415 | if (!resolvableProto) {
|
416 | return [this]
|
417 | }
|
418 |
|
419 | const resolver = resolvers.get(resolvableProto.name)
|
420 | if (!resolver) {
|
421 | throw errCode(new Error(`no available resolver for ${resolvableProto.name}`), 'ERR_NO_AVAILABLE_RESOLVER')
|
422 | }
|
423 |
|
424 | const addresses = await resolver(this)
|
425 | return addresses.map((a) => new Multiaddr(a))
|
426 | }
|
427 |
|
428 | /**
|
429 | * Gets a Multiaddrs node-friendly address object. Note that protocol information
|
430 | * is left out: in Node (and most network systems) the protocol is unknowable
|
431 | * given only the address.
|
432 | *
|
433 | * Has to be a ThinWaist Address, otherwise throws error
|
434 | *
|
435 | * @example
|
436 | * ```js
|
437 | * new Multiaddr('/ip4/127.0.0.1/tcp/4001').nodeAddress()
|
438 | * // {family: 4, address: '127.0.0.1', port: 4001}
|
439 | * ```
|
440 | *
|
441 | * @returns {{family: 4 | 6, address: string, port: number}}
|
442 | * @throws {Error} Throws error if Multiaddr is not a Thin Waist address
|
443 | */
|
444 | nodeAddress () {
|
445 | const codes = this.protoCodes()
|
446 | const names = this.protoNames()
|
447 | const parts = this.toString().split('/').slice(1)
|
448 |
|
449 | if (parts.length < 4) {
|
450 | throw new Error('multiaddr must have a valid format: "/{ip4, ip6, dns4, dns6}/{address}/{tcp, udp}/{port}".')
|
451 | } else if (codes[0] !== 4 && codes[0] !== 41 && codes[0] !== 54 && codes[0] !== 55) {
|
452 | throw new Error(`no protocol with name: "'${names[0]}'". Must have a valid family name: "{ip4, ip6, dns4, dns6}".`)
|
453 | } else if (parts[2] !== 'tcp' && parts[2] !== 'udp') {
|
454 | throw new Error(`no protocol with name: "'${names[1]}'". Must have a valid transport protocol: "{tcp, udp}".`)
|
455 | }
|
456 |
|
457 | return {
|
458 | family: (codes[0] === 41 || codes[0] === 55) ? 6 : 4,
|
459 | address: parts[1],
|
460 | port: parseInt(parts[3]) // tcp or udp port
|
461 | }
|
462 | }
|
463 |
|
464 | /**
|
465 | * Returns if a Multiaddr is a Thin Waist address or not.
|
466 | *
|
467 | * Thin Waist is if a Multiaddr adheres to the standard combination of:
|
468 | *
|
469 | * `{IPv4, IPv6}/{TCP, UDP}`
|
470 | *
|
471 | * @example
|
472 | * ```js
|
473 | * const mh1 = new Multiaddr('/ip4/127.0.0.1/tcp/4001')
|
474 | * // <Multiaddr 047f000001060fa1 - /ip4/127.0.0.1/tcp/4001>
|
475 | * const mh2 = new Multiaddr('/ip4/192.168.2.1/tcp/5001')
|
476 | * // <Multiaddr 04c0a80201061389 - /ip4/192.168.2.1/tcp/5001>
|
477 | * const mh3 = mh1.encapsulate(mh2)
|
478 | * // <Multiaddr 047f000001060fa104c0a80201061389 - /ip4/127.0.0.1/tcp/4001/ip4/192.168.2.1/tcp/5001>
|
479 | * const mh4 = new Multiaddr('/ip4/127.0.0.1/tcp/2000/wss/p2p-webrtc-star/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSooo2a')
|
480 | * // <Multiaddr 047f0000010607d0de039302a503221220d52ebb89d85b02a284948203a62ff28389c57c9f42beec4ec20db76a64835843 - /ip4/127.0.0.1/tcp/2000/wss/p2p-webrtc-star/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSooo2a>
|
481 | * mh1.isThinWaistAddress()
|
482 | * // true
|
483 | * mh2.isThinWaistAddress()
|
484 | * // true
|
485 | * mh3.isThinWaistAddress()
|
486 | * // false
|
487 | * mh4.isThinWaistAddress()
|
488 | * // false
|
489 | * ```
|
490 | *
|
491 | * @param {Multiaddr} [addr] - Defaults to using `this` instance
|
492 | */
|
493 | isThinWaistAddress (addr) {
|
494 | const protos = (addr || this).protos()
|
495 |
|
496 | if (protos.length !== 2) {
|
497 | return false
|
498 | }
|
499 |
|
500 | if (protos[0].code !== 4 && protos[0].code !== 41) {
|
501 | return false
|
502 | }
|
503 | if (protos[1].code !== 6 && protos[1].code !== 273) {
|
504 | return false
|
505 | }
|
506 | return true
|
507 | }
|
508 |
|
509 | /**
|
510 | * Creates a Multiaddr from a node-friendly address object
|
511 | *
|
512 | * @example
|
513 | * ```js
|
514 | * Multiaddr.fromNodeAddress({address: '127.0.0.1', port: '4001'}, 'tcp')
|
515 | * // <Multiaddr 047f000001060fa1 - /ip4/127.0.0.1/tcp/4001>
|
516 | * ```
|
517 | *
|
518 | * @param {{family: 4 | 6, address: string, port: number}} addr
|
519 | * @param {string} transport
|
520 | */
|
521 | static fromNodeAddress (addr, transport) {
|
522 | if (!addr) { throw new Error('requires node address object') }
|
523 | if (!transport) { throw new Error('requires transport protocol') }
|
524 | let ip
|
525 | switch (addr.family) {
|
526 | case 4:
|
527 | ip = 'ip4'
|
528 | break
|
529 | case 6:
|
530 | ip = 'ip6'
|
531 | break
|
532 | default:
|
533 | throw Error(`Invalid addr family. Got '${addr.family}' instead of 4 or 6`)
|
534 | }
|
535 | return new Multiaddr('/' + [ip, addr.address, transport, addr.port].join('/'))
|
536 | }
|
537 |
|
538 | /**
|
539 | * Returns if something is a Multiaddr that is a name
|
540 | *
|
541 | * @param {Multiaddr} addr
|
542 | * @returns {boolean} isName
|
543 | */
|
544 | static isName (addr) {
|
545 | if (!Multiaddr.isMultiaddr(addr)) {
|
546 | return false
|
547 | }
|
548 |
|
549 | // if a part of the multiaddr is resolvable, then return true
|
550 | return addr.protos().some((proto) => proto.resolvable)
|
551 | }
|
552 |
|
553 | /**
|
554 | * Check if object is a CID instance
|
555 | *
|
556 | * @param {any} value
|
557 | * @returns {value is Multiaddr}
|
558 | */
|
559 | static isMultiaddr (value) {
|
560 | return value instanceof Multiaddr || Boolean(value && value[symbol])
|
561 | }
|
562 |
|
563 | /**
|
564 | * Returns Multiaddr as a human-readable string.
|
565 | * For post Node.js v10.0.0.
|
566 | * https://nodejs.org/api/deprecations.html#deprecations_dep0079_custom_inspection_function_on_objects_via_inspect
|
567 | *
|
568 | * @example
|
569 | * ```js
|
570 | * console.log(new Multiaddr('/ip4/127.0.0.1/tcp/4001'))
|
571 | * // '<Multiaddr 047f000001060fa1 - /ip4/127.0.0.1/tcp/4001>'
|
572 | * ```
|
573 | *
|
574 | * @returns {string}
|
575 | */
|
576 | [inspect] () {
|
577 | return '<Multiaddr ' +
|
578 | uint8ArrayToString(this.bytes, 'base16') + ' - ' +
|
579 | codec.bytesToString(this.bytes) + '>'
|
580 | }
|
581 |
|
582 | /**
|
583 | * Returns Multiaddr as a human-readable string.
|
584 | * Fallback for pre Node.js v10.0.0.
|
585 | * https://nodejs.org/api/deprecations.html#deprecations_dep0079_custom_inspection_function_on_objects_via_inspect
|
586 | *
|
587 | * @example
|
588 | * ```js
|
589 | * new Multiaddr('/ip4/127.0.0.1/tcp/4001').inspect()
|
590 | * // '<Multiaddr 047f000001060fa1 - /ip4/127.0.0.1/tcp/4001>'
|
591 | * ```
|
592 | *
|
593 | * @returns {string}
|
594 | */
|
595 | inspect () {
|
596 | return '<Multiaddr ' +
|
597 | uint8ArrayToString(this.bytes, 'base16') + ' - ' +
|
598 | codec.bytesToString(this.bytes) + '>'
|
599 | }
|
600 | }
|
601 |
|
602 | /**
|
603 | * Object containing table, names and codes of all supported protocols.
|
604 | * To get the protocol values from a Multiaddr, you can use
|
605 | * [`.protos()`](#multiaddrprotos),
|
606 | * [`.protoCodes()`](#multiaddrprotocodes) or
|
607 | * [`.protoNames()`](#multiaddrprotonames)
|
608 | *
|
609 | * @returns {{table: Array, names: Object, codes: Object}}
|
610 | */
|
611 | Multiaddr.protocols = protocols
|
612 |
|
613 | Multiaddr.resolvers = resolvers
|
614 |
|
615 | /**
|
616 | * Static factory
|
617 | *
|
618 | * @param {MultiaddrInput} addr
|
619 | */
|
620 | function multiaddr (addr) {
|
621 | return new Multiaddr(addr)
|
622 | }
|
623 |
|
624 | module.exports = { Multiaddr, multiaddr, protocols, resolvers }
|