Skip to content
minip2p
Esc
navigateopen⌘Jpreview
On this page

Endpoint lifecycle

Create and persist an identity, own a React Native endpoint with useMinip2p, and coordinate AppState and shutdown.

A React Native Minip2p object owns one native endpoint. Its identity, driver, events, pending Promises, and streams all share that lifetime.

Identity first

The secret key is the node’s identity. Generate it once, store the raw 32 bytes in platform-appropriate secure storage, and supply the same bytes on later launches when the app needs a stable peer ID.

import {
  generateSecretKey,
  peerIdFromSecretKey,
} from "@minip2p/react-native";

const secretKey = generateSecretKey();
const peerId = peerIdFromSecretKey(secretKey);

peerIdFromSecretKey derives the public peer identity without starting an endpoint. Treat secretKey as credentials: do not log it, transmit it, or put it in ordinary preferences.

Prefer the lifecycle hook

useMinip2p is the normal component API. It starts in starting, then exposes the endpoint only after native construction succeeds.

const node = useMinip2p(createConfig);

switch (node.status) {
  case "starting":
    return <LoadingView />;
  case "failed":
    return <ErrorView error={node.error} />;
  case "closed":
    return <ClosedView />;
  case "running":
    return <PeerView endpoint={node.endpoint} peerId={node.peerId} />;
}
Status Available state
starting Native construction is scheduled after commit.
running endpoint, peerId, and the initial listenAddrs.
closed The endpoint closed normally.
failed Construction failed or the native driver stopped unexpectedly.

Every state also carries an idempotent close() callback. Component cleanup unbinds AppState and closes the endpoint automatically.

Foreground and background

The hook immediately mirrors the current React Native AppState and keeps it in sync:

  • active selects foreground polling;
  • every other state selects the native idle behavior.

This changes driver cadence; it does not destroy the endpoint. When the app returns to the foreground, the same endpoint resumes active polling.

If the endpoint is not component-owned, bind and release AppState manually:

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

const endpoint = Minip2p.create({
  secretKey: generateSecretKey(),
});
const unbindAppState = bindAppState(endpoint);

// Later, in the owner's cleanup path:
unbindAppState();
endpoint.close();

bindAppState applies the current state before it subscribes to later changes.

Close is terminal

endpoint.close() is idempotent. It:

  1. rejects pending Promise operations;
  2. closes owned Stream handles;
  3. stops and destroys the native endpoint;
  4. invokes each onClose observer once.
const removeClose = endpoint.onClose((reason) => {
  if (reason.reason === "driverFailed") {
    console.error(reason.error.kind, reason.error.message);
  }
});

endpoint.close();
removeClose();

Use isDriverFailure(node) to narrow a failed hook state to DriverFailedError when the UI needs the machine-readable failure kind.

Public SDK boundary

Application code should import from @minip2p/react-native. That package re-exports the platform-neutral high-level types from @minip2p/core.

The generated UniFFI surface at @minip2p/react-native/native and the adapter contract at @minip2p/core/backend are low-level integration APIs. They expose native lifecycle details and raw tagged unions; ordinary applications should not use them.

Next: Connections and streams.

Last updated on July 31, 2026

Was this page helpful?