@@ -16,6 +16,7 @@ import {
1616 amount ,
1717 canonicalAddress ,
1818 isAttested ,
19+ isCompleted ,
1920 isDestinationQueued ,
2021 isFailed ,
2122 isNative ,
@@ -710,143 +711,152 @@ export namespace MultiTokenNttRoute {
710711 isManual ?: boolean ,
711712 timeout ?: number
712713 ) {
713- if ( isSourceInitiated ( receipt ) || isSourceFinalized ( receipt ) ) {
714- const txid = receipt . originTxs . at ( - 1 ) ! ;
715-
716- // TODO: can pass txid when this is published: https://github.com/wormhole-foundation/wormhole-sdk-ts/pull/909
717- const fromChain = wh . getChain ( receipt . from ) ;
718- const [ msg ] = await fromChain . parseTransaction ( txid . txid ) ;
719- if ( ! msg ) throw new Error ( "No Wormhole messages found" ) ;
720-
721- const vaa = await wh . getVaa (
722- msg ,
723- "MultiTokenNtt:WormholeTransfer" ,
724- timeout
725- ) ;
726- if ( ! vaa ) throw new Error ( "No VAA found for transaction: " + txid . txid ) ;
727-
728- const msgId : WormholeMessageId = {
729- chain : vaa . emitterChain ,
730- emitter : vaa . emitterAddress ,
731- sequence : vaa . sequence ,
732- } ;
733-
734- receipt = {
735- ...receipt ,
736- state : TransferState . Attested ,
737- attestation : {
738- id : msgId ,
739- attestation : vaa ,
740- } ,
741- } ;
742- yield receipt ;
743- }
744-
745- const toChain = wh . getChain ( receipt . to ) ;
746- const destinationNtt = await toChain . getProtocol ( "MultiTokenNtt" , {
747- multiTokenNtt : receipt . params . normalizedParams . destinationContracts ,
748- } ) ;
749-
750- // Check if the transfer was redeemed
751- if ( isAttested ( receipt ) || isFailed ( receipt ) ) {
752- if ( ! receipt . attestation ) {
753- throw new Error ( "No attestation found" ) ;
754- }
714+ let leftover = timeout ? timeout : 60 * 60 * 1000 ;
715+ while ( leftover > 0 && ! isCompleted ( receipt ) ) {
716+ const start = Date . now ( ) ;
717+
718+ if ( isSourceInitiated ( receipt ) || isSourceFinalized ( receipt ) ) {
719+ const txid = receipt . originTxs . at ( - 1 ) ! ;
720+
721+ // TODO: can pass txid when this is published: https://github.com/wormhole-foundation/wormhole-sdk-ts/pull/909
722+ const fromChain : ChainContext < N > = wh . getChain ( receipt . from ) ;
723+ const [ msg ] = await fromChain . parseTransaction ( txid . txid ) ;
724+ if ( ! msg ) throw new Error ( "No Wormhole messages found" ) ;
725+
726+ const vaa = await wh . getVaa (
727+ msg ,
728+ "MultiTokenNtt:WormholeTransfer" ,
729+ timeout
730+ ) ;
731+ if ( ! vaa ) throw new Error ( "No VAA found for transaction: " + txid . txid ) ;
755732
756- const vaa = receipt . attestation . attestation ;
733+ const msgId : WormholeMessageId = {
734+ chain : vaa . emitterChain ,
735+ emitter : vaa . emitterAddress ,
736+ sequence : vaa . sequence ,
737+ } ;
757738
758- if ( await destinationNtt . getIsApproved ( vaa ) ) {
759- // All transceivers have approved the transfer
760739 receipt = {
761740 ...receipt ,
762- state : TransferState . DestinationInitiated ,
763- attestation : receipt . attestation ,
741+ state : TransferState . Attested ,
742+ attestation : {
743+ id : msgId ,
744+ attestation : vaa ,
745+ } ,
764746 } ;
765747 yield receipt ;
766- } else {
767- const { sendTransceivers } = receipt . params . normalizedParams ;
768-
769- // The Wormhole transceiver may wait to attest until all other transceivers have attested
770- // so we want to check it last
771- const sortedTransceivers = [ ...sendTransceivers ] . sort ( ( a , b ) => {
772- const aType = a . type . toLowerCase ( ) ;
773- const bType = b . type . toLowerCase ( ) ;
774- if ( aType === "wormhole" && bType !== "wormhole" ) return 1 ;
775- if ( aType !== "wormhole" && bType === "wormhole" ) return - 1 ;
776- return 0 ;
777- } ) ;
778-
779- for ( const transceiver of sortedTransceivers ) {
780- const transceiverType = transceiver . type . toLowerCase ( ) ;
781- if ( receipt . trackingInfo . transceiverAttested [ transceiverType ] ) {
782- continue ;
783- }
748+ }
784749
785- const attested = await destinationNtt . transceiverAttestedToMessage (
786- receipt . from ,
787- vaa . payload . nttManagerPayload ,
788- transceiver . index
789- ) ;
790- if ( attested ) {
791- receipt . trackingInfo . transceiverAttested [ transceiverType ] = true ;
792- if ( isFailed ( receipt ) ) {
793- // Reset the receipt status if the transceiver attested
794- receipt = {
795- ...receipt ,
796- attestation : receipt . attestation ! ,
797- state : TransferState . Attested ,
798- } ;
799- yield receipt ;
800- }
801- continue ;
802- }
750+ const toChain = wh . getChain ( receipt . to ) ;
751+ const destinationNtt = await toChain . getProtocol ( "MultiTokenNtt" , {
752+ multiTokenNtt : receipt . params . normalizedParams . destinationContracts ,
753+ } ) ;
803754
804- if ( transceiverType === "wormhole" ) {
805- // Manual transfers don't use executor
806- if ( ! isManual ) {
807- receipt = await trackExecutor ( wh . network , receipt ) ;
755+ // Check if the transfer was redeemed
756+ if ( isAttested ( receipt ) || isFailed ( receipt ) ) {
757+ if ( ! receipt . attestation ) {
758+ throw new Error ( "No attestation found" ) ;
759+ }
760+
761+ const vaa = receipt . attestation . attestation ;
762+
763+ if ( await destinationNtt . getIsApproved ( vaa ) ) {
764+ // All transceivers have approved the transfer
765+ receipt = {
766+ ...receipt ,
767+ state : TransferState . DestinationInitiated ,
768+ attestation : receipt . attestation ,
769+ } ;
770+ yield receipt ;
771+ } else {
772+ const { sendTransceivers } = receipt . params . normalizedParams ;
773+
774+ // The Wormhole transceiver may wait to attest until all other transceivers have attested
775+ // so we want to check it last
776+ const sortedTransceivers = [ ...sendTransceivers ] . sort ( ( a , b ) => {
777+ const aType = a . type . toLowerCase ( ) ;
778+ const bType = b . type . toLowerCase ( ) ;
779+ if ( aType === "wormhole" && bType !== "wormhole" ) return 1 ;
780+ if ( aType !== "wormhole" && bType === "wormhole" ) return - 1 ;
781+ return 0 ;
782+ } ) ;
783+
784+ for ( const transceiver of sortedTransceivers ) {
785+ const transceiverType = transceiver . type . toLowerCase ( ) ;
786+ if ( receipt . trackingInfo . transceiverAttested [ transceiverType ] ) {
787+ continue ;
808788 }
809- } else if ( transceiverType === "axelar" ) {
810- receipt = await trackAxelar ( wh . network , receipt ) ;
811- } else {
812- throw new Error (
813- `Unsupported transceiver type: ${ transceiver . type } `
789+
790+ const attested = await destinationNtt . transceiverAttestedToMessage (
791+ receipt . from ,
792+ vaa . payload . nttManagerPayload ,
793+ transceiver . index
814794 ) ;
795+ if ( attested ) {
796+ receipt . trackingInfo . transceiverAttested [ transceiverType ] = true ;
797+ if ( isFailed ( receipt ) ) {
798+ // Reset the receipt status if the transceiver attested
799+ receipt = {
800+ ...receipt ,
801+ attestation : receipt . attestation ! ,
802+ state : TransferState . Attested ,
803+ } ;
804+ yield receipt ;
805+ }
806+ continue ;
807+ }
808+
809+ if ( transceiverType === "wormhole" ) {
810+ // Manual transfers don't use executor
811+ if ( ! isManual ) {
812+ receipt = await trackExecutor ( wh . network , receipt ) ;
813+ }
814+ } else if ( transceiverType === "axelar" ) {
815+ receipt = await trackAxelar ( wh . network , receipt ) ;
816+ } else {
817+ throw new Error (
818+ `Unsupported transceiver type: ${ transceiver . type } `
819+ ) ;
820+ }
821+ yield receipt ;
822+ // We are breaking here so we only track one transceiver at a time
823+ // until all transceivers have attested. Otherwise the receipt state
824+ // may jump around too much resulting in a glitchy UI.
825+ break ;
815826 }
816- yield receipt ;
817- // We are breaking here so we only track one transceiver at a time
818- // until all transceivers have attested. Otherwise the receipt state
819- // may jump around too much resulting in a glitchy UI.
820- break ;
821827 }
822828 }
823- }
824829
825- if ( isRedeemed ( receipt ) || isDestinationQueued ( receipt ) ) {
826- const vaa = receipt . attestation . attestation ;
830+ if ( isRedeemed ( receipt ) || isDestinationQueued ( receipt ) ) {
831+ const vaa = receipt . attestation . attestation ;
827832
828- const queuedTransfer = await destinationNtt . getInboundQueuedTransfer (
829- vaa . emitterChain ,
830- vaa . payload . nttManagerPayload
831- ) ;
832- if ( queuedTransfer !== null ) {
833- receipt = {
834- ...receipt ,
835- state : TransferState . DestinationQueued ,
836- queueReleaseTime : new Date (
837- queuedTransfer . rateLimitExpiryTimestamp * 1000
838- ) ,
839- } ;
840- yield receipt ;
841- } else if ( await destinationNtt . getIsExecuted ( vaa ) ) {
842- receipt = {
843- ...receipt ,
844- state : TransferState . DestinationFinalized ,
845- } ;
846- yield receipt ;
833+ const queuedTransfer = await destinationNtt . getInboundQueuedTransfer (
834+ vaa . emitterChain ,
835+ vaa . payload . nttManagerPayload
836+ ) ;
837+ if ( queuedTransfer !== null ) {
838+ receipt = {
839+ ...receipt ,
840+ state : TransferState . DestinationQueued ,
841+ queueReleaseTime : new Date (
842+ queuedTransfer . rateLimitExpiryTimestamp * 1000
843+ ) ,
844+ } ;
845+ } else if ( await destinationNtt . getIsExecuted ( vaa ) ) {
846+ receipt = {
847+ ...receipt ,
848+ state : TransferState . DestinationFinalized ,
849+ } ;
850+ }
847851 }
852+
853+ yield receipt ;
854+
855+ // sleep for a few seconds so we don't spam the endpoints
856+ await new Promise ( ( resolve ) => setTimeout ( resolve , 3000 ) ) ;
857+ leftover -= Date . now ( ) - start ;
848858 }
849859
850- yield receipt ;
860+ return receipt ;
851861 }
852862}
0 commit comments