feat: successful confirmation from relay
This commit is contained in:
parent
aad74cf1a7
commit
58d16dbe85
@ -194,16 +194,29 @@ export class NostrHttpServer {
|
||||
/**
|
||||
* Publish an event to all configured relays
|
||||
* @param event The event to publish
|
||||
* @returns A map of relay URLs to their publish results
|
||||
*/
|
||||
private async publishToRelays(event: any): Promise<void> {
|
||||
for (const relayUrl of this.config.relayUrls) {
|
||||
private async publishToRelays(event: any): Promise<Map<string, { success: boolean; message: string }>> {
|
||||
const results = new Map<string, { success: boolean; message: string }>();
|
||||
const publishPromises = this.config.relayUrls.map(async (relayUrl) => {
|
||||
try {
|
||||
await this.publishToRelay(event, relayUrl);
|
||||
const result = await this.publishToRelay(event, relayUrl);
|
||||
results.set(relayUrl, result);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(`Error publishing to relay ${relayUrl}:`, error);
|
||||
// Continue to the next relay
|
||||
const errorResult = {
|
||||
success: false,
|
||||
message: `Error publishing to relay ${relayUrl}: ${String(error)}`
|
||||
};
|
||||
results.set(relayUrl, errorResult);
|
||||
console.error(errorResult.message);
|
||||
return errorResult;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Wait for all publish attempts to complete
|
||||
await Promise.all(publishPromises);
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -211,57 +224,114 @@ export class NostrHttpServer {
|
||||
* @param event The event to publish
|
||||
* @param relayUrl The relay URL
|
||||
*/
|
||||
private async publishToRelay(event: any, relayUrl: string): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
private async publishToRelay(event: any, relayUrl: string): Promise<{ success: boolean; message: string }> {
|
||||
return new Promise<{ success: boolean; message: string }>((resolve, reject) => {
|
||||
try {
|
||||
console.log(`[${relayUrl}] Initiating WebSocket connection...`);
|
||||
|
||||
// Ensure the event has all required fields in the correct format
|
||||
const formattedEvent = {
|
||||
id: event.id || '',
|
||||
pubkey: event.pubkey || '',
|
||||
created_at: typeof event.created_at === 'number' ? event.created_at : Math.floor(Date.now() / 1000),
|
||||
kind: typeof event.kind === 'number' ? event.kind : 21121,
|
||||
tags: Array.isArray(event.tags) ? event.tags : [],
|
||||
content: typeof event.content === 'string' ? event.content : '',
|
||||
sig: event.sig || ''
|
||||
};
|
||||
|
||||
console.log(`[${relayUrl}] Formatted event:`, JSON.stringify(formattedEvent, null, 2));
|
||||
|
||||
// Create a WebSocket connection
|
||||
const ws = new WebSocket(relayUrl);
|
||||
let connected = false;
|
||||
let ackReceived = false;
|
||||
|
||||
// Set a timeout for the connection
|
||||
const connectionTimeout = setTimeout(() => {
|
||||
if (!connected) {
|
||||
console.log(`[${relayUrl}] Connection timeout - closing WebSocket`);
|
||||
ws.close();
|
||||
reject(new Error(`Connection timeout to relay: ${relayUrl}`));
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
// Set a timeout for the publish operation
|
||||
const timeout = setTimeout(() => {
|
||||
ws.close();
|
||||
reject(new Error(`Timed out connecting to relay: ${relayUrl}`));
|
||||
const publishTimeout = setTimeout(() => {
|
||||
if (!ackReceived) {
|
||||
console.log(`[${relayUrl}] Publish timeout - closing WebSocket`);
|
||||
ws.close();
|
||||
reject(new Error(`Publish timeout waiting for acknowledgment from relay: ${relayUrl}`));
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
ws.onopen = () => {
|
||||
clearTimeout(timeout);
|
||||
console.log(`[${relayUrl}] WebSocket connection established`);
|
||||
clearTimeout(connectionTimeout);
|
||||
connected = true;
|
||||
|
||||
// Send the event
|
||||
const reqId = `pub-${Date.now()}`;
|
||||
const reqMsg = JSON.stringify(["EVENT", reqId, event]);
|
||||
// Format the message according to NIP-01 specification
|
||||
const reqMsg = JSON.stringify(["EVENT", formattedEvent]);
|
||||
console.log(`[${relayUrl}] Event content length: ${formattedEvent.content?.length || 0} bytes`);
|
||||
console.log(`[${relayUrl}] Event tags: ${JSON.stringify(formattedEvent.tags)}`);
|
||||
console.log(`[${relayUrl}] Sending message:`, reqMsg);
|
||||
ws.send(reqMsg);
|
||||
};
|
||||
|
||||
// Wait for OK response
|
||||
const okTimeout = setTimeout(() => {
|
||||
ws.close();
|
||||
resolve(); // Resolve anyway, we don't want to block on OK response
|
||||
}, 5000);
|
||||
ws.onmessage = (msg) => {
|
||||
try {
|
||||
const data = JSON.parse(msg.data as string);
|
||||
if (Array.isArray(data)) {
|
||||
console.log(`[${relayUrl}] Received message: ${JSON.stringify(data).substring(0, 200)}...`);
|
||||
|
||||
const messageHandler = (msg: any) => {
|
||||
try {
|
||||
const data = JSON.parse(msg.data as string);
|
||||
if (Array.isArray(data) && data[0] === "OK" && data[1] === reqId) {
|
||||
clearTimeout(okTimeout);
|
||||
ws.removeListener('message', messageHandler);
|
||||
if (data[0] === "OK") {
|
||||
ackReceived = true;
|
||||
clearTimeout(publishTimeout);
|
||||
const success = data[2] === true;
|
||||
const message = success ?
|
||||
`Event acknowledged by ${relayUrl}` :
|
||||
`Event rejected by ${relayUrl}: ${data[3] || 'Unknown reason'}`;
|
||||
console.log(`[${relayUrl}] ${message}`);
|
||||
ws.close();
|
||||
resolve();
|
||||
resolve({ success, message });
|
||||
} else if (data[0] === "EVENT") {
|
||||
console.log(`[${relayUrl}] Received EVENT message (ignoring, waiting for OK)`);
|
||||
} else if (data[0] === "NOTICE") {
|
||||
console.error(`[${relayUrl}] Received NOTICE: ${data[1]}`);
|
||||
// Don't reject here, wait for OK or timeout
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore parsing errors
|
||||
}
|
||||
};
|
||||
|
||||
ws.on('message', messageHandler);
|
||||
} catch (e) {
|
||||
console.error(`[${relayUrl}] Error parsing message:`, e);
|
||||
}
|
||||
};
|
||||
|
||||
ws.onerror = (err) => {
|
||||
clearTimeout(timeout);
|
||||
reject(new Error(`WebSocket error: ${err.toString()}`));
|
||||
if (!ackReceived) {
|
||||
console.error(`[${relayUrl}] WebSocket error:`, err);
|
||||
clearTimeout(connectionTimeout);
|
||||
clearTimeout(publishTimeout);
|
||||
const errorMsg = `WebSocket error with relay ${relayUrl}: ${err.toString()}`;
|
||||
console.error(`[${relayUrl}] ${errorMsg}`);
|
||||
ws.close();
|
||||
reject(new Error(errorMsg));
|
||||
}
|
||||
};
|
||||
|
||||
ws.onclose = (event) => {
|
||||
console.log(`[${relayUrl}] WebSocket closed with code ${event.code}${event.reason ? `: ${event.reason}` : ''}`);
|
||||
clearTimeout(connectionTimeout);
|
||||
clearTimeout(publishTimeout);
|
||||
if (!ackReceived) {
|
||||
const errorMsg = `WebSocket connection closed with relay ${relayUrl} before acknowledgment`;
|
||||
console.error(`[${relayUrl}] ${errorMsg}`);
|
||||
reject(new Error(errorMsg));
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
console.error(`[${relayUrl}] Error in publishToRelay:`, error);
|
||||
reject(new Error(`Error setting up WebSocket connection to ${relayUrl}: ${String(error)}`));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -859,10 +929,34 @@ ${responseBody}`;
|
||||
throw new Error('Failed to sign response event');
|
||||
}
|
||||
|
||||
console.log('signedEvent', signedEvent);
|
||||
console.log('Sending response event:', signedEvent.id);
|
||||
|
||||
// Publish to all relays
|
||||
await this.publishToRelays(signedEvent);
|
||||
// Publish to all relays and wait for acknowledgments
|
||||
const results = await this.publishToRelays(signedEvent);
|
||||
|
||||
// Log results for each relay
|
||||
let successCount = 0;
|
||||
let failureCount = 0;
|
||||
|
||||
results.forEach((result, relayUrl) => {
|
||||
if (result.success) {
|
||||
successCount++;
|
||||
console.log(`✓ ${result.message}`);
|
||||
} else {
|
||||
failureCount++;
|
||||
console.error(`✗ ${result.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Log summary
|
||||
console.log(`Response event ${signedEvent.id} published to ${this.config.relayUrls.length} relays:`);
|
||||
console.log(` Success: ${successCount}`);
|
||||
console.log(` Failed: ${failureCount}`);
|
||||
|
||||
// If all relays failed, throw an error
|
||||
if (failureCount === this.config.relayUrls.length) {
|
||||
throw new Error('Failed to publish response event to any relay');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error sending response event:', error);
|
||||
throw error;
|
||||
|
Loading…
x
Reference in New Issue
Block a user