95 lines
3.5 KiB
TypeScript
95 lines
3.5 KiB
TypeScript
// Copyright (C) 2026 Whiterun LLC,
|
|
// This software is licensed under the GNU Lesser General Public License (LGPL), version 3.0 or later.
|
|
// A copy of the license can be found in the LICENSE file or at https://www.gnu.org/licenses/lgpl-3.0.html
|
|
|
|
/// Base protocol — DappReadyMessage and WalletReadyMessage
|
|
///
|
|
/// These are protocol-agnostic handshake messages shared across all
|
|
/// application-level protocols (hdwalletv1, future hdwalletv2, etc.).
|
|
///
|
|
/// The wallet populates `session` for every protocol it supports, keyed by
|
|
/// protocol name. The dapp selects the first protocol from its own
|
|
/// `supported_protocols` list that is also present in the wallet's list,
|
|
/// then reads `session[selectedProtocol]` for protocol-specific data.
|
|
|
|
import {
|
|
RelayMsgAction,
|
|
ProtocolMessage,
|
|
isProtocolMessage,
|
|
} from "./hdwalletv1.js";
|
|
|
|
export interface DappReadyMessage extends ProtocolMessage {
|
|
action: RelayMsgAction.DappReady;
|
|
/// Protocols this dapp supports, in preference order.
|
|
supported_protocols: string[];
|
|
/// Set on the reactive dapp_ready (after seeing wallet_ready).
|
|
/// Absent on the proactive send (before the dapp has seen the wallet).
|
|
selected_protocol?: string;
|
|
/// True if the dapp has already seen this wallet in the current runtime session.
|
|
wallet_discovered: boolean;
|
|
dapp_name?: string;
|
|
dapp_icon?: string;
|
|
}
|
|
|
|
export interface WalletReadyMessage extends ProtocolMessage {
|
|
action: RelayMsgAction.WalletReady;
|
|
wallet_name: string;
|
|
wallet_icon: string;
|
|
/// True if the wallet has already seen this dapp in the current runtime session.
|
|
/// The dapp uses this to skip sending a reactive dapp_ready when already known.
|
|
dapp_discovered: boolean;
|
|
/// Protocols this wallet supports.
|
|
supported_protocols: string[];
|
|
/// Session data keyed by protocol name.
|
|
/// e.g. { "hdwalletv1": { paths: PathXpub[], next_indices: NextIndex[] } }
|
|
/// The dapp picks the first compatible protocol and reads session[selectedProtocol].
|
|
session: Record<string, unknown>;
|
|
/// Wallet's Nostr x-only public key (hex, 32 bytes). Replaces the old key_exchange_response.
|
|
public_key: string;
|
|
/// Echo of the shared secret from the connection URI (hex, 8 bytes). MITM prevention.
|
|
secret: string;
|
|
}
|
|
|
|
export function isDappReadyMessage(msg: unknown): msg is DappReadyMessage {
|
|
return (
|
|
isProtocolMessage(msg) &&
|
|
msg.action === RelayMsgAction.DappReady &&
|
|
Array.isArray((msg as DappReadyMessage).supported_protocols) &&
|
|
typeof (msg as DappReadyMessage).wallet_discovered === "boolean"
|
|
);
|
|
}
|
|
|
|
export function isWalletReadyMessage(msg: unknown): msg is WalletReadyMessage {
|
|
const m = msg as WalletReadyMessage;
|
|
return (
|
|
isProtocolMessage(msg) &&
|
|
msg.action === RelayMsgAction.WalletReady &&
|
|
typeof m.wallet_name === "string" &&
|
|
typeof m.wallet_icon === "string" &&
|
|
typeof m.dapp_discovered === "boolean" &&
|
|
Array.isArray(m.supported_protocols) &&
|
|
m.session !== null &&
|
|
typeof m.session === "object" &&
|
|
typeof m.public_key === "string" &&
|
|
typeof m.secret === "string"
|
|
);
|
|
}
|
|
|
|
export enum DisconnectReason {
|
|
ProtocolMismatch = "protocol_mismatch",
|
|
UserDisconnect = "user_disconnect",
|
|
}
|
|
|
|
export interface DisconnectMessage extends ProtocolMessage {
|
|
action: RelayMsgAction.Disconnect;
|
|
reason: DisconnectReason;
|
|
message?: string;
|
|
}
|
|
|
|
export function isDisconnectMessage(msg: unknown): msg is DisconnectMessage {
|
|
return (
|
|
isProtocolMessage(msg) &&
|
|
(msg as DisconnectMessage).action === RelayMsgAction.Disconnect &&
|
|
typeof (msg as DisconnectMessage).reason === "string"
|
|
);
|
|
}
|