@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.
- package/lib/esm/index.d.ts +2 -1
- package/lib/esm/index.js +2 -1
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/usePeer.d.ts +25 -11
- package/lib/esm/usePeer.js +115 -126
- package/lib/esm/usePeer.js.map +1 -1
- package/lib/esm/useProgram.d.ts +6 -0
- package/lib/esm/useProgram.js +38 -0
- package/lib/esm/useProgram.js.map +1 -0
- package/package.json +8 -11
- package/src/index.ts +2 -6
- package/src/usePeer.tsx +175 -190
- package/src/useProgram.tsx +49 -0
package/lib/esm/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export { PeerProvider, PeerContext, usePeer
|
|
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
|
|
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
|
package/lib/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
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"}
|
package/lib/esm/usePeer.d.ts
CHANGED
|
@@ -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:
|
|
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
|
-
|
|
14
|
+
type IFrameOptions = {
|
|
15
|
+
type: "proxy";
|
|
16
|
+
targetOrigin: string;
|
|
17
|
+
};
|
|
18
|
+
type NodeOptions = {
|
|
19
|
+
type?: "node";
|
|
17
20
|
network: "local" | "remote";
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
}
|
|
36
|
+
};
|
|
37
|
+
type PeerOptions = (TopAndIframeOptions | TopOptions) & WithChildren;
|
|
38
|
+
export declare const PeerProvider: (options: PeerOptions) => import("react/jsx-runtime").JSX.Element;
|
|
25
39
|
export {};
|
package/lib/esm/usePeer.js
CHANGED
|
@@ -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 = (
|
|
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
|
|
37
|
+
peer?.identity?.publicKey?.hashcode(),
|
|
54
38
|
]);
|
|
55
39
|
useMount(() => {
|
|
56
40
|
setLoading(true);
|
|
57
|
-
const fn = async (
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
|
|
159
|
-
console.error("
|
|
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
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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(
|
|
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
|
package/lib/esm/usePeer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePeer.js","sourceRoot":"","sources":["../../src/usePeer.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;
|
|
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
|
+
"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
|
-
"@
|
|
26
|
-
"@
|
|
27
|
-
"@
|
|
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": "^
|
|
32
|
+
"peerbit": "^2",
|
|
35
33
|
"react": "^18.2.0",
|
|
36
34
|
"react-dom": "^18.2.0",
|
|
37
|
-
"react-router-dom": "^6.
|
|
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": "
|
|
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:
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
152
|
-
|
|
153
|
-
(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
"
|
|
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
|
-
|
|
241
|
-
|
|
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
|
-
|
|
244
|
-
|
|
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
|
-
|
|
229
|
+
if (nodeOptions.host) {
|
|
230
|
+
newPeer = await createHost(newPeer);
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const promise = connectFn();
|
|
256
235
|
|
|
257
|
-
|
|
236
|
+
// Make sure data flow as expected between tabs and windows locally (offline states)
|
|
258
237
|
|
|
259
|
-
|
|
260
|
-
|
|
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(
|
|
247
|
+
setPromise(fn());
|
|
267
248
|
});
|
|
268
249
|
|
|
269
|
-
return
|
|
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
|
+
};
|