@openlv/session 0.1.2 → 0.1.3
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/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/messages/correlate.js +11 -10
- package/dist/messages/correlate.js.map +1 -1
- package/dist/messages/index.js.map +1 -1
- package/dist/utils/log.d.ts +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -48,7 +48,7 @@ export const createSession = async (initParameters, signalLayer, transportLayers
|
|
|
48
48
|
const server = initParameters.s;
|
|
49
49
|
const capabilities = {
|
|
50
50
|
transports: transportLayers.map(layer => layer.transportId),
|
|
51
|
-
...(options?.info
|
|
51
|
+
...(options?.info && { info: options.info }),
|
|
52
52
|
};
|
|
53
53
|
let peerCaps;
|
|
54
54
|
const updateStatus = (newStatus) => {
|
|
@@ -210,17 +210,17 @@ export const createSession = async (initParameters, signalLayer, transportLayers
|
|
|
210
210
|
};
|
|
211
211
|
const onSignalMessage = async (message) => {
|
|
212
212
|
log("Session: received message from signaling", message);
|
|
213
|
-
const
|
|
214
|
-
if (
|
|
215
|
-
messages.emit("message",
|
|
213
|
+
const sessionMessage = message;
|
|
214
|
+
if (sessionMessage.type === "response") {
|
|
215
|
+
messages.emit("message", sessionMessage);
|
|
216
216
|
}
|
|
217
|
-
if (
|
|
217
|
+
if (sessionMessage.type === "request") {
|
|
218
218
|
if (!transport) {
|
|
219
219
|
log("dropping negotiation message: transport not selected yet");
|
|
220
220
|
return;
|
|
221
221
|
}
|
|
222
222
|
try {
|
|
223
|
-
await transport.handle(
|
|
223
|
+
await transport.handle(sessionMessage.payload);
|
|
224
224
|
}
|
|
225
225
|
catch (error) {
|
|
226
226
|
// Negotiation payloads come from the (untrusted) relay; a malformed
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n decodeConnectionURL,\n OPENLV_PROTOCOL_VERSION,\n type SessionHandshakeParameters,\n type SessionLinkParameters,\n} from \"@openlv/core\";\nimport {\n deriveSymmetricKey,\n type EncryptionKey,\n generateHandshakeKey,\n generateSessionId,\n initEncryptionKeys,\n initHash,\n parseEncryptionKey,\n} from \"@openlv/core/encryption\";\nimport {\n type PeerCapabilities,\n type PeerInfo,\n SIGNAL_STATE,\n type SignalingLayer,\n type SignalingProtocol,\n type SignalState,\n validatePeerInfo,\n} from \"@openlv/signaling\";\nimport { dynamicSignalingLayer } from \"@openlv/signaling/dynamic\";\nimport {\n TRANSPORT_STATE,\n type TransportLayer,\n type TransportLayerFn,\n type TransportMessage,\n} from \"@openlv/transport\";\nimport { EventEmitter } from \"eventemitter3\";\n\nimport type { SessionEvents } from \"./events.js\";\nimport { awaitCorrelatedResponse } from \"./messages/correlate.js\";\nimport type { SessionMessage } from \"./messages/index.js\";\nimport { selectTransportId } from \"./transports.js\";\nimport { log } from \"./utils/log.js\";\n\nexport type { PeerCapabilities, PeerInfo } from \"@openlv/signaling\";\n\nexport const SESSION_STATE = {\n CREATED: \"created\",\n SIGNALING: \"signaling\",\n READY: \"ready\",\n LINKING: \"linking\",\n CONNECTED: \"connected\",\n DISCONNECTED: \"disconnected\",\n} as const;\nexport type SessionState = (typeof SESSION_STATE)[keyof typeof SESSION_STATE];\n\nexport type SessionStateObject = {\n status: SessionState;\n signaling?: {\n state: SignalState;\n };\n /** The peer's self-description, set once capabilities are exchanged. */\n peerInfo?: PeerInfo;\n /** Human-readable reason for the last disconnect/failure, if any. */\n error?: string;\n};\n\nexport type SessionOptions = {\n /** Shared with the peer during the handshake and shown in its UI. */\n info?: PeerInfo;\n};\n\n/**\n * an OpenLV Session\n *\n * https://openlv.sh/api/session\n */\nexport type Session = {\n getState(): SessionStateObject;\n getHandshakeParameters(): SessionHandshakeParameters;\n connect(): Promise<void>;\n waitForLink(): Promise<void>;\n close(): Promise<void>;\n /**\n * Send a request to the remote peer and await a correlated response.\n *\n * Two-phase timeout:\n * - `ackTimeout` (default 10 s): the remote peer must send back an ack\n * within this window, confirming it received the message.\n * - After an ack arrives the wait is extended to `responseTimeout`\n * (default 1 hour) — enough for user-interactive flows such as\n * `eth_sendTransaction` or `personal_sign`.\n */\n send(message: object, ackTimeout?: number, responseTimeout?: number): Promise<unknown>;\n emitter: EventEmitter<SessionEvents>;\n _internal: {\n signal: SignalingLayer;\n /** Instantiated when signaling reaches ENCRYPTED and a transport is selected. */\n transport: TransportLayer | undefined;\n };\n};\n\n/**\n * OpenLV Session\n *\n * https://openlv.sh/api/session\n */\nexport const createSession = async (\n initParameters: SessionLinkParameters,\n signalLayer: SignalingProtocol,\n transportLayers: TransportLayerFn[],\n onMessage: (message: object) => Promise<object | string>,\n options?: SessionOptions,\n): Promise<Session> => {\n if (transportLayers.length === 0) {\n throw new Error(\"At least one transport is required\");\n }\n\n if (options?.info) {\n // A receiver silently drops out-of-bounds info with the whole packet,\n // which would surface only as a handshake timeout — fail loudly here.\n const problem = validatePeerInfo(options.info);\n\n if (problem) throw new Error(`Invalid session info: ${problem}`);\n }\n\n const emitter = new EventEmitter<SessionEvents>();\n const messages = new EventEmitter<{ message: SessionMessage; }>();\n const sessionId\n = \"sessionId\" in initParameters\n ? initParameters.sessionId\n : generateSessionId();\n const {\n encryptionKey,\n decryptionKey: { decrypt },\n } = await initEncryptionKeys(initParameters);\n let relyingPublicKey: EncryptionKey | undefined;\n const handshakeKey\n = \"k\" in initParameters\n ? await deriveSymmetricKey(initParameters.k)\n : await generateHandshakeKey();\n const { hash, isHost } = await initHash(\n \"h\" in initParameters ? initParameters.h : undefined,\n encryptionKey,\n );\n let status: SessionState = SESSION_STATE.CREATED;\n let lastError: string | undefined;\n const protocol = initParameters.p;\n const server = initParameters.s;\n const capabilities: PeerCapabilities = {\n transports: transportLayers.map(layer => layer.transportId),\n ...(options?.info ? { info: options.info } : {}),\n };\n let peerCaps: PeerCapabilities | undefined;\n\n const updateStatus = (newStatus: SessionState) => {\n log(\"updateStatus\", newStatus);\n status = newStatus;\n emitter.emit(\"state_change\", {\n status,\n signaling: signal.getState(),\n peerInfo: peerCaps?.info,\n error: lastError,\n });\n };\n\n const signaling = await signalLayer({\n topic: sessionId,\n url: server,\n });\n const signal = await signaling({\n h: hash,\n canEncrypt() {\n return relyingPublicKey !== undefined;\n },\n async encrypt(message) {\n if (!relyingPublicKey) {\n throw new Error(\"Relying party public key not found\");\n }\n\n return await relyingPublicKey.encrypt(message);\n },\n decrypt,\n publicKey: encryptionKey,\n k: handshakeKey,\n async rpDiscovered(rpKey) {\n const role = isHost ? \"host\" : \"client\";\n\n log(`rpKey discovered by ${role}`, rpKey);\n\n relyingPublicKey = await parseEncryptionKey(rpKey);\n },\n capabilities,\n peerCapabilities(received) {\n log(\"peer capabilities received\", received);\n peerCaps = received;\n // Re-emit the current status so observers see peerInfo the moment the\n // capabilities exchange completes, not at the next status transition.\n updateStatus(status);\n },\n isHost,\n });\n\n let transport: TransportLayer | undefined;\n\n const createTransport = (layer: TransportLayerFn): TransportLayer => layer.create({\n encrypt(message) {\n if (!relyingPublicKey) {\n throw new Error(\"Relying party public key not found\");\n }\n\n return relyingPublicKey?.encrypt(message);\n },\n decrypt,\n isHost,\n onmessage: async (message: { type: string; payload: object; messageId: string; }) => {\n log(\"Session: received message from transport\", message);\n\n if (message[\"type\"] === \"request\") {\n const messageId = message[\"messageId\"] as string;\n\n try {\n // Immediately acknowledge receipt so the sender's ack-timeout does\n // not fire while the handler (which may await user interaction) runs.\n await transport?.send({ type: \"ack\", messageId } satisfies SessionMessage);\n\n // Notify observers before processing (e.g. wallet UI can show a\n // pending indicator before the handler resolves).\n emitter.emit(\"request\", message[\"payload\"] as object);\n\n const data = await onMessage(message[\"payload\"] as object)\n // A throwing handler must still answer, otherwise the peer waits\n // out its full response timeout.\n .catch(() => ({ error: { code: -32_603, message: \"Internal error\" } }));\n\n await transport?.send({\n type: \"response\",\n messageId,\n payload: data,\n } satisfies SessionMessage);\n }\n catch (error) {\n log(\"failed to respond to peer request\", error);\n }\n }\n\n if (message[\"type\"] === \"response\" || message[\"type\"] === \"ack\") {\n // Both acks and responses are forwarded to the send() correlator.\n messages.emit(\"message\", message as SessionMessage);\n }\n },\n async subsend(message) {\n log(\"Session: sending trans msg to signal\", message);\n const sessionMessage: SessionMessage = {\n type: \"request\",\n messageId: crypto.randomUUID(),\n payload: message,\n };\n\n await signal.send(sessionMessage);\n },\n });\n\n /**\n * Sessions resumed with a known peer key never exchange capabilities and\n * keep the first configured transport.\n */\n const selectTransportLayer = (): TransportLayerFn | undefined => {\n if (!peerCaps) return transportLayers[0];\n\n const selected = selectTransportId(isHost, capabilities.transports, peerCaps.transports);\n\n return transportLayers.find(layer => layer.transportId === selected);\n };\n\n // Once both peers are present (signaling encrypted) the transport should\n // connect promptly; if it cannot (e.g. no ICE candidates on a restricted\n // network) fail loudly instead of sitting in \"linking\" forever.\n const TRANSPORT_LINK_TIMEOUT_MS = 45_000;\n let linkDeadline: ReturnType<typeof setTimeout> | undefined;\n\n const clearLinkDeadline = () => {\n clearTimeout(linkDeadline);\n linkDeadline = undefined;\n };\n\n const onTransportStateChange = (state: string) => {\n log(\"transport state change\", state);\n\n if (state === TRANSPORT_STATE.CONNECTED) {\n clearLinkDeadline();\n lastError = undefined;\n updateStatus(SESSION_STATE.CONNECTED);\n }\n\n if (state === TRANSPORT_STATE.ERROR) {\n clearLinkDeadline();\n lastError ??= \"Peer-to-peer transport failed\";\n updateStatus(SESSION_STATE.DISCONNECTED);\n }\n };\n\n const onTransportError = (reason?: string) => {\n if (reason) lastError = reason;\n };\n\n const startTransport = () => {\n if (!transport) {\n const layer = selectTransportLayer();\n\n if (!layer) {\n log(\"no common transport with peer\", capabilities.transports, peerCaps?.transports);\n lastError ??= \"No common transport with peer\";\n updateStatus(SESSION_STATE.DISCONNECTED);\n\n return;\n }\n\n log(\"selected transport\", layer.transportId);\n transport = createTransport(layer);\n transport.emitter.on(\"state_change\", onTransportStateChange);\n transport.emitter.on(\"error\", onTransportError);\n }\n\n linkDeadline ??= setTimeout(() => {\n if (status === SESSION_STATE.CONNECTED) return;\n\n log(\"transport failed to connect in time\");\n lastError ??= \"Timed out establishing the peer-to-peer connection\";\n updateStatus(SESSION_STATE.DISCONNECTED);\n }, TRANSPORT_LINK_TIMEOUT_MS);\n\n Promise.resolve(transport.setup()).catch((error) => {\n log(\"transport setup failed\", error);\n clearLinkDeadline();\n lastError ??= error instanceof Error ? error.message : \"Transport setup failed\";\n updateStatus(SESSION_STATE.DISCONNECTED);\n });\n };\n\n const onSignalMessage = async (message: object) => {\n log(\"Session: received message from signaling\", message);\n\n const sessionMsg = message as SessionMessage;\n\n if (sessionMsg.type === \"response\") {\n messages.emit(\"message\", sessionMsg);\n }\n\n if (sessionMsg.type === \"request\") {\n if (!transport) {\n log(\"dropping negotiation message: transport not selected yet\");\n\n return;\n }\n\n try {\n await transport.handle(sessionMsg.payload as TransportMessage);\n }\n catch (error) {\n // Negotiation payloads come from the (untrusted) relay; a malformed\n // one must not become an unhandled rejection.\n log(\"failed to handle negotiation message\", error);\n }\n }\n };\n\n const onSignalStateChange = (state: SignalState) => {\n log(\"signal state change\", state);\n\n if (state === SIGNAL_STATE.READY) {\n updateStatus(SESSION_STATE.READY);\n }\n\n if (\n (\n [\n SIGNAL_STATE.HANDSHAKE,\n SIGNAL_STATE.HANDSHAKE_PARTIAL,\n ] as SignalState[]\n ).includes(state)\n ) {\n updateStatus(SESSION_STATE.LINKING);\n }\n\n if (state === SIGNAL_STATE.ENCRYPTED) {\n startTransport();\n }\n\n if (state === SIGNAL_STATE.ERROR) {\n log(\"signaling error — marking session disconnected\");\n lastError ??= \"Signaling failed or timed out\";\n updateStatus(SESSION_STATE.DISCONNECTED);\n }\n };\n\n return {\n connect: async () => {\n updateStatus(SESSION_STATE.SIGNALING);\n log(\"connecting to session, isHost:\", isHost);\n\n signal.on(\"message\", onSignalMessage);\n signal.on(\"state_change\", onSignalStateChange);\n\n await signal.setup();\n },\n async close() {\n log(\"session teardown\");\n clearLinkDeadline();\n signal.off(\"message\", onSignalMessage);\n signal.off(\"state_change\", onSignalStateChange);\n transport?.emitter.off(\"state_change\", onTransportStateChange);\n transport?.emitter.off(\"error\", onTransportError);\n await Promise.all([\n transport?.teardown(),\n signal.teardown(),\n ]);\n updateStatus(SESSION_STATE.DISCONNECTED);\n },\n getState() {\n return {\n status,\n signaling: signal.getState(),\n peerInfo: peerCaps?.info,\n error: lastError,\n };\n },\n getHandshakeParameters() {\n return {\n version: OPENLV_PROTOCOL_VERSION,\n sessionId,\n h: hash,\n k: handshakeKey.toString(),\n p: protocol,\n s: server,\n };\n },\n waitForLink: async () => new Promise<void>((resolve, reject) => {\n const handler = (state?: SessionStateObject) => {\n if (state?.status === SESSION_STATE.CONNECTED) {\n emitter.off(\"state_change\", handler);\n resolve();\n }\n else if (state?.status === SESSION_STATE.DISCONNECTED) {\n emitter.off(\"state_change\", handler);\n reject(new Error(lastError ?? \"Session failed to connect\"));\n }\n };\n\n // Subscribe before inspecting the current status so a transition\n // between the check and the subscription cannot be missed.\n emitter.on(\"state_change\", handler);\n handler({ status });\n }),\n async send(\n message: object,\n ackTimeout: number = 10_000,\n responseTimeout: number = 60 * 60_000,\n ) {\n if (!transport || signal.getState().state !== SIGNAL_STATE.ENCRYPTED) {\n throw new Error(\"Session not ready\");\n }\n\n const messageId = crypto.randomUUID();\n const sessionMessage: SessionMessage = {\n type: \"request\",\n messageId,\n payload: message,\n };\n\n await transport.send(sessionMessage);\n\n return awaitCorrelatedResponse(messages, messageId, ackTimeout, responseTimeout);\n },\n _internal: {\n signal,\n get transport() {\n return transport;\n },\n },\n emitter,\n };\n};\n\n/**\n * Connect to a session from its openlv:// URL\n */\nexport const connectSession = async (\n connectionUrl: string,\n onMessage: (message: object) => Promise<object | string>,\n transports: TransportLayerFn[],\n options?: SessionOptions,\n): Promise<Session> => {\n const initParameters = decodeConnectionURL(connectionUrl);\n\n const signaling = await dynamicSignalingLayer(initParameters.p);\n\n if (!signaling) {\n throw new Error(`Invalid signaling protocol: ${initParameters.p}`);\n }\n\n return createSession(initParameters, signaling, transports, onMessage, options);\n};\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,uBAAuB,GAGxB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,EAElB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACR,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAGL,YAAY,EAIZ,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EACL,eAAe,GAIhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAG7C,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAElE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAIrC,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,WAAW;IACtB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,WAAW;IACtB,YAAY,EAAE,cAAc;CACpB,CAAC;AAiDX;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAChC,cAAqC,EACrC,WAA8B,EAC9B,eAAmC,EACnC,SAAwD,EACxD,OAAwB,EACN,EAAE;IACpB,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,OAAO,EAAE,IAAI,EAAE,CAAC;QAClB,sEAAsE;QACtE,sEAAsE;QACtE,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE/C,IAAI,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,YAAY,EAAiB,CAAC;IAClD,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAgC,CAAC;IAClE,MAAM,SAAS,GACX,WAAW,IAAI,cAAc;QAC7B,CAAC,CAAC,cAAc,CAAC,SAAS;QAC1B,CAAC,CAAC,iBAAiB,EAAE,CAAC;IAC1B,MAAM,EACJ,aAAa,EACb,aAAa,EAAE,EAAE,OAAO,EAAE,GAC3B,GAAG,MAAM,kBAAkB,CAAC,cAAc,CAAC,CAAC;IAC7C,IAAI,gBAA2C,CAAC;IAChD,MAAM,YAAY,GACd,GAAG,IAAI,cAAc;QACrB,CAAC,CAAC,MAAM,kBAAkB,CAAC,cAAc,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,MAAM,oBAAoB,EAAE,CAAC;IACnC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CACrC,GAAG,IAAI,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EACpD,aAAa,CACd,CAAC;IACF,IAAI,MAAM,GAAiB,aAAa,CAAC,OAAO,CAAC;IACjD,IAAI,SAA6B,CAAC;IAClC,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC;IAChC,MAAM,YAAY,GAAqB;QACrC,UAAU,EAAE,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC;QAC3D,GAAG,CAAC,OAAO,EAAE,IAAI,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;KAC7C,CAAC;IACF,IAAI,QAAsC,CAAC;IAE3C,MAAM,YAAY,GAAG,CAAC,SAAuB,EAAE,EAAE;QAC/C,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;QAC/B,MAAM,GAAG,SAAS,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE;YAC3B,MAAM;YACN,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE;YAC5B,QAAQ,EAAE,QAAQ,EAAE,IAAI;YACxB,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC;QAClC,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,MAAM;KACZ,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC;QAC7B,CAAC,EAAE,IAAI;QACP,UAAU;YACR,OAAO,gBAAgB,KAAK,SAAS,CAAC;QACxC,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,OAAO;YACnB,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACxD,CAAC;YAED,OAAO,MAAM,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACjD,CAAC;QACD,OAAO;QACP,SAAS,EAAE,aAAa;QACxB,CAAC,EAAE,YAAY;QACf,KAAK,CAAC,YAAY,CAAC,KAAK;YACtB,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;YAExC,GAAG,CAAC,uBAAuB,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC;YAE1C,gBAAgB,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACrD,CAAC;QACD,YAAY;QACZ,gBAAgB,CAAC,QAAQ;YACvB,GAAG,CAAC,4BAA4B,EAAE,QAAQ,CAAC,CAAC;YAC5C,QAAQ,GAAG,QAAQ,CAAC;YACpB,sEAAsE;YACtE,sEAAsE;YACtE,YAAY,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;QACD,MAAM;KACP,CAAC,CAAC;IAEH,IAAI,SAAqC,CAAC;IAE1C,MAAM,eAAe,GAAG,CAAC,KAAuB,EAAkB,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;QAChF,OAAO,CAAC,OAAO;YACb,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACxD,CAAC;YAED,OAAO,gBAAgB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO;QACP,MAAM;QACN,SAAS,EAAE,KAAK,EAAE,OAA8D,EAAE,EAAE;YAClF,GAAG,CAAC,0CAA0C,EAAE,OAAO,CAAC,CAAC;YAEzD,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,SAAS,EAAE,CAAC;gBAClC,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAW,CAAC;gBAEjD,IAAI,CAAC;oBACH,mEAAmE;oBACnE,sEAAsE;oBACtE,MAAM,SAAS,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAA2B,CAAC,CAAC;oBAE3E,gEAAgE;oBAChE,kDAAkD;oBAClD,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAW,CAAC,CAAC;oBAEtD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,SAAS,CAAW,CAAC;wBACxD,iEAAiE;wBACjE,iCAAiC;yBAChC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC,CAAC;oBAE1E,MAAM,SAAS,EAAE,IAAI,CAAC;wBACpB,IAAI,EAAE,UAAU;wBAChB,SAAS;wBACT,OAAO,EAAE,IAAI;qBACW,CAAC,CAAC;gBAC9B,CAAC;gBACD,OAAO,KAAK,EAAE,CAAC;oBACb,GAAG,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,EAAE,CAAC;gBAChE,kEAAkE;gBAClE,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,OAAyB,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,OAAO;YACnB,GAAG,CAAC,sCAAsC,EAAE,OAAO,CAAC,CAAC;YACrD,MAAM,cAAc,GAAmB;gBACrC,IAAI,EAAE,SAAS;gBACf,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE;gBAC9B,OAAO,EAAE,OAAO;aACjB,CAAC;YAEF,MAAM,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACpC,CAAC;KACF,CAAC,CAAC;IAEH;;;OAGG;IACH,MAAM,oBAAoB,GAAG,GAAiC,EAAE;QAC9D,IAAI,CAAC,QAAQ;YAAE,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC;QAEzC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,EAAE,YAAY,CAAC,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;QAEzF,OAAO,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC;IACvE,CAAC,CAAC;IAEF,yEAAyE;IACzE,yEAAyE;IACzE,gEAAgE;IAChE,MAAM,yBAAyB,GAAG,KAAM,CAAC;IACzC,IAAI,YAAuD,CAAC;IAE5D,MAAM,iBAAiB,GAAG,GAAG,EAAE;QAC7B,YAAY,CAAC,YAAY,CAAC,CAAC;QAC3B,YAAY,GAAG,SAAS,CAAC;IAC3B,CAAC,CAAC;IAEF,MAAM,sBAAsB,GAAG,CAAC,KAAa,EAAE,EAAE;QAC/C,GAAG,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;QAErC,IAAI,KAAK,KAAK,eAAe,CAAC,SAAS,EAAE,CAAC;YACxC,iBAAiB,EAAE,CAAC;YACpB,SAAS,GAAG,SAAS,CAAC;YACtB,YAAY,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,KAAK,KAAK,eAAe,CAAC,KAAK,EAAE,CAAC;YACpC,iBAAiB,EAAE,CAAC;YACpB,SAAS,KAAT,SAAS,GAAK,+BAA+B,EAAC;YAC9C,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,gBAAgB,GAAG,CAAC,MAAe,EAAE,EAAE;QAC3C,IAAI,MAAM;YAAE,SAAS,GAAG,MAAM,CAAC;IACjC,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,GAAG,EAAE;QAC1B,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,KAAK,GAAG,oBAAoB,EAAE,CAAC;YAErC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,GAAG,CAAC,+BAA+B,EAAE,YAAY,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;gBACpF,SAAS,KAAT,SAAS,GAAK,+BAA+B,EAAC;gBAC9C,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;gBAEzC,OAAO;YACT,CAAC;YAED,GAAG,CAAC,oBAAoB,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;YAC7C,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;YACnC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,cAAc,EAAE,sBAAsB,CAAC,CAAC;YAC7D,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;QAClD,CAAC;QAED,YAAY,KAAZ,YAAY,GAAK,UAAU,CAAC,GAAG,EAAE;YAC/B,IAAI,MAAM,KAAK,aAAa,CAAC,SAAS;gBAAE,OAAO;YAE/C,GAAG,CAAC,qCAAqC,CAAC,CAAC;YAC3C,SAAS,KAAT,SAAS,GAAK,oDAAoD,EAAC;YACnE,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QAC3C,CAAC,EAAE,yBAAyB,CAAC,EAAC;QAE9B,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACjD,GAAG,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;YACrC,iBAAiB,EAAE,CAAC;YACpB,SAAS,KAAT,SAAS,GAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,EAAC;YAChF,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,KAAK,EAAE,OAAe,EAAE,EAAE;QAChD,GAAG,CAAC,0CAA0C,EAAE,OAAO,CAAC,CAAC;QAEzD,MAAM,cAAc,GAAG,OAAyB,CAAC;QAEjD,IAAI,cAAc,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACvC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QAC3C,CAAC;QAED,IAAI,cAAc,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACtC,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,GAAG,CAAC,0DAA0D,CAAC,CAAC;gBAEhE,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,SAAS,CAAC,MAAM,CAAC,cAAc,CAAC,OAA2B,CAAC,CAAC;YACrE,CAAC;YACD,OAAO,KAAK,EAAE,CAAC;gBACb,oEAAoE;gBACpE,8CAA8C;gBAC9C,GAAG,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,mBAAmB,GAAG,CAAC,KAAkB,EAAE,EAAE;QACjD,GAAG,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;QAElC,IAAI,KAAK,KAAK,YAAY,CAAC,KAAK,EAAE,CAAC;YACjC,YAAY,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;QAED,IAEI;YACE,YAAY,CAAC,SAAS;YACtB,YAAY,CAAC,iBAAiB;SAEjC,CAAC,QAAQ,CAAC,KAAK,CAAC,EACjB,CAAC;YACD,YAAY,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACtC,CAAC;QAED,IAAI,KAAK,KAAK,YAAY,CAAC,SAAS,EAAE,CAAC;YACrC,cAAc,EAAE,CAAC;QACnB,CAAC;QAED,IAAI,KAAK,KAAK,YAAY,CAAC,KAAK,EAAE,CAAC;YACjC,GAAG,CAAC,gDAAgD,CAAC,CAAC;YACtD,SAAS,KAAT,SAAS,GAAK,+BAA+B,EAAC;YAC9C,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,YAAY,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;YACtC,GAAG,CAAC,gCAAgC,EAAE,MAAM,CAAC,CAAC;YAE9C,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;YACtC,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;YAE/C,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QACD,KAAK,CAAC,KAAK;YACT,GAAG,CAAC,kBAAkB,CAAC,CAAC;YACxB,iBAAiB,EAAE,CAAC;YACpB,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;YACvC,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;YAChD,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,sBAAsB,CAAC,CAAC;YAC/D,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;YAClD,MAAM,OAAO,CAAC,GAAG,CAAC;gBAChB,SAAS,EAAE,QAAQ,EAAE;gBACrB,MAAM,CAAC,QAAQ,EAAE;aAClB,CAAC,CAAC;YACH,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QAC3C,CAAC;QACD,QAAQ;YACN,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE;gBAC5B,QAAQ,EAAE,QAAQ,EAAE,IAAI;gBACxB,KAAK,EAAE,SAAS;aACjB,CAAC;QACJ,CAAC;QACD,sBAAsB;YACpB,OAAO;gBACL,OAAO,EAAE,uBAAuB;gBAChC,SAAS;gBACT,CAAC,EAAE,IAAI;gBACP,CAAC,EAAE,YAAY,CAAC,QAAQ,EAAE;gBAC1B,CAAC,EAAE,QAAQ;gBACX,CAAC,EAAE,MAAM;aACV,CAAC;QACJ,CAAC;QACD,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC7D,MAAM,OAAO,GAAG,CAAC,KAA0B,EAAE,EAAE;gBAC7C,IAAI,KAAK,EAAE,MAAM,KAAK,aAAa,CAAC,SAAS,EAAE,CAAC;oBAC9C,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;oBACrC,OAAO,EAAE,CAAC;gBACZ,CAAC;qBACI,IAAI,KAAK,EAAE,MAAM,KAAK,aAAa,CAAC,YAAY,EAAE,CAAC;oBACtD,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;oBACrC,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,IAAI,2BAA2B,CAAC,CAAC,CAAC;gBAC9D,CAAC;YACH,CAAC,CAAC;YAEF,iEAAiE;YACjE,2DAA2D;YAC3D,OAAO,CAAC,EAAE,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;YACpC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACtB,CAAC,CAAC;QACF,KAAK,CAAC,IAAI,CACR,OAAe,EACf,aAAqB,KAAM,EAC3B,kBAA0B,EAAE,GAAG,KAAM;YAErC,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC,KAAK,KAAK,YAAY,CAAC,SAAS,EAAE,CAAC;gBACrE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACvC,CAAC;YAED,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;YACtC,MAAM,cAAc,GAAmB;gBACrC,IAAI,EAAE,SAAS;gBACf,SAAS;gBACT,OAAO,EAAE,OAAO;aACjB,CAAC;YAEF,MAAM,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAErC,OAAO,uBAAuB,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;QACnF,CAAC;QACD,SAAS,EAAE;YACT,MAAM;YACN,IAAI,SAAS;gBACX,OAAO,SAAS,CAAC;YACnB,CAAC;SACF;QACD,OAAO;KACR,CAAC;AACJ,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EACjC,aAAqB,EACrB,SAAwD,EACxD,UAA8B,EAC9B,OAAwB,EACN,EAAE;IACpB,MAAM,cAAc,GAAG,mBAAmB,CAAC,aAAa,CAAC,CAAC;IAE1D,MAAM,SAAS,GAAG,MAAM,qBAAqB,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IAEhE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,+BAA+B,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,aAAa,CAAC,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAClF,CAAC,CAAC","sourcesContent":["import {\n decodeConnectionURL,\n OPENLV_PROTOCOL_VERSION,\n type SessionHandshakeParameters,\n type SessionLinkParameters,\n} from \"@openlv/core\";\nimport {\n deriveSymmetricKey,\n type EncryptionKey,\n generateHandshakeKey,\n generateSessionId,\n initEncryptionKeys,\n initHash,\n parseEncryptionKey,\n} from \"@openlv/core/encryption\";\nimport {\n type PeerCapabilities,\n type PeerInfo,\n SIGNAL_STATE,\n type SignalingLayer,\n type SignalingProtocol,\n type SignalState,\n validatePeerInfo,\n} from \"@openlv/signaling\";\nimport { dynamicSignalingLayer } from \"@openlv/signaling/dynamic\";\nimport {\n TRANSPORT_STATE,\n type TransportLayer,\n type TransportLayerFn,\n type TransportMessage,\n} from \"@openlv/transport\";\nimport { EventEmitter } from \"eventemitter3\";\n\nimport type { SessionEvents } from \"./events.js\";\nimport { awaitCorrelatedResponse } from \"./messages/correlate.js\";\nimport type { SessionMessage } from \"./messages/index.js\";\nimport { selectTransportId } from \"./transports.js\";\nimport { log } from \"./utils/log.js\";\n\nexport type { PeerCapabilities, PeerInfo } from \"@openlv/signaling\";\n\nexport const SESSION_STATE = {\n CREATED: \"created\",\n SIGNALING: \"signaling\",\n READY: \"ready\",\n LINKING: \"linking\",\n CONNECTED: \"connected\",\n DISCONNECTED: \"disconnected\",\n} as const;\nexport type SessionState = (typeof SESSION_STATE)[keyof typeof SESSION_STATE];\n\nexport type SessionStateObject = {\n status: SessionState;\n signaling?: {\n state: SignalState;\n };\n /** The peer's self-description, set once capabilities are exchanged. */\n peerInfo?: PeerInfo;\n /** Human-readable reason for the last disconnect/failure, if any. */\n error?: string;\n};\n\nexport type SessionOptions = {\n /** Shared with the peer during the handshake and shown in its UI. */\n info?: PeerInfo;\n};\n\n/**\n * an OpenLV Session\n *\n * https://openlv.sh/api/session\n */\nexport type Session = {\n getState(): SessionStateObject;\n getHandshakeParameters(): SessionHandshakeParameters;\n connect(): Promise<void>;\n waitForLink(): Promise<void>;\n close(): Promise<void>;\n /**\n * Send a request to the remote peer and await a correlated response.\n *\n * Two-phase timeout:\n * - `ackTimeout` (default 10 s): the remote peer must send back an ack\n * within this window, confirming it received the message.\n * - After an ack arrives the wait is extended to `responseTimeout`\n * (default 1 hour) — enough for user-interactive flows such as\n * `eth_sendTransaction` or `personal_sign`.\n */\n send(message: object, ackTimeout?: number, responseTimeout?: number): Promise<unknown>;\n emitter: EventEmitter<SessionEvents>;\n _internal: {\n signal: SignalingLayer;\n /** Instantiated when signaling reaches ENCRYPTED and a transport is selected. */\n transport: TransportLayer | undefined;\n };\n};\n\n/**\n * OpenLV Session\n *\n * https://openlv.sh/api/session\n */\nexport const createSession = async (\n initParameters: SessionLinkParameters,\n signalLayer: SignalingProtocol,\n transportLayers: TransportLayerFn[],\n onMessage: (message: object) => Promise<object | string>,\n options?: SessionOptions,\n): Promise<Session> => {\n if (transportLayers.length === 0) {\n throw new Error(\"At least one transport is required\");\n }\n\n if (options?.info) {\n // A receiver silently drops out-of-bounds info with the whole packet,\n // which would surface only as a handshake timeout — fail loudly here.\n const problem = validatePeerInfo(options.info);\n\n if (problem) throw new Error(`Invalid session info: ${problem}`);\n }\n\n const emitter = new EventEmitter<SessionEvents>();\n const messages = new EventEmitter<{ message: SessionMessage; }>();\n const sessionId\n = \"sessionId\" in initParameters\n ? initParameters.sessionId\n : generateSessionId();\n const {\n encryptionKey,\n decryptionKey: { decrypt },\n } = await initEncryptionKeys(initParameters);\n let relyingPublicKey: EncryptionKey | undefined;\n const handshakeKey\n = \"k\" in initParameters\n ? await deriveSymmetricKey(initParameters.k)\n : await generateHandshakeKey();\n const { hash, isHost } = await initHash(\n \"h\" in initParameters ? initParameters.h : undefined,\n encryptionKey,\n );\n let status: SessionState = SESSION_STATE.CREATED;\n let lastError: string | undefined;\n const protocol = initParameters.p;\n const server = initParameters.s;\n const capabilities: PeerCapabilities = {\n transports: transportLayers.map(layer => layer.transportId),\n ...(options?.info && { info: options.info }),\n };\n let peerCaps: PeerCapabilities | undefined;\n\n const updateStatus = (newStatus: SessionState) => {\n log(\"updateStatus\", newStatus);\n status = newStatus;\n emitter.emit(\"state_change\", {\n status,\n signaling: signal.getState(),\n peerInfo: peerCaps?.info,\n error: lastError,\n });\n };\n\n const signaling = await signalLayer({\n topic: sessionId,\n url: server,\n });\n const signal = await signaling({\n h: hash,\n canEncrypt() {\n return relyingPublicKey !== undefined;\n },\n async encrypt(message) {\n if (!relyingPublicKey) {\n throw new Error(\"Relying party public key not found\");\n }\n\n return await relyingPublicKey.encrypt(message);\n },\n decrypt,\n publicKey: encryptionKey,\n k: handshakeKey,\n async rpDiscovered(rpKey) {\n const role = isHost ? \"host\" : \"client\";\n\n log(`rpKey discovered by ${role}`, rpKey);\n\n relyingPublicKey = await parseEncryptionKey(rpKey);\n },\n capabilities,\n peerCapabilities(received) {\n log(\"peer capabilities received\", received);\n peerCaps = received;\n // Re-emit the current status so observers see peerInfo the moment the\n // capabilities exchange completes, not at the next status transition.\n updateStatus(status);\n },\n isHost,\n });\n\n let transport: TransportLayer | undefined;\n\n const createTransport = (layer: TransportLayerFn): TransportLayer => layer.create({\n encrypt(message) {\n if (!relyingPublicKey) {\n throw new Error(\"Relying party public key not found\");\n }\n\n return relyingPublicKey?.encrypt(message);\n },\n decrypt,\n isHost,\n onmessage: async (message: { type: string; payload: object; messageId: string; }) => {\n log(\"Session: received message from transport\", message);\n\n if (message[\"type\"] === \"request\") {\n const messageId = message[\"messageId\"] as string;\n\n try {\n // Immediately acknowledge receipt so the sender's ack-timeout does\n // not fire while the handler (which may await user interaction) runs.\n await transport?.send({ type: \"ack\", messageId } satisfies SessionMessage);\n\n // Notify observers before processing (e.g. wallet UI can show a\n // pending indicator before the handler resolves).\n emitter.emit(\"request\", message[\"payload\"] as object);\n\n const data = await onMessage(message[\"payload\"] as object)\n // A throwing handler must still answer, otherwise the peer waits\n // out its full response timeout.\n .catch(() => ({ error: { code: -32_603, message: \"Internal error\" } }));\n\n await transport?.send({\n type: \"response\",\n messageId,\n payload: data,\n } satisfies SessionMessage);\n }\n catch (error) {\n log(\"failed to respond to peer request\", error);\n }\n }\n\n if (message[\"type\"] === \"response\" || message[\"type\"] === \"ack\") {\n // Both acks and responses are forwarded to the send() correlator.\n messages.emit(\"message\", message as SessionMessage);\n }\n },\n async subsend(message) {\n log(\"Session: sending trans msg to signal\", message);\n const sessionMessage: SessionMessage = {\n type: \"request\",\n messageId: crypto.randomUUID(),\n payload: message,\n };\n\n await signal.send(sessionMessage);\n },\n });\n\n /**\n * Sessions resumed with a known peer key never exchange capabilities and\n * keep the first configured transport.\n */\n const selectTransportLayer = (): TransportLayerFn | undefined => {\n if (!peerCaps) return transportLayers[0];\n\n const selected = selectTransportId(isHost, capabilities.transports, peerCaps.transports);\n\n return transportLayers.find(layer => layer.transportId === selected);\n };\n\n // Once both peers are present (signaling encrypted) the transport should\n // connect promptly; if it cannot (e.g. no ICE candidates on a restricted\n // network) fail loudly instead of sitting in \"linking\" forever.\n const TRANSPORT_LINK_TIMEOUT_MS = 45_000;\n let linkDeadline: ReturnType<typeof setTimeout> | undefined;\n\n const clearLinkDeadline = () => {\n clearTimeout(linkDeadline);\n linkDeadline = undefined;\n };\n\n const onTransportStateChange = (state: string) => {\n log(\"transport state change\", state);\n\n if (state === TRANSPORT_STATE.CONNECTED) {\n clearLinkDeadline();\n lastError = undefined;\n updateStatus(SESSION_STATE.CONNECTED);\n }\n\n if (state === TRANSPORT_STATE.ERROR) {\n clearLinkDeadline();\n lastError ??= \"Peer-to-peer transport failed\";\n updateStatus(SESSION_STATE.DISCONNECTED);\n }\n };\n\n const onTransportError = (reason?: string) => {\n if (reason) lastError = reason;\n };\n\n const startTransport = () => {\n if (!transport) {\n const layer = selectTransportLayer();\n\n if (!layer) {\n log(\"no common transport with peer\", capabilities.transports, peerCaps?.transports);\n lastError ??= \"No common transport with peer\";\n updateStatus(SESSION_STATE.DISCONNECTED);\n\n return;\n }\n\n log(\"selected transport\", layer.transportId);\n transport = createTransport(layer);\n transport.emitter.on(\"state_change\", onTransportStateChange);\n transport.emitter.on(\"error\", onTransportError);\n }\n\n linkDeadline ??= setTimeout(() => {\n if (status === SESSION_STATE.CONNECTED) return;\n\n log(\"transport failed to connect in time\");\n lastError ??= \"Timed out establishing the peer-to-peer connection\";\n updateStatus(SESSION_STATE.DISCONNECTED);\n }, TRANSPORT_LINK_TIMEOUT_MS);\n\n Promise.resolve(transport.setup()).catch((error) => {\n log(\"transport setup failed\", error);\n clearLinkDeadline();\n lastError ??= error instanceof Error ? error.message : \"Transport setup failed\";\n updateStatus(SESSION_STATE.DISCONNECTED);\n });\n };\n\n const onSignalMessage = async (message: object) => {\n log(\"Session: received message from signaling\", message);\n\n const sessionMessage = message as SessionMessage;\n\n if (sessionMessage.type === \"response\") {\n messages.emit(\"message\", sessionMessage);\n }\n\n if (sessionMessage.type === \"request\") {\n if (!transport) {\n log(\"dropping negotiation message: transport not selected yet\");\n\n return;\n }\n\n try {\n await transport.handle(sessionMessage.payload as TransportMessage);\n }\n catch (error) {\n // Negotiation payloads come from the (untrusted) relay; a malformed\n // one must not become an unhandled rejection.\n log(\"failed to handle negotiation message\", error);\n }\n }\n };\n\n const onSignalStateChange = (state: SignalState) => {\n log(\"signal state change\", state);\n\n if (state === SIGNAL_STATE.READY) {\n updateStatus(SESSION_STATE.READY);\n }\n\n if (\n (\n [\n SIGNAL_STATE.HANDSHAKE,\n SIGNAL_STATE.HANDSHAKE_PARTIAL,\n ] as SignalState[]\n ).includes(state)\n ) {\n updateStatus(SESSION_STATE.LINKING);\n }\n\n if (state === SIGNAL_STATE.ENCRYPTED) {\n startTransport();\n }\n\n if (state === SIGNAL_STATE.ERROR) {\n log(\"signaling error — marking session disconnected\");\n lastError ??= \"Signaling failed or timed out\";\n updateStatus(SESSION_STATE.DISCONNECTED);\n }\n };\n\n return {\n connect: async () => {\n updateStatus(SESSION_STATE.SIGNALING);\n log(\"connecting to session, isHost:\", isHost);\n\n signal.on(\"message\", onSignalMessage);\n signal.on(\"state_change\", onSignalStateChange);\n\n await signal.setup();\n },\n async close() {\n log(\"session teardown\");\n clearLinkDeadline();\n signal.off(\"message\", onSignalMessage);\n signal.off(\"state_change\", onSignalStateChange);\n transport?.emitter.off(\"state_change\", onTransportStateChange);\n transport?.emitter.off(\"error\", onTransportError);\n await Promise.all([\n transport?.teardown(),\n signal.teardown(),\n ]);\n updateStatus(SESSION_STATE.DISCONNECTED);\n },\n getState() {\n return {\n status,\n signaling: signal.getState(),\n peerInfo: peerCaps?.info,\n error: lastError,\n };\n },\n getHandshakeParameters() {\n return {\n version: OPENLV_PROTOCOL_VERSION,\n sessionId,\n h: hash,\n k: handshakeKey.toString(),\n p: protocol,\n s: server,\n };\n },\n waitForLink: async () => new Promise<void>((resolve, reject) => {\n const handler = (state?: SessionStateObject) => {\n if (state?.status === SESSION_STATE.CONNECTED) {\n emitter.off(\"state_change\", handler);\n resolve();\n }\n else if (state?.status === SESSION_STATE.DISCONNECTED) {\n emitter.off(\"state_change\", handler);\n reject(new Error(lastError ?? \"Session failed to connect\"));\n }\n };\n\n // Subscribe before inspecting the current status so a transition\n // between the check and the subscription cannot be missed.\n emitter.on(\"state_change\", handler);\n handler({ status });\n }),\n async send(\n message: object,\n ackTimeout: number = 10_000,\n responseTimeout: number = 60 * 60_000,\n ) {\n if (!transport || signal.getState().state !== SIGNAL_STATE.ENCRYPTED) {\n throw new Error(\"Session not ready\");\n }\n\n const messageId = crypto.randomUUID();\n const sessionMessage: SessionMessage = {\n type: \"request\",\n messageId,\n payload: message,\n };\n\n await transport.send(sessionMessage);\n\n return awaitCorrelatedResponse(messages, messageId, ackTimeout, responseTimeout);\n },\n _internal: {\n signal,\n get transport() {\n return transport;\n },\n },\n emitter,\n };\n};\n\n/**\n * Connect to a session from its openlv:// URL\n */\nexport const connectSession = async (\n connectionUrl: string,\n onMessage: (message: object) => Promise<object | string>,\n transports: TransportLayerFn[],\n options?: SessionOptions,\n): Promise<Session> => {\n const initParameters = decodeConnectionURL(connectionUrl);\n\n const signaling = await dynamicSignalingLayer(initParameters.p);\n\n if (!signaling) {\n throw new Error(`Invalid signaling protocol: ${initParameters.p}`);\n }\n\n return createSession(initParameters, signaling, transports, onMessage, options);\n};\n"]}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* — enough for user-interactive flows such as `eth_sendTransaction`.
|
|
7
7
|
*/
|
|
8
8
|
export const awaitCorrelatedResponse = (messages, messageId, ackTimeoutMs, responseTimeoutMs) => new Promise((resolve, reject) => {
|
|
9
|
-
let
|
|
9
|
+
let isAckReceived = false;
|
|
10
10
|
// eslint-disable-next-line prefer-const
|
|
11
11
|
let ackTimer;
|
|
12
12
|
let responseTimer;
|
|
@@ -15,11 +15,11 @@ export const awaitCorrelatedResponse = (messages, messageId, ackTimeoutMs, respo
|
|
|
15
15
|
clearTimeout(responseTimer);
|
|
16
16
|
messages.off("message", handler);
|
|
17
17
|
};
|
|
18
|
-
const handler = (
|
|
19
|
-
if (
|
|
18
|
+
const handler = (message) => {
|
|
19
|
+
if (message.messageId !== messageId)
|
|
20
20
|
return;
|
|
21
|
-
if (
|
|
22
|
-
|
|
21
|
+
if (message.type === "ack" && !isAckReceived) {
|
|
22
|
+
isAckReceived = true;
|
|
23
23
|
clearTimeout(ackTimer);
|
|
24
24
|
// The other side confirmed receipt; wait for the full response.
|
|
25
25
|
responseTimer = setTimeout(() => {
|
|
@@ -28,18 +28,19 @@ export const awaitCorrelatedResponse = (messages, messageId, ackTimeoutMs, respo
|
|
|
28
28
|
}, responseTimeoutMs);
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
|
-
if (
|
|
31
|
+
if (message.type === "response") {
|
|
32
32
|
cleanup();
|
|
33
|
-
resolve(
|
|
33
|
+
resolve(message.payload);
|
|
34
34
|
}
|
|
35
35
|
};
|
|
36
36
|
messages.on("message", handler);
|
|
37
37
|
// Short window for the ack — tells us the peer is alive and processing.
|
|
38
38
|
ackTimer = setTimeout(() => {
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
reject(new Error("Request timed out: remote peer did not acknowledge"));
|
|
39
|
+
if (isAckReceived) {
|
|
40
|
+
return;
|
|
42
41
|
}
|
|
42
|
+
cleanup();
|
|
43
|
+
reject(new Error("Request timed out: remote peer did not acknowledge"));
|
|
43
44
|
}, ackTimeoutMs);
|
|
44
45
|
});
|
|
45
46
|
//# sourceMappingURL=correlate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"correlate.js","sourceRoot":"","sources":["../../src/messages/correlate.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,QAAoD,EACpD,SAAiB,EACjB,YAAoB,EACpB,iBAAyB,EACP,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IACrD,IAAI,
|
|
1
|
+
{"version":3,"file":"correlate.js","sourceRoot":"","sources":["../../src/messages/correlate.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,QAAoD,EACpD,SAAiB,EACjB,YAAoB,EACpB,iBAAyB,EACP,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IACrD,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,wCAAwC;IACxC,IAAI,QAAmD,CAAC;IACxD,IAAI,aAAwD,CAAC;IAE7D,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,YAAY,CAAC,QAAQ,CAAC,CAAC;QACvB,YAAY,CAAC,aAAa,CAAC,CAAC;QAC5B,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,OAAuB,EAAE,EAAE;QAC1C,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS;YAAE,OAAO;QAE5C,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;YAC7C,aAAa,GAAG,IAAI,CAAC;YACrB,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvB,gEAAgE;YAChE,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC9B,OAAO,EAAE,CAAC;gBACV,MAAM,CAAC,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC,CAAC;YAC5E,CAAC,EAAE,iBAAiB,CAAC,CAAC;YAEtB,OAAO;QACT,CAAC;QAED,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAChC,OAAO,EAAE,CAAC;YACV,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC;IAEF,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAEhC,wEAAwE;IACxE,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE;QACzB,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QAED,OAAO,EAAE,CAAC;QACV,MAAM,CAAC,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC,CAAC;IAC1E,CAAC,EAAE,YAAY,CAAC,CAAC;AACnB,CAAC,CAAC,CAAC","sourcesContent":["import type { EventEmitter } from \"eventemitter3\";\n\nimport type { SessionMessage } from \"./index.js\";\n\n/**\n * Await the ack and response correlated to a sent request.\n *\n * Two-phase timeout: the peer must ack within `ackTimeoutMs`, confirming it\n * received the message; after the ack the wait extends to `responseTimeoutMs`\n * — enough for user-interactive flows such as `eth_sendTransaction`.\n */\nexport const awaitCorrelatedResponse = (\n messages: EventEmitter<{ message: SessionMessage; }>,\n messageId: string,\n ackTimeoutMs: number,\n responseTimeoutMs: number,\n): Promise<unknown> => new Promise((resolve, reject) => {\n let isAckReceived = false;\n // eslint-disable-next-line prefer-const\n let ackTimer: ReturnType<typeof setTimeout> | undefined;\n let responseTimer: ReturnType<typeof setTimeout> | undefined;\n\n const cleanup = () => {\n clearTimeout(ackTimer);\n clearTimeout(responseTimer);\n messages.off(\"message\", handler);\n };\n\n const handler = (message: SessionMessage) => {\n if (message.messageId !== messageId) return;\n\n if (message.type === \"ack\" && !isAckReceived) {\n isAckReceived = true;\n clearTimeout(ackTimer);\n // The other side confirmed receipt; wait for the full response.\n responseTimer = setTimeout(() => {\n cleanup();\n reject(new Error(\"Request timed out: no response after acknowledgement\"));\n }, responseTimeoutMs);\n\n return;\n }\n\n if (message.type === \"response\") {\n cleanup();\n resolve(message.payload);\n }\n };\n\n messages.on(\"message\", handler);\n\n // Short window for the ack — tells us the peer is alive and processing.\n ackTimer = setTimeout(() => {\n if (isAckReceived) {\n return;\n }\n\n cleanup();\n reject(new Error(\"Request timed out: remote peer did not acknowledge\"));\n }, ackTimeoutMs);\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/messages/index.ts"],"names":[],"mappings":"","sourcesContent":["export type SessionMessage
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/messages/index.ts"],"names":[],"mappings":"","sourcesContent":["export type SessionMessage\n = | SessionMessageRequest\n | SessionMessageResponse\n | SessionMessageAck;\n\nexport type SessionMessageRequest = {\n type: \"request\";\n messageId: string;\n payload: object | string;\n};\n\nexport type SessionMessageResponse = {\n type: \"response\";\n messageId: string;\n payload: object | string;\n};\n\nexport type SessionMessageAck = {\n type: \"ack\";\n messageId: string;\n};\n"]}
|
package/dist/utils/log.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const log: (...
|
|
1
|
+
export declare const log: (...arguments_: Parameters<typeof console.log>) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openlv/session",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"open-lavatory"
|
|
6
6
|
],
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
"eventemitter3": "^5.0.1",
|
|
38
38
|
"globals": "^16.2.0",
|
|
39
39
|
"ts-pattern": "^5",
|
|
40
|
-
"@openlv/core": "0.1.
|
|
41
|
-
"@openlv/signaling": "0.1.
|
|
42
|
-
"@openlv/transport": "0.1.
|
|
40
|
+
"@openlv/core": "0.1.2",
|
|
41
|
+
"@openlv/signaling": "0.1.3",
|
|
42
|
+
"@openlv/transport": "0.1.2"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@vitest/browser-playwright": "^4.0.8",
|