@peerkit/transport-libp2p-react-native 0.1.0-alpha.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +155 -0
  2. package/dist/datachannel-early-message-polyfill.d.ts +23 -0
  3. package/dist/datachannel-early-message-polyfill.d.ts.map +1 -0
  4. package/dist/datachannel-early-message-polyfill.js +131 -0
  5. package/dist/datachannel-early-message-polyfill.js.map +1 -0
  6. package/dist/event-target-polyfill.d.ts +40 -0
  7. package/dist/event-target-polyfill.d.ts.map +1 -0
  8. package/dist/event-target-polyfill.js +192 -0
  9. package/dist/event-target-polyfill.js.map +1 -0
  10. package/dist/factories.d.ts +68 -0
  11. package/dist/factories.d.ts.map +1 -0
  12. package/dist/factories.js +73 -0
  13. package/dist/factories.js.map +1 -0
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +3 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/polyfills.d.ts +41 -0
  19. package/dist/polyfills.d.ts.map +1 -0
  20. package/dist/polyfills.js +67 -0
  21. package/dist/polyfills.js.map +1 -0
  22. package/dist/quick-crypto-noise.d.ts +35 -0
  23. package/dist/quick-crypto-noise.d.ts.map +1 -0
  24. package/dist/quick-crypto-noise.js +105 -0
  25. package/dist/quick-crypto-noise.js.map +1 -0
  26. package/dist/text-codec-polyfill.d.ts +25 -0
  27. package/dist/text-codec-polyfill.d.ts.map +1 -0
  28. package/dist/text-codec-polyfill.js +79 -0
  29. package/dist/text-codec-polyfill.js.map +1 -0
  30. package/dist/webrtc-certificate-polyfill.d.ts +37 -0
  31. package/dist/webrtc-certificate-polyfill.d.ts.map +1 -0
  32. package/dist/webrtc-certificate-polyfill.js +53 -0
  33. package/dist/webrtc-certificate-polyfill.js.map +1 -0
  34. package/dist/websocket-buffered-amount-polyfill.d.ts +21 -0
  35. package/dist/websocket-buffered-amount-polyfill.d.ts.map +1 -0
  36. package/dist/websocket-buffered-amount-polyfill.js +41 -0
  37. package/dist/websocket-buffered-amount-polyfill.js.map +1 -0
  38. package/package.json +78 -0
  39. package/src/datachannel-early-message-polyfill.ts +176 -0
  40. package/src/event-target-polyfill.ts +268 -0
  41. package/src/factories.ts +116 -0
  42. package/src/index.ts +10 -0
  43. package/src/polyfills.ts +72 -0
  44. package/src/quick-crypto-noise.ts +130 -0
  45. package/src/rn-modules.d.ts +100 -0
  46. package/src/text-codec-polyfill.ts +118 -0
  47. package/src/webrtc-certificate-polyfill.ts +60 -0
  48. package/src/websocket-buffered-amount-polyfill.ts +45 -0
