Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WEB-6: useTrackTransfer optimization: sleep until 1 minute before transfer ETA #3212

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 29 additions & 15 deletions wormhole-connect/src/hooks/useTrackTransfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ import { sleep } from 'utils';

import type { AttestationReceipt } from '@wormhole-foundation/sdk';

const TRACK_INTERVAL = 5000;
const TRACK_INTERVAL_FAST = 1000;
// We don't start trying to fetch transfer updates until 1 minute from ETA
const MINIMUM_ETA = 60 * 1000;

const TRACK_TIMEOUT = 120 * 1000;

type Props = {
route: string | undefined;
receipt: routes.Receipt<AttestationReceipt> | null;
eta?: number;
// Timestamp the transfer was estimated to be finished
eta?: Date;
};

type ReturnProps = {
Expand All @@ -39,13 +41,6 @@ const useTrackTransfer = (props: Props): ReturnProps => {
useEffect(() => {
let isActive = true;

let sleepTime = TRACK_INTERVAL;

if (eta && eta < 30_000) {
// Poll aggressively for very fast transfers
sleepTime = TRACK_INTERVAL_FAST;
}

const track = async () => {
if (!routeName || !receipt) {
return;
Expand All @@ -57,12 +52,24 @@ const useTrackTransfer = (props: Props): ReturnProps => {
return;
}

const millisUntilEta = (eta: Date) =>
eta.valueOf() - new Date().valueOf();

const wh = await getWormholeContextV2();
const sdkRoute = new route.rc(wh);

let stateChanged = false;
while (isActive && !isCompleted(receipt)) {
if (eta !== undefined) {
// If we have an ETA, and it's longer than 2 minutes out, we wait until 2 minutes are left
artursapek marked this conversation as resolved.
Show resolved Hide resolved
// before trying to track the transfer's progress.
const msRemaining = millisUntilEta(eta);

if (msRemaining > MINIMUM_ETA) {
// Sleep until 1 minute from ETA
await sleep(msRemaining - MINIMUM_ETA);
}
}

while (isActive && !isCompleted(receipt) && !stateChanged) {
try {
// We need to consume all of the values the track generator yields in case any of them
// update the receipt state.
Expand All @@ -83,7 +90,6 @@ const useTrackTransfer = (props: Props): ReturnProps => {

if (isCompleted(currentReceipt)) {
setCompleted(true);
stateChanged = true;
break;
}

Expand All @@ -98,11 +104,19 @@ const useTrackTransfer = (props: Props): ReturnProps => {
}
} catch (e) {
console.error('Error tracking transfer:', e);
sleepTime = TRACK_INTERVAL; // Back off if we were polling aggressively
}

let sleepTime = 5_000;

// For automatic routes which are estimated to be done soon, we re-attempt more frequently
if (eta !== undefined && route.AUTOMATIC_DEPOSIT) {
const msRemaining = millisUntilEta(eta);
if (msRemaining < 10_000) {
sleepTime = 1_000;
}
}

// Retry
// TODO: exponential backoff depending on the current state?
await sleep(sleepTime);
}
};
Expand Down
43 changes: 26 additions & 17 deletions wormhole-connect/src/views/v2/Redeem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,36 @@ const Redeem = () => {

const getUSDAmount = useUSDamountGetter();

const etaDate: Date | undefined = useMemo(() => {
if (eta && txTimestamp) {
return new Date(txTimestamp + eta);
} else {
return undefined;
}
}, [eta]);
artursapek marked this conversation as resolved.
Show resolved Hide resolved

// Initialize the countdown with 0, 0 as we might not have eta or txTimestamp yet
const { seconds, minutes, isRunning, restart } = useTimer({
expiryTimestamp: new Date(),
autoStart: false,
onExpire: () => setEtaExpired(true),
});

// Side-effect to start the ETA timer when we have the ETA and tx timestamp
useEffect(() => {
// Only start when we have the required values and if the timer hasn't been started yet
if (!txTimestamp || !eta || isRunning) {
return;
}

restart(new Date(txTimestamp + eta), true);
}, [eta, isRunning, restart, txTimestamp]);

// Start tracking changes in the transaction
const txTrackingResult = useTrackTransfer({
receipt,
route: routeName,
eta: etaDate,
});

// We need check the initial receipt state and tracking result together
Expand Down Expand Up @@ -335,23 +361,6 @@ const Redeem = () => {
(state: RootState) => state.wallet.receiving,
);

// Initialize the countdown with 0, 0 as we might not have eta or txTimestamp yet
const { seconds, minutes, isRunning, restart } = useTimer({
expiryTimestamp: new Date(),
autoStart: false,
onExpire: () => setEtaExpired(true),
});

// Side-effect to start the ETA timer when we have the ETA and tx timestamp
useEffect(() => {
// Only start when we have the required values and if the timer hasn't been started yet
if (!txTimestamp || !eta || isRunning) {
return;
}

restart(new Date(txTimestamp + eta), true);
}, [eta, isRunning, restart, txTimestamp]);

// Time remaining to reach the estimated completion of the transaction
const remainingEta = useMemo(() => {
const etaCompletion = txTimestamp + eta;
Expand Down
2 changes: 1 addition & 1 deletion wormhole-connect/src/views/v2/TxHistory/Widget/Item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ const WidgetItem = (props: Props) => {
isReadyToClaim,
receipt: trackingReceipt,
} = useTrackTransfer({
eta,
eta: eta ? new Date(timestamp + eta) : undefined,
receipt: initialReceipt,
route,
});
Expand Down
Loading