@@ -13,6 +13,7 @@ import {
1313 TransferReceipt as _TransferReceipt ,
1414 TransferState ,
1515 UniversalAddress ,
16+ UnsignedTransaction ,
1617 Wormhole ,
1718 WormholeMessageId ,
1819 amount ,
@@ -39,6 +40,7 @@ import "@wormhole-foundation/sdk-definitions-ntt";
3940import { NttRoute } from "../types.js" ;
4041import {
4142 calculateReferrerFee ,
43+ collectTransactions ,
4244 fetchCapabilities ,
4345 fetchSignedQuote ,
4446 fetchStatus ,
@@ -449,12 +451,12 @@ export class NttExecutorRoute<N extends Network>
449451 } ;
450452 }
451453
452- async initiate (
454+ async _buildInitiateXfer (
453455 request : routes . RouteTransferRequest < N > ,
454- signer : Signer ,
455- quote : Q ,
456- to : ChainAddress
457- ) : Promise < R > {
456+ sender : ChainAddress ,
457+ to : ChainAddress ,
458+ quote : Q
459+ ) {
458460 if ( ! quote . details ) {
459461 throw new Error ( "Missing quote details" ) ;
460462 }
@@ -477,7 +479,10 @@ export class NttExecutorRoute<N extends Network>
477479 } ) ;
478480
479481 const { fromChain } = request ;
480- const sender = Wormhole . parseAddress ( signer . chain ( ) , signer . address ( ) ) ;
482+ const senderAddress = Wormhole . parseAddress (
483+ sender . chain ,
484+ sender . address . toString ( )
485+ ) ;
481486
482487 const nttWithExec = await fromChain . getProtocol ( "NttWithExecutor" , {
483488 ntt : params . normalizedParams . sourceContracts ,
@@ -489,15 +494,43 @@ export class NttExecutorRoute<N extends Network>
489494
490495 const wrapNative = isNative ( request . source . id . address ) ;
491496
492- const initXfer = nttWithExec . transfer (
493- sender ,
497+ return nttWithExec . transfer (
498+ senderAddress ,
494499 to ,
495500 amount . units ( params . normalizedParams . amount ) ,
496501 details ,
497502 ntt ,
498503 wrapNative
499504 ) ;
500- const txids = await signSendWait ( fromChain , initXfer , signer ) ;
505+ }
506+
507+ async buildInitiateTransactions (
508+ request : routes . RouteTransferRequest < N > ,
509+ sender : ChainAddress ,
510+ recipient : ChainAddress ,
511+ quote : Q
512+ ) : Promise < UnsignedTransaction < N , Chain > [ ] > {
513+ const xfer = await this . _buildInitiateXfer (
514+ request ,
515+ sender ,
516+ recipient ,
517+ quote
518+ ) ;
519+ const txs = await collectTransactions ( xfer ) ;
520+ return txs as UnsignedTransaction < N , Chain > [ ] ;
521+ }
522+
523+ async initiate (
524+ request : routes . RouteTransferRequest < N > ,
525+ signer : Signer ,
526+ quote : Q ,
527+ to : ChainAddress
528+ ) : Promise < R > {
529+ const sender = Wormhole . chainAddress ( signer . chain ( ) , signer . address ( ) ) ;
530+ const xfer = await this . _buildInitiateXfer ( request , sender , to , quote ) ;
531+
532+ const { fromChain } = request ;
533+ const txids = await signSendWait ( fromChain , xfer , signer ) ;
501534
502535 // Status the transfer immediately before returning
503536 let statusAttempts = 0 ;
@@ -532,13 +565,13 @@ export class NttExecutorRoute<N extends Network>
532565 to : to . chain ,
533566 state : TransferState . SourceInitiated ,
534567 originTxs : txids ,
535- params,
568+ params : quote . params ,
536569 } ;
537570 }
538571
539- async complete ( signer : Signer , receipt : R ) : Promise < R > {
572+ async _buildCompleteXfer ( sender : ChainAddress , receipt : R ) {
540573 if ( ! isAttested ( receipt ) && ! isFailed ( receipt ) ) {
541- if ( isRedeemed ( receipt ) ) return receipt ;
574+ if ( isRedeemed ( receipt ) ) return null ;
542575 throw new Error (
543576 "The source must be finalized in order to complete the transfer"
544577 ) ;
@@ -552,16 +585,36 @@ export class NttExecutorRoute<N extends Network>
552585 const ntt = await toChain . getProtocol ( "Ntt" , {
553586 ntt : receipt . params . normalizedParams . destinationContracts ,
554587 } ) ;
555- const sender = Wormhole . parseAddress ( signer . chain ( ) , signer . address ( ) ) ;
556- const completeXfer = ntt . redeem ( [ receipt . attestation . attestation ] , sender ) ;
588+ const senderAddress = Wormhole . parseAddress (
589+ sender . chain ,
590+ sender . address . toString ( )
591+ ) ;
592+ return ntt . redeem ( [ receipt . attestation . attestation ] , senderAddress ) ;
593+ }
594+
595+ async buildCompleteTransactions (
596+ sender : ChainAddress ,
597+ receipt : R
598+ ) : Promise < UnsignedTransaction < N , Chain > [ ] > {
599+ const xfer = await this . _buildCompleteXfer ( sender , receipt ) ;
600+ if ( xfer === null ) return [ ] ;
601+
602+ const txs = await collectTransactions ( xfer ) ;
603+ return txs as UnsignedTransaction < N , Chain > [ ] ;
604+ }
605+
606+ async complete ( signer : Signer , receipt : R ) : Promise < R > {
607+ const sender = Wormhole . chainAddress ( signer . chain ( ) , signer . address ( ) ) ;
608+ const xfer = await this . _buildCompleteXfer ( sender , receipt ) ;
609+ if ( xfer === null ) return receipt ;
557610
558- const txids = await signSendWait ( toChain , completeXfer , signer ) ;
611+ const toChain = this . wh . getChain ( receipt . to ) ;
612+ const txids = await signSendWait ( toChain , xfer , signer ) ;
559613 return {
560614 ...receipt ,
561615 state : TransferState . DestinationInitiated ,
562- attestation : receipt . attestation ,
563616 destinationTxs : txids ,
564- } ;
617+ } as R ;
565618 }
566619
567620 async resume ( tx : TransactionId ) : Promise < R > {
@@ -643,7 +696,7 @@ export class NttExecutorRoute<N extends Network>
643696
644697 // Even though this is an automatic route, the transfer may need to be
645698 // manually finalized if it was queued
646- async finalize ( signer : Signer , receipt : R ) : Promise < R > {
699+ async _buildFinalizeXfer ( sender : ChainAddress , receipt : R ) {
647700 if ( ! isDestinationQueued ( receipt ) ) {
648701 throw new Error (
649702 "The transfer must be destination queued in order to finalize"
@@ -658,13 +711,34 @@ export class NttExecutorRoute<N extends Network>
658711 const ntt = await toChain . getProtocol ( "Ntt" , {
659712 ntt : receipt . params . normalizedParams . destinationContracts ,
660713 } ) ;
661- const sender = Wormhole . chainAddress ( signer . chain ( ) , signer . address ( ) ) ;
662- const completeTransfer = ntt . completeInboundQueuedTransfer (
714+ return ntt . completeInboundQueuedTransfer (
663715 receipt . from ,
664716 vaa . payload [ "nttManagerPayload" ] ,
665717 sender . address
666718 ) ;
667- const finalizeTxids = await signSendWait ( toChain , completeTransfer , signer ) ;
719+ }
720+
721+ async buildFinalizeTransactions (
722+ sender : ChainAddress ,
723+ receipt : R
724+ ) : Promise < UnsignedTransaction < N , Chain > [ ] > {
725+ const txs = await collectTransactions (
726+ await this . _buildFinalizeXfer ( sender , receipt )
727+ ) ;
728+ return txs as UnsignedTransaction < N , Chain > [ ] ;
729+ }
730+
731+ async finalize ( signer : Signer , receipt : R ) : Promise < R > {
732+ if ( ! isDestinationQueued ( receipt ) ) {
733+ throw new Error (
734+ "The transfer must be destination queued in order to finalize"
735+ ) ;
736+ }
737+
738+ const sender = Wormhole . chainAddress ( signer . chain ( ) , signer . address ( ) ) ;
739+ const xfer = await this . _buildFinalizeXfer ( sender , receipt ) ;
740+ const toChain = this . wh . getChain ( receipt . to ) ;
741+ const finalizeTxids = await signSendWait ( toChain , xfer , signer ) ;
668742 return {
669743 ...receipt ,
670744 state : TransferState . DestinationFinalized ,
0 commit comments