---
title: TypeScript API
description: 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:

**Node.js**

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

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

**React Native**

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

`useMinip2p` and `bindAppState` exist only here.

Setup per runtime: [Node.js](/typescript/setup-node),
[React Native](/typescript/setup-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. |
| `transports` | `Minip2pTransports` | Enabled transports. Omitted means dual-stack QUIC only. |
| `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. |
| `pubsubRouter` | `PubsubRouter` | `Gossipsub` by default; choose `Floodsub` explicitly. |
| `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.

Each transport accepts `true` or
`{ listen?: readonly [string, ...string[]] }`; omit a
transport to disable it. `true` listens on that transport's IPv4 and IPv6
defaults. An explicit `listen` array replaces those defaults exactly; an empty
array is rejected. QUIC accepts at most one explicit listener per IP family.
An omitted or empty `transports` object defaults to QUIC.

```ts
// QUIC only, IPv4 + IPv6 (also the default when `transports` is omitted)
transports: { quic: true }

// QUIC + TCP, both IPv4 + IPv6
transports: { quic: true, tcp: true }

// TCP on exactly these listeners
transports: {
  tcp: {
    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)` | <Badge>React Native</Badge> Hook state plus an idempotent `close` callback. |
| `bindAppState(endpoint)` | <Badge>React Native</Badge> Idempotent unsubscribe for manual lifecycle ownership. |
| `endpoint.close()` | Terminal, idempotent shutdown. |
| `endpoint[Symbol.dispose]()` | Equivalent to `close()`; supports `using` where the toolchain does. |
| `endpoint.onClose(handler)` | One-shot close observer unsubscribe. |
| `endpoint.isRunning()` | Whether the endpoint still accepts work. |
| `endpoint.setActive(active)` | Choose normal behavior or reduced background work. |

<Badge>Node.js</Badge> A started endpoint keeps the Node.js process alive until
`close()`. See [Endpoint lifecycle](/typescript/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 Identify completed. |
| `peerInfo(peerId)` | Latest remote Identify snapshot, if known. |
| `knownPeers()` | Multi-source discovery address book. |
| `discoveryNowMs()` | Discovery monotonic time, when enabled. |
| `path(peerId)` | Authoritative current `Path`, if connected. |
| `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.

| API | Result |
| --- | --- |
| `connect(peerId, options?)` | First usable path to a known peer. |
| `connectWithAddrs(peerId, addrs, options?)` | First usable path from explicit candidates. |
| `connectAddr(addr, options?)` | First usable path from a complete peer address. |
| `startConnect*` / `waitConnectResult` | Split-phase connection flow using a `connectId`. |
| `cancelConnect(connectId)` | Cancel a split-phase attempt. |
| `dial` / `dialIp4` / `dialIp6` | Start direct-only QUIC or TCP dialing and return connection IDs. |
| `waitPeerReady(peerId, options?)` | Peer ID and advertised protocol list after Identify. |
| `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. |
| `on("data", handler)` | Flowing read mode; mutually exclusive with `read()`. |
| `write(stringOrBytes)` | Send UTF-8 text or bytes. |
| `closeWrite()` | Graceful local half-close. |
| `reset()` | Abrupt reset. |
| `abandon()` | Reset and relinquish the handle. |

Stream events are `data`, `remoteWriteClosed`, `closed`, and `dataOverflow`.

## 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`, `peerReady`, `identifyReceived` |
| Ping and streams | `pingRttMeasured`, `pingTimeout`, `stream` |
| Relay and NAT | `reachabilityChanged`, `publicAddressesChanged`, `relayReserved`, `relayReservationLost`, `pathEstablished`, `pathUpgraded`, `holePunchFailed`, `fellBackToRelay`, `connectFailed`, `inboundDirectUpgrade` |
| Pubsub | `message`, `peerSubscribed`, `peerUnsubscribed`, `pubsubOutboundFailure`, `pubsubProtocolViolation` |
| Discovery | `peerDiscovered`, `peerUpdated`, `peerExpired`, `discoveryDialFailed`, `discoveryProtocolViolation` |

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. |
| `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. |
| `BackpressureError` | The outbound pubsub queue is full. |
| `MessageTooLargeError` | A payload exceeds the protocol limit. |
| `NotPermittedError` | Endpoint policy rejected the operation. |
