Skip to content
minip2p
Esc
↑↓navigate↵open⌘Jpreview
On this page

TypeScript API

Concise reference for the high-level TypeScript configuration, endpoint methods, streams, events, and public errors on Node.js and React Native.

The TypeScript SDK has one interface on two runtimes. Install @minip2p/node or @minip2p/react-native and import application APIs from that package.

Choose the import for the application’s runtime:

import {
  Minip2p,
  circuitAddress,
  generateSecretKey,
  peerIdFromSecretKey,
} from "@minip2p/node";

@minip2p/node is ESM-only and requires Node.js 24 or newer.

import {
  Minip2p,
  bindAppState,
  circuitAddress,
  generateSecretKey,
  peerIdFromSecretKey,
  useMinip2p,
} from "@minip2p/react-native";

useMinip2p and bindAppState exist only here.

Setup per runtime: Node.js, React Native.

Configuration

Minip2p.create(config) constructs and starts an endpoint synchronously.

Minip2pConfig field Type Purpose
secretKey ArrayBuffer | Uint8Array Required 32-byte Ed25519 secret key.
agentVersion string Identify agent string.
listen readonly [string, ...string[]] Listen multiaddresses; each address’s shape selects QUIC or TCP. Omitted means dual-stack QUIC on ephemeral ports.
protocols readonly string[] Custom protocols accepted on inbound streams.
relays readonly string[] Direct QUIC or TCP relay peer addresses.
autonatServers readonly string[] Reachability probe-server addresses.
forceRelay boolean Route outbound connectivity through relays only.
allowUnsigned boolean Accept unsigned inbound application pubsub messages; default false.
discovery Minip2pDiscoveryOptions Signed-beacon topic, timing, and auto-dial policy.
mdns boolean | Minip2pMdnsOptions Enable local-link discovery with defaults or explicit options.

discovery.topic is required when signed discovery is enabled. Both discovery options objects accept autoDial; remaining timing and capacity fields are typed in the exported declarations and use defaults when omitted. Signed discovery and mDNS share one automatic-dial policy. If both set autoDial, the values must match.

listen is the only listen setting. A /udp/<port>/quic-v1 address binds QUIC and a /tcp/<port> address binds TCP; a transport with no listen address is not bound. An explicit array replaces the defaults exactly, and QUIC accepts at most one listener per IP family.

// Omitted: QUIC on /ip4/0.0.0.0/udp/0/quic-v1 and /ip6/::/udp/0/quic-v1

// QUIC + TCP on fixed IPv4 ports
listen: ["/ip4/0.0.0.0/udp/4001/quic-v1", "/ip4/0.0.0.0/tcp/4001"];

// TCP only, IPv4 + IPv6
listen: ["/ip4/0.0.0.0/tcp/4001", "/ip6/::/tcp/4001"];

Identity and lifecycle

API Result
generateSecretKey() New Uint8Array containing a 32-byte Ed25519 secret.
peerIdFromSecretKey(secretKey) Base58 peer ID without starting an endpoint.
Minip2p.create(config) Started Minip2p endpoint.
useMinip2p(createConfig) React Native Hook state plus an idempotent close callback.
bindAppState(endpoint) React Native Idempotent unsubscribe for manual lifecycle ownership.
endpoint.close(timeoutMs?) Terminal, idempotent shutdown; resolves with an EndpointCloseReport once native drained for up to timeoutMs (default 500).
endpoint[Symbol.asyncDispose]() Awaits close(); supports await using.
endpoint[Symbol.dispose]() Starts close() without waiting; supports using.
endpoint.onClose(handler) One-shot close observer, called with the same report once the drain finishes; returns an unsubscribe.
endpoint.isRunning() Whether the endpoint still accepts work.
endpoint.setActive(active) Choose normal behavior or reduced background work.

Node.js A started endpoint keeps the Node.js process alive until close(). See Endpoint lifecycle for signal handling and shutdown order.

State queries

API Result
peerId() Local peer ID.
listenAddrs() Currently bound peer multiaddresses.
connectedPeers() Peer IDs with live transport connections.
isPeerReady(peerId) Whether the current connection completed Identify.
peerInfo(peerId) Latest remote Identify snapshot, if known.
knownPeers() Multi-source discovery address book.
discoveryNowMs() Discovery monotonic time, when enabled.
path(peerId) The current connection’s Path (direct, punched, or relayed), if connected.
connectionInfo(peerId) The current connection’s { peerId, connId, remoteAddr, path, readyProtocols? }, if connected; readyProtocols is set once that connection is ready.
reachability() Latest AutoNAT reachability verdict.
activeReservation() Active relay reservation metadata.
circuitAddress Usable local circuit address, when reserved.

Operations

Promise operations use { timeoutMs?, signal? }. Their default timeout is 65 seconds; timeoutMs: 0 disables it. For Connection attempts a timeout ends only the wait (set cancelOnTimeout: true to also cancel), while an aborted signal cancels the attempt and the wait settles from its terminal.

API Result
connect(target, options?) First usable path to a ConnectTarget: a peer ID, one complete peer address, or a list of complete addresses naming one peer.
startConnect(target) / waitConnectResult(connectId, options?) Split-phase connection flow using a connectId.
cancelConnect(connectId) Cancel an attempt; its terminal event settles any pending wait.
waitPeerReady(peerId, options?) Peer ID and advertised protocol list once the peer’s current connection completes Identify. A peerReady for a replaced connection does not resolve it.
ping(peerId, options?) RTT in milliseconds.
openStream(peerId, protocol, options?) Negotiated Stream.
disconnect(peerId) Close the active peer connection.

