parent
edd5f9f254
commit
865710390a
client/src
@ -180,7 +180,6 @@ export class Nostr21121Creator {
|
||||
} else {
|
||||
privateKeyHex = privateKey;
|
||||
}
|
||||
|
||||
// Get the public key from the private key
|
||||
const privateKeyBytes = Buffer.from(privateKeyHex, 'hex');
|
||||
const pubKey = nostrTools.getPublicKey(privateKeyBytes);
|
||||
@ -229,16 +228,8 @@ export class Nostr21121Creator {
|
||||
pubkey: pubKey
|
||||
};
|
||||
|
||||
// Sign the event - simplified for demo
|
||||
// In a real implementation, we would use proper signing from nostr-tools
|
||||
const id = nostrTools.getEventHash(eventData);
|
||||
const sig = 'simulated_signature_for_demo';
|
||||
|
||||
const signedEvent: NostrEvent = {
|
||||
...eventData,
|
||||
id,
|
||||
sig
|
||||
};
|
||||
// Use nostrTools.finalizeEvent to sign the event
|
||||
const signedEvent = nostrTools.finalizeEvent(eventData, privateKeyBytes);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
@ -286,19 +277,24 @@ export class Nostr21121Creator {
|
||||
// Begin publishing status
|
||||
ToastNotifier.show(`Publishing to ${targetRelays.length} relay(s)...`, 'info');
|
||||
|
||||
// For demonstration purposes - simulate relay publishing
|
||||
console.log(`Would publish event to relays: ${targetRelays.join(', ')}`);
|
||||
// Actually publish the event to the relays
|
||||
console.log(`Publishing event to relays: ${targetRelays.join(', ')}`);
|
||||
console.log('Event:', result.event);
|
||||
|
||||
// Simulate successful relay publishing
|
||||
const successCount = targetRelays.length;
|
||||
// Create a relay pool
|
||||
const relayPool = new nostrTools.SimplePool();
|
||||
|
||||
// In a real implementation, we would use:
|
||||
// const relayPool = new nostrTools.SimplePool();
|
||||
// const pubPromises = targetRelays.map(url => relayPool.publish([url], result.event!));
|
||||
// const publishResults = await Promise.allSettled(pubPromises);
|
||||
// const successCount = publishResults.filter(res => res.status === 'fulfilled').length;
|
||||
// relayPool.close(targetRelays);
|
||||
// Publish to all target relays - cast to the expected type
|
||||
const pubPromises = targetRelays.map(url => relayPool.publish([url], result.event as any));
|
||||
|
||||
// Wait for all publish operations to complete
|
||||
const publishResults = await Promise.allSettled(pubPromises);
|
||||
|
||||
// Count successful publishes
|
||||
const successCount = publishResults.filter(res => res.status === 'fulfilled').length;
|
||||
|
||||
// Clean up relay pool
|
||||
relayPool.close(targetRelays);
|
||||
|
||||
// Add event to local event manager if it has an ID
|
||||
if (result.event && result.event.id) {
|
||||
|
@ -120,8 +120,55 @@ export class ServerUI {
|
||||
// Load server identity if available
|
||||
this.loadServerIdentity();
|
||||
|
||||
// Automatically connect to the default relay
|
||||
this.autoConnectToRelay();
|
||||
|
||||
console.log('Server UI initialized');
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically connect to the default relay
|
||||
*/
|
||||
private autoConnectToRelay(): void {
|
||||
console.log('Auto-connecting to relay...');
|
||||
|
||||
// Update status to show auto-connection attempt
|
||||
const relayStatus = document.getElementById(this.options.relayStatusContainer);
|
||||
if (relayStatus) {
|
||||
relayStatus.textContent = 'Auto-connecting...';
|
||||
relayStatus.className = 'relay-status connecting';
|
||||
}
|
||||
|
||||
// Get the relay URL from the input field (using the default value)
|
||||
const relayUrlInput = document.getElementById(this.options.relayUrlInput) as HTMLInputElement;
|
||||
if (!relayUrlInput) {
|
||||
console.error('Relay URL input element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const relayUrl = relayUrlInput.value.trim() || 'wss://relay.degmods.com';
|
||||
console.log(`Using relay URL for auto-connection: ${relayUrl}`);
|
||||
|
||||
// Get show all events state (default to true for auto-connection)
|
||||
const showAllEventsCheckbox = document.getElementById('showAllEvents') as HTMLInputElement;
|
||||
const showAllEvents = showAllEventsCheckbox?.checked ?? true;
|
||||
|
||||
// Force the checkbox state to match what we're using for auto-connection
|
||||
if (showAllEventsCheckbox) {
|
||||
showAllEventsCheckbox.checked = showAllEvents;
|
||||
}
|
||||
|
||||
// Connect to relay and subscribe
|
||||
this.connectToRelayAndSubscribe(relayUrl, showAllEvents)
|
||||
.then(() => {
|
||||
console.log('Auto-connection successful');
|
||||
ToastNotifier.show(`Auto-connected to ${relayUrl}`, 'success');
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Auto-connection failed:', error);
|
||||
// We don't show an error toast for auto-connection failures to avoid annoying users
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up event listeners for UI interactions
|
||||
@ -176,8 +223,22 @@ export class ServerUI {
|
||||
// Update the relay URL input with the actual URL used
|
||||
relayUrlInput.value = relayUrl;
|
||||
|
||||
// Update the connect button state to show connecting
|
||||
const connectButton = document.getElementById(this.options.connectButton) as HTMLButtonElement;
|
||||
if (connectButton) {
|
||||
connectButton.textContent = 'Connecting...';
|
||||
connectButton.disabled = true;
|
||||
}
|
||||
|
||||
// Connect to relay and subscribe
|
||||
this.connectToRelayAndSubscribe(relayUrl, showAllEvents);
|
||||
this.connectToRelayAndSubscribe(relayUrl, showAllEvents)
|
||||
.finally(() => {
|
||||
// Re-enable the connect button after connection attempt
|
||||
if (connectButton) {
|
||||
connectButton.textContent = 'Connect';
|
||||
connectButton.disabled = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4,7 +4,7 @@ import qrcode from 'qrcode-generator';
|
||||
|
||||
// Internal imports
|
||||
import { defaultServerConfig, appSettings } from './config';
|
||||
import { convertNpubToHex } from './relay';
|
||||
import { convertNpubToHex, publishToRelay } from './relay';
|
||||
import { showSuccess } from './utils';
|
||||
import { encryptWithWebCrypto, encryptKeyWithNostrExtension } from './utils/crypto-utils';
|
||||
|
||||
@ -409,12 +409,23 @@ export async function displayConvertedEvent(): Promise<void> {
|
||||
// Display the event JSON
|
||||
eventOutputPre.textContent = JSON.stringify(signedEvent, null, 2);
|
||||
|
||||
// Add a helpful message about publishing the event
|
||||
// Automatically publish the event to the relay
|
||||
const publishRelayInput = document.getElementById('publishRelay') as HTMLInputElement;
|
||||
if (publishRelayInput) {
|
||||
const publishResult = document.getElementById('publishResult');
|
||||
const relayUrl = publishRelayInput.value.trim() || defaultServerConfig.defaultRelay;
|
||||
|
||||
if (publishResult) {
|
||||
showSuccess(publishResult, 'Event created successfully. Ready to publish!');
|
||||
publishResult.innerHTML = '<span class="loading">Publishing to relay...</span>';
|
||||
|
||||
// Publish the event using the publishToRelay function
|
||||
publishToRelay(signedEvent, relayUrl)
|
||||
.then((result: string) => {
|
||||
showSuccess(publishResult, result);
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
publishResult.innerHTML = `<span class="error">Error publishing: ${error.message}</span>`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,13 @@ export class NostrRelayService {
|
||||
*/
|
||||
public async connectToRelay(relayUrl: string): Promise<boolean> {
|
||||
try {
|
||||
// If already connected to the requested relay, just return true
|
||||
if (this.isConnected() && this.activeRelayUrl === relayUrl) {
|
||||
console.log(`Already connected to relay: ${relayUrl}`);
|
||||
this.updateStatus('Connected', 'connected');
|
||||
return true;
|
||||
}
|
||||
|
||||
this.updateStatus('Connecting to relay...', 'connecting');
|
||||
|
||||
// Test the connection first
|
||||
|
@ -21,56 +21,76 @@ export class WebSocketManager {
|
||||
*/
|
||||
public async connect(url: string, options: WebSocketOptions = {}): Promise<WebSocket> {
|
||||
return new Promise<WebSocket>((resolve, reject) => {
|
||||
// Safely close any existing connection first
|
||||
this.close();
|
||||
|
||||
this.url = url;
|
||||
this.ws = new WebSocket(url);
|
||||
this.connected = false;
|
||||
let timeoutId: number | undefined;
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
if (!this.connected) {
|
||||
this.close();
|
||||
reject(new Error(`Connection timeout after ${options.timeout || 5000}ms`));
|
||||
}
|
||||
}, options.timeout || 5000);
|
||||
|
||||
this.ws.onopen = () => {
|
||||
clearTimeout(timeout);
|
||||
this.connected = true;
|
||||
if (options.onOpen) {
|
||||
options.onOpen(this.ws as WebSocket);
|
||||
}
|
||||
resolve(this.ws as WebSocket);
|
||||
};
|
||||
|
||||
this.ws.onmessage = (msg) => {
|
||||
if (options.onMessage && typeof msg.data === 'string') {
|
||||
try {
|
||||
const parsedData = JSON.parse(msg.data);
|
||||
options.onMessage(parsedData);
|
||||
} catch {
|
||||
// Ignore parsing errors
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.ws.onerror = (errorEvt) => {
|
||||
clearTimeout(timeout);
|
||||
if (options.onError) {
|
||||
options.onError(errorEvt);
|
||||
}
|
||||
if (!this.connected) {
|
||||
reject(new Error(`WebSocket error: ${errorEvt.toString()}`));
|
||||
}
|
||||
};
|
||||
|
||||
this.ws.onclose = () => {
|
||||
clearTimeout(timeout);
|
||||
try {
|
||||
// Create a new WebSocket connection
|
||||
this.url = url;
|
||||
this.ws = new WebSocket(url);
|
||||
this.connected = false;
|
||||
if (options.onClose) {
|
||||
options.onClose();
|
||||
|
||||
console.log(`Attempting WebSocket connection to: ${url}`);
|
||||
|
||||
// Set a timeout for the connection attempt
|
||||
timeoutId = window.setTimeout(() => {
|
||||
if (!this.connected) {
|
||||
console.warn(`WebSocket connection timed out after ${options.timeout || 5000}ms`);
|
||||
this.close();
|
||||
reject(new Error(`Connection timeout after ${options.timeout || 5000}ms`));
|
||||
}
|
||||
}, options.timeout || 5000);
|
||||
|
||||
// Set up event handlers
|
||||
if (this.ws) {
|
||||
this.ws.onopen = () => {
|
||||
if (timeoutId) clearTimeout(timeoutId);
|
||||
this.connected = true;
|
||||
if (options.onOpen && this.ws) {
|
||||
options.onOpen(this.ws);
|
||||
}
|
||||
resolve(this.ws as WebSocket);
|
||||
};
|
||||
|
||||
this.ws.onmessage = (msg) => {
|
||||
if (options.onMessage && typeof msg.data === 'string') {
|
||||
try {
|
||||
const parsedData = JSON.parse(msg.data);
|
||||
options.onMessage(parsedData);
|
||||
} catch {
|
||||
// Ignore parsing errors
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.ws.onerror = (errorEvt) => {
|
||||
if (timeoutId) clearTimeout(timeoutId);
|
||||
if (options.onError) {
|
||||
options.onError(errorEvt);
|
||||
}
|
||||
if (!this.connected) {
|
||||
reject(new Error(`WebSocket error: ${errorEvt.toString()}`));
|
||||
}
|
||||
};
|
||||
|
||||
this.ws.onclose = () => {
|
||||
if (timeoutId) clearTimeout(timeoutId);
|
||||
this.connected = false;
|
||||
if (options.onClose) {
|
||||
options.onClose();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
throw new Error('Failed to create WebSocket instance');
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error creating WebSocket connection:', error);
|
||||
if (timeoutId) clearTimeout(timeoutId);
|
||||
this.close();
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user