@@ -77,6 +77,18 @@ class MempoolAcceptanceCallback implements payjoin.CanBroadcast {
7777 }
7878}
7979
80+ class MempoolAcceptanceCallbackAsync implements payjoin . CanBroadcastAsync {
81+ private inner : MempoolAcceptanceCallback ;
82+
83+ constructor ( connection : testUtils . RpcClient ) {
84+ this . inner = new MempoolAcceptanceCallback ( connection ) ;
85+ }
86+
87+ async callback ( tx : ArrayBuffer ) : Promise < boolean > {
88+ return this . inner . callback ( tx ) ;
89+ }
90+ }
91+
8092class IsScriptOwnedCallback implements payjoin . IsScriptOwned {
8193 private connection : testUtils . RpcClient ;
8294
@@ -143,6 +155,18 @@ class IsScriptOwnedCallback implements payjoin.IsScriptOwned {
143155 }
144156}
145157
158+ class IsScriptOwnedCallbackAsync implements payjoin . IsScriptOwnedAsync {
159+ private inner : IsScriptOwnedCallback ;
160+
161+ constructor ( connection : testUtils . RpcClient ) {
162+ this . inner = new IsScriptOwnedCallback ( connection ) ;
163+ }
164+
165+ async callback ( script : ArrayBuffer ) : Promise < boolean > {
166+ return this . inner . callback ( script ) ;
167+ }
168+ }
169+
146170class CheckInputsNotSeenCallback implements payjoin . IsOutputKnown {
147171 private connection : testUtils . RpcClient ;
148172
@@ -155,6 +179,18 @@ class CheckInputsNotSeenCallback implements payjoin.IsOutputKnown {
155179 }
156180}
157181
182+ class CheckInputsNotSeenCallbackAsync implements payjoin . IsOutputKnownAsync {
183+ private inner : CheckInputsNotSeenCallback ;
184+
185+ constructor ( connection : testUtils . RpcClient ) {
186+ this . inner = new CheckInputsNotSeenCallback ( connection ) ;
187+ }
188+
189+ async callback ( outpoint : payjoin . PlainOutPoint ) : Promise < boolean > {
190+ return this . inner . callback ( outpoint ) ;
191+ }
192+ }
193+
158194class ProcessPsbtCallback implements payjoin . ProcessPsbt {
159195 private connection : testUtils . RpcClient ;
160196
@@ -170,6 +206,18 @@ class ProcessPsbtCallback implements payjoin.ProcessPsbt {
170206 }
171207}
172208
209+ class ProcessPsbtCallbackAsync implements payjoin . ProcessPsbtAsync {
210+ private inner : ProcessPsbtCallback ;
211+
212+ constructor ( connection : testUtils . RpcClient ) {
213+ this . inner = new ProcessPsbtCallback ( connection ) ;
214+ }
215+
216+ async callback ( psbt : string ) : Promise < string > {
217+ return this . inner . callback ( psbt ) ;
218+ }
219+ }
220+
173221function createReceiverContext (
174222 address : string ,
175223 directory : string ,
@@ -244,10 +292,21 @@ function processProvisionalProposal(
244292 receiver : testUtils . RpcClient ,
245293 recvPersister : InMemoryReceiverPersister ,
246294) : payjoin . PayjoinProposal {
247- const payjoinProposal = proposal
295+ return proposal
248296 . finalizeProposal ( new ProcessPsbtCallback ( receiver ) )
249297 . save ( recvPersister ) as payjoin . PayjoinProposal ;
250- return payjoinProposal ;
298+ }
299+
300+ async function processProvisionalProposalAsync (
301+ proposal : payjoin . ProvisionalProposal ,
302+ receiver : testUtils . RpcClient ,
303+ recvPersister : InMemoryReceiverPersister ,
304+ ) : Promise < payjoin . PayjoinProposal > {
305+ return (
306+ await proposal . finalizeProposalAsync (
307+ new ProcessPsbtCallbackAsync ( receiver ) ,
308+ )
309+ ) . save ( recvPersister ) as payjoin . PayjoinProposal ;
251310}
252311
253312function processWantsFeeRange (
@@ -265,6 +324,21 @@ function processWantsFeeRange(
265324 ) ;
266325}
267326
327+ async function processWantsFeeRangeAsync (
328+ proposal : payjoin . WantsFeeRange ,
329+ receiver : testUtils . RpcClient ,
330+ recvPersister : InMemoryReceiverPersister ,
331+ ) : Promise < payjoin . PayjoinProposal > {
332+ const provisionalProposal = proposal
333+ . applyFeeRange ( 1n , 10n )
334+ . save ( recvPersister ) as payjoin . ProvisionalProposal ;
335+ return processProvisionalProposalAsync (
336+ provisionalProposal ,
337+ receiver ,
338+ recvPersister ,
339+ ) ;
340+ }
341+
268342function processWantsInputs (
269343 proposal : payjoin . WantsInputs ,
270344 receiver : testUtils . RpcClient ,
@@ -277,6 +351,18 @@ function processWantsInputs(
277351 return processWantsFeeRange ( wantsFeeRange , receiver , recvPersister ) ;
278352}
279353
354+ async function processWantsInputsAsync (
355+ proposal : payjoin . WantsInputs ,
356+ receiver : testUtils . RpcClient ,
357+ recvPersister : InMemoryReceiverPersister ,
358+ ) : Promise < payjoin . PayjoinProposal > {
359+ const wantsFeeRange = proposal
360+ . contributeInputs ( getInputs ( receiver ) )
361+ . commitInputs ( )
362+ . save ( recvPersister ) as payjoin . WantsFeeRange ;
363+ return processWantsFeeRangeAsync ( wantsFeeRange , receiver , recvPersister ) ;
364+ }
365+
280366function processWantsOutputs (
281367 proposal : payjoin . WantsOutputs ,
282368 receiver : testUtils . RpcClient ,
@@ -288,6 +374,17 @@ function processWantsOutputs(
288374 return processWantsInputs ( wantsInputs , receiver , recvPersister ) ;
289375}
290376
377+ async function processWantsOutputsAsync (
378+ proposal : payjoin . WantsOutputs ,
379+ receiver : testUtils . RpcClient ,
380+ recvPersister : InMemoryReceiverPersister ,
381+ ) : Promise < payjoin . PayjoinProposal > {
382+ const wantsInputs = proposal
383+ . commitOutputs ( )
384+ . save ( recvPersister ) as payjoin . WantsInputs ;
385+ return processWantsInputsAsync ( wantsInputs , receiver , recvPersister ) ;
386+ }
387+
291388function processOutputsUnknown (
292389 proposal : payjoin . OutputsUnknown ,
293390 receiver : testUtils . RpcClient ,
@@ -299,6 +396,19 @@ function processOutputsUnknown(
299396 return processWantsOutputs ( wantsOutputs , receiver , recvPersister ) ;
300397}
301398
399+ async function processOutputsUnknownAsync (
400+ proposal : payjoin . OutputsUnknown ,
401+ receiver : testUtils . RpcClient ,
402+ recvPersister : InMemoryReceiverPersister ,
403+ ) : Promise < payjoin . PayjoinProposal > {
404+ const wantsOutputs = (
405+ await proposal . identifyReceiverOutputsAsync (
406+ new IsScriptOwnedCallbackAsync ( receiver ) ,
407+ )
408+ ) . save ( recvPersister ) as payjoin . WantsOutputs ;
409+ return processWantsOutputsAsync ( wantsOutputs , receiver , recvPersister ) ;
410+ }
411+
302412function processMaybeInputsSeen (
303413 proposal : payjoin . MaybeInputsSeen ,
304414 receiver : testUtils . RpcClient ,
@@ -310,6 +420,19 @@ function processMaybeInputsSeen(
310420 return processOutputsUnknown ( outputsUnknown , receiver , recvPersister ) ;
311421}
312422
423+ async function processMaybeInputsSeenAsync (
424+ proposal : payjoin . MaybeInputsSeen ,
425+ receiver : testUtils . RpcClient ,
426+ recvPersister : InMemoryReceiverPersister ,
427+ ) : Promise < payjoin . PayjoinProposal > {
428+ const outputsUnknown = (
429+ await proposal . checkNoInputsSeenBeforeAsync (
430+ new CheckInputsNotSeenCallbackAsync ( receiver ) ,
431+ )
432+ ) . save ( recvPersister ) as payjoin . OutputsUnknown ;
433+ return processOutputsUnknownAsync ( outputsUnknown , receiver , recvPersister ) ;
434+ }
435+
313436function processMaybeInputsOwned (
314437 proposal : payjoin . MaybeInputsOwned ,
315438 receiver : testUtils . RpcClient ,
@@ -321,6 +444,23 @@ function processMaybeInputsOwned(
321444 return processMaybeInputsSeen ( maybeInputsSeen , receiver , recvPersister ) ;
322445}
323446
447+ async function processMaybeInputsOwnedAsync (
448+ proposal : payjoin . MaybeInputsOwned ,
449+ receiver : testUtils . RpcClient ,
450+ recvPersister : InMemoryReceiverPersister ,
451+ ) : Promise < payjoin . PayjoinProposal > {
452+ const maybeInputsSeen = (
453+ await proposal . checkInputsNotOwnedAsync (
454+ new IsScriptOwnedCallbackAsync ( receiver ) ,
455+ )
456+ ) . save ( recvPersister ) as payjoin . MaybeInputsSeen ;
457+ return processMaybeInputsSeenAsync (
458+ maybeInputsSeen ,
459+ receiver ,
460+ recvPersister ,
461+ ) ;
462+ }
463+
324464function processUncheckedProposal (
325465 proposal : payjoin . UncheckedOriginalPayload ,
326466 receiver : testUtils . RpcClient ,
@@ -335,10 +475,29 @@ function processUncheckedProposal(
335475 return processMaybeInputsOwned ( maybeInputsOwned , receiver , recvPersister ) ;
336476}
337477
478+ async function processUncheckedProposalAsync (
479+ proposal : payjoin . UncheckedOriginalPayload ,
480+ receiver : testUtils . RpcClient ,
481+ recvPersister : InMemoryReceiverPersister ,
482+ ) : Promise < payjoin . PayjoinProposal > {
483+ const maybeInputsOwned = (
484+ await proposal . checkBroadcastSuitabilityAsync (
485+ undefined ,
486+ new MempoolAcceptanceCallbackAsync ( receiver ) ,
487+ )
488+ ) . save ( recvPersister ) as payjoin . MaybeInputsOwned ;
489+ return processMaybeInputsOwnedAsync (
490+ maybeInputsOwned ,
491+ receiver ,
492+ recvPersister ,
493+ ) ;
494+ }
495+
338496async function retrieveReceiverProposal (
339497 receiver : payjoin . Initialized ,
340498 recvPersister : InMemoryReceiverPersister ,
341499 ohttpRelay : string ,
500+ useAsync : boolean ,
342501) : Promise < payjoin . PayjoinProposal | null > {
343502 const request = receiver . createPollRequest ( ohttpRelay ) ;
344503 const response = await fetch ( request . request . url , {
@@ -355,11 +514,17 @@ async function retrieveReceiverProposal(
355514 return null ;
356515 } else if ( res instanceof payjoin . InitializedTransitionOutcome . Progress ) {
357516 const proposal = res . inner . inner as payjoin . UncheckedOriginalPayload ;
358- return processUncheckedProposal (
359- proposal ,
360- recvPersister . connection ! ,
361- recvPersister ,
362- ) ;
517+ return useAsync
518+ ? processUncheckedProposalAsync (
519+ proposal ,
520+ recvPersister . connection ! ,
521+ recvPersister ,
522+ )
523+ : processUncheckedProposal (
524+ proposal ,
525+ recvPersister . connection ! ,
526+ recvPersister ,
527+ ) ;
363528 }
364529
365530 throw new Error ( `Unknown initialized transition outcome` ) ;
@@ -380,42 +545,63 @@ async function processReceiverProposal(
380545 receiverRpc : testUtils . RpcClient ,
381546 recvPersister : InMemoryReceiverPersister ,
382547 ohttpRelay : string ,
548+ useAsync : boolean = false ,
383549) : Promise < payjoin . PayjoinProposal | null > {
384550 if ( receiver instanceof payjoin . Initialized ) {
385- const res = await retrieveReceiverProposal (
551+ return retrieveReceiverProposal (
386552 receiver ,
387553 recvPersister ,
388554 ohttpRelay ,
555+ useAsync ,
389556 ) ;
390- if ( res === null ) {
391- return null ;
392- }
393- return res ;
394557 }
395-
396558 if ( receiver instanceof payjoin . UncheckedOriginalPayload ) {
397- return processUncheckedProposal ( receiver , receiverRpc , recvPersister ) ;
559+ return useAsync
560+ ? processUncheckedProposalAsync (
561+ receiver ,
562+ receiverRpc ,
563+ recvPersister ,
564+ )
565+ : processUncheckedProposal ( receiver , receiverRpc , recvPersister ) ;
398566 }
399567 if ( receiver instanceof payjoin . MaybeInputsOwned ) {
400- return processMaybeInputsOwned ( receiver , receiverRpc , recvPersister ) ;
568+ return useAsync
569+ ? processMaybeInputsOwnedAsync ( receiver , receiverRpc , recvPersister )
570+ : processMaybeInputsOwned ( receiver , receiverRpc , recvPersister ) ;
401571 }
402572 if ( receiver instanceof payjoin . MaybeInputsSeen ) {
403- return processMaybeInputsSeen ( receiver , receiverRpc , recvPersister ) ;
573+ return useAsync
574+ ? processMaybeInputsSeenAsync ( receiver , receiverRpc , recvPersister )
575+ : processMaybeInputsSeen ( receiver , receiverRpc , recvPersister ) ;
404576 }
405577 if ( receiver instanceof payjoin . OutputsUnknown ) {
406- return processOutputsUnknown ( receiver , receiverRpc , recvPersister ) ;
578+ return useAsync
579+ ? processOutputsUnknownAsync ( receiver , receiverRpc , recvPersister )
580+ : processOutputsUnknown ( receiver , receiverRpc , recvPersister ) ;
407581 }
408582 if ( receiver instanceof payjoin . WantsOutputs ) {
409- return processWantsOutputs ( receiver , receiverRpc , recvPersister ) ;
583+ return useAsync
584+ ? processWantsOutputsAsync ( receiver , receiverRpc , recvPersister )
585+ : processWantsOutputs ( receiver , receiverRpc , recvPersister ) ;
410586 }
411587 if ( receiver instanceof payjoin . WantsInputs ) {
412- return processWantsInputs ( receiver , receiverRpc , recvPersister ) ;
588+ return useAsync
589+ ? processWantsInputsAsync ( receiver , receiverRpc , recvPersister )
590+ : processWantsInputs ( receiver , receiverRpc , recvPersister ) ;
413591 }
414592 if ( receiver instanceof payjoin . WantsFeeRange ) {
415- return processWantsFeeRange ( receiver , receiverRpc , recvPersister ) ;
593+ return useAsync
594+ ? processWantsFeeRangeAsync ( receiver , receiverRpc , recvPersister )
595+ : processWantsFeeRange ( receiver , receiverRpc , recvPersister ) ;
416596 }
417597 if ( receiver instanceof payjoin . ProvisionalProposal ) {
418- return processProvisionalProposal ( receiver , receiverRpc , recvPersister ) ;
598+ return useAsync
599+ ? processProvisionalProposalAsync (
600+ receiver ,
601+ receiverRpc ,
602+ recvPersister ,
603+ )
604+ : processProvisionalProposal ( receiver , receiverRpc , recvPersister ) ;
419605 }
420606 if ( receiver instanceof payjoin . PayjoinProposal ) {
421607 return receiver ;
@@ -524,7 +710,7 @@ function testFfiValidation(): void {
524710 } , / A m o u n t O u t O f R a n g e / ) ;
525711}
526712
527- async function testIntegrationV2ToV2 ( ) : Promise < void > {
713+ async function testIntegrationV2ToV2 ( useAsync : boolean = false ) : Promise < void > {
528714 const env = testUtils . initBitcoindSenderReceiver ( ) ;
529715 const receiver = env . getReceiver ( ) ;
530716 const sender = env . getSender ( ) ;
@@ -557,6 +743,7 @@ async function testIntegrationV2ToV2(): Promise<void> {
557743 receiver ,
558744 recvPersister ,
559745 ohttpRelay ,
746+ useAsync ,
560747 ) ;
561748 assert . strictEqual (
562749 processResponse ,
@@ -586,6 +773,7 @@ async function testIntegrationV2ToV2(): Promise<void> {
586773 receiver ,
587774 recvPersister ,
588775 ohttpRelay ,
776+ useAsync ,
589777 ) ;
590778 assert . notStrictEqual (
591779 payjoinProposal ,
@@ -634,7 +822,6 @@ async function testIntegrationV2ToV2(): Promise<void> {
634822 }
635823 attempts += 1 ;
636824 if ( attempts >= 3 ) {
637- // Receiver not ready yet; mirror Dart/Python tolerance.
638825 return ;
639826 }
640827 }
@@ -677,7 +864,8 @@ async function testIntegrationV2ToV2(): Promise<void> {
677864async function runTests ( ) : Promise < void > {
678865 await uniffiInitAsync ( ) ;
679866 testFfiValidation ( ) ;
680- await testIntegrationV2ToV2 ( ) ;
867+ await testIntegrationV2ToV2 ( false ) ; // sync callbacks
868+ await testIntegrationV2ToV2 ( true ) ; // async callbacks
681869}
682870
683871runTests ( ) . catch ( ( error : unknown ) => {
0 commit comments