@@ -0,0 +1,73 @@
1
+ import { noise } from "@chainsafe/libp2p-noise";
2
+ import { yamux } from "@chainsafe/libp2p-yamux";
3
+ import { circuitRelayTransport } from "@libp2p/circuit-relay-v2";
4
+ import { identify } from "@libp2p/identify";
5
+ import { webRTC, webRTCDirect } from "@libp2p/webrtc";
6
+ import { TransportLibp2p, } from "@peerkit/transport-libp2p-core";
7
+ import { createLibp2p } from "libp2p";
8
+ import { quickCryptoNoise } from "./quick-crypto-noise.js";
9
+ /**
10
+ * Default libp2p listen addresses for a React Native peerkit node.
11
+ *
12
+ * Mobile peers cannot accept inbound direct TCP/UDP (CGNAT, no listen socket
13
+ * survives backgrounding on iOS / Android), so reachability is always
14
+ * relay-mediated: `/p2p-circuit` advertises a reservation on a connected
15
+ * relay, `/webrtc` advertises that the peer can be upgraded to a direct
16
+ * WebRTC connection through the relay-coordinated SDP exchange.
17
+ */
18
+ export const defaultNodeListenAddrs = [
19
+ "/p2p-circuit",
20
+ "/webrtc",
21
+ ];
22
+ /**
23
+ * Build a React Native peerkit transport. Configures libp2p with WebRTC +
24
+ * WebRTC Direct + circuit-relay-v2 client + noise + yamux + identify.
25
+ *
26
+ * Noise is wired with `quickCryptoNoise`, the JSI-backed `ICryptoInterface`
27
+ * from `./quick-crypto-noise`, so SHA-256, HKDF, and ChaCha20-Poly1305 are
28
+ * offloaded to `react-native-quick-crypto`. X25519 stays on pure JS because
29
+ * `ICryptoInterface` is synchronous and quick-crypto's X25519 surface is not.
30
+ *
31
+ * Crypto primitives, RNG and the WebRTC globals come from runtime polyfills
32
+ * — the consumer must import `@peerkit/transport-libp2p-react-native/polyfills`
33
+ * once from the app entry before this factory runs.
34
+ *
35
+ * Handles all three peerkit protocols (access, agents, messages). DCUtR is
36
+ * deliberately not registered: mobile cannot listen on TCP/QUIC, so there is
37
+ * no relayed connection that can be upgraded by hole-punching; WebRTC ICE
38
+ * provides the only viable direct-connection path on mobile.
39
+ */
40
+ export async function createNode(options) {
41
+ // Build array of ICE servers if provided or leave undefined to use
42
+ // libp2p default.
43
+ const iceServers = options.iceServerUrls &&
44
+ options.iceServerUrls.map((url) => ({
45
+ urls: url,
46
+ }));
47
+ const libp2pNode = await createLibp2p({
48
+ // Defer listening so TransportLibp2p can register protocol handlers
49
+ // (including /peerkit/access/v1) before any inbound connection arrives.
50
+ start: false,
51
+ transports: [
52
+ webRTC({ rtcConfiguration: { iceServers } }),
53
+ webRTCDirect(),
54
+ circuitRelayTransport(),
55
+ ],
56
+ connectionEncrypters: [noise({ crypto: quickCryptoNoise })],
57
+ streamMuxers: [yamux()],
58
+ services: { identify: identify() },
59
+ connectionGater: options.connectionGater,
60
+ addresses: {
61
+ listen: options.addrs ?? defaultNodeListenAddrs,
62
+ },
63
+ });
64
+ const transport = new TransportLibp2p(libp2pNode, options);
65
+ await libp2pNode.start();
66
+ // Connect to all provided relays. Fire-and-forget: the transport calls
67
+ // connectedToRelayCallback on successful connect to a relay.
68
+ if (options.bootstrapRelays?.length) {
69
+ transport.connectToRelays(options.bootstrapRelays);
70
+ }
71
+ return transport;
72
+ }
73
+ //# sourceMappingURL=factories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factories.js","sourceRoot":"","sources":["../src/factories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EACL,eAAe,GAEhB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,cAAc;IACd,SAAS;CACV,CAAC;AAsCF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAA0B;IACzD,mEAAmE;IACnE,kBAAkB;IAClB,MAAM,UAAU,GACd,OAAO,CAAC,aAAa;QACrB,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAClC,IAAI,EAAE,GAAG;SACV,CAAC,CAAC,CAAC;IACN,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC;QACpC,oEAAoE;QACpE,wEAAwE;QACxE,KAAK,EAAE,KAAK;QACZ,UAAU,EAAE;YACV,MAAM,CAAC,EAAE,gBAAgB,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC;YAC5C,YAAY,EAAE;YACd,qBAAqB,EAAE;SACxB;QACD,oBAAoB,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAC3D,YAAY,EAAE,CAAC,KAAK,EAAE,CAAC;QACvB,QAAQ,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE;QAClC,eAAe,EAAE,OAAO,CAAC,eAAe;QACxC,SAAS,EAAE;YACT,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,sBAAsB;SAChD;KACF,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC3D,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;IACzB,uEAAuE;IACvE,6DAA6D;IAC7D,IAAI,OAAO,CAAC,eAAe,EAAE,MAAM,EAAE,CAAC;QACpC,SAAS,CAAC,eAAe,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from "./factories.js";
2
+ export { TransportLibp2p, CURRENT_ACCESS_PROTOCOL, CURRENT_AGENTS_PROTOCOL, CURRENT_MESSAGE_PROTOCOL, type NodeOptions, type RelayOptions, type TransportOptionsBase, } from "@peerkit/transport-libp2p-core";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,wBAAwB,EACxB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,oBAAoB,GAC1B,MAAM,gCAAgC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./factories.js";
2
+ export { TransportLibp2p, CURRENT_ACCESS_PROTOCOL, CURRENT_AGENTS_PROTOCOL, CURRENT_MESSAGE_PROTOCOL, } from "@peerkit/transport-libp2p-core";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,wBAAwB,GAIzB,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Runtime polyfills required by libp2p when running on React Native (Hermes).
3
+ *
4
+ * Side-effect import from the app entry, **before any other import**:
5
+ *
6
+ * ```ts
7
+ * import "@peerkit/transport-libp2p-react-native/polyfills";
8
+ * ```
9
+ *
10
+ * Order matters:
11
+ * 1. `react-native-get-random-values` — patches `globalThis.crypto.getRandomValues`.
12
+ * Must run first so anything that touches RNG during module init (peer-id,
13
+ * noise key generation) observes the JSI implementation.
14
+ * 2. `react-native-quick-crypto` `install()` — installs the JSI-backed
15
+ * `globalThis.crypto.subtle` (Ed25519, X25519, AES-GCM, ChaCha20-Poly1305,
16
+ * HMAC, SHA-256) used by `@chainsafe/libp2p-noise`.
17
+ * 3. `react-native-webrtc` `registerGlobals()` — defines the global
18
+ * `RTCPeerConnection`, `RTCSessionDescription`, etc. used by
19
+ * `@libp2p/webrtc`, followed by `installWebRtcCertificatePolyfill()` which
20
+ * adds the static `RTCPeerConnection.generateCertificate` method the
21
+ * webrtc-direct dialer needs but `react-native-webrtc` does not provide
22
+ * (see `webrtc-certificate-polyfill`), and
23
+ * `installDataChannelEarlyMessagePolyfill()` which recovers the first
24
+ * inbound datachannel message `react-native-webrtc` drops during connection
25
+ * setup, otherwise mobile-to-mobile stream handshakes hang (see
26
+ * `datachannel-early-message-polyfill`).
27
+ *
28
+ * It also installs the WHATWG `Event` / `EventTarget` / `CustomEvent` globals
29
+ * that Hermes lacks but libp2p extends at module-evaluation time (see
30
+ * `event-target-polyfill`), plus the `TextEncoder` / `TextDecoder` globals that
31
+ * `uint8arrays` constructs at module-evaluation time (see `text-codec-polyfill`).
32
+ * Those steps are order-independent relative to the three above.
33
+ *
34
+ * Consumers must also configure Metro to map bare Node imports (`crypto`,
35
+ * `stream`, `buffer`, `events`) to their React Native equivalents and enable
36
+ * `@babel/plugin-transform-private-methods` (loose) so libp2p's ES2022
37
+ * private fields parse under Hermes. See the package README for the full
38
+ * Metro / Babel configuration.
39
+ */
40
+ import "react-native-get-random-values";
41
+ //# sourceMappingURL=polyfills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polyfills.d.ts","sourceRoot":"","sources":["../src/polyfills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,gCAAgC,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Runtime polyfills required by libp2p when running on React Native (Hermes).
3
+ *
4
+ * Side-effect import from the app entry, **before any other import**:
5
+ *
6
+ * ```ts
7
+ * import "@peerkit/transport-libp2p-react-native/polyfills";
8
+ * ```
9
+ *
10
+ * Order matters:
11
+ * 1. `react-native-get-random-values` — patches `globalThis.crypto.getRandomValues`.
12
+ * Must run first so anything that touches RNG during module init (peer-id,
13
+ * noise key generation) observes the JSI implementation.
14
+ * 2. `react-native-quick-crypto` `install()` — installs the JSI-backed
15
+ * `globalThis.crypto.subtle` (Ed25519, X25519, AES-GCM, ChaCha20-Poly1305,
16
+ * HMAC, SHA-256) used by `@chainsafe/libp2p-noise`.
17
+ * 3. `react-native-webrtc` `registerGlobals()` — defines the global
18
+ * `RTCPeerConnection`, `RTCSessionDescription`, etc. used by
19
+ * `@libp2p/webrtc`, followed by `installWebRtcCertificatePolyfill()` which
20
+ * adds the static `RTCPeerConnection.generateCertificate` method the
21
+ * webrtc-direct dialer needs but `react-native-webrtc` does not provide
22
+ * (see `webrtc-certificate-polyfill`), and
23
+ * `installDataChannelEarlyMessagePolyfill()` which recovers the first
24
+ * inbound datachannel message `react-native-webrtc` drops during connection
25
+ * setup, otherwise mobile-to-mobile stream handshakes hang (see
26
+ * `datachannel-early-message-polyfill`).
27
+ *
28
+ * It also installs the WHATWG `Event` / `EventTarget` / `CustomEvent` globals
29
+ * that Hermes lacks but libp2p extends at module-evaluation time (see
30
+ * `event-target-polyfill`), plus the `TextEncoder` / `TextDecoder` globals that
31
+ * `uint8arrays` constructs at module-evaluation time (see `text-codec-polyfill`).
32
+ * Those steps are order-independent relative to the three above.
33
+ *
34
+ * Consumers must also configure Metro to map bare Node imports (`crypto`,
35
+ * `stream`, `buffer`, `events`) to their React Native equivalents and enable
36
+ * `@babel/plugin-transform-private-methods` (loose) so libp2p's ES2022
37
+ * private fields parse under Hermes. See the package README for the full
38
+ * Metro / Babel configuration.
39
+ */
40
+ import "react-native-get-random-values";
41
+ import { Buffer } from "buffer";
42
+ import process from "process";
43
+ import { install as installQuickCrypto } from "react-native-quick-crypto";
44
+ import { registerGlobals as registerWebRtcGlobals } from "react-native-webrtc";
45
+ import { installDataChannelEarlyMessagePolyfill } from "./datachannel-early-message-polyfill.js";
46
+ import { installEventTargetPolyfill } from "./event-target-polyfill.js";
47
+ import { installTextCodecPolyfill } from "./text-codec-polyfill.js";
48
+ import { installWebRtcCertificatePolyfill } from "./webrtc-certificate-polyfill.js";
49
+ import { installWebSocketBufferedAmountPolyfill } from "./websocket-buffered-amount-polyfill.js";
50
+ // Buffer + process must live on globalThis: some libp2p dependencies reach for these as globals
51
+ // rather than as ES module imports. Metro's `extraNodeModules` only rewrites
52
+ // bare imports — code that touches `globalThis.Buffer` or
53
+ // `globalThis.process.nextTick` directly relies on this assignment.
54
+ const globalScope = globalThis;
55
+ globalScope.Buffer ??= Buffer;
56
+ globalScope.process ??= process;
57
+ installEventTargetPolyfill();
58
+ installTextCodecPolyfill();
59
+ installWebSocketBufferedAmountPolyfill();
60
+ installQuickCrypto();
61
+ registerWebRtcGlobals();
62
+ // Must run after `registerWebRtcGlobals()`: both patch the global
63
+ // `RTCPeerConnection` that step installs (the early-message polyfill also probes
64
+ // it for the `RTCDataChannel` prototype).
65
+ installWebRtcCertificatePolyfill();
66
+ installDataChannelEarlyMessagePolyfill();
67
+ //# sourceMappingURL=polyfills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polyfills.js","sourceRoot":"","sources":["../src/polyfills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,gCAAgC,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAAE,eAAe,IAAI,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,sCAAsC,EAAE,MAAM,yCAAyC,CAAC;AACjG,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,gCAAgC,EAAE,MAAM,kCAAkC,CAAC;AACpF,OAAO,EAAE,sCAAsC,EAAE,MAAM,yCAAyC,CAAC;AAEjG,gGAAgG;AAChG,6EAA6E;AAC7E,0DAA0D;AAC1D,oEAAoE;AACpE,MAAM,WAAW,GAAG,UAGnB,CAAC;AACF,WAAW,CAAC,MAAM,KAAK,MAAM,CAAC;AAC9B,WAAW,CAAC,OAAO,KAAK,OAAO,CAAC;AAEhC,0BAA0B,EAAE,CAAC;AAC7B,wBAAwB,EAAE,CAAC;AAC3B,sCAAsC,EAAE,CAAC;AACzC,kBAAkB,EAAE,CAAC;AACrB,qBAAqB,EAAE,CAAC;AACxB,kEAAkE;AAClE,iFAAiF;AACjF,0CAA0C;AAC1C,gCAAgC,EAAE,CAAC;AACnC,sCAAsC,EAAE,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * `ICryptoInterface` implementation backed by `react-native-quick-crypto`,
3
+ * intended to be passed to `noise({ crypto: quickCryptoNoise })` on React
4
+ * Native. JSI-backed primitives are noticeably faster than the pure-JS Noise
5
+ * defaults on Hermes, which matters for handshake latency and bulk transfer.
6
+ *
7
+ * Only the primitives that have a usable synchronous quick-crypto mapping are
8
+ * overridden:
9
+ *
10
+ * - `hashSHA256` — `createHash('sha256')`
11
+ * - `getHKDF` — RFC 5869 HKDF built on `createHmac('sha256', ...)`
12
+ * - `chaCha20Poly1305Encrypt` / `chaCha20Poly1305Decrypt` —
13
+ * `createCipheriv` / `createDecipheriv` with the `chacha20-poly1305`
14
+ * AEAD, 16-byte authentication tag appended to / split from the
15
+ * ciphertext per the Noise specification.
16
+ *
17
+ * X25519 key generation and shared-secret derivation are delegated to
18
+ * `pureJsCrypto` because the quick-crypto X25519 API is asynchronous
19
+ * (subtle-style) whereas `ICryptoInterface` requires synchronous methods.
20
+ * The pure-JS X25519 implementation is fast enough that JSI offers little
21
+ * practical gain.
22
+ *
23
+ * This module pulls in `react-native-quick-crypto` at import time and must
24
+ * therefore only be imported in a React Native bundle. It is exposed via the
25
+ * dedicated `./quick-crypto-noise` subexport so the package's main entry
26
+ * remains free of React Native-only side effects.
27
+ */
28
+ import { type ICryptoInterface } from "@chainsafe/libp2p-noise";
29
+ /**
30
+ * Quick-crypto-backed Noise crypto. Inherits synchronous X25519 operations
31
+ * from `pureJsCrypto`; overrides SHA-256, HKDF, and ChaCha20-Poly1305 with
32
+ * JSI-backed implementations.
33
+ */
34
+ export declare const quickCryptoNoise: ICryptoInterface;
35
+ //# sourceMappingURL=quick-crypto-noise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quick-crypto-noise.d.ts","sourceRoot":"","sources":["../src/quick-crypto-noise.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AA0F9E;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,gBAM9B,CAAC"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * `ICryptoInterface` implementation backed by `react-native-quick-crypto`,
3
+ * intended to be passed to `noise({ crypto: quickCryptoNoise })` on React
4
+ * Native. JSI-backed primitives are noticeably faster than the pure-JS Noise
5
+ * defaults on Hermes, which matters for handshake latency and bulk transfer.
6
+ *
7
+ * Only the primitives that have a usable synchronous quick-crypto mapping are
8
+ * overridden:
9
+ *
10
+ * - `hashSHA256` — `createHash('sha256')`
11
+ * - `getHKDF` — RFC 5869 HKDF built on `createHmac('sha256', ...)`
12
+ * - `chaCha20Poly1305Encrypt` / `chaCha20Poly1305Decrypt` —
13
+ * `createCipheriv` / `createDecipheriv` with the `chacha20-poly1305`
14
+ * AEAD, 16-byte authentication tag appended to / split from the
15
+ * ciphertext per the Noise specification.
16
+ *
17
+ * X25519 key generation and shared-secret derivation are delegated to
18
+ * `pureJsCrypto` because the quick-crypto X25519 API is asynchronous
19
+ * (subtle-style) whereas `ICryptoInterface` requires synchronous methods.
20
+ * The pure-JS X25519 implementation is fast enough that JSI offers little
21
+ * practical gain.
22
+ *
23
+ * This module pulls in `react-native-quick-crypto` at import time and must
24
+ * therefore only be imported in a React Native bundle. It is exposed via the
25
+ * dedicated `./quick-crypto-noise` subexport so the package's main entry
26
+ * remains free of React Native-only side effects.
27
+ */
28
+ import { pureJsCrypto } from "@chainsafe/libp2p-noise";
29
+ import QuickCrypto from "react-native-quick-crypto";
30
+ const TAG_LENGTH = 16;
31
+ function toBytes(data) {
32
+ // `Uint8ArrayList.subarray()` returns a contiguous Uint8Array view, which
33
+ // is what quick-crypto's Node-compatible API expects.
34
+ return data instanceof Uint8Array ? data : data.subarray();
35
+ }
36
+ function hashSHA256(data) {
37
+ return QuickCrypto.createHash("sha256").update(toBytes(data)).digest();
38
+ }
39
+ function hmacSHA256(key, data) {
40
+ return QuickCrypto.createHmac("sha256", key).update(data).digest();
41
+ }
42
+ function getHKDF(ck, ikm) {
43
+ // RFC 5869 HKDF with SHA-256, three 32-byte outputs as required by the
44
+ // Noise specification. Extract step: PRK = HMAC(ck, ikm). Expand step:
45
+ // outN = HMAC(PRK, outN-1 || counter), starting from an empty previous
46
+ // block.
47
+ const prk = hmacSHA256(ck, ikm);
48
+ const out1 = hmacSHA256(prk, new Uint8Array([0x01]));
49
+ const out2Input = new Uint8Array(out1.length + 1);
50
+ out2Input.set(out1, 0);
51
+ out2Input[out1.length] = 0x02;
52
+ const out2 = hmacSHA256(prk, out2Input);
53
+ const out3Input = new Uint8Array(out2.length + 1);
54
+ out3Input.set(out2, 0);
55
+ out3Input[out2.length] = 0x03;
56
+ const out3 = hmacSHA256(prk, out3Input);
57
+ return [out1, out2, out3];
58
+ }
59
+ function chaCha20Poly1305Encrypt(plaintext, nonce, ad, k) {
60
+ const cipher = QuickCrypto.createCipheriv("chacha20-poly1305", k, nonce, {
61
+ authTagLength: TAG_LENGTH,
62
+ });
63
+ cipher.setAAD(ad);
64
+ const head = cipher.update(toBytes(plaintext));
65
+ const tail = cipher.final();
66
+ const tag = cipher.getAuthTag();
67
+ // Noise wire format: ciphertext || tag (16 bytes).
68
+ const out = new Uint8Array(head.length + tail.length + tag.length);
69
+ out.set(head, 0);
70
+ out.set(tail, head.length);
71
+ out.set(tag, head.length + tail.length);
72
+ return out;
73
+ }
74
+ function chaCha20Poly1305Decrypt(ciphertext, nonce, ad, k) {
75
+ const bytes = toBytes(ciphertext);
76
+ if (bytes.length < TAG_LENGTH) {
77
+ throw new Error("ChaCha20-Poly1305 ciphertext shorter than tag length");
78
+ }
79
+ const ct = bytes.subarray(0, bytes.length - TAG_LENGTH);
80
+ const tag = bytes.subarray(bytes.length - TAG_LENGTH);
81
+ const decipher = QuickCrypto.createDecipheriv("chacha20-poly1305", k, nonce, {
82
+ authTagLength: TAG_LENGTH,
83
+ });
84
+ decipher.setAAD(ad);
85
+ decipher.setAuthTag(tag);
86
+ const head = decipher.update(ct);
87
+ const tail = decipher.final();
88
+ const out = new Uint8Array(head.length + tail.length);
89
+ out.set(head, 0);
90
+ out.set(tail, head.length);
91
+ return out;
92
+ }
93
+ /**
94
+ * Quick-crypto-backed Noise crypto. Inherits synchronous X25519 operations
95
+ * from `pureJsCrypto`; overrides SHA-256, HKDF, and ChaCha20-Poly1305 with
96
+ * JSI-backed implementations.
97
+ */
98
+ export const quickCryptoNoise = {
99
+ ...pureJsCrypto,
100
+ hashSHA256,
101
+ getHKDF,
102
+ chaCha20Poly1305Encrypt,
103
+ chaCha20Poly1305Decrypt,
104
+ };
105
+ //# sourceMappingURL=quick-crypto-noise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quick-crypto-noise.js","sourceRoot":"","sources":["../src/quick-crypto-noise.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * A `TextEncoder` / `TextDecoder` polyfill for the React Native Hermes engine.
3
+ *
4
+ * Hermes ships neither global, yet libp2p reaches for them at
5
+ * module-evaluation time: `uint8arrays` (a transitive dependency of nearly
6
+ * every libp2p package) constructs `new TextEncoder()` / `new TextDecoder()`
7
+ * to convert between UTF-8 strings and byte arrays for peer ids, multiaddrs,
8
+ * and protocol names. Without these globals the bundle red-screens with
9
+ * `Property 'TextDecoder' doesn't exist` before any application code runs.
10
+ *
11
+ * Only UTF-8 is implemented — the single encoding libp2p uses through these
12
+ * APIs. The conversion is delegated to `Buffer` (already a required shim, see
13
+ * `polyfills`), which provides a spec-correct UTF-8 implementation including
14
+ * surrogate-pair handling and replacement of malformed sequences. Owning a
15
+ * thin wrapper here, rather than pulling in a third-party text-encoding
16
+ * package, keeps the polyfill surface small and dependency-free.
17
+ */
18
+ /**
19
+ * Install `TextEncoder` and `TextDecoder` on the global scope if the runtime
20
+ * does not already provide them. Idempotent and safe to call more than once;
21
+ * on a runtime that ships its own implementations (e.g. Node in tests) this is
22
+ * a no-op.
23
+ */
24
+ export declare function installTextCodecPolyfill(): void;
25
+ //# sourceMappingURL=text-codec-polyfill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-codec-polyfill.d.ts","sourceRoot":"","sources":["../src/text-codec-polyfill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAwFH;;;;;GAKG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAO/C"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * A `TextEncoder` / `TextDecoder` polyfill for the React Native Hermes engine.
3
+ *
4
+ * Hermes ships neither global, yet libp2p reaches for them at
5
+ * module-evaluation time: `uint8arrays` (a transitive dependency of nearly
6
+ * every libp2p package) constructs `new TextEncoder()` / `new TextDecoder()`
7
+ * to convert between UTF-8 strings and byte arrays for peer ids, multiaddrs,
8
+ * and protocol names. Without these globals the bundle red-screens with
9
+ * `Property 'TextDecoder' doesn't exist` before any application code runs.
10
+ *
11
+ * Only UTF-8 is implemented — the single encoding libp2p uses through these
12
+ * APIs. The conversion is delegated to `Buffer` (already a required shim, see
13
+ * `polyfills`), which provides a spec-correct UTF-8 implementation including
14
+ * surrogate-pair handling and replacement of malformed sequences. Owning a
15
+ * thin wrapper here, rather than pulling in a third-party text-encoding
16
+ * package, keeps the polyfill surface small and dependency-free.
17
+ */
18
+ import { Buffer } from "buffer";
19
+ const UTF8_ENCODING = "utf-8";
20
+ // The WHATWG labels that all denote UTF-8. A `TextDecoder` constructed with any
21
+ // other label must throw, matching browser behavior and surfacing accidental
22
+ // non-UTF-8 usage rather than silently misdecoding.
23
+ const UTF8_LABELS = new Set([
24
+ "utf-8",
25
+ "utf8",
26
+ "unicode-1-1-utf-8",
27
+ ]);
28
+ const bufferFactory = Buffer;
29
+ /** WHATWG `TextEncoder`, UTF-8 only. */
30
+ class PolyfillTextEncoder {
31
+ get encoding() {
32
+ return UTF8_ENCODING;
33
+ }
34
+ encode(input = "") {
35
+ return new Uint8Array(bufferFactory.from(input, "utf8"));
36
+ }
37
+ }
38
+ /**
39
+ * WHATWG `TextDecoder`, UTF-8 only.
40
+ *
41
+ * `fatal` and `ignoreBOM` are accepted and reflected as readonly properties for
42
+ * API-shape compatibility, but not honored: `Buffer.toString('utf8')` always
43
+ * replaces malformed sequences (`fatal: false`) and never strips a BOM. libp2p
44
+ * constructs decoders with default options, so this is sufficient — a caller
45
+ * relying on `fatal`/`ignoreBOM` semantics is out of this polyfill's scope.
46
+ */
47
+ class PolyfillTextDecoder {
48
+ encoding = UTF8_ENCODING;
49
+ fatal;
50
+ ignoreBOM;
51
+ constructor(label = UTF8_ENCODING, options = {}) {
52
+ if (!UTF8_LABELS.has(label.toLowerCase())) {
53
+ throw new RangeError(`Unsupported encoding: ${label}. Only UTF-8 is supported.`);
54
+ }
55
+ this.fatal = options.fatal ?? false;
56
+ this.ignoreBOM = options.ignoreBOM ?? false;
57
+ }
58
+ decode(input) {
59
+ if (input == null) {
60
+ return "";
61
+ }
62
+ const bytes = ArrayBuffer.isView(input)
63
+ ? bufferFactory.from(input.buffer, input.byteOffset, input.byteLength)
64
+ : bufferFactory.from(input);
65
+ return bytes.toString("utf8");
66
+ }
67
+ }
68
+ /**
69
+ * Install `TextEncoder` and `TextDecoder` on the global scope if the runtime
70
+ * does not already provide them. Idempotent and safe to call more than once;
71
+ * on a runtime that ships its own implementations (e.g. Node in tests) this is
72
+ * a no-op.
73
+ */
74
+ export function installTextCodecPolyfill() {
75
+ const codecScope = globalThis;
76
+ codecScope.TextEncoder ??= PolyfillTextEncoder;
77
+ codecScope.TextDecoder ??= PolyfillTextDecoder;
78
+ }
79
+ //# sourceMappingURL=text-codec-polyfill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-codec-polyfill.js","sourceRoot":"","sources":["../src/text-codec-polyfill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,MAAM,aAAa,GAAG,OAAO,CAAC;AAE9B,gFAAgF;AAChF,6EAA6E;AAC7E,oDAAoD;AACpD,MAAM,WAAW,GAAwB,IAAI,GAAG,CAAC;IAC/C,OAAO;IACP,MAAM;IACN,mBAAmB;CACpB,CAAC,CAAC;AAwBH,MAAM,aAAa,GAAG,MAAkC,CAAC;AAEzD,wCAAwC;AACxC,MAAM,mBAAmB;IACvB,IAAI,QAAQ;QACV,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,QAAgB,EAAE;QACvB,OAAO,IAAI,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3D,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,mBAAmB;IACd,QAAQ,GAAG,aAAa,CAAC;IACzB,KAAK,CAAU;IACf,SAAS,CAAU;IAE5B,YACE,QAAgB,aAAa,EAC7B,UAAkC,EAAE;QAEpC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,UAAU,CAClB,yBAAyB,KAAK,4BAA4B,CAC3D,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;IAC9C,CAAC;IAED,MAAM,CAAC,KAAqC;QAC1C,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC;YACrC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC;YACtE,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,OAAO,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB;IACtC,MAAM,UAAU,GAAG,UAGlB,CAAC;IACF,UAAU,CAAC,WAAW,KAAK,mBAAmB,CAAC;IAC/C,UAAU,CAAC,WAAW,KAAK,mBAAmB,CAAC;AACjD,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Give React Native's `RTCPeerConnection` the static `generateCertificate`
3
+ * method that `@libp2p/webrtc`'s webrtc-direct dialer requires.
4
+ *
5
+ * Metro selects the browser build of `@libp2p/webrtc` on React Native. Its
6
+ * dialer creates the peer connection like this:
7
+ *
8
+ * ```js
9
+ * const certificate = await RTCPeerConnection.generateCertificate({
10
+ * name: "ECDSA",
11
+ * namedCurve: "P-256",
12
+ * });
13
+ * new RTCPeerConnection({ certificates: [certificate] });
14
+ * ```
15
+ *
16
+ * `react-native-webrtc` (v124) implements neither the static
17
+ * `generateCertificate` method nor the `certificates` constructor option — it
18
+ * always generates its own DTLS certificate natively — so the dialer throws
19
+ * `RTCPeerConnection.generateCertificate is not a function`.
20
+ *
21
+ * Supplying a specific certificate is unnecessary for webrtc-direct. The dialer
22
+ * reads its own fingerprint back out of the generated local SDP
23
+ * (`getFingerprintFromSdp(peerConnection.localDescription.sdp)`) and binds it
24
+ * into the Noise prologue, so the certificate the native layer produces is the
25
+ * one that actually gets authenticated. We only need the call to resolve: the
26
+ * returned value is forwarded as the `certificates` option, which
27
+ * `react-native-webrtc` does not read, so a plain placeholder object that the
28
+ * native bridge can serialize is sufficient.
29
+ */
30
+ /**
31
+ * Install the static `generateCertificate` method on the global
32
+ * `RTCPeerConnection`. Idempotent, and a no-op when the global is absent
33
+ * (`registerGlobals()` has not run, or under tests) or already provides the
34
+ * method (a browser, or a future `react-native-webrtc` release).
35
+ */
36
+ export declare function installWebRtcCertificatePolyfill(): void;
37
+ //# sourceMappingURL=webrtc-certificate-polyfill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webrtc-certificate-polyfill.d.ts","sourceRoot":"","sources":["../src/webrtc-certificate-polyfill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAQH;;;;;GAKG;AACH,wBAAgB,gCAAgC,IAAI,IAAI,CAiBvD"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Give React Native's `RTCPeerConnection` the static `generateCertificate`
3
+ * method that `@libp2p/webrtc`'s webrtc-direct dialer requires.
4
+ *
5
+ * Metro selects the browser build of `@libp2p/webrtc` on React Native. Its
6
+ * dialer creates the peer connection like this:
7
+ *
8
+ * ```js
9
+ * const certificate = await RTCPeerConnection.generateCertificate({
10
+ * name: "ECDSA",
11
+ * namedCurve: "P-256",
12
+ * });
13
+ * new RTCPeerConnection({ certificates: [certificate] });
14
+ * ```
15
+ *
16
+ * `react-native-webrtc` (v124) implements neither the static
17
+ * `generateCertificate` method nor the `certificates` constructor option — it
18
+ * always generates its own DTLS certificate natively — so the dialer throws
19
+ * `RTCPeerConnection.generateCertificate is not a function`.
20
+ *
21
+ * Supplying a specific certificate is unnecessary for webrtc-direct. The dialer
22
+ * reads its own fingerprint back out of the generated local SDP
23
+ * (`getFingerprintFromSdp(peerConnection.localDescription.sdp)`) and binds it
24
+ * into the Noise prologue, so the certificate the native layer produces is the
25
+ * one that actually gets authenticated. We only need the call to resolve: the
26
+ * returned value is forwarded as the `certificates` option, which
27
+ * `react-native-webrtc` does not read, so a plain placeholder object that the
28
+ * native bridge can serialize is sufficient.
29
+ */
30
+ const CERTIFICATE_TTL_MS = 365 * 24 * 60 * 60 * 1000;
31
+ /**
32
+ * Install the static `generateCertificate` method on the global
33
+ * `RTCPeerConnection`. Idempotent, and a no-op when the global is absent
34
+ * (`registerGlobals()` has not run, or under tests) or already provides the
35
+ * method (a browser, or a future `react-native-webrtc` release).
36
+ */
37
+ export function installWebRtcCertificatePolyfill() {
38
+ const scope = globalThis;
39
+ const peerConnection = scope.RTCPeerConnection;
40
+ if (peerConnection == null) {
41
+ return;
42
+ }
43
+ if (typeof peerConnection.generateCertificate === "function") {
44
+ return;
45
+ }
46
+ peerConnection.generateCertificate = () => {
47
+ // react-native-webrtc generates its own DTLS certificate natively; libp2p
48
+ // reads the resulting fingerprint from the SDP rather than from this
49
+ // object, so a serializable placeholder is enough to satisfy the dialer.
50
+ return Promise.resolve({ expires: Date.now() + CERTIFICATE_TTL_MS });
51
+ };
52
+ }
53
+ //# sourceMappingURL=webrtc-certificate-polyfill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webrtc-certificate-polyfill.js","sourceRoot":"","sources":["../src/webrtc-certificate-polyfill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAMH,MAAM,kBAAkB,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAErD;;;;;GAKG;AACH,MAAM,UAAU,gCAAgC;IAC9C,MAAM,KAAK,GAAG,UAEb,CAAC;IACF,MAAM,cAAc,GAAG,KAAK,CAAC,iBAAiB,CAAC;IAC/C,IAAI,cAAc,IAAI,IAAI,EAAE,CAAC;QAC3B,OAAO;IACT,CAAC;IACD,IAAI,OAAO,cAAc,CAAC,mBAAmB,KAAK,UAAU,EAAE,CAAC;QAC7D,OAAO;IACT,CAAC;IACD,cAAc,CAAC,mBAAmB,GAAG,GAAqB,EAAE;QAC1D,0EAA0E;QAC1E,qEAAqE;QACrE,yEAAyE;QACzE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,kBAAkB,EAAE,CAAC,CAAC;IACvE,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Make React Native's `WebSocket` report a numeric `bufferedAmount`.
3
+ *
4
+ * React Native declares `bufferedAmount` on its `WebSocket` but never assigns
5
+ * it, so it reads as `undefined`. `@libp2p/websockets` drives write backpressure
6
+ * off that value, and the `undefined` comparisons leave every write parked
7
+ * waiting for a `drain` that never fires, hanging the connection.
8
+ *
9
+ * React Native hands every frame straight to the native socket with no
10
+ * JS-visible send buffer to measure, so `0` ("fully flushed") is the correct,
11
+ * backpressure-free answer. A prototype accessor returns `0` for reads and
12
+ * swallows React Native's `undefined` field initialization with a no-op setter,
13
+ * so no shadowing own property is left on the instance.
14
+ */
15
+ /**
16
+ * Install the `bufferedAmount` accessor on the global `WebSocket` prototype.
17
+ * Idempotent, and a no-op when the runtime already exposes a real getter (e.g.
18
+ * a browser or Node polyfill) or provides no `WebSocket` at all (e.g. tests).
19
+ */
20
+ export declare function installWebSocketBufferedAmountPolyfill(): void;
21
+ //# sourceMappingURL=websocket-buffered-amount-polyfill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-buffered-amount-polyfill.d.ts","sourceRoot":"","sources":["../src/websocket-buffered-amount-polyfill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH;;;;GAIG;AACH,wBAAgB,sCAAsC,IAAI,IAAI,CAoB7D"}