Skip to content

Commit 1b8c5ba

Browse files
committed
connect: Added eta to quote interface
The eta tells us the estimated transfer time in milliseconds (essentially finality time).
1 parent 3b27d05 commit 1b8c5ba

File tree

7 files changed

+36
-3
lines changed

7 files changed

+36
-3
lines changed

connect/src/protocols/cctp/cctpTransfer.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import type {
3737
import { TransferState, isAttested, isSourceFinalized, isSourceInitiated } from "../../types.js";
3838
import { Wormhole } from "../../wormhole.js";
3939
import type { WormholeTransfer } from "../wormholeTransfer.js";
40+
import { finality } from "@wormhole-foundation/sdk-base";
4041

4142
export class CircleTransfer<N extends Network = Network>
4243
implements WormholeTransfer<CircleTransfer.Protocol>
@@ -225,10 +226,10 @@ export class CircleTransfer<N extends Network = Network>
225226
try {
226227
msgIds = await fromChain.parseTransaction(txid);
227228
} catch (e: any) {
228-
if (e.message.includes('no bridge messages found')) {
229+
if (e.message.includes("no bridge messages found")) {
229230
// This means it's a Circle attestation; swallow
230231
} else {
231-
throw e
232+
throw e;
232233
}
233234
}
234235

@@ -584,10 +585,14 @@ export namespace CircleTransfer {
584585
const dstToken = Wormhole.chainAddress(dstChain.chain, dstUsdcAddress);
585586
const srcToken = Wormhole.chainAddress(srcChain.chain, srcUsdcAddress);
586587

588+
// https://developers.circle.com/stablecoins/docs/required-block-confirmations
589+
const eta =
590+
srcChain.chain === "Polygon" ? 2_000 * 200 : finality.estimateFinalityTime(srcChain.chain);
587591
if (!transfer.automatic) {
588592
return {
589593
sourceToken: { token: srcToken, amount: transfer.amount },
590594
destinationToken: { token: dstToken, amount: transfer.amount },
595+
eta,
591596
};
592597
}
593598

@@ -619,6 +624,7 @@ export namespace CircleTransfer {
619624
destinationToken: { token: dstToken, amount: dstAmount },
620625
relayFee: { token: srcToken, amount: fee },
621626
destinationNativeGas,
627+
eta,
622628
};
623629
}
624630

connect/src/protocols/tokenBridge/tokenTransfer.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Chain, Network } from "@wormhole-foundation/sdk-base";
2-
import { amount, encoding, toChain as toChainName } from "@wormhole-foundation/sdk-base";
2+
import { amount, encoding, finality, toChain as toChainName } from "@wormhole-foundation/sdk-base";
33
import type {
44
AttestationId,
55
AutomaticTokenBridge,
@@ -701,11 +701,13 @@ export namespace TokenTransfer {
701701
const dstDecimals = await dstChain.getDecimals(dstToken.address);
702702
const dstAmountReceivable = amount.scale(srcAmountTruncated, dstDecimals);
703703

704+
const eta = finality.estimateFinalityTime(srcChain.chain);
704705
if (!transfer.automatic) {
705706
return {
706707
sourceToken: { token: srcToken, amount: amount.units(srcAmountTruncated) },
707708
destinationToken: { token: dstToken, amount: amount.units(dstAmountReceivable) },
708709
warnings: warnings.length > 0 ? warnings : undefined,
710+
eta,
709711
};
710712
}
711713

@@ -796,6 +798,7 @@ export namespace TokenTransfer {
796798
relayFee: { token: srcToken, amount: fee },
797799
destinationNativeGas,
798800
warnings: warnings.length > 0 ? warnings : undefined,
801+
eta,
799802
};
800803
}
801804

connect/src/routes/portico/automatic.ts

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
} from "./../../index.js";
3737
import type { ChainAddress } from "@wormhole-foundation/sdk-definitions";
3838
import type { RouteTransferRequest } from "../request.js";
39+
import { finality } from "@wormhole-foundation/sdk-base";
3940

4041
export const SLIPPAGE_BPS = 15n; // 0.15%
4142
export const BPS_PER_HUNDRED_PERCENT = 10000n;
@@ -255,6 +256,7 @@ export class AutomaticPorticoRoute<N extends Network>
255256
token: params.normalizedParams.destinationToken,
256257
amount: fee,
257258
},
259+
eta: finality.estimateFinalityTime(request.fromChain.chain),
258260
},
259261
params,
260262
details,

connect/src/routes/request.ts

+2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ export class RouteTransferRequest<N extends Network> {
6868
dq.warnings = [...quote.warnings];
6969
}
7070

71+
dq.eta = quote.eta;
72+
7173
if (details) {
7274
dq.details = details;
7375
}

connect/src/routes/types.ts

+3
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ export type Quote<
7575
// If the transfer being quoted has any warnings
7676
// such as high slippage or a delay, they will be included here
7777
warnings?: QuoteWarning[];
78+
79+
// Estimated time to completion in milliseconds
80+
eta?: number;
7881
};
7982

8083
export type QuoteError = {

connect/src/types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -193,4 +193,6 @@ export interface TransferQuote {
193193
// If the transfer being quoted has any warnings
194194
// such as high slippage or a delay, they will be included here
195195
warnings?: QuoteWarning[];
196+
// Estimated time to completion in milliseconds
197+
eta?: number;
196198
}

core/base/src/constants/finality.ts

+15
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,18 @@ export function consistencyLevelToBlock(
176176
throw new Error("Only Ethereum safe is supported for now");
177177
}
178178
}
179+
180+
/**
181+
* Estimates the time required for a transaction to be considered "final"
182+
* @param chain The chain to estimate finality time for
183+
* @returns The estimated time in milliseconds
184+
*/
185+
export function estimateFinalityTime(chain: Chain): number {
186+
const finality = finalityThreshold.get(chain);
187+
if (finality === undefined) throw new Error("Cannot find finality for " + chain);
188+
189+
const time = blockTime.get(chain);
190+
if (time === undefined) throw new Error("Cannot find block time for " + chain);
191+
192+
return finality * time;
193+
}

0 commit comments

Comments
 (0)