66 */
77
88import { SimplePool , verifyEvent , type Event } from "nostr-tools" ;
9+ import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime" ;
910import type { NostrProfile } from "./config-schema.js" ;
1011import { validateUrlSafety } from "./nostr-profile-url-safety.js" ;
1112import { contentToProfile , type ProfileContent } from "./nostr-profile.js" ;
@@ -85,7 +86,8 @@ function sanitizeProfileUrls(profile: NostrProfile): NostrProfile {
8586export async function importProfileFromRelays (
8687 opts : ProfileImportOptions ,
8788) : Promise < ProfileImportResult > {
88- const { pubkey, relays, timeoutMs = DEFAULT_TIMEOUT_MS } = opts ;
89+ const { pubkey, relays } = opts ;
90+ const timeoutMs = resolveTimerTimeoutMs ( opts . timeoutMs , DEFAULT_TIMEOUT_MS ) ;
8991
9092 if ( ! pubkey || ! / ^ [ 0 - 9 a - f A - F ] { 64 } $ / . test ( pubkey ) ) {
9193 return {
@@ -105,14 +107,21 @@ export async function importProfileFromRelays(
105107
106108 const pool = new SimplePool ( ) ;
107109 const relaysQueried : string [ ] = [ ] ;
110+ const timers : Array < ReturnType < typeof setTimeout > > = [ ] ;
111+ const scheduleTimeout = ( callback : ( ) => void ) => {
112+ const timer = setTimeout ( callback , timeoutMs ) ;
113+ timer . unref ?.( ) ;
114+ timers . push ( timer ) ;
115+ return timer ;
116+ } ;
108117
109118 try {
110119 // Query all relays for kind:0 events from this pubkey
111120 const events : Array < { event : Event ; relay : string } > = [ ] ;
112121
113122 // Create timeout promise
114123 const timeoutPromise = new Promise < void > ( ( resolve ) => {
115- setTimeout ( resolve , timeoutMs ) ;
124+ scheduleTimeout ( resolve ) ;
116125 } ) ;
117126
118127 // Create subscription promise
@@ -147,14 +156,17 @@ export async function importProfileFromRelays(
147156 } ) ;
148157
149158 // Clean up subscription after timeout
150- setTimeout ( ( ) => {
159+ scheduleTimeout ( ( ) => {
151160 sub . close ( ) ;
152- } , timeoutMs ) ;
161+ } ) ;
153162 }
154163 } ) ;
155164
156165 // Wait for either all relays to respond or timeout
157166 await Promise . race ( [ subscriptionPromise , timeoutPromise ] ) ;
167+ for ( const timer of timers . splice ( 0 ) ) {
168+ clearTimeout ( timer ) ;
169+ }
158170
159171 // No events found
160172 if ( events . length === 0 ) {
@@ -223,6 +235,9 @@ export async function importProfileFromRelays(
223235 sourceRelay : bestEvent . relay ,
224236 } ;
225237 } finally {
238+ for ( const timer of timers ) {
239+ clearTimeout ( timer ) ;
240+ }
226241 pool . close ( relays ) ;
227242 }
228243}
0 commit comments