@peerbit/react 0.0.3 → 0.0.5

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.
@@ -1,3 +1,4 @@
1
- export { PeerProvider, PeerContext, usePeer, submitKeypairChange, } from "./usePeer.js";
1
+ export { PeerProvider, PeerContext, usePeer } from "./usePeer.js";
2
2
  export * from "./utils.js";
3
3
  export { FastMutex } from "./lockstorage.js";
4
+ export { useProgram } from "./useProgram.js";
package/lib/esm/index.js CHANGED
@@ -1,4 +1,5 @@
1
- export { PeerProvider, PeerContext, usePeer, submitKeypairChange, } from "./usePeer.js";
1
+ export { PeerProvider, PeerContext, usePeer } from "./usePeer.js";
2
2
  export * from "./utils.js";
3
3
  export { FastMutex } from "./lockstorage.js";
4
+ export { useProgram } from "./useProgram.js";
4
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,YAAY,EACZ,WAAW,EACX,OAAO,EACP,mBAAmB,GACtB,MAAM,cAAc,CAAC;AACtB,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAClE,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,25 +1,39 @@
1
1
  import React from "react";
2
2
  import { Multiaddr } from "@multiformats/multiaddr";
3
- import { Peerbit } from "peerbit";
4
3
  import { Ed25519Keypair } from "@peerbit/crypto";
4
+ import { ProgramClient } from "@peerbit/program";
5
5
  export type ConnectionStatus = "disconnected" | "connected" | "connecting" | "failed";
6
6
  interface IPeerContext {
7
- peer: Peerbit | undefined;
7
+ peer: ProgramClient | undefined;
8
8
  promise: Promise<void> | undefined;
9
9
  loading: boolean;
10
10
  status: ConnectionStatus;
11
11
  }
12
- export declare const subscribeToKeypairChange: (onChange: (keypair: Ed25519Keypair) => any) => void;
13
- export declare const submitKeypairChange: (element: HTMLIFrameElement, keypair: Ed25519Keypair, origin: string) => void;
14
12
  export declare const PeerContext: React.Context<IPeerContext>;
15
13
  export declare const usePeer: () => IPeerContext;
16
- export declare const PeerProvider: ({ network, bootstrap, children, inMemory, keypair, waitForConnnected, waitForKeypairInIFrame, }: {
14
+ type IFrameOptions = {
15
+ type: "proxy";
16
+ targetOrigin: string;
17
+ };
18
+ type NodeOptions = {
19
+ type?: "node";
17
20
  network: "local" | "remote";
18
- inMemory?: boolean | undefined;
19
- waitForConnnected?: boolean | undefined;
20
- keypair?: Ed25519Keypair | undefined;
21
- waitForKeypairInIFrame?: boolean | undefined;
22
- bootstrap?: (string | Multiaddr)[] | undefined;
21
+ waitForConnnected?: boolean;
22
+ keypair?: Ed25519Keypair;
23
+ bootstrap?: (Multiaddr | string)[];
24
+ host?: boolean;
25
+ };
26
+ type TopOptions = NodeOptions & WithMemory;
27
+ type TopAndIframeOptions = {
28
+ iframe: IFrameOptions | NodeOptions;
29
+ top: TopOptions;
30
+ };
31
+ type WithMemory = {
32
+ inMemory?: boolean;
33
+ };
34
+ type WithChildren = {
23
35
  children: JSX.Element;
24
- }) => import("react/jsx-runtime").JSX.Element;
36
+ };
37
+ type PeerOptions = (TopAndIframeOptions | TopOptions) & WithChildren;
38
+ export declare const PeerProvider: (options: PeerOptions) => import("react/jsx-runtime").JSX.Element;
25
39
  export {};
@@ -1,41 +1,25 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import React, { useContext } from "react";
3
- import { multiaddr } from "@multiformats/multiaddr";
4
3
  import { Peerbit } from "peerbit";
5
4
  import { webSockets } from "@libp2p/websockets";
5
+ import { DirectSub } from "@peerbit/pubsub";
6
6
  import { mplex } from "@libp2p/mplex";
7
7
  import { getFreeKeypair, getTabId, inIframe } from "./utils.js";
8
- import { resolveBootstrapAddresses } from "@peerbit/network-utils";
9
8
  import { noise } from "@dao-xyz/libp2p-noise";
10
9
  import { v4 as uuid } from "uuid";
11
- import { Ed25519Keypair } from "@peerbit/crypto";
12
10
  import { FastMutex } from "./lockstorage.js";
13
- import { serialize, deserialize } from "@dao-xyz/borsh";
14
- import { waitFor } from "@peerbit/time";
15
11
  import sodium from "libsodium-wrappers";
16
12
  import * as filters from "@libp2p/websockets/filters";
17
13
  import { useMount } from "./useMount.js";
