@multiformats/multiaddr
Version:
The JavaScript implementation of the Multiaddr spec
306 lines (285 loc) • 7.85 kB
text/typescript
/**
* @packageDocumentation
*
* A standard way to represent addresses that
*
* - support any standard network protocol
* - have a binary packed format
* - have a nice string representation
* - encapsulate well
*
* @example
*
* ```TypeScript
* import { multiaddr } from '@multiformats/multiaddr'
*
* const addr = multiaddr('/ip4/127.0.0.1/udp/1234')
* // Multiaddr(/ip4/127.0.0.1/udp/1234)
*
* addr.bytes
* // <Uint8Array 04 7f 00 00 01 11 04 d2>
*
* addr.toString()
* // '/ip4/127.0.0.1/udp/1234'
*
* addr.getComponents()
* // [
* // { code: 4, name: 'ip4', value: '127.0.0.1' },
* // { code: 273, name: 'udp', value: '1234' }
* // ]
*
* addr.encapsulate('/sctp/5678')
* // Multiaddr(/ip4/127.0.0.1/udp/1234/sctp/5678)
* ```
*
* @example Adding custom protocols
*
* To add application-specific or experimental protocols, add a protocol codec
* to the protocol registry:
*
* ```ts
* import { registry, V, multiaddr } from '@multiformats/multiaddr'
* import type { ProtocolCodec } from '@multiformats/multiaddr'
*
* const maWithCustomTuple = '/custom-protocol/hello'
*
* // throws UnknownProtocolError
* multiaddr(maWithCustomTuple)
*
* const protocol: ProtocolCodec = {
* code: 2059,
* name: 'custom-protocol',
* size: V
* // V means variable length, can also be 0, a positive integer (e.g. a fixed
* // length or omitted
* }
*
* registry.addProtocol(protocol)
*
* // does not throw UnknownProtocolError
* multiaddr(maWithCustomTuple)
*
* // protocols can also be removed
* registry.removeProtocol(protocol.code)
* ```
*/
import { Multiaddr as MultiaddrClass, symbol } from './multiaddr.js'
import { registry, V } from './registry.ts'
import type { ProtocolCodec } from './registry.ts'
/**
* The protocol registry stores protocol codecs that allow transformation of
* multiaddr tuples from bytes to string and back again, and also validation of
* the address values.
*/
export interface Registry {
/**
* Retrieve a protocol definition by it's code or name
*/
getProtocol (key: string | number): ProtocolCodec
/**
* Add a new protocol definition
*/
addProtocol (codec: ProtocolCodec): void
/**
* Remove a protocol definition by it's code
*/
removeProtocol (code: number): void
}
/**
* These types can be parsed into a {@link Multiaddr} object
*/
export type MultiaddrInput = string | Multiaddr | Uint8Array | null | Component[]
/**
* A Component is a section of a multiaddr with a name/code, possibly with a
* value.
*
* Component names/codes are defined in the protocol table.
*
* @see https://github.com/multiformats/multiaddr/blob/master/protocols.csv
*/
export interface Component {
/**
* The code of the component as defined in the protocol table
*/
code: number
/**
* The name of the component as defined in the protocol table
*/
name: string
/**
* The component value, if one is present
*/
value?: string
/**
* The bytes that make up the component. This will be set if the multiaddr
* was parsed from a `Uint8Array`, or if `.bytes` has been accessed on it.
*/
bytes?: Uint8Array
}
export interface Multiaddr {
bytes: Uint8Array
/**
* Returns Multiaddr as a String
*
* @example
* ```js
* import { multiaddr } from '@multiformats/multiaddr'
*
* multiaddr('/ip4/127.0.0.1/tcp/4001').toString()
* // '/ip4/127.0.0.1/tcp/4001'
* ```
*/
toString(): string
/**
* Returns Multiaddr as a JSON encoded object
*
* @example
* ```js
* import { multiaddr } from '@multiformats/multiaddr'
*
* JSON.stringify(multiaddr('/ip4/127.0.0.1/tcp/4001'))
* // '/ip4/127.0.0.1/tcp/4001'
* ```
*/
toJSON(): string
/**
* Returns the components that make up this Multiaddr
*
* @example
* ```ts
* import { multiaddr } from '@multiformats/multiaddr'
*
* multiaddr('/ip4/127.0.0.1/tcp/4001').getComponents()
* // [{ name: 'ip4', code: 4, value: '127.0.0.1' }, { name: 'tcp', code: 6, value: '4001' }]
* ```
*/
getComponents(): Component[]
/**
* Encapsulates a Multiaddr in another Multiaddr
*
* @example
* ```js
* import { multiaddr } from '@multiformats/multiaddr'
*
* const mh1 = multiaddr('/ip4/8.8.8.8/tcp/1080')
* // Multiaddr(/ip4/8.8.8.8/tcp/1080)
*
* const mh2 = multiaddr('/ip4/127.0.0.1/tcp/4001')
* // Multiaddr(/ip4/127.0.0.1/tcp/4001)
*
* const mh3 = mh1.encapsulate(mh2)
* // Multiaddr(/ip4/8.8.8.8/tcp/1080/ip4/127.0.0.1/tcp/4001)
*
* mh3.toString()
* // '/ip4/8.8.8.8/tcp/1080/ip4/127.0.0.1/tcp/4001'
* ```
*
* @param {MultiaddrInput} addr - Multiaddr to add into this Multiaddr
*/
encapsulate(addr: MultiaddrInput): Multiaddr
/**
* Decapsulates a Multiaddr from another Multiaddr
*
* @example
* ```js
* import { multiaddr } from '@multiformats/multiaddr'
*
* const mh1 = multiaddr('/ip4/8.8.8.8/tcp/1080')
* // Multiaddr(/ip4/8.8.8.8/tcp/1080)
*
* const mh2 = multiaddr('/ip4/127.0.0.1/tcp/4001')
* // Multiaddr(/ip4/127.0.0.1/tcp/4001)
*
* const mh3 = mh1.encapsulate(mh2)
* // Multiaddr(/ip4/8.8.8.8/tcp/1080/ip4/127.0.0.1/tcp/4001)
*
* mh3.decapsulate(mh2).toString()
* // '/ip4/8.8.8.8/tcp/1080'
* ```
*
* @param {Multiaddr | string} addr - Multiaddr to remove from this Multiaddr
*/
decapsulate(addr: Multiaddr | string): Multiaddr
/**
* A more reliable version of `decapsulate` if you are targeting a specific
* code, such as 421 (the `p2p` protocol code). The last index of the code
* will be removed from the `Multiaddr`, and a new instance will be returned.
* If the code is not present, the original `Multiaddr` is returned.
*
* @example
* ```js
* import { multiaddr } from '@multiformats/multiaddr'
*
* const addr = multiaddr('/ip4/0.0.0.0/tcp/8080/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC')
* // Multiaddr(/ip4/0.0.0.0/tcp/8080/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC)
*
* addr.decapsulateCode(421).toString()
* // '/ip4/0.0.0.0/tcp/8080'
*
* multiaddr('/ip4/127.0.0.1/tcp/8080').decapsulateCode(421).toString()
* // '/ip4/127.0.0.1/tcp/8080'
* ```
*/
decapsulateCode(code: number): Multiaddr
/**
* Checks if two Multiaddrs are the same
*
* @example
* ```js
* import { multiaddr } from '@multiformats/multiaddr'
*
* const mh1 = multiaddr('/ip4/8.8.8.8/tcp/1080')
* // Multiaddr(/ip4/8.8.8.8/tcp/1080)
*
* const mh2 = multiaddr('/ip4/127.0.0.1/tcp/4001')
* // Multiaddr(/ip4/127.0.0.1/tcp/4001)
*
* mh1.equals(mh1)
* // true
*
* mh1.equals(mh2)
* // false
* ```
*/
equals(addr: { bytes: Uint8Array }): boolean
}
/**
* Check if object is a {@link Multiaddr} instance
*
* @example
*
* ```js
* import { isMultiaddr, multiaddr } from '@multiformats/multiaddr'
*
* isMultiaddr(5)
* // false
* isMultiaddr(multiaddr('/ip4/127.0.0.1'))
* // true
* ```
*/
export function isMultiaddr (value: any): value is Multiaddr {
return Boolean(value?.[symbol])
}
/**
* A function that takes a {@link MultiaddrInput} and returns a {@link Multiaddr}
*
* @example
* ```js
* import { multiaddr } from '@libp2p/multiaddr'
*
* multiaddr('/ip4/127.0.0.1/tcp/4001')
* // Multiaddr(/ip4/127.0.0.1/tcp/4001)
* ```
*
* @param {MultiaddrInput} [addr] - If String or Uint8Array, needs to adhere to the address format of a [multiaddr](https://github.com/multiformats/multiaddr#string-format)
*/
export function multiaddr (addr?: MultiaddrInput): Multiaddr {
return new MultiaddrClass(addr)
}
/**
* Export all table.csv codes. These are all named exports so can be tree-shaken
* out by bundlers.
*/
export * from './constants.ts'
export { registry, V }
export type { ProtocolCodec }