4
4
ChainAddress ,
5
5
ChainContext ,
6
6
CompletedTransferReceipt ,
7
+ DestinationQueuedTransferReceipt ,
7
8
Network ,
8
9
RedeemedTransferReceipt ,
9
10
Signer ,
@@ -14,6 +15,7 @@ import {
14
15
amount ,
15
16
chainToPlatform ,
16
17
isAttested ,
18
+ isDestinationQueued ,
17
19
isRedeemed ,
18
20
isSourceFinalized ,
19
21
isSourceInitiated ,
@@ -155,7 +157,7 @@ export class NttAutomaticRoute<N extends Network>
155
157
params . normalizedParams . options
156
158
) ;
157
159
158
- return {
160
+ const result : QR = {
159
161
success : true ,
160
162
params,
161
163
sourceToken : {
@@ -178,6 +180,28 @@ export class NttAutomaticRoute<N extends Network>
178
180
toChain . config . nativeTokenDecimals
179
181
) ,
180
182
} ;
183
+ const dstNtt = await toChain . getProtocol ( "Ntt" , {
184
+ ntt : params . normalizedParams . destinationContracts ,
185
+ } ) ;
186
+ const duration = await dstNtt . getRateLimitDuration ( ) ;
187
+ if ( duration > 0n ) {
188
+ const capacity = await dstNtt . getCurrentInboundCapacity ( fromChain . chain ) ;
189
+ const dstAmount = amount . parse (
190
+ params . amount ,
191
+ request . destination . decimals
192
+ ) ;
193
+ if (
194
+ NttRoute . isCapacityThresholdExceeded ( amount . units ( dstAmount ) , capacity )
195
+ ) {
196
+ result . warnings = [
197
+ {
198
+ type : "DestinationCapacityWarning" ,
199
+ delayDurationSec : Number ( duration ) ,
200
+ } ,
201
+ ] ;
202
+ }
203
+ }
204
+ return result ;
181
205
}
182
206
183
207
async initiate (
@@ -211,6 +235,41 @@ export class NttAutomaticRoute<N extends Network>
211
235
} ;
212
236
}
213
237
238
+ // Even though this is an automatic route, the transfer may need to be
239
+ // manually finalized if it was queued
240
+ async finalize ( signer : Signer , receipt : R ) : Promise < R > {
241
+ if ( ! isDestinationQueued ( receipt ) ) {
242
+ throw new Error (
243
+ "The transfer must be destination queued in order to finalize"
244
+ ) ;
245
+ }
246
+
247
+ const {
248
+ attestation : { attestation : vaa } ,
249
+ } = receipt ;
250
+
251
+ const toChain = this . wh . getChain ( receipt . to ) ;
252
+ const ntt = await toChain . getProtocol ( "Ntt" , {
253
+ ntt : receipt . params . normalizedParams . destinationContracts ,
254
+ } ) ;
255
+ const sender = Wormhole . chainAddress ( signer . chain ( ) , signer . address ( ) ) ;
256
+ const payload =
257
+ vaa . payloadName === "WormholeTransfer"
258
+ ? vaa . payload
259
+ : vaa . payload . payload ;
260
+ const completeTransfer = ntt . completeInboundQueuedTransfer (
261
+ receipt . from ,
262
+ payload [ "nttManagerPayload" ] ,
263
+ sender . address
264
+ ) ;
265
+ const finalizeTxids = await signSendWait ( toChain , completeTransfer , signer ) ;
266
+ return {
267
+ ...receipt ,
268
+ state : TransferState . DestinationFinalized ,
269
+ destinationTxs : [ ...( receipt . destinationTxs ?? [ ] ) , ...finalizeTxids ] ,
270
+ } ;
271
+ }
272
+
214
273
public override async * track ( receipt : R , timeout ?: number ) {
215
274
if ( isSourceInitiated ( receipt ) || isSourceFinalized ( receipt ) ) {
216
275
const { txid } = receipt . originTxs [ receipt . originTxs . length - 1 ] ! ;
@@ -264,12 +323,29 @@ export class NttAutomaticRoute<N extends Network>
264
323
}
265
324
}
266
325
267
- if ( isRedeemed ( receipt ) ) {
326
+ if ( isRedeemed ( receipt ) || isDestinationQueued ( receipt ) ) {
268
327
const {
269
328
attestation : { attestation : vaa } ,
270
329
} = receipt ;
271
330
272
- if ( await ntt . getIsExecuted ( vaa ) ) {
331
+ const payload =
332
+ vaa . payloadName === "WormholeTransfer"
333
+ ? vaa . payload
334
+ : vaa . payload . payload ;
335
+ const queuedTransfer = await ntt . getInboundQueuedTransfer (
336
+ vaa . emitterChain ,
337
+ payload [ "nttManagerPayload" ]
338
+ ) ;
339
+ if ( queuedTransfer !== null ) {
340
+ receipt = {
341
+ ...receipt ,
342
+ state : TransferState . DestinationQueued ,
343
+ queueReleaseTime : new Date (
344
+ queuedTransfer . rateLimitExpiryTimestamp * 1000
345
+ ) ,
346
+ } satisfies DestinationQueuedTransferReceipt < NttRoute . AutomaticAttestationReceipt > ;
347
+ yield receipt ;
348
+ } else if ( await ntt . getIsExecuted ( vaa ) ) {
273
349
receipt = {
274
350
...receipt ,
275
351
state : TransferState . DestinationFinalized ,
0 commit comments