Pubsub and protocols

API Result
subscribe(topic) Whether the subscription set changed.
unsubscribe(topic) Whether the subscription set changed.
publish(topic, stringOrBytes) Queue an application pubsub message.
addProtocol(protocolId) Accept future inbound streams for a protocol.
circuitAddress(relayAddress, peerId) Build a relay circuit multiaddress.

Stream

Member Meaning
peerId, protocolId Remote identity and negotiated protocol.
streamId, connId Endpoint-local numeric identifiers.
initiatedLocally Whether this endpoint opened the stream.
read() Next Uint8Array, or undefined after remote half-close. Returning a chunk consumes it, which lets the sender continue.
on("data", handler) Flowing read mode; mutually exclusive with read(). A chunk is consumed once every handler returns, so an async handler is consumed when it returns its Promise, not when the Promise settles.
write(stringOrBytes) Send UTF-8 text or bytes; resolves once every byte is accepted. Rejects with WriteBufferFullError when bytes are already buffered and the write would push them past writeHighWaterMark. A queued write reads its buffer only when it reaches native, so leave the buffer untouched until the Promise settles.
writeHighWaterMark Bytes a stream buffers before write rejects (default 256 KiB, counting the in-flight write). A write into an empty buffer is always admitted, whatever its size.
closeWrite() Graceful local half-close after every earlier write. Throws if native refuses it while no write is pending; a close queued behind writes reports failure through the stream’s terminal event.
reset() Abrupt reset.
abandon() Reset and relinquish the handle.

Stream events are data, remoteWriteClosed, writeStopped, and closed. Stream data is never dropped: each stream delivers at most one receive window that has not been consumed, so a reader that stops reading stalls its sender.

Events

on(name, handler) is the typed application path. once and waitFor expose the same named map as Promises. on(handler) receives catch-all metadata with a discriminating type.

events({ signal?, bufferCap? }) returns an async iterator over the catch-all event stream. It ends when the endpoint closes or the signal aborts. A slow iterator yields queueOverflow before continuing with retained events.

Family Named events
Endpoint and queue eventsDropped, queueOverflow, driverFailed, handlerError, endpointError
Connection and Identify connectionEstablished, connectionClosed, connectionReplaced, peerReady, identifyReceived
Ping and streams pingRttMeasured, pingTimeout, stream
Relay and NAT reachabilityChanged, publicAddressesChanged, relayReserved, relayReservationLost, pathEstablished, pathUpgraded, holePunchFailed, connectFailed, connectCancelled, inboundDirectUpgrade
Pubsub message, peerSubscribed, peerUnsubscribed, gossipsubOutboundFailure, gossipsubProtocolViolation
Discovery peerDiscovered, peerUpdated, peerExpired, discoveryDialFailed, discoveryProtocolViolation

connectionReplaced ({ peerId, oldConnId, newConnId }) reports a newer connection taking over the peer’s single connection slot; the peer stays connected, streams and pending opens on oldConnId end with StreamClosedError, and peerReady (which carries connId) fires again for newConnId. connectionClosed ({ peerId, connId, reason }) means the peer’s last connection closed; reason is a ConnectionCloseReason: { kind: "local" }, { kind: "remote", code } (the peer’s QUIC close or Yamux GoAway code, a bigint), { kind: "timedOut" }, { kind: "stalled" }, or { kind: "error", message }. A failure that ended the connection is its reason, not a separate endpointError.

The catch-all stream uses inboundStream metadata instead of the live stream handle. Subscribe to the named stream event to claim an inbound stream.

Public errors

Use instanceof for control flow and the typed kind fields for telemetry.

Error Meaning
AbortError This caller’s wait was cancelled.
ConnectCancelledError An AbortError: the attempt ended with a connectCancelled terminal; includes connectId and peerId.
ConnectResultLostError A dropped event carried the attempt’s terminal; recover state with connectedPeers() / path().
TimeoutError A Promise operation exceeded its timeout.
EventQueueOverflowError Event loss made an in-flight result unknowable. Refresh state, then retry the operation.
ClosedError The endpoint or stream is already closed.
DriverFailedError The endpoint stopped; kind identifies the failed subsystem.
ConnectFailedError NAT orchestration ended without a path; includes connectId, peerId, and kind.
ConnectResultUnavailableError A split-phase result is unknown, already awaited, or consumed.
PeerDisconnectedError The peer disconnected during a pending operation.
OpenStreamError Opening or negotiation failed, with structured peer/stream context.
StreamClosedError A stream closed before outbound negotiation completed.
WriteBufferFullError A stream write would push buffered bytes past writeHighWaterMark; includes buffered and highWaterMark. Await earlier writes before writing more.
BackpressureError The outbound pubsub queue is full.
MessageTooLargeError A payload exceeds the protocol limit.
NotPermittedError Endpoint policy rejected the operation.

Other native failures, such as an invalid peer ID or address, are rethrown unchanged. On Node.js they are Errors whose code is the native FfiError variant name (for example InvalidPeerId) and whose detail, when present, is the variant’s detail text.

Last updated on October 22, 2026

Was this page helpful?