diff --git a/packages/bridge-sdk/src/bridge/transfer/fromSolana.ts b/packages/bridge-sdk/src/bridge/transfer/fromSolana.ts index d9efd72..4c23179 100644 --- a/packages/bridge-sdk/src/bridge/transfer/fromSolana.ts +++ b/packages/bridge-sdk/src/bridge/transfer/fromSolana.ts @@ -1,4 +1,4 @@ -import { programIds, sendTransactionWithRetry } from '@oyster/common'; +import { programIds, sendTransactionWithRetry, sleep } from '@oyster/common'; import { WalletAdapter } from '@solana/wallet-base'; import { ethers } from 'ethers'; import { WormholeFactory } from '../../contracts/WormholeFactory'; @@ -113,6 +113,17 @@ export const fromSolana = async ( wallet, [ix, fee_ix, lock_ix], [], + undefined, + false, + undefined, + () => { + setProgress({ + message: 'Executing Solana Transaction', + type: 'wait', + group, + step: counter++, + }); + }, ); return steps.wait(request, transferKey, slot); @@ -124,31 +135,39 @@ export const fromSolana = async ( ) => { return new Promise((resolve, reject) => { let completed = false; + let unsubscribed = false; let startSlot = slot; let group = 'Lock assets'; const solConfirmationMessage = (current: number) => - `Awaiting ETH confirmations: ${current} out of 32`; + `Awaiting Solana confirmations: ${current} out of 32`; + let replaceMessage = false; let slotUpdateListener = connection.onSlotChange(slot => { - if (completed) return; - const passedSlots = slot.slot - startSlot; + if (unsubscribed) { + return; + } + + const passedSlots = Math.min(Math.max(slot.slot - startSlot, 0), 32); const isLast = passedSlots - 1 === 31; - if (passedSlots < 32) { + if (passedSlots <= 32) { setProgress({ message: solConfirmationMessage(passedSlots), type: isLast ? 'done' : 'wait', step: counter++, group, - replace: passedSlots > 0, + replace: replaceMessage, + }); + replaceMessage = true; + } + + if (completed || isLast) { + unsubscribed = true; + setProgress({ + message: 'Awaiting guardian confirmation. (Up to few min.)', + type: 'wait', + step: counter++, + group, }); - if (isLast) { - setProgress({ - message: 'Awaiting guardian confirmation', - type: 'wait', - step: counter++, - group, - }); - } } }); @@ -175,10 +194,19 @@ export const fromSolana = async ( completed = true; connection.removeAccountChangeListener(accountChangeListener); connection.removeSlotChangeListener(slotUpdateListener); + let signatures; + + while (!signatures) { + try { + signatures = await bridge.fetchSignatureStatus( + lockup.signatureAccount, + ); + break; + } catch { + await sleep(500); + } + } - let signatures = await bridge.fetchSignatureStatus( - lockup.signatureAccount, - ); let sigData = Buffer.of( ...signatures.reduce((previousValue, currentValue) => { previousValue.push(currentValue.index); @@ -217,7 +245,7 @@ export const fromSolana = async ( }); let tx = await wh.submitVAA(vaa); setProgress({ - message: 'Waiting for tokens unlock to be mined...', + message: 'Waiting for tokens unlock to be mined... (Up to few min.)', type: 'wait', group, step: counter++, diff --git a/packages/bridge-sdk/src/bridge/transfer/interface.ts b/packages/bridge-sdk/src/bridge/transfer/interface.ts index 63efd0e..3eb4b85 100644 --- a/packages/bridge-sdk/src/bridge/transfer/interface.ts +++ b/packages/bridge-sdk/src/bridge/transfer/interface.ts @@ -1,5 +1,5 @@ import { BigNumber } from 'bignumber.js'; -import {ethers} from "ethers"; +import { ethers } from 'ethers'; import { ASSET_CHAIN } from '../constants'; export interface ProgressUpdate { diff --git a/packages/bridge-sdk/src/bridge/transfer/toSolana.ts b/packages/bridge-sdk/src/bridge/transfer/toSolana.ts index f1dc021..57be58a 100644 --- a/packages/bridge-sdk/src/bridge/transfer/toSolana.ts +++ b/packages/bridge-sdk/src/bridge/transfer/toSolana.ts @@ -21,7 +21,7 @@ import { import { AccountInfo } from '@solana/spl-token'; import { TransferRequest, ProgressUpdate } from './interface'; import { WalletAdapter } from '@solana/wallet-base'; -import { BigNumber } from "bignumber.js"; +import { BigNumber } from 'bignumber.js'; export const toSolana = async ( connection: Connection, @@ -180,7 +180,7 @@ export const toSolana = async ( }); let res = await e.approve(programIds().wormhole.bridge, amountBN); setProgress({ - message: 'Waiting for ETH transaction to be mined...', + message: 'Waiting for ETH transaction to be mined... (Up to few min.)', type: 'wait', group, step: counter++, @@ -243,7 +243,7 @@ export const toSolana = async ( false, ); setProgress({ - message: 'Waiting for ETH transaction to be mined...', + message: 'Waiting for ETH transaction to be mined... (Up to few min.)', type: 'wait', group, step: counter++, diff --git a/packages/bridge-sdk/src/core/bridge.ts b/packages/bridge-sdk/src/core/bridge.ts index cfd6fc9..a6d943d 100644 --- a/packages/bridge-sdk/src/core/bridge.ts +++ b/packages/bridge-sdk/src/core/bridge.ts @@ -7,6 +7,16 @@ import * as BufferLayout from 'buffer-layout'; import * as bs58 from 'bs58'; import { AssetMeta } from '../bridge'; +export enum LockupStatus { + AWAITING_VAA, + UNCLAIMED_VAA, + COMPLETED, +} + +export interface LockupWithStatus extends Lockup { + status: LockupStatus; +} + export interface Lockup { lockupAddress: PublicKey; amount: BN; diff --git a/packages/bridge/src/components/RecentTransactionsTable/index.tsx b/packages/bridge/src/components/RecentTransactionsTable/index.tsx index 8d3bb30..9fc5bc2 100644 --- a/packages/bridge/src/components/RecentTransactionsTable/index.tsx +++ b/packages/bridge/src/components/RecentTransactionsTable/index.tsx @@ -1,5 +1,5 @@ import { Button, Table, Tabs, notification } from 'antd'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import './index.less'; @@ -34,11 +34,7 @@ const { TabPane } = Tabs; export const RecentTransactionsTable = (props: { showUserTransactions?: boolean; }) => { - const { - loading: loadingTransfers, - transfers, - userTransfers, - } = useWormholeTransactions(); + const { loading: loadingTransfers, transfers } = useWormholeTransactions(); const { provider } = useEthereum(); const bridge = useBridge(); @@ -154,221 +150,197 @@ export const RecentTransactionsTable = (props: { }, }, ]; - const columns = [ - ...baseColumns, - { - title: 'Status', - dataIndex: 'status', - key: 'status', - render(text: string, record: any) { - return { - props: { style: {} }, - children: ( - - {record.status} - - ), - }; - }, - }, - ]; - const userColumns = [ - ...baseColumns, - { - title: 'Status', - dataIndex: 'status', - key: 'status', - render(text: string, record: any) { - const status = - completedVAAs.indexOf(record.txhash) > 0 - ? 'Completed' - : record.status; - return { - props: { style: {} }, - children: ( - <> - - {status} - - {status === 'Failed' ? ( -