14
+ import { createClient, createHost } from "@peerbit/proxy-window";
15
+ import { identifyService } from "libp2p/identify";
16
+ import { detectIncognito } from "detectincognitojs";
18
17
  if (!window.name) {
19
18
  window.name = uuid();
20
19
  }
21
- export const subscribeToKeypairChange = (onChange) => {
22
- window.onmessage = (c) => {
23
- if (c.data.type == "keypair") {
24
- onChange(deserialize(c.data.bytes, Ed25519Keypair));
25
- }
26
- };
27
- };
28
- export const submitKeypairChange = (element, keypair, origin) => {
29
- element.contentWindow.postMessage({ type: "keypair", bytes: serialize(keypair) }, origin);
30
- };
31
- let keypairMessages = [];
32
- subscribeToKeypairChange((keypair) => {
33
- console.log("got keypair!", keypair);
34
- keypairMessages.push(keypair);
35
- });
36
20
  export const PeerContext = React.createContext({});
37
21
  export const usePeer = () => useContext(PeerContext);
38
- export const PeerProvider = ({ network, bootstrap, children, inMemory, keypair, waitForConnnected, waitForKeypairInIFrame, }) => {
22
+ export const PeerProvider = (options) => {
39
23
  const [peer, setPeer] = React.useState(undefined);
40
24
  const [promise, setPromise] = React.useState(undefined);
41
25
  const [loading, setLoading] = React.useState(false);
@@ -50,131 +34,136 @@ export const PeerProvider = ({ network, bootstrap, children, inMemory, keypair,
50
34
  loading,
51
35
  !!promise,
52
36
  connectionState,
53
- peer?.identity?.publicKey.toString(),
37
+ peer?.identity?.publicKey?.hashcode(),
54
38
  ]);
55
39
  useMount(() => {
56
40
  setLoading(true);
57
- const fn = async (keypair = keypairMessages[keypairMessages.length - 1]) => {
41
+ const fn = async () => {
58
42
  await sodium.ready;
59
- if (!keypair && waitForKeypairInIFrame && inIframe()) {
60
- await waitFor(() => (keypair = keypairMessages[keypairMessages.length - 1]));
61
- }
62
- if (keypair &&
63
- keypairMessages[keypairMessages.length - 1] &&
64
- keypairMessages[keypairMessages.length - 1].equals(keypair)) {
65
- console.log("Creating client from identity sent from parent window: " +
66
- keypair.publicKey.hashcode());
67
- }
68
- else {
69
- if (!keypair) {
70
- console.log("Generating new keypair for client");
71
- }
72
- else {
73
- console.log("Keypair missmatch with latest keypair message", keypairMessages.map((x) => x.publicKey.hashcode()), keypair.publicKey.hashcode());
74
- }
75
- }
76
43
  if (peer) {
77
44
  await peer.stop();
78
45
  setPeer(undefined);
79
46
  }
80
- const nodeId = keypair ||
81
- (await getFreeKeypair("", new FastMutex({ clientId: getTabId(), timeout: 1000 }), undefined, true // reuse keypairs from same tab, (force release)
82
- )).key;
83
- // We create a new directrory to make tab to tab communication go smoothly
84
- const newPeer = await Peerbit.create({
85
- libp2p: {
86
- addresses: {
87
- listen: [
88
- /* '/webrtc' */
89
- ],
90
- },
91
- connectionEncryption: [noise()],
92
- peerId: await nodeId.toPeerId(),
93
- connectionManager: {
94
- maxConnections: 100,
95
- minConnections: 0,
96
- },
97
- streamMuxers: [mplex()],
98
- ...(network === "local"
99
- ? {
100
- connectionGater: {
101
- denyDialMultiaddr: () => {
102
- // by default we refuse to dial local addresses from the browser since they
103
- // are usually sent by remote peers broadcasting undialable multiaddrs but
104
- // here we are explicitly connecting to a local node so do not deny dialing
105
- // any discovered address
106
- return false;
107
- },
108
- },
109
- transports: [
110
- // Add websocket impl so we can connect to "unsafe" ws (production only allows wss)
111
- webSockets({
112
- filter: filters.all,
113
- }),
114
- /* circuitRelayTransport({ discoverRelays: 1 }),
115
- webRTC(), */
47
+ let newPeer;
48
+ const nodeOptions = options.top
49
+ ? inIframe()
50
+ ? options.iframe
51
+ : options.top
52
+ : options;
53
+ if (nodeOptions.type !== "proxy") {
54
+ const nodeId = nodeOptions.keypair ||
55
+ (await getFreeKeypair("", new FastMutex({
56
+ clientId: getTabId(),
57
+ timeout: 1000,
58
+ }), undefined, true // reuse keypairs from same tab, (force release)
59
+ )).key;
60
+ // We create a new directrory to make tab to tab communication go smoothly
61
+ newPeer = await Peerbit.create({
62
+ libp2p: {
63
+ addresses: {
64
+ listen: [
65
+ /* "/webrtc" */
116
66
  ],
117
- }
118
- : {
119
- connectionGater: {
120
- denyDialMultiaddr: () => {
121
- // by default we refuse to dial local addresses from the browser since they
122
- // are usually sent by remote peers broadcasting undialable multiaddrs but
123
- // here we are explicitly connecting to a local node so do not deny dialing
124
- // any discovered address
125
- return false;
67
+ },
68
+ connectionEncryption: [noise()],
69
+ peerId: await nodeId.toPeerId(),
70
+ connectionManager: {
71
+ maxConnections: 100,
72
+ minConnections: 0,
73
+ },
74
+ streamMuxers: [mplex() /* , mplex() */],
75
+ ...(nodeOptions.network === "local"
76
+ ? {
77
+ connectionGater: {
78
+ denyDialMultiaddr: () => {
79
+ // by default we refuse to dial local addresses from the browser since they
80
+ // are usually sent by remote peers broadcasting undialable multiaddrs but
81
+ // here we are explicitly connecting to a local node so do not deny dialing
82
+ // any discovered address
83
+ return false;
84
+ },
126
85
  },
127
- },
128
- transports: [
129
- webSockets({ filter: filters.all }),
130
- /* circuitRelayTransport({ discoverRelays: 1 }),
131
- webRTC(), */
132
- ],
133
- }),
134
- },
135
- directory: !inMemory ? "./repo" : undefined,
136
- limitSigning: true,
137
- });
138
- setConnectionState("connecting");
139
- // Resolve bootstrap nodes async (we want to return before this is done)
140
- const connectFn = async () => {
141
- try {
142
- const addresses = await (bootstrap
143
- ? Promise.resolve(bootstrap)
144
- : resolveBootstrapAddresses(network));
145
- if (addresses && addresses?.length > 0) {
146
- try {
147
- await Promise.all(addresses
148
- .map((a) => typeof a === "string" ? multiaddr(a) : a)
149
- .map((a) => newPeer.dial(a)));
150
- setConnectionState("connected");
86
+ transports: [
87
+ // Add websocket impl so we can connect to "unsafe" ws (production only allows wss)
88
+ webSockets({
89
+ filter: filters.all,
90
+ }),
91
+ /* circuitRelayTransport({
92
+ discoverRelays: 1,
93
+ }),
94
+ webRTC(), */
95
+ /* circuitRelayTransport({ discoverRelays: 1 }),
96
+ webRTC(), */
97
+ ],
98
+ }
99
+ : {
100
+ transports: [
101
+ webSockets({ filter: filters.wss }),
102
+ /* circuitRelayTransport({
103
+ discoverRelays: 1,
104
+ }),
105
+ webRTC(), */
106
+ ],
107
+ }),
108
+ services: {
109
+ pubsub: (c) => new DirectSub(c, {
110
+ canRelayMessage: true,
111
+ emitSelf: true,
112
+ /* connectionManager: {
113
+ autoDial: false,
114
+ }, */
115
+ }),
116
+ identify: identifyService(),
117
+ },
118
+ },
119
+ directory: !nodeOptions.inMemory &&
120
+ !(await detectIncognito()).isPrivate
121
+ ? "./repo"
122
+ : undefined,
123
+ });
124
+ setConnectionState("connecting");
125
+ // Resolve bootstrap nodes async (we want to return before this is done)
126
+ const connectFn = async () => {
127
+ try {
128
+ if (nodeOptions.network === "local") {
129
+ await newPeer.dial("/ip4/127.0.0.1/tcp/8002/ws/p2p/" +
130
+ (await (await fetch("http://localhost:8082/peer/id")).text()));
151
131
  }
152
- catch (error) {
153
- console.error("Failed to resolve relay node. Please come back later or start the demo locally");
154
- setConnectionState("failed");
155
- throw error;
132
+ else {
133
+ // TODO fix types. When proxy client this will not be available
134
+ if (nodeOptions.bootstrap) {
135
+ for (const addr of nodeOptions.bootstrap) {
136
+ await newPeer.dial(addr);
137
+ }
138
+ }
139
+ else {
140
+ await newPeer["bootstrap"]?.();
141
+ }
156
142
  }
143
+ setConnectionState("connected");
157
144
  }
158
- else {
159
- console.error("No addresses to connect to");
145
+ catch (err) {
146
+ console.error("Failed to resolve relay addresses. " + err?.message);
160
147
  setConnectionState("failed");
161
148
  }
149
+ if (nodeOptions.host) {
150
+ newPeer = await createHost(newPeer);
151
+ }
152
+ };
153
+ const promise = connectFn();
154
+ // Make sure data flow as expected between tabs and windows locally (offline states)
155
+ if (nodeOptions.waitForConnnected !== false) {
156
+ await promise;
162
157
  }
163
- catch (err) {
164
- console.error("Failed to resolve relay addresses. " + err?.message);
165
- setConnectionState("failed");
166
- }
167
- };
168
- const promise = connectFn();
169
- // Make sure data flow as expected between tabs and windows locally (offline states)
170
- if (waitForConnnected) {
171
- await promise;
158
+ }
159
+ else {
160
+ newPeer = await createClient(nodeOptions.targetOrigin);
172
161
  }
173
162
  setPeer(newPeer);
174
163
  setLoading(false);
175
164
  };
176
- setPromise(fn(keypair));
165
+ setPromise(fn());
177
166
  });
178
- return _jsx(PeerContext.Provider, { value: memo, children: children });
167
+ return (_jsx(PeerContext.Provider, { value: memo, children: options.children }));
179
168
  };
180
169
  //# sourceMappingURL=usePeer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"usePeer.js","sourceRoot":"","sources":["../../src/usePeer.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"usePeer.js","sourceRoot":"","sources":["../../src/usePeer.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Program, ProgramEvents, OpenOptions } from "@peerbit/program";
2
+ export declare const useProgram: <A, B extends ProgramEvents, P extends Program<A, B>>(addressOrOpen: string | P, options?: OpenOptions<A, P> | undefined) => {
3
+ program: P | undefined;
4
+ loading: boolean;
5
+ promise: Promise<P> | undefined;
6
+ };
@@ -0,0 +1,38 @@
1
+ import { usePeer } from "./usePeer.js";
2
+ import { useEffect, useRef, useState } from "react";
3
+ const addressOrUndefined = (p) => {
4
+ try {
5
+ return p.address;
6
+ }
7
+ catch (error) {
8
+ return undefined;
9
+ }
10
+ };
11
+ export const useProgram = (addressOrOpen, options) => {
12
+ const { peer } = usePeer();
13
+ let [program, setProgram] = useState();
14
+ let programRef = useRef();
15
+ let [loading, setLoading] = useState(false);
16
+ useEffect(() => {
17
+ if (!peer || !addressOrOpen) {
18
+ return;
19
+ }
20
+ setLoading(true);
21
+ programRef.current = peer
22
+ ?.open(addressOrOpen, { ...options, existing: "reuse" })
23
+ .then((p) => {
24
+ setProgram(p);
25
+ return p;
26
+ })
27
+ .finally(() => {
28
+ setLoading(false);
29
+ });
30
+ }, [
31
+ peer?.identity.publicKey.hashcode(),
32
+ typeof addressOrOpen === "string"
33
+ ? addressOrOpen
34
+ : addressOrUndefined(addressOrOpen),
35
+ ]);
36
+ return { program, loading, promise: programRef.current };
37
+ };
38
+ //# sourceMappingURL=useProgram.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useProgram.js","sourceRoot":"","sources":["../../src/useProgram.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEpD,MAAM,kBAAkB,GAAG,CAKvB,CAAI,EACN,EAAE;IACA,IAAI;QACA,OAAO,CAAC,CAAC,OAAO,CAAC;KACpB;IAAC,OAAO,KAAK,EAAE;QACZ,OAAO,SAAS,CAAC;KACpB;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CACtB,aAAyB,EACzB,OAA2B,EAC7B,EAAE;IACA,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC;IAC3B,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,EAAiB,CAAC;IACtD,IAAI,UAAU,GAAG,MAAM,EAAc,CAAC;IACtC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE5C,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE;YACzB,OAAO;SACV;QACD,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,UAAU,CAAC,OAAO,GAAG,IAAI;YACrB,EAAE,IAAI,CAAC,aAAa,EAAE,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;aACvD,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YACR,UAAU,CAAC,CAAC,CAAC,CAAC;YACd,OAAO,CAAC,CAAC;QACb,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACV,UAAU,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;IACX,CAAC,EAAE;QACC,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE;QACnC,OAAO,aAAa,KAAK,QAAQ;YAC7B,CAAC,CAAC,aAAa;YACf,CAAC,CAAC,kBAAkB,CAAC,aAAa,CAAC;KAC1C,CAAC,CAAC;IACH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC;AAC7D,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peerbit/react",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "homepage": "https://dao-xyz.github.io/peerbit-examples",
5
5
  "module": "lib/esm/index.js",
6
6
  "types": "lib/esm/index.d.ts",
@@ -22,19 +22,17 @@
22
22
  "react": "*"
23
23
  },
24
24
  "dependencies": {
25
- "@emotion/react": "^11.10.5",
26
- "@emotion/styled": "^11.10.5",
27
- "@libp2p/webrtc": "^2.0.11",
28
- "@mui/icons-material": "^5.10.16",
29
- "@mui/material": "^5.10.13",
30
- "@peerbit/network-utils": "^0.0.2",
25
+ "@chainsafe/libp2p-yamux": "^5.0.0",
26
+ "@libp2p/webrtc": "^3.2.1",
27
+ "@peerbit/proxy-window": "^1.0.1",
31
28
  "@types/react": "^18.0.25",
32
29
  "@types/react-dom": "^18.0.8",
30
+ "detectincognitojs": "^1.3.0",
33
31
  "path-browserify": "^1.0.1",
34
- "peerbit": "^1.1.5",
32
+ "peerbit": "^2",
35
33
  "react": "^18.2.0",
36
34
  "react-dom": "^18.2.0",
37
- "react-router-dom": "^6.8.0",
35
+ "react-router-dom": "^6.16.0",
38
36
  "react-use": "^17.4.0"
39
37
  },
40
38
  "devDependencies": {
@@ -42,7 +40,6 @@
42
40
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
43
41
  "@babel/plugin-transform-typescript": "^7.20.2",
44
42
  "@types/sinon": "^10.0.13",
45
- "gh-pages": "^4.0.0",
46
43
  "node-localstorage": "^2.2.1",
47
44
  "sinon": "^15.0.1"
48
45
  },
@@ -72,5 +69,5 @@
72
69
  "last 1 safari version"
73
70
  ]
74
71
  },
75
- "gitHead": "f8266c28458441809aeeabaf2d686995ce05e707"
72
+ "gitHead": "00c275554aa08e6a70bceaee3e3377936ca0e8d9"
76
73
  }
package/src/index.ts CHANGED
@@ -1,8 +1,4 @@
1
- export {
2
- PeerProvider,
3
- PeerContext,
4
- usePeer,
5
- submitKeypairChange,
6
- } from "./usePeer.js";
1
+ export { PeerProvider, PeerContext, usePeer } from "./usePeer.js";
7
2
  export * from "./utils.js";
8
3
  export { FastMutex } from "./lockstorage.js";
4
+ export { useProgram } from "./useProgram.js";
package/src/usePeer.tsx CHANGED
@@ -2,25 +2,33 @@ import React, { useContext } from "react";
2
2
  import { multiaddr, Multiaddr } from "@multiformats/multiaddr";
3
3
  import { Peerbit } from "peerbit";
4
4
  import { webSockets } from "@libp2p/websockets";
5
+ import { DirectSub } from "@peerbit/pubsub";
6
+
5
7
  import { mplex } from "@libp2p/mplex";
8
+ import { yamux } from "@chainsafe/libp2p-yamux";
9
+
6
10
  import { getFreeKeypair, getTabId, inIframe } from "./utils.js";
7
- import { resolveBootstrapAddresses } from "@peerbit/network-utils";
8
11
  import { noise } from "@dao-xyz/libp2p-noise";
9
12
  import { v4 as uuid } from "uuid";
10
13
  import { Ed25519Keypair } from "@peerbit/crypto";
11
14
  import { FastMutex } from "./lockstorage.js";
12
- import { serialize, deserialize } from "@dao-xyz/borsh";
13
- import { waitFor } from "@peerbit/time";
14
15
  import sodium from "libsodium-wrappers";
15
16
  import * as filters from "@libp2p/websockets/filters";
16
17
  import { useMount } from "./useMount.js";
18
+ import { createClient, createHost } from "@peerbit/proxy-window";
19
+ import { ProgramClient } from "@peerbit/program";
20
+ import { circuitRelayTransport } from "libp2p/circuit-relay";
21
+ import { webRTC } from "@libp2p/webrtc";
22
+ import { identifyService } from "libp2p/identify";
23
+ import { detectIncognito } from "detectincognitojs";
24
+
17
25
  export type ConnectionStatus =
18
26
  | "disconnected"
19
27
  | "connected"
20
28
  | "connecting"
21
29
  | "failed";
22
30
  interface IPeerContext {
23
- peer: Peerbit | undefined;
31
+ peer: ProgramClient | undefined;
24
32
  promise: Promise<void> | undefined;
25
33
  loading: boolean;
26
34
  status: ConnectionStatus;
@@ -30,59 +38,38 @@ if (!window.name) {
30
38
  window.name = uuid();
31
39
  }
32
40
 
33
- interface KeypairMessage {
34
- type: "keypair";
35
- bytes: Uint8Array;
36
- }
37
- export const subscribeToKeypairChange = (
38
- onChange: (keypair: Ed25519Keypair) => any
39
- ) => {
40
- window.onmessage = (c: MessageEvent) => {
41
- if ((c.data as KeypairMessage).type == "keypair") {
42
- onChange(
43
- deserialize((c.data as KeypairMessage).bytes, Ed25519Keypair)
44
- );
45
- }
46
- };
47
- };
48
-
49
- export const submitKeypairChange = (
50
- element: HTMLIFrameElement,
51
- keypair: Ed25519Keypair,
52
- origin: string
53
- ) => {
54
- element.contentWindow!.postMessage(
55
- { type: "keypair", bytes: serialize(keypair) } as KeypairMessage,
56
- origin
57
- );
58
- };
59
-
60
- let keypairMessages: Ed25519Keypair[] = [];
61
- subscribeToKeypairChange((keypair) => {
62
- console.log("got keypair!", keypair);
63
- keypairMessages.push(keypair);
64
- });
65
-
66
41
  export const PeerContext = React.createContext<IPeerContext>({} as any);
67
42
  export const usePeer = () => useContext(PeerContext);
68
- export const PeerProvider = ({
69
- network,
70
- bootstrap,
71
- children,
72
- inMemory,
73
- keypair,
74
- waitForConnnected,
75
- waitForKeypairInIFrame,
76
- }: {
43
+ type IFrameOptions = {
44
+ type: "proxy";
45
+ targetOrigin: string;
46
+ };
47
+
48
+ type NodeOptions = {
49
+ type?: "node";
77
50
  network: "local" | "remote";
78
- inMemory?: boolean;
79
51
  waitForConnnected?: boolean;
80
52
  keypair?: Ed25519Keypair;
81
- waitForKeypairInIFrame?: boolean;
82
53
  bootstrap?: (Multiaddr | string)[];
54
+ host?: boolean;
55
+ };
56
+ type TopOptions = NodeOptions & WithMemory;
57
+ type TopAndIframeOptions = {
58
+ iframe: IFrameOptions | NodeOptions;
59
+ top: TopOptions;
60
+ };
61
+ type WithMemory = {
62
+ inMemory?: boolean;
63
+ };
64
+ type WithChildren = {
83
65
  children: JSX.Element;
84
- }) => {
85
- const [peer, setPeer] = React.useState<Peerbit | undefined>(undefined);
66
+ };
67
+ type PeerOptions = (TopAndIframeOptions | TopOptions) & WithChildren;
68
+
69
+ export const PeerProvider = (options: PeerOptions) => {
70
+ const [peer, setPeer] = React.useState<ProgramClient | undefined>(
71
+ undefined
72
+ );
86
73
  const [promise, setPromise] = React.useState<Promise<void> | undefined>(
87
74
  undefined
88
75
  );
@@ -102,169 +89,167 @@ export const PeerProvider = ({
102
89
  loading,
103
90
  !!promise,
104
91
  connectionState,
105
- peer?.identity?.publicKey.toString(),
92
+ peer?.identity?.publicKey?.hashcode(),
106
93
  ]
107
94
  );
108
95
 
109
96
  useMount(() => {
110
97
  setLoading(true);
111
- const fn = async (
112
- keypair: Ed25519Keypair = keypairMessages[
113
- keypairMessages.length - 1
114
- ]
115
- ) => {
98
+ const fn = async () => {
116
99
  await sodium.ready;
117
-
118
- if (!keypair && waitForKeypairInIFrame && inIframe()) {
119
- await waitFor(
120
- () =>
121
- (keypair = keypairMessages[keypairMessages.length - 1])
122
- );
123
- }
124
-
125
- if (
126
- keypair &&
127
- keypairMessages[keypairMessages.length - 1] &&
128
- keypairMessages[keypairMessages.length - 1].equals(keypair)
129
- ) {
130
- console.log(
131
- "Creating client from identity sent from parent window: " +
132
- keypair.publicKey.hashcode()
133
- );
134
- } else {
135
- if (!keypair) {
136
- console.log("Generating new keypair for client");
137
- } else {
138
- console.log(
139
- "Keypair missmatch with latest keypair message",
140
- keypairMessages.map((x) => x.publicKey.hashcode()),
141
- keypair.publicKey.hashcode()
142
- );
143
- }
144
- }
145
-
146
100
  if (peer) {
147
101
  await peer.stop();
148
102
  setPeer(undefined);
149
103
  }
150
104
 
151
- const nodeId =
152
- keypair ||
153
- (
154
- await getFreeKeypair(
155
- "",
156
- new FastMutex({ clientId: getTabId(), timeout: 1000 }),
157
- undefined,
158
- true // reuse keypairs from same tab, (force release)
159
- )
160
- ).key;
161
-
162
- // We create a new directrory to make tab to tab communication go smoothly
163
- const newPeer = await Peerbit.create({
164
- libp2p: {
165
- addresses: {
166
- listen: [
167
- /* '/webrtc' */
168
- ],
169
- },
170
- connectionEncryption: [noise()],
171
- peerId: await nodeId.toPeerId(), //, having the same peer accross broswers does not work, only one tab will be recognized by other peers
172
- connectionManager: {
173
- maxConnections: 100,
174
- minConnections: 0,
175
- },
176
- streamMuxers: [mplex()],
177
- ...(network === "local"
178
- ? {
179
- connectionGater: {
180
- denyDialMultiaddr: () => {
181
- // by default we refuse to dial local addresses from the browser since they
182
- // are usually sent by remote peers broadcasting undialable multiaddrs but
183
- // here we are explicitly connecting to a local node so do not deny dialing
184
- // any discovered address
185
- return false;
105
+ let newPeer: ProgramClient;
106
+ const nodeOptions = (options as TopAndIframeOptions).top
107
+ ? inIframe()
108
+ ? (options as TopAndIframeOptions).iframe
109
+ : (options as TopAndIframeOptions).top
110
+ : (options as TopOptions);
111
+ if (nodeOptions.type !== "proxy") {
112
+ const nodeId =
113
+ nodeOptions.keypair ||
114
+ (
115
+ await getFreeKeypair(
116
+ "",
117
+ new FastMutex({
118
+ clientId: getTabId(),
119
+ timeout: 1000,
120
+ }),
121
+ undefined,
122
+ true // reuse keypairs from same tab, (force release)
123
+ )
124
+ ).key;
125
+
126
+ // We create a new directrory to make tab to tab communication go smoothly
127
+ newPeer = await Peerbit.create({
128
+ libp2p: {
129
+ addresses: {
130
+ listen: [
131
+ /* "/webrtc" */
132
+ ],
133
+ },
134
+ connectionEncryption: [noise()],
135
+ peerId: await nodeId.toPeerId(), //, having the same peer accross broswers does not work, only one tab will be recognized by other peers
136
+ connectionManager: {
137
+ maxConnections: 100,
138
+ minConnections: 0,
139
+ },
140
+
141
+ streamMuxers: [mplex() /* , mplex() */],
142
+ ...(nodeOptions.network === "local"
143
+ ? {
144
+ connectionGater: {
145
+ denyDialMultiaddr: () => {
146
+ // by default we refuse to dial local addresses from the browser since they
147
+ // are usually sent by remote peers broadcasting undialable multiaddrs but
148
+ // here we are explicitly connecting to a local node so do not deny dialing
149
+ // any discovered address
150
+ return false;
151
+ },
186
152
  },
187
- },
188
- transports: [
189
- // Add websocket impl so we can connect to "unsafe" ws (production only allows wss)
190
- webSockets({
191
- filter: filters.all,
192
- }),
193
- /* circuitRelayTransport({ discoverRelays: 1 }),
194
- webRTC(), */
195
- ],
196
- }
197
- : {
198
- connectionGater: {
199
- denyDialMultiaddr: () => {
200
- // by default we refuse to dial local addresses from the browser since they
201
- // are usually sent by remote peers broadcasting undialable multiaddrs but
202
- // here we are explicitly connecting to a local node so do not deny dialing
203
- // any discovered address
204
- return false;
205
- },
206
- },
207
- transports: [
208
- webSockets({ filter: filters.all }),
209
- /* circuitRelayTransport({ discoverRelays: 1 }),
210
- webRTC(), */
211
- ],
212
- }),
213
- },
214
- directory: !inMemory ? "./repo" : undefined,
215
- limitSigning: true,
216
- });
217
-
218
- setConnectionState("connecting");
219
-
220
- // Resolve bootstrap nodes async (we want to return before this is done)
221
- const connectFn = async () => {
222
- try {
223
- const addresses = await (bootstrap
224
- ? Promise.resolve(bootstrap)
225
- : resolveBootstrapAddresses(network));
226
- if (addresses && addresses?.length > 0) {
227
- try {
228
- await Promise.all(
229
- addresses
230
- .map((a) =>
231
- typeof a === "string" ? multiaddr(a) : a
232
- )
233
- .map((a) => newPeer.dial(a))
234
- );
235
- setConnectionState("connected");
236
- } catch (error) {
237
- console.error(
238
- "Failed to resolve relay node. Please come back later or start the demo locally"
153
+ transports: [
154
+ // Add websocket impl so we can connect to "unsafe" ws (production only allows wss)
155
+ webSockets({
156
+ filter: filters.all,
157
+ }),
158
+ /* circuitRelayTransport({
159
+ discoverRelays: 1,
160
+ }),
161
+ webRTC(), */
162
+ /* circuitRelayTransport({ discoverRelays: 1 }),
163
+ webRTC(), */
164
+ ],
165
+ }
166
+ : {
167
+ transports: [
168
+ webSockets({ filter: filters.wss }),
169
+ /* circuitRelayTransport({
170
+ discoverRelays: 1,
171
+ }),
172
+ webRTC(), */
173
+ ],
174
+ }),
175
+
176
+ services: {
177
+ pubsub: (c) =>
178
+ new DirectSub(c, {
179
+ canRelayMessage: true,
180
+ emitSelf: true,
181
+ /* connectionManager: {
182
+ autoDial: false,
183
+ }, */
184
+ }),
185
+ identify: identifyService(),
186
+ },
187
+ },
188
+ directory:
189
+ !(nodeOptions as WithMemory).inMemory &&
190
+ !(
191
+ await detectIncognito()
192
+ ).isPrivate
193
+ ? "./repo"
194
+ : undefined,
195
+ });
196
+
197
+ setConnectionState("connecting");
198
+
199
+ // Resolve bootstrap nodes async (we want to return before this is done)
200
+ const connectFn = async () => {
201
+ try {
202
+ if (nodeOptions.network === "local") {
203
+ await newPeer.dial(
204
+ "/ip4/127.0.0.1/tcp/8002/ws/p2p/" +
205
+ (await (
206
+ await fetch(
207
+ "http://localhost:8082/peer/id"
208
+ )
209
+ ).text())
239
210
  );
240
- setConnectionState("failed");
241
- throw error;
211
+ } else {
212
+ // TODO fix types. When proxy client this will not be available
213
+ if (nodeOptions.bootstrap) {
214
+ for (const addr of nodeOptions.bootstrap) {
215
+ await newPeer.dial(addr);
216
+ }
217
+ } else {
218
+ await newPeer["bootstrap"]?.();
219
+ }
242
220
  }
243
- } else {
244
- console.error("No addresses to connect to");
221
+ setConnectionState("connected");
222
+ } catch (err: any) {
223
+ console.error(
224
+ "Failed to resolve relay addresses. " + err?.message
225
+ );
245
226
  setConnectionState("failed");
246
227
  }
247
- } catch (err: any) {
248
- console.error(
249
- "Failed to resolve relay addresses. " + err?.message
250
- );
251
- setConnectionState("failed");
252
- }
253
- };
254
228
 
255
- const promise = connectFn();
229
+ if (nodeOptions.host) {
230
+ newPeer = await createHost(newPeer);
231
+ }
232
+ };
233
+
234
+ const promise = connectFn();
256
235
 
257
- // Make sure data flow as expected between tabs and windows locally (offline states)
236
+ // Make sure data flow as expected between tabs and windows locally (offline states)
258
237
 
259
- if (waitForConnnected) {
260
- await promise;
238
+ if (nodeOptions.waitForConnnected !== false) {
239
+ await promise;
240
+ }
241
+ } else {
242
+ newPeer = await createClient(nodeOptions.targetOrigin);
261
243
  }
262
-
263
244
  setPeer(newPeer);
264
245
  setLoading(false);
265
246
  };
266
- setPromise(fn(keypair));
247
+ setPromise(fn());
267
248
  });
268
249
 
269
- return <PeerContext.Provider value={memo}>{children}</PeerContext.Provider>;
250
+ return (
251
+ <PeerContext.Provider value={memo}>
252
+ {options.children}
253
+ </PeerContext.Provider>
254
+ );
270
255
  };
@@ -0,0 +1,49 @@
1
+ import { Program, ProgramEvents, OpenOptions } from "@peerbit/program";
2
+ import { usePeer } from "./usePeer.js";
3
+ import { useEffect, useRef, useState } from "react";
4
+
5
+ const addressOrUndefined = <
6
+ A,
7
+ B extends ProgramEvents,
8
+ P extends Program<A, B>
9
+ >(
10
+ p: P
11
+ ) => {
12
+ try {
13
+ return p.address;
14
+ } catch (error) {
15
+ return undefined;
16
+ }
17
+ };
18
+
19
+ export const useProgram = <A, B extends ProgramEvents, P extends Program<A, B>>(
20
+ addressOrOpen: P | string,
21
+ options?: OpenOptions<A, P>
22
+ ) => {
23
+ const { peer } = usePeer();
24
+ let [program, setProgram] = useState<P | undefined>();
25
+ let programRef = useRef<Promise<P>>();
26
+ let [loading, setLoading] = useState(false);
27
+
28
+ useEffect(() => {
29
+ if (!peer || !addressOrOpen) {
30
+ return;
31
+ }
32
+ setLoading(true);
33
+ programRef.current = peer
34
+ ?.open(addressOrOpen, { ...options, existing: "reuse" })
35
+ .then((p) => {
36
+ setProgram(p);
37
+ return p;
38
+ })
39
+ .finally(() => {
40
+ setLoading(false);
41
+ });
42
+ }, [
43
+ peer?.identity.publicKey.hashcode(),
44
+ typeof addressOrOpen === "string"
45
+ ? addressOrOpen
46
+ : addressOrUndefined(addressOrOpen),
47
+ ]);
48
+ return { program, loading, promise: programRef.current };
49
+ };