@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.
- package/README.md +155 -0
- package/dist/datachannel-early-message-polyfill.d.ts +23 -0
- package/dist/datachannel-early-message-polyfill.d.ts.map +1 -0
- package/dist/datachannel-early-message-polyfill.js +131 -0
- package/dist/datachannel-early-message-polyfill.js.map +1 -0
- package/dist/event-target-polyfill.d.ts +40 -0
- package/dist/event-target-polyfill.d.ts.map +1 -0
- package/dist/event-target-polyfill.js +192 -0
- package/dist/event-target-polyfill.js.map +1 -0
- package/dist/factories.d.ts +68 -0
- package/dist/factories.d.ts.map +1 -0
- package/dist/factories.js +73 -0
- package/dist/factories.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/polyfills.d.ts +41 -0
- package/dist/polyfills.d.ts.map +1 -0
- package/dist/polyfills.js +67 -0
- package/dist/polyfills.js.map +1 -0
- package/dist/quick-crypto-noise.d.ts +35 -0
- package/dist/quick-crypto-noise.d.ts.map +1 -0
- package/dist/quick-crypto-noise.js +105 -0
- package/dist/quick-crypto-noise.js.map +1 -0
- package/dist/text-codec-polyfill.d.ts +25 -0
- package/dist/text-codec-polyfill.d.ts.map +1 -0
- package/dist/text-codec-polyfill.js +79 -0
- package/dist/text-codec-polyfill.js.map +1 -0
- package/dist/webrtc-certificate-polyfill.d.ts +37 -0
- package/dist/webrtc-certificate-polyfill.d.ts.map +1 -0
- package/dist/webrtc-certificate-polyfill.js +53 -0
- package/dist/webrtc-certificate-polyfill.js.map +1 -0
- package/dist/websocket-buffered-amount-polyfill.d.ts +21 -0
- package/dist/websocket-buffered-amount-polyfill.d.ts.map +1 -0
- package/dist/websocket-buffered-amount-polyfill.js +41 -0
- package/dist/websocket-buffered-amount-polyfill.js.map +1 -0
- package/package.json +78 -0
- package/src/datachannel-early-message-polyfill.ts +176 -0
- package/src/event-target-polyfill.ts +268 -0
- package/src/factories.ts +116 -0
- package/src/index.ts +10 -0
- package/src/polyfills.ts +72 -0
- package/src/quick-crypto-noise.ts +130 -0
- package/src/rn-modules.d.ts +100 -0
- package/src/text-codec-polyfill.ts +118 -0
- package/src/webrtc-certificate-polyfill.ts +60 -0
- 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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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 @@
|
|
|
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":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,YAAY,EAAyB,MAAM,yBAAyB,CAAC;AAC9E,OAAO,WAAW,MAAM,2BAA2B,CAAC;AAGpD,MAAM,UAAU,GAAG,EAAE,CAAC;AAEtB,SAAS,OAAO,CAAC,IAAiC;IAChD,0EAA0E;IAC1E,sDAAsD;IACtD,OAAO,IAAI,YAAY,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;AAC7D,CAAC;AAED,SAAS,UAAU,CAAC,IAAiC;IACnD,OAAO,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;AACzE,CAAC;AAED,SAAS,UAAU,CAAC,GAAe,EAAE,IAAgB;IACnD,OAAO,WAAW,CAAC,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;AACrE,CAAC;AAED,SAAS,OAAO,CACd,EAAc,EACd,GAAe;IAEf,uEAAuE;IACvE,uEAAuE;IACvE,uEAAuE;IACvE,SAAS;IACT,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,EAAE,IAAI,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAErD,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAClD,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACvB,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC9B,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAExC,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAClD,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACvB,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC9B,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAExC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,uBAAuB,CAC9B,SAAsC,EACtC,KAAiB,EACjB,EAAc,EACd,CAAa;IAEb,MAAM,MAAM,GAAG,WAAW,CAAC,cAAc,CAAC,mBAAmB,EAAE,CAAC,EAAE,KAAK,EAAE;QACvE,aAAa,EAAE,UAAU;KAC1B,CAAC,CAAC;IACH,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAClB,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;IAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IAChC,mDAAmD;IACnD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IACnE,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACjB,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3B,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IACxC,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,uBAAuB,CAC9B,UAAuC,EACvC,KAAiB,EACjB,EAAc,EACd,CAAa;IAEb,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAClC,IAAI,KAAK,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;IACxD,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,WAAW,CAAC,gBAAgB,CAAC,mBAAmB,EAAE,CAAC,EAAE,KAAK,EAAE;QAC3E,aAAa,EAAE,UAAU;KAC1B,CAAC,CAAC;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACpB,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IACtD,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACjB,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3B,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAqB;IAChD,GAAG,YAAY;IACf,UAAU;IACV,OAAO;IACP,uBAAuB;IACvB,uBAAuB;CACxB,CAAC"}
|
|
@@ -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"}
|