@waku/relay
Version:
Relay Protocol for Waku
1,665 lines (1,640 loc) • 1.74 MB
JavaScript
const connectionSymbol = Symbol.for('@libp2p/connection');
/**
* Any object that implements this Symbol as a property should return a
* Partial<ContentRouting> instance as the property value, similar to how
* `Symbol.Iterable` can be used to return an `Iterable` from an `Iterator`.
*
* @example
*
* ```TypeScript
* import { contentRoutingSymbol, ContentRouting } from '@libp2p/content-routing'
*
* class MyContentRouter implements ContentRouting {
* get [contentRoutingSymbol] () {
* return this
* }
*
* // ...other methods
* }
* ```
*/
const contentRoutingSymbol = Symbol.for('@libp2p/content-routing');
/**
* Any object that implements this Symbol as a property should return a
* PeerDiscovery instance as the property value, similar to how
* `Symbol.Iterable` can be used to return an `Iterable` from an `Iterator`.
*
* @example
*
* ```TypeScript
* import { peerDiscovery, PeerDiscovery } from '@libp2p/peer-discovery'
*
* class MyPeerDiscoverer implements PeerDiscovery {
* get [peerDiscovery] () {
* return this
* }
*
* // ...other methods
* }
* ```
*/
const peerDiscoverySymbol = Symbol.for('@libp2p/peer-discovery');
/**
* All PeerId implementations must use this symbol as the name of a property
* with a boolean `true` value
*/
const peerIdSymbol = Symbol.for('@libp2p/peer-id');
/**
* Returns true if the passed argument is a PeerId implementation
*/
function isPeerId(other) {
return Boolean(other?.[peerIdSymbol]);
}
/**
* Any object that implements this Symbol as a property should return a
* PeerRouting instance as the property value, similar to how `Symbol.Iterable`
* can be used to return an `Iterable` from an `Iterator`.
*
* @example
*
* ```TypeScript
* import { peerRouting, PeerRouting } from '@libp2p/peer-routing'
*
* class MyPeerRouter implements PeerRouting {
* get [peerRouting] () {
* return this
* }
*
* // ...other methods
* }
* ```
*/
const peerRoutingSymbol = Symbol.for('@libp2p/peer-routing');
/**
* When a peer that is tagged with this prefix disconnects, we will attempt to
* redial it, up to a limit.
*
* To allow multiple components to add/remove their own keep-alive tags without
* accidentally overwriting those of other components, attach a unique suffix to
* the tag, e.g. `keep-alive-circuit-relay` or `keep-alive-kad-dht`, etc.
*/
const KEEP_ALIVE = 'keep-alive';
/**
* On the producing side:
* - Build messages with the signature, key (from may be enough for certain inlineable public key types), from and seqno fields.
*
* On the consuming side:
* - Enforce the fields to be present, reject otherwise.
* - Propagate only if the fields are valid and signature can be verified, reject otherwise.
*/
const StrictSign = 'StrictSign';
/**
* On the producing side:
* - Build messages without the signature, key, from and seqno fields.
* - The corresponding protobuf key-value pairs are absent from the marshaled message, not just empty.
*
* On the consuming side:
* - Enforce the fields to be absent, reject otherwise.
* - Propagate only if the fields are absent, reject otherwise.
* - A message_id function will not be able to use the above fields, and should instead rely on the data field. A commonplace strategy is to calculate a hash.
*/
const StrictNoSign = 'StrictNoSign';
var TopicValidatorResult;
(function (TopicValidatorResult) {
/**
* The message is considered valid, and it should be delivered and forwarded to the network
*/
TopicValidatorResult["Accept"] = "accept";
/**
* The message is neither delivered nor forwarded to the network
*/
TopicValidatorResult["Ignore"] = "ignore";
/**
* The message is considered invalid, and it should be rejected
*/
TopicValidatorResult["Reject"] = "reject";
})(TopicValidatorResult || (TopicValidatorResult = {}));
const transportSymbol = Symbol.for('@libp2p/transport');
/**
* Enum Transport Manager Fault Tolerance values
*/
var FaultTolerance;
(function (FaultTolerance) {
/**
* should be used for failing in any listen circumstance
*/
FaultTolerance[FaultTolerance["FATAL_ALL"] = 0] = "FATAL_ALL";
/**
* should be used for not failing when not listening
*/
FaultTolerance[FaultTolerance["NO_FATAL"] = 1] = "NO_FATAL";
})(FaultTolerance || (FaultTolerance = {}));
/**
* When this error is thrown it means an operation was aborted,
* usually in response to the `abort` event being emitted by an
* AbortSignal.
*/
let AbortError$6 = class AbortError extends Error {
static name = 'AbortError';
constructor(message = 'The operation was aborted') {
super(message);
this.name = 'AbortError';
}
};
/**
* Thrown when a remote Peer ID does not match the expected one
*/
class UnexpectedPeerError extends Error {
static name = 'UnexpectedPeerError';
constructor(message = 'Unexpected Peer') {
super(message);
this.name = 'UnexpectedPeerError';
}
}
/**
* Thrown when a crypto exchange fails
*/
let InvalidCryptoExchangeError$1 = class InvalidCryptoExchangeError extends Error {
static name = 'InvalidCryptoExchangeError';
constructor(message = 'Invalid crypto exchange') {
super(message);
this.name = 'InvalidCryptoExchangeError';
}
};
/**
* Thrown when invalid parameters are passed to a function or method call
*/
let InvalidParametersError$1 = class InvalidParametersError extends Error {
static name = 'InvalidParametersError';
constructor(message = 'Invalid parameters') {
super(message);
this.name = 'InvalidParametersError';
}
};
/**
* Thrown when a public key is invalid
*/
class InvalidPublicKeyError extends Error {
static name = 'InvalidPublicKeyError';
constructor(message = 'Invalid public key') {
super(message);
this.name = 'InvalidPublicKeyError';
}
}
/**
* Thrown when a connection is closing
*/
class ConnectionClosingError extends Error {
static name = 'ConnectionClosingError';
constructor(message = 'The connection is closing') {
super(message);
this.name = 'ConnectionClosingError';
}
}
/**
* Thrown when a connection is closed
*/
class ConnectionClosedError extends Error {
static name = 'ConnectionClosedError';
constructor(message = 'The connection is closed') {
super(message);
this.name = 'ConnectionClosedError';
}
}
/**
* Thrown when a connection fails
*/
class ConnectionFailedError extends Error {
static name = 'ConnectionFailedError';
constructor(message = 'Connection failed') {
super(message);
this.name = 'ConnectionFailedError';
}
}
/**
* Thrown when the muxer is closed and an attempt to open a stream occurs
*/
class MuxerClosedError extends Error {
static name = 'MuxerClosedError';
constructor(message = 'The muxer is closed') {
super(message);
this.name = 'MuxerClosedError';
}
}
/**
* Thrown when a protocol stream is reset by the remote muxer
*/
class StreamResetError extends Error {
static name = 'StreamResetError';
constructor(message = 'The stream has been reset') {
super(message);
this.name = 'StreamResetError';
}
}
/**
* Thrown when a stream is in an invalid state
*/
class StreamStateError extends Error {
static name = 'StreamStateError';
constructor(message = 'The stream is in an invalid state') {
super(message);
this.name = 'StreamStateError';
}
}
/**
* Thrown when a value could not be found
*/
let NotFoundError$1 = class NotFoundError extends Error {
static name = 'NotFoundError';
constructor(message = 'Not found') {
super(message);
this.name = 'NotFoundError';
}
};
/**
* Thrown when an invalid peer ID is encountered
*/
class InvalidPeerIdError extends Error {
static name = 'InvalidPeerIdError';
constructor(message = 'Invalid PeerID') {
super(message);
this.name = 'InvalidPeerIdError';
}
}
/**
* Thrown when an invalid multiaddr is encountered
*/
let InvalidMultiaddrError$1 = class InvalidMultiaddrError extends Error {
static name = 'InvalidMultiaddrError';
constructor(message = 'Invalid multiaddr') {
super(message);
this.name = 'InvalidMultiaddrError';
}
};
/**
* Thrown when an invalid CID is encountered
*/
class InvalidCIDError extends Error {
static name = 'InvalidCIDError';
constructor(message = 'Invalid CID') {
super(message);
this.name = 'InvalidCIDError';
}
}
/**
* Thrown when an invalid multihash is encountered
*/
class InvalidMultihashError extends Error {
static name = 'InvalidMultihashError';
constructor(message = 'Invalid Multihash') {
super(message);
this.name = 'InvalidMultihashError';
}
}
/**
* Thrown when a protocol is not supported
*/
class UnsupportedProtocolError extends Error {
static name = 'UnsupportedProtocolError';
constructor(message = 'Unsupported protocol error') {
super(message);
this.name = 'UnsupportedProtocolError';
}
}
/**
* An invalid or malformed message was encountered during a protocol exchange
*/
class InvalidMessageError extends Error {
static name = 'InvalidMessageError';
constructor(message = 'Invalid message') {
super(message);
this.name = 'InvalidMessageError';
}
}
/**
* Thrown when a remote peer sends a structurally valid message that does not
* comply with the protocol
*/
let ProtocolError$1 = class ProtocolError extends Error {
static name = 'ProtocolError';
constructor(message = 'Protocol error') {
super(message);
this.name = 'ProtocolError';
}
};
/**
* Throw when an operation times out
*/
let TimeoutError$1 = class TimeoutError extends Error {
static name = 'TimeoutError';
constructor(message = 'Timed out') {
super(message);
this.name = 'TimeoutError';
}
};
/**
* Thrown when a startable component is interacted with but it has not been
* started yet
*/
class NotStartedError extends Error {
static name = 'NotStartedError';
constructor(message = 'Not started') {
super(message);
this.name = 'NotStartedError';
}
}
/**
* Thrown when dialing an address failed
*/
class DialError extends Error {
static name = 'DialError';
constructor(message = 'Dial error') {
super(message);
this.name = 'DialError';
}
}
/**
* This error is thrown when a limited connection is encountered, i.e. if the
* user tried to open a stream on a connection for a protocol that is not
* configured to run over limited connections.
*/
class LimitedConnectionError extends Error {
static name = 'LimitedConnectionError';
constructor(message = 'Limited connection') {
super(message);
this.name = 'LimitedConnectionError';
}
}
/**
* This error is thrown where there are too many inbound protocols streams open
*/
class TooManyInboundProtocolStreamsError extends Error {
static name = 'TooManyInboundProtocolStreamsError';
constructor(message = 'Too many inbound protocol streams') {
super(message);
this.name = 'TooManyInboundProtocolStreamsError';
}
}
/**
* This error is thrown where there are too many outbound protocols streams open
*/
class TooManyOutboundProtocolStreamsError extends Error {
static name = 'TooManyOutboundProtocolStreamsError';
constructor(message = 'Too many outbound protocol streams') {
super(message);
this.name = 'TooManyOutboundProtocolStreamsError';
}
}
/**
* Thrown when an attempt to operate on an unsupported key was made
*/
class UnsupportedKeyTypeError extends Error {
static name = 'UnsupportedKeyTypeError';
constructor(message = 'Unsupported key type') {
super(message);
this.name = 'UnsupportedKeyTypeError';
}
}
/**
* Noop for browser compatibility
*/
function setMaxListeners() { }
/**
* @packageDocumentation
*
* Adds types to the EventTarget class.
*
* Hopefully this won't be necessary
* forever:
*
* - https://github.com/microsoft/TypeScript/issues/28357
* - https://github.com/microsoft/TypeScript/issues/43477
* - https://github.com/microsoft/TypeScript/issues/299
* - https://www.npmjs.com/package/typed-events
* - https://www.npmjs.com/package/typed-event-emitter
* - https://www.npmjs.com/package/typed-event-target
* - etc
*
* In addition to types, a `safeDispatchEvent` method is available which
* prevents dispatching events that aren't in the event map, and a
* `listenerCount` method which reports the number of listeners that are
* currently registered for a given event.
*
* @example
*
* ```ts
* import { TypedEventEmitter } from 'main-event'
* import type { TypedEventTarget } from 'main-event'
*
* interface EventTypes {
* 'test': CustomEvent<string>
* }
*
* const target = new TypedEventEmitter<EventTypes>()
*
* // it's a regular EventTarget
* console.info(target instanceof EventTarget) // true
*
* // register listeners normally
* target.addEventListener('test', (evt) => {
* // evt is CustomEvent<string>
* })
*
* // @ts-expect-error 'derp' is not in the event map
* target.addEventListener('derp', () => {})
*
* // use normal dispatchEvent method
* target.dispatchEvent(new CustomEvent('test', {
* detail: 'hello'
* }))
*
* // use type safe dispatch method
* target.safeDispatchEvent('test', {
* detail: 'world'
* })
*
* // report listener count
* console.info(target.listenerCount('test')) // 0
*
* // event emitters can be used purely as interfaces too
* function acceptTarget (target: TypedEventTarget<EventTypes>) {
* // ...
* }
* ```
*/
/**
* An implementation of a typed event target
*/
class TypedEventEmitter extends EventTarget {
#listeners = new Map();
constructor() {
super();
}
listenerCount(type) {
const listeners = this.#listeners.get(type);
if (listeners == null) {
return 0;
}
return listeners.length;
}
addEventListener(type, listener, options) {
super.addEventListener(type, listener, options);
let list = this.#listeners.get(type);
if (list == null) {
list = [];
this.#listeners.set(type, list);
}
list.push({
callback: listener,
once: (options !== true && options !== false && options?.once) ?? false
});
}
removeEventListener(type, listener, options) {
super.removeEventListener(type.toString(), listener ?? null, options);
let list = this.#listeners.get(type);
if (list == null) {
return;
}
list = list.filter(({ callback }) => callback !== listener);
this.#listeners.set(type, list);
}
dispatchEvent(event) {
const result = super.dispatchEvent(event);
let list = this.#listeners.get(event.type);
if (list == null) {
return result;
}
list = list.filter(({ once }) => !once);
this.#listeners.set(event.type, list);
return result;
}
safeDispatchEvent(type, detail = {}) {
return this.dispatchEvent(new CustomEvent(type, detail));
}
}
/**
* Returns `true` if the object has type overlap with `Startable`
*/
function isStartable(obj) {
return obj != null && typeof obj.start === 'function' && typeof obj.stop === 'function';
}
/**
* A function that can be used to start and objects passed to it. This checks
* that an object is startable before invoking its lifecycle methods so it is
* safe to pass non-`Startable`s in.
*
* @example
*
* ```TypeScript
* import { start } from '@libp2p/interface'
* import type { Startable } from '@libp2p/interface'
*
* const startable: Startable = {
* start: () => {},
* stop: () => {}
* }
*
* const notStartable = 5
*
* await start(
* startable,
* notStartable
* )
* ```
*/
async function start(...objs) {
const startables = [];
for (const obj of objs) {
if (isStartable(obj)) {
startables.push(obj);
}
}
await Promise.all(startables.map(async (s) => {
if (s.beforeStart != null) {
await s.beforeStart();
}
}));
await Promise.all(startables.map(async (s) => {
await s.start();
}));
await Promise.all(startables.map(async (s) => {
if (s.afterStart != null) {
await s.afterStart();
}
}));
}
/**
* A function that can be used to stop and objects passed to it. This checks
* that an object is startable before invoking its lifecycle methods so it is
* safe to pass non-`Startable`s in.
*
* @example
*
* ```TypeScript
* import { stop } from '@libp2p/interface'
* import type { Startable } from '@libp2p/interface'
*
* const startable: Startable = {
* start: () => {},
* stop: () => {}
* }
*
* const notStartable = 5
*
* await stop(
* startable,
* notStartable
* )
* ```
*/
async function stop(...objs) {
const startables = [];
for (const obj of objs) {
if (isStartable(obj)) {
startables.push(obj);
}
}
await Promise.all(startables.map(async (s) => {
if (s.beforeStop != null) {
await s.beforeStop();
}
}));
await Promise.all(startables.map(async (s) => {
await s.stop();
}));
await Promise.all(startables.map(async (s) => {
if (s.afterStop != null) {
await s.afterStop();
}
}));
}
/**
* @packageDocumentation
*
* Exports a `Libp2p` type for modules to use as a type argument.
*
* @example
*
* ```typescript
* import type { Libp2p } from '@libp2p/interface'
*
* function doSomethingWithLibp2p (node: Libp2p) {
* // ...
* }
* ```
*/
/**
* This symbol is used by libp2p services to define the capabilities they can
* provide to other libp2p services.
*
* The service should define a property with this symbol as the key and the
* value should be a string array of provided capabilities.
*/
const serviceCapabilities = Symbol.for('@libp2p/service-capabilities');
/**
* This symbol is used by libp2p services to define the capabilities they
* require from other libp2p services.
*
* The service should define a property with this symbol as the key and the
* value should be a string array of required capabilities.
*/
const serviceDependencies = Symbol.for('@libp2p/service-dependencies');
function equals$2(aa, bb) {
if (aa === bb) {
return true;
}
if (aa.byteLength !== bb.byteLength) {
return false;
}
for (let ii = 0; ii < aa.byteLength; ii++) {
if (aa[ii] !== bb[ii]) {
return false;
}
}
return true;
}
function coerce(o) {
if (o instanceof Uint8Array && o.constructor.name === 'Uint8Array') {
return o;
}
if (o instanceof ArrayBuffer) {
return new Uint8Array(o);
}
if (ArrayBuffer.isView(o)) {
return new Uint8Array(o.buffer, o.byteOffset, o.byteLength);
}
throw new Error('Unknown type, must be binary type');
}
function fromString$1(str) {
return new TextEncoder().encode(str);
}
function toString$1(b) {
return new TextDecoder().decode(b);
}
/* eslint-disable */
// base-x encoding / decoding
// Copyright (c) 2018 base-x contributors
// Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp)
// Distributed under the MIT software license, see the accompanying
// file LICENSE or http://www.opensource.org/licenses/mit-license.php.
/**
* @param {string} ALPHABET
* @param {any} name
*/
function base$1(ALPHABET, name) {
if (ALPHABET.length >= 255) {
throw new TypeError('Alphabet too long');
}
var BASE_MAP = new Uint8Array(256);
for (var j = 0; j < BASE_MAP.length; j++) {
BASE_MAP[j] = 255;
}
for (var i = 0; i < ALPHABET.length; i++) {
var x = ALPHABET.charAt(i);
var xc = x.charCodeAt(0);
if (BASE_MAP[xc] !== 255) {
throw new TypeError(x + ' is ambiguous');
}
BASE_MAP[xc] = i;
}
var BASE = ALPHABET.length;
var LEADER = ALPHABET.charAt(0);
var FACTOR = Math.log(BASE) / Math.log(256); // log(BASE) / log(256), rounded up
var iFACTOR = Math.log(256) / Math.log(BASE); // log(256) / log(BASE), rounded up
/**
* @param {any[] | Iterable<number>} source
*/
function encode(source) {
// @ts-ignore
if (source instanceof Uint8Array)
;
else if (ArrayBuffer.isView(source)) {
source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
}
else if (Array.isArray(source)) {
source = Uint8Array.from(source);
}
if (!(source instanceof Uint8Array)) {
throw new TypeError('Expected Uint8Array');
}
if (source.length === 0) {
return '';
}
// Skip & count leading zeroes.
var zeroes = 0;
var length = 0;
var pbegin = 0;
var pend = source.length;
while (pbegin !== pend && source[pbegin] === 0) {
pbegin++;
zeroes++;
}
// Allocate enough space in big-endian base58 representation.
var size = ((pend - pbegin) * iFACTOR + 1) >>> 0;
var b58 = new Uint8Array(size);
// Process the bytes.
while (pbegin !== pend) {
var carry = source[pbegin];
// Apply "b58 = b58 * 256 + ch".
var i = 0;
for (var it1 = size - 1; (carry !== 0 || i < length) && (it1 !== -1); it1--, i++) {
carry += (256 * b58[it1]) >>> 0;
b58[it1] = (carry % BASE) >>> 0;
carry = (carry / BASE) >>> 0;
}
if (carry !== 0) {
throw new Error('Non-zero carry');
}
length = i;
pbegin++;
}
// Skip leading zeroes in base58 result.
var it2 = size - length;
while (it2 !== size && b58[it2] === 0) {
it2++;
}
// Translate the result into a string.
var str = LEADER.repeat(zeroes);
for (; it2 < size; ++it2) {
str += ALPHABET.charAt(b58[it2]);
}
return str;
}
/**
* @param {string | string[]} source
*/
function decodeUnsafe(source) {
if (typeof source !== 'string') {
throw new TypeError('Expected String');
}
if (source.length === 0) {
return new Uint8Array();
}
var psz = 0;
// Skip leading spaces.
if (source[psz] === ' ') {
return;
}
// Skip and count leading '1's.
var zeroes = 0;
var length = 0;
while (source[psz] === LEADER) {
zeroes++;
psz++;
}
// Allocate enough space in big-endian base256 representation.
var size = (((source.length - psz) * FACTOR) + 1) >>> 0; // log(58) / log(256), rounded up.
var b256 = new Uint8Array(size);
// Process the characters.
while (source[psz]) {
// Decode character
var carry = BASE_MAP[source.charCodeAt(psz)];
// Invalid character
if (carry === 255) {
return;
}
var i = 0;
for (var it3 = size - 1; (carry !== 0 || i < length) && (it3 !== -1); it3--, i++) {
carry += (BASE * b256[it3]) >>> 0;
b256[it3] = (carry % 256) >>> 0;
carry = (carry / 256) >>> 0;
}
if (carry !== 0) {
throw new Error('Non-zero carry');
}
length = i;
psz++;
}
// Skip trailing spaces.
if (source[psz] === ' ') {
return;
}
// Skip leading zeroes in b256.
var it4 = size - length;
while (it4 !== size && b256[it4] === 0) {
it4++;
}
var vch = new Uint8Array(zeroes + (size - it4));
var j = zeroes;
while (it4 !== size) {
vch[j++] = b256[it4++];
}
return vch;
}
/**
* @param {string | string[]} string
*/
function decode(string) {
var buffer = decodeUnsafe(string);
if (buffer) {
return buffer;
}
throw new Error(`Non-${name} character`);
}
return {
encode: encode,
decodeUnsafe: decodeUnsafe,
decode: decode
};
}
var src = base$1;
var _brrp__multiformats_scope_baseX = src;
/**
* Class represents both BaseEncoder and MultibaseEncoder meaning it
* can be used to encode to multibase or base encode without multibase
* prefix.
*/
let Encoder$2 = class Encoder {
name;
prefix;
baseEncode;
constructor(name, prefix, baseEncode) {
this.name = name;
this.prefix = prefix;
this.baseEncode = baseEncode;
}
encode(bytes) {
if (bytes instanceof Uint8Array) {
return `${this.prefix}${this.baseEncode(bytes)}`;
}
else {
throw Error('Unknown type, must be binary type');
}
}
};
/**
* Class represents both BaseDecoder and MultibaseDecoder so it could be used
* to decode multibases (with matching prefix) or just base decode strings
* with corresponding base encoding.
*/
let Decoder$2 = class Decoder {
name;
prefix;
baseDecode;
prefixCodePoint;
constructor(name, prefix, baseDecode) {
this.name = name;
this.prefix = prefix;
const prefixCodePoint = prefix.codePointAt(0);
/* c8 ignore next 3 */
if (prefixCodePoint === undefined) {
throw new Error('Invalid prefix character');
}
this.prefixCodePoint = prefixCodePoint;
this.baseDecode = baseDecode;
}
decode(text) {
if (typeof text === 'string') {
if (text.codePointAt(0) !== this.prefixCodePoint) {
throw Error(`Unable to decode multibase string ${JSON.stringify(text)}, ${this.name} decoder only supports inputs prefixed with ${this.prefix}`);
}
return this.baseDecode(text.slice(this.prefix.length));
}
else {
throw Error('Can only multibase decode strings');
}
}
or(decoder) {
return or$2(this, decoder);
}
};
class ComposedDecoder {
decoders;
constructor(decoders) {
this.decoders = decoders;
}
or(decoder) {
return or$2(this, decoder);
}
decode(input) {
const prefix = input[0];
const decoder = this.decoders[prefix];
if (decoder != null) {
return decoder.decode(input);
}
else {
throw RangeError(`Unable to decode multibase string ${JSON.stringify(input)}, only inputs prefixed with ${Object.keys(this.decoders)} are supported`);
}
}
}
function or$2(left, right) {
return new ComposedDecoder({
...(left.decoders ?? { [left.prefix]: left }),
...(right.decoders ?? { [right.prefix]: right })
});
}
class Codec {
name;
prefix;
baseEncode;
baseDecode;
encoder;
decoder;
constructor(name, prefix, baseEncode, baseDecode) {
this.name = name;
this.prefix = prefix;
this.baseEncode = baseEncode;
this.baseDecode = baseDecode;
this.encoder = new Encoder$2(name, prefix, baseEncode);
this.decoder = new Decoder$2(name, prefix, baseDecode);
}
encode(input) {
return this.encoder.encode(input);
}
decode(input) {
return this.decoder.decode(input);
}
}
function from$1({ name, prefix, encode, decode }) {
return new Codec(name, prefix, encode, decode);
}
function baseX({ name, prefix, alphabet }) {
const { encode, decode } = _brrp__multiformats_scope_baseX(alphabet, name);
return from$1({
prefix,
name,
encode,
decode: (text) => coerce(decode(text))
});
}
function decode$8(string, alphabetIdx, bitsPerChar, name) {
// Count the padding bytes:
let end = string.length;
while (string[end - 1] === '=') {
--end;
}
// Allocate the output:
const out = new Uint8Array((end * bitsPerChar / 8) | 0);
// Parse the data:
let bits = 0; // Number of bits currently in the buffer
let buffer = 0; // Bits waiting to be written out, MSB first
let written = 0; // Next byte to write
for (let i = 0; i < end; ++i) {
// Read one character from the string:
const value = alphabetIdx[string[i]];
if (value === undefined) {
throw new SyntaxError(`Non-${name} character`);
}
// Append the bits to the buffer:
buffer = (buffer << bitsPerChar) | value;
bits += bitsPerChar;
// Write out some bits if the buffer has a byte's worth:
if (bits >= 8) {
bits -= 8;
out[written++] = 0xff & (buffer >> bits);
}
}
// Verify that we have received just enough bits:
if (bits >= bitsPerChar || (0xff & (buffer << (8 - bits))) !== 0) {
throw new SyntaxError('Unexpected end of data');
}
return out;
}
function encode$8(data, alphabet, bitsPerChar) {
const pad = alphabet[alphabet.length - 1] === '=';
const mask = (1 << bitsPerChar) - 1;
let out = '';
let bits = 0; // Number of bits currently in the buffer
let buffer = 0; // Bits waiting to be written out, MSB first
for (let i = 0; i < data.length; ++i) {
// Slurp data into the buffer:
buffer = (buffer << 8) | data[i];
bits += 8;
// Write out as much as we can:
while (bits > bitsPerChar) {
bits -= bitsPerChar;
out += alphabet[mask & (buffer >> bits)];
}
}
// Partial character:
if (bits !== 0) {
out += alphabet[mask & (buffer << (bitsPerChar - bits))];
}
// Add padding characters until we hit a byte boundary:
if (pad) {
while (((out.length * bitsPerChar) & 7) !== 0) {
out += '=';
}
}
return out;
}
function createAlphabetIdx(alphabet) {
// Build the character lookup table:
const alphabetIdx = {};
for (let i = 0; i < alphabet.length; ++i) {
alphabetIdx[alphabet[i]] = i;
}
return alphabetIdx;
}
/**
* RFC4648 Factory
*/
function rfc4648({ name, prefix, bitsPerChar, alphabet }) {
const alphabetIdx = createAlphabetIdx(alphabet);
return from$1({
prefix,
name,
encode(input) {
return encode$8(input, alphabet, bitsPerChar);
},
decode(input) {
return decode$8(input, alphabetIdx, bitsPerChar, name);
}
});
}
const base58btc = baseX({
name: 'base58btc',
prefix: 'z',
alphabet: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
});
const base58flickr = baseX({
name: 'base58flickr',
prefix: 'Z',
alphabet: '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
});
var base58 = /*#__PURE__*/Object.freeze({
__proto__: null,
base58btc: base58btc,
base58flickr: base58flickr
});
const base32$2 = rfc4648({
prefix: 'b',
name: 'base32',
alphabet: 'abcdefghijklmnopqrstuvwxyz234567',
bitsPerChar: 5
});
const base32upper = rfc4648({
prefix: 'B',
name: 'base32upper',
alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
bitsPerChar: 5
});
const base32pad = rfc4648({
prefix: 'c',
name: 'base32pad',
alphabet: 'abcdefghijklmnopqrstuvwxyz234567=',
bitsPerChar: 5
});
const base32padupper = rfc4648({
prefix: 'C',
name: 'base32padupper',
alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=',
bitsPerChar: 5
});
const base32hex = rfc4648({
prefix: 'v',
name: 'base32hex',
alphabet: '0123456789abcdefghijklmnopqrstuv',
bitsPerChar: 5
});
const base32hexupper = rfc4648({
prefix: 'V',
name: 'base32hexupper',
alphabet: '0123456789ABCDEFGHIJKLMNOPQRSTUV',
bitsPerChar: 5
});
const base32hexpad = rfc4648({
prefix: 't',
name: 'base32hexpad',
alphabet: '0123456789abcdefghijklmnopqrstuv=',
bitsPerChar: 5
});
const base32hexpadupper = rfc4648({
prefix: 'T',
name: 'base32hexpadupper',
alphabet: '0123456789ABCDEFGHIJKLMNOPQRSTUV=',
bitsPerChar: 5
});
const base32z = rfc4648({
prefix: 'h',
name: 'base32z',
alphabet: 'ybndrfg8ejkmcpqxot1uwisza345h769',
bitsPerChar: 5
});
var base32$3 = /*#__PURE__*/Object.freeze({
__proto__: null,
base32: base32$2,
base32hex: base32hex,
base32hexpad: base32hexpad,
base32hexpadupper: base32hexpadupper,
base32hexupper: base32hexupper,
base32pad: base32pad,
base32padupper: base32padupper,
base32upper: base32upper,
base32z: base32z
});
const base36 = baseX({
prefix: 'k',
name: 'base36',
alphabet: '0123456789abcdefghijklmnopqrstuvwxyz'
});
const base36upper = baseX({
prefix: 'K',
name: 'base36upper',
alphabet: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
});
var base36$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
base36: base36,
base36upper: base36upper
});
/* eslint-disable */
var encode_1 = encode$7;
var MSB$2 = 0x80, MSBALL = -128, INT = Math.pow(2, 31);
/**
* @param {number} num
* @param {number[]} out
* @param {number} offset
*/
function encode$7(num, out, offset) {
out = out || [];
offset = offset || 0;
var oldOffset = offset;
while (num >= INT) {
out[offset++] = (num & 0xFF) | MSB$2;
num /= 128;
}
while (num & MSBALL) {
out[offset++] = (num & 0xFF) | MSB$2;
num >>>= 7;
}
out[offset] = num | 0;
// @ts-ignore
encode$7.bytes = offset - oldOffset + 1;
return out;
}
var decode$7 = read$2;
var MSB$1$1 = 0x80, REST$1$1 = 0x7F;
/**
* @param {string | any[]} buf
* @param {number} offset
*/
function read$2(buf, offset) {
var res = 0, offset = offset || 0, shift = 0, counter = offset, b, l = buf.length;
do {
if (counter >= l) {
// @ts-ignore
read$2.bytes = 0;
throw new RangeError('Could not decode varint');
}
b = buf[counter++];
res += shift < 28
? (b & REST$1$1) << shift
: (b & REST$1$1) * Math.pow(2, shift);
shift += 7;
} while (b >= MSB$1$1);
// @ts-ignore
read$2.bytes = counter - offset;
return res;
}
var N1$1 = Math.pow(2, 7);
var N2$1 = Math.pow(2, 14);
var N3$1 = Math.pow(2, 21);
var N4$1 = Math.pow(2, 28);
var N5$1 = Math.pow(2, 35);
var N6$1 = Math.pow(2, 42);
var N7$1 = Math.pow(2, 49);
var N8 = Math.pow(2, 56);
var N9 = Math.pow(2, 63);
var length$1 = function (/** @type {number} */ value) {
return (value < N1$1 ? 1
: value < N2$1 ? 2
: value < N3$1 ? 3
: value < N4$1 ? 4
: value < N5$1 ? 5
: value < N6$1 ? 6
: value < N7$1 ? 7
: value < N8 ? 8
: value < N9 ? 9
: 10);
};
var varint = {
encode: encode_1,
decode: decode$7,
encodingLength: length$1
};
var _brrp_varint = varint;
function decode$6(data, offset = 0) {
const code = _brrp_varint.decode(data, offset);
return [code, _brrp_varint.decode.bytes];
}
function encodeTo(int, target, offset = 0) {
_brrp_varint.encode(int, target, offset);
return target;
}
function encodingLength$1(int) {
return _brrp_varint.encodingLength(int);
}
/**
* Creates a multihash digest.
*/
function create(code, digest) {
const size = digest.byteLength;
const sizeOffset = encodingLength$1(code);
const digestOffset = sizeOffset + encodingLength$1(size);
const bytes = new Uint8Array(digestOffset + size);
encodeTo(code, bytes, 0);
encodeTo(size, bytes, sizeOffset);
bytes.set(digest, digestOffset);
return new Digest(code, size, digest, bytes);
}
/**
* Turns bytes representation of multihash digest into an instance.
*/
function decode$5(multihash) {
const bytes = coerce(multihash);
const [code, sizeOffset] = decode$6(bytes);
const [size, digestOffset] = decode$6(bytes.subarray(sizeOffset));
const digest = bytes.subarray(sizeOffset + digestOffset);
if (digest.byteLength !== size) {
throw new Error('Incorrect length');
}
return new Digest(code, size, digest, bytes);
}
function equals$1(a, b) {
if (a === b) {
return true;
}
else {
const data = b;
return (a.code === data.code &&
a.size === data.size &&
data.bytes instanceof Uint8Array &&
equals$2(a.bytes, data.bytes));
}
}
/**
* Represents a multihash digest which carries information about the
* hashing algorithm and an actual hash digest.
*/
class Digest {
code;
size;
digest;
bytes;
/**
* Creates a multihash digest.
*/
constructor(code, size, digest, bytes) {
this.code = code;
this.size = size;
this.digest = digest;
this.bytes = bytes;
}
}
function format(link, base) {
const { bytes, version } = link;
switch (version) {
case 0:
return toStringV0(bytes, baseCache(link), base ?? base58btc.encoder);
default:
return toStringV1(bytes, baseCache(link), (base ?? base32$2.encoder));
}
}
const cache$1 = new WeakMap();
function baseCache(cid) {
const baseCache = cache$1.get(cid);
if (baseCache == null) {
const baseCache = new Map();
cache$1.set(cid, baseCache);
return baseCache;
}
return baseCache;
}
class CID {
code;
version;
multihash;
bytes;
'/';
/**
* @param version - Version of the CID
* @param code - Code of the codec content is encoded in, see https://github.com/multiformats/multicodec/blob/master/table.csv
* @param multihash - (Multi)hash of the of the content.
*/
constructor(version, code, multihash, bytes) {
this.code = code;
this.version = version;
this.multihash = multihash;
this.bytes = bytes;
// flag to serializers that this is a CID and
// should be treated specially
this['/'] = bytes;
}
/**
* Signalling `cid.asCID === cid` has been replaced with `cid['/'] === cid.bytes`
* please either use `CID.asCID(cid)` or switch to new signalling mechanism
*
* @deprecated
*/
get asCID() {
return this;
}
// ArrayBufferView
get byteOffset() {
return this.bytes.byteOffset;
}
// ArrayBufferView
get byteLength() {
return this.bytes.byteLength;
}
toV0() {
switch (this.version) {
case 0: {
return this;
}
case 1: {
const { code, multihash } = this;
if (code !== DAG_PB_CODE) {
throw new Error('Cannot convert a non dag-pb CID to CIDv0');
}
// sha2-256
if (multihash.code !== SHA_256_CODE) {
throw new Error('Cannot convert non sha2-256 multihash CID to CIDv0');
}
return (CID.createV0(multihash));
}
default: {
throw Error(`Can not convert CID version ${this.version} to version 0. This is a bug please report`);
}
}
}
toV1() {
switch (this.version) {
case 0: {
const { code, digest } = this.multihash;
const multihash = create(code, digest);
return (CID.createV1(this.code, multihash));
}
case 1: {
return this;
}
default: {
throw Error(`Can not convert CID version ${this.version} to version 1. This is a bug please report`);
}
}
}
equals(other) {
return CID.equals(this, other);
}
static equals(self, other) {
const unknown = other;
return (unknown != null &&
self.code === unknown.code &&
self.version === unknown.version &&
equals$1(self.multihash, unknown.multihash));
}
toString(base) {
return format(this, base);
}
toJSON() {
return { '/': format(this) };
}
link() {
return this;
}
[Symbol.toStringTag] = 'CID';
// Legacy
[Symbol.for('nodejs.util.inspect.custom')]() {
return `CID(${this.toString()})`;
}
/**
* Takes any input `value` and returns a `CID` instance if it was
* a `CID` otherwise returns `null`. If `value` is instanceof `CID`
* it will return value back. If `value` is not instance of this CID
* class, but is compatible CID it will return new instance of this
* `CID` class. Otherwise returns null.
*
* This allows two different incompatible versions of CID library to
* co-exist and interop as long as binary interface is compatible.
*/
static asCID(input) {
if (input == null) {
return null;
}
const value = input;
if (value instanceof CID) {
// If value is instance of CID then we're all set.
return value;
}
else if ((value['/'] != null && value['/'] === value.bytes) || value.asCID === value) {
// If value isn't instance of this CID class but `this.asCID === this` or
// `value['/'] === value.bytes` is true it is CID instance coming from a
// different implementation (diff version or duplicate). In that case we
// rebase it to this `CID` implementation so caller is guaranteed to get
// instance with expected API.
const { version, code, multihash, bytes } = value;
return new CID(version, code, multihash, bytes ?? encodeCID(version, code, multihash.bytes));
}
else if (value[cidSymbol] === true) {
// If value is a CID from older implementation that used to be tagged via
// symbol we still rebase it to the this `CID` implementation by
// delegating that to a constructor.
const { version, multihash, code } = value;
const digest = decode$5(multihash);
return CID.create(version, code, digest);
}
else {
// Otherwise value is not a CID (or an incompatible version of it) in
// which case we return `null`.
return null;
}
}
/**
* @param version - Version of the CID
* @param code - Code of the codec content is encoded in, see https://github.com/multiformats/multicodec/blob/master/table.csv
* @param digest - (Multi)hash of the of the content.
*/
static create(version, code, digest) {
if (typeof code !== 'number') {
throw new Error('String codecs are no longer supported');
}
if (!(digest.bytes instanceof Uint8Array)) {
throw new Error('Invalid digest');
}
switch (version) {
case 0: {
if (code !== DAG_PB_CODE) {
throw new Error(`Version 0 CID must use dag-pb (code: ${DAG_PB_CODE}) block encoding`);
}
else {
return new CID(version, code, digest, digest.bytes);
}
}
case 1: {
const bytes = encodeCID(version, code, digest.bytes);
return new CID(version, code, digest, bytes);
}
default: {
throw new Error('Invalid version');
}
}
}
/**
* Simplified version of `create` for CIDv0.
*/
static createV0(digest) {
return CID.create(0, DAG_PB_CODE, digest);
}
/**
* Simplified version of `create` for CIDv1.
*
* @param code - Content encoding format code.
* @param digest - Multihash of the content.
*/
static createV1(code, digest) {
return CID.create(1, code, digest);
}
/**
* Decoded a CID from its binary representation. The byte array must contain
* only the CID with no additional bytes.
*
* An error will be thrown if the bytes provided do not contain a valid
* binary representation of a CID.
*/
static decode(bytes) {
const [cid, remainder] = CID.decodeFirst(bytes);
if (remainder.length !== 0) {
throw new Error('Incorrect length');
}
return cid;
}
/**
* Decoded a CID from its binary representation at the beginning of a byte
* array.
*
* Returns an array with the first element containing the CID and the second
* element containing the remainder of the original byte array. The remainder
* will be a zero-length byte array if the provided bytes only contained a
* binary CID representation.
*/
static decodeFirst(bytes) {
const specs = CID.inspectBytes(bytes);
const prefixSize = specs.size - specs.multihashSize;
const multihashBytes = coerce(bytes.subarray(prefixSize, prefixSize + specs.multihashSize));
if (multihashBytes.byteLength !== specs.multihashSize) {
throw new Error('Incorrect length');
}
const digestBytes = multihashBytes.subarray(specs.multihashSize - specs.digestSize);
const digest = new Digest(specs.multihashCode, specs.digestSize, digestBytes, multihashBytes);
const cid = specs.version === 0
? CID.createV0(digest)
: CID.createV1(specs.codec, digest);
return [cid, bytes.subarray(specs.size)];
}
/**
* Inspect the initial bytes of a CID to determine its properties.
*
* Involves decoding up to 4 varints. Typically this will require only 4 to 6
* bytes but for larger multicodec code values and larger multihash digest
* lengths these varints can be quite large. It is recommended that at least
* 10 bytes be made available in the `initialBytes` argument for a complete
* inspection.
*/
static inspectBytes(initialBytes) {
let offset = 0;
const next = () => {
const [i, length] = decode$6(initialBytes.subarray(offset));
offset += length;
return i;
};
let version = next();
let codec = DAG_PB_CODE;
if (version === 18) {
// CIDv0
version = 0;
offset = 0;
}
else {
codec = next();
}
if (version !== 0 && version !== 1) {
throw new RangeError(`Invalid CID version ${version}`);
}
const prefixSize = offset;
const multihashCode = next(); // multihash code
const digestSize = next(); // multihash length
const size = offset + digestSize;
const multihashSize = size - prefixSize;
return { version, codec, multihashCode, digestSize, multihashSize, size };
}
/**
* Takes cid in a string representation and creates an instance. If `base`
* decoder is not provided will use a default from the configuration. It will
* throw an error if encoding of the CID is not compatible with supplied (or
* a default decoder).
*/
static parse(source, base) {
const [prefix, bytes] = parseCIDtoBytes(source, base);
const cid = CID.decode(bytes);
if (cid.version === 0 && source[0] !== 'Q') {
throw Error('Version 0 CID string must not include multibase prefix');
}
// Cache string representation to avoid computing it on `this.toString()`
baseCache(cid).set(prefix, source);
return cid;
}
}
function parseCIDtoBytes(source, base) {
switch (source[0]) {
// CIDv0 is parsed differently
case 'Q': {
const decoder = base ?? base58btc;
return [
base58btc.prefix,
decoder.decode(`${base58btc.prefix}${source}`)
];
}
case base58btc.prefix: {
const decoder = base ?? base58btc;
return [base58btc.prefix, decoder.decode(source)];
}
case base32$2.prefix: {
const decoder = base ?? base32$2;
return [base32$2.prefix, decoder.decode(source)];
}
case base36.prefix: {
const decoder = base ?? base36;
return [base36.prefix, decoder.decode(source)];
}
default: {
if (base == null) {
throw Error('To parse non base32, base36 or base58btc encoded CID multibase decoder must be provided');
}
return [source[0], base.decode(source)];
}
}
}
function toStringV0(bytes, cache, base) {
const { prefix } = base;
if (prefix !== base58btc.prefix) {
throw Error(`Cannot string encode V0 in ${base.name} encoding`);
}
const cid = cache.get(prefix);
if (cid == null) {
const cid = base.encode(bytes).slice(1);
cache.set(prefix, cid);
return cid;
}
else {
return cid;
}
}
function toStringV1(bytes, cache, base) {
const { prefix } = base;
const cid = cache.get(prefix);
if (cid == null) {
const cid = base.encode(bytes);
cache.set(prefix, cid);
return cid;
}
else {
return cid;
}
}
const DAG_PB_CODE = 0x70;
const SHA_256_CODE = 0x12;
function encodeCID(version, code, multihash) {
const codeOffset = encodingLength$1(version);
const hashOffset = codeOffset + encodingLength$1(code);
co