diff --git a/.github/workflows/blobstorage-preview.yml b/.github/workflows/blobstorage-preview.yml new file mode 100644 index 0000000000..57db84c9c1 --- /dev/null +++ b/.github/workflows/blobstorage-preview.yml @@ -0,0 +1,33 @@ +env: + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID_BLOBSTORAGE }} + +on: + push: + branches-ignore: + - main + - release-please-* + paths: + - "packages/blobstorage/**" + +jobs: + Deploy-Preview: + runs-on: [taiko-runner] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install pnpm dependencies + uses: ./.github/actions/install-pnpm-dependencies + + - name: Install Vercel CLI + run: pnpm add --global vercel@latest + + - name: Pull Vercel Environment Information + run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} + + - name: Build Project Artifacts + run: vercel build --token=${{ secrets.VERCEL_TOKEN }} + + - name: Deploy Project Artifacts to Vercel + run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} diff --git a/.github/workflows/blobstorage-production.yml b/.github/workflows/blobstorage-production.yml new file mode 100644 index 0000000000..41c60b5694 --- /dev/null +++ b/.github/workflows/blobstorage-production.yml @@ -0,0 +1,30 @@ +env: + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID_BLOBSTORAGE }} + +on: + push: + tags: + - "blobstorage-*" + +jobs: + Deploy-Production: + runs-on: [taiko-runner] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install pnpm dependencies + uses: ./.github/actions/install-pnpm-dependencies + + - name: Install Vercel CLI + run: pnpm add --global vercel@latest + + - name: Pull Vercel Environment Information + run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }} + + - name: Build Project Artifacts + run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }} + + - name: Deploy Project Artifacts to Vercel + run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }} diff --git a/.github/workflows/bridge-ui-preview.yml b/.github/workflows/bridge-ui-preview.yml index 13344cfa87..54e142188b 100644 --- a/.github/workflows/bridge-ui-preview.yml +++ b/.github/workflows/bridge-ui-preview.yml @@ -1,6 +1,7 @@ +name: Vercel Preview Deployment + env: - VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} - VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID_BRIDGE_UI }} + VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} on: push: @@ -13,21 +14,24 @@ on: jobs: Deploy-Preview: runs-on: [taiko-runner] + strategy: + matrix: + include: + - project: "Public" + org_id: ${{ secrets.VERCEL_ORG_ID}} + project_id: ${{ secrets.VERCEL_PROJECT_ID_BRIDGE_UI}} + - project: "Internal" + org_id: ${{ secrets.VERCEL_ORG_ID }} + project_id: ${{ secrets.VERCEL_PROJECT_ID_BRIDGE_UI_INTERNAL}} steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Install pnpm dependencies - uses: ./.github/actions/install-pnpm-dependencies - + - uses: actions/checkout@v2 - name: Install Vercel CLI - run: pnpm add --global vercel@latest - - - name: Pull Vercel Environment Information - run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} - - - name: Build Project Artifacts + run: npm install --global vercel@latest + - name: Setup Vercel Environment for ${{ matrix.project }} + run: | + vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} --scope=${{ matrix.org_id }} --project-id=${{ matrix.project_id }} + vercel link --token=${{ secrets.VERCEL_TOKEN }} --confirm --name=${{ matrix.project }} --scope=${{ matrix.org_id }} + - name: Build Project Artifacts for ${{ matrix.project }} run: vercel build --token=${{ secrets.VERCEL_TOKEN }} - - - name: Deploy Project Artifacts to Vercel + - name: Deploy Project Artifacts to Vercel for ${{ matrix.project }} run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} diff --git a/.gitignore b/.gitignore index 91a3e81bbd..967a0a478d 100644 --- a/.gitignore +++ b/.gitignore @@ -117,3 +117,4 @@ __pycache__/ # VSCode .vscode/launch.json packages/protocol/config.js +.vercel diff --git a/packages/bridge-ui/src/components/Transactions/Dialogs/Claim.svelte b/packages/bridge-ui/src/components/Transactions/Dialogs/Claim.svelte index db38f7d7b3..53f0058d8d 100644 --- a/packages/bridge-ui/src/components/Transactions/Dialogs/Claim.svelte +++ b/packages/bridge-ui/src/components/Transactions/Dialogs/Claim.svelte @@ -2,6 +2,7 @@ import { switchChain } from '@wagmi/core'; import { log } from 'debug'; import { createEventDispatcher } from 'svelte'; + import type { Hash } from 'viem'; import { bridges, type BridgeTransaction } from '$libs/bridge'; import { NotConnectedError } from '$libs/error'; @@ -10,6 +11,9 @@ import { account } from '$stores/account'; import { connectedSourceChain } from '$stores/network'; + import { selectedRetryMethod } from './RetryDialog/state'; + import { RETRY_OPTION } from './RetryDialog/types'; + const dispatch = createEventDispatcher(); export let bridgeTx: BridgeTransaction; @@ -49,7 +53,13 @@ log(`Claiming ${bridgeTx.tokenType} for transaction`, bridgeTx); // Step 4: Call claim() method on the bridge - const txHash = await bridge.claim({ wallet, bridgeTx }); + let txHash: Hash; + if ($selectedRetryMethod === RETRY_OPTION.RETRY_ONCE) { + log('Claiming with lastAttempt flag'); + txHash = await bridge.claim({ wallet, bridgeTx, lastAttempt: true }); + } else { + txHash = await bridge.claim({ wallet, bridgeTx }); + } dispatch('claimingTxSent', { txHash, type: 'claim' }); } catch (err) { diff --git a/packages/bridge-ui/src/components/Transactions/Dialogs/ClaimDialog/ClaimDialog.svelte b/packages/bridge-ui/src/components/Transactions/Dialogs/ClaimDialog/ClaimDialog.svelte index a5c9405fef..863459cdee 100644 --- a/packages/bridge-ui/src/components/Transactions/Dialogs/ClaimDialog/ClaimDialog.svelte +++ b/packages/bridge-ui/src/components/Transactions/Dialogs/ClaimDialog/ClaimDialog.svelte @@ -52,36 +52,35 @@ export let nft: NFT | null = null; + export let proofReceipt: GetProofReceiptResponse; + + export let activeStep: ClaimSteps = INITIAL_STEP; + + export let bridgeTx: BridgeTransaction; + export const handleClaimClick = async () => { claiming = true; await ClaimComponent.claim(); - // claiming = false; - }; - - const handleAccountChange = () => { - activeStep = INITIAL_STEP; }; let canContinue = false; - - export let proofReceipt: GetProofReceiptResponse; - let claiming: boolean; let claimingDone = false; + let ClaimComponent: Claim; + let txHash: Hash; + + const handleAccountChange = () => { + activeStep = INITIAL_STEP; + }; const closeDialog = () => { dialogOpen = false; reset(); }; - let ClaimComponent: Claim; - - export let activeStep: ClaimSteps = INITIAL_STEP; - - export let bridgeTx: BridgeTransaction; - const handleClaimTxSent = async (event: CustomEvent<{ txHash: Hash; type: ClaimTypes }>) => { - const { txHash, type } = event.detail; + const { txHash: transactionHash, type } = event.detail; + txHash = transactionHash; log('handle claim tx sent', txHash, type); claiming = true; @@ -135,10 +134,6 @@ }), }); } - - //TODO: this could be just step 1 of 2, change text accordingly - - // claiming = false; }; const handleClaimError = (event: CustomEvent<{ error: unknown; type: ClaimTypes }>) => { @@ -252,7 +247,7 @@ {$t('transactions.claim.steps.review.name')} + isActive={activeStep === ClaimSteps.REVIEW}>{$t('common.review')} {:else if activeStep === ClaimSteps.CONFIRM} import { createEventDispatcher } from 'svelte'; import { t } from 'svelte-i18n'; + import type { Hash } from 'viem'; + import { chainConfig } from '$chainConfig'; import ActionButton from '$components/Button/ActionButton.svelte'; import { Icon, type IconType } from '$components/Icon'; import { Spinner } from '$components/Spinner'; - import { connectedSourceChain } from '$stores/network'; + import type { BridgeTransaction } from '$libs/bridge'; import { theme } from '$stores/theme'; import { TWO_STEP_STATE } from '../types'; @@ -16,7 +18,11 @@ export let claiming = false; - export let proveOrClaimStep: TWO_STEP_STATE; + export let proveOrClaimStep: TWO_STEP_STATE | null; + + export let bridgeTx: BridgeTransaction; + + export let txHash: Hash; const dispatch = createEventDispatcher(); @@ -33,13 +39,20 @@ }; const getSuccessDescription = () => { + if (!txHash) return; if (proveOrClaimStep === TWO_STEP_STATE.PROVE) { return $t('bridge.step.confirm.success.prove_description'); } + const explorer = chainConfig[Number(bridgeTx.destChainId)]?.blockExplorers?.default.url; + const url = `${explorer}/tx/${txHash}`; - return $t('transactions.actions.claim.success.message', { values: { network: $connectedSourceChain.name } }); + successDescription = $t('transactions.actions.claim.success.message', { values: { url } }); }; + $: if (txHash && claimingDone) { + getSuccessDescription(); + } + $: claimOrProveActionButton = proveOrClaimStep === TWO_STEP_STATE.CLAIM ? $t('transactions.claim.steps.confirm.claim_button') @@ -59,7 +72,7 @@ $: successIcon = `success-${$theme}` as IconType; $: statusTitle = getSuccessTitle(); - $: statusDescription = getSuccessDescription(); + let successDescription = ''; $: claimDisabled = !canClaim || claiming; @@ -74,7 +87,7 @@

{@html statusTitle}

- {@html statusDescription} + {@html successDescription} {:else if claiming} diff --git a/packages/bridge-ui/src/components/Transactions/Dialogs/RetryDialog/RetryDialog.svelte b/packages/bridge-ui/src/components/Transactions/Dialogs/RetryDialog/RetryDialog.svelte index 63a7b7edf9..697168c4c0 100644 --- a/packages/bridge-ui/src/components/Transactions/Dialogs/RetryDialog/RetryDialog.svelte +++ b/packages/bridge-ui/src/components/Transactions/Dialogs/RetryDialog/RetryDialog.svelte @@ -1,61 +1,103 @@ @@ -67,30 +109,52 @@ - + + here.", "title": "Transaction completed" }, "tx": { @@ -472,7 +473,7 @@ } }, "review": { - "name": "Prerequisites", + "name": "Review", "title": "Claim Transaction details" }, "title": "Claim your assets" @@ -507,6 +508,14 @@ "explorer_short": "View" }, "no_transactions": "No transactions found", + "retry": { + "steps": { + "select": { + "title": "Select" + }, + "title": "Retry claiming" + } + }, "status": { "claim": { "description": "Your asset is now ready for claiming on the destination chain and requires a transaction. If you have set a processing fee, the relayer will automatically handle the claiming process on your behalf.", diff --git a/packages/relayer/docker-compose/prometheus.yml b/packages/relayer/docker-compose/prometheus.yml index 578890489c..ca10d4ddf5 100644 --- a/packages/relayer/docker-compose/prometheus.yml +++ b/packages/relayer/docker-compose/prometheus.yml @@ -10,3 +10,8 @@ scrape_configs: - job_name: "rabbitmq" static_configs: - targets: ["host.docker.internal:15692"] + + - job_name: "rabbitmq_queue" + metrics_path: /metrics/per-object + static_configs: + - targets: ["host.docker.internal:15692"] diff --git a/packages/relayer/indexer/handle_message_received_event.go b/packages/relayer/indexer/handle_message_received_event.go index d796789c14..fbc6ae9ef9 100644 --- a/packages/relayer/indexer/handle_message_received_event.go +++ b/packages/relayer/indexer/handle_message_received_event.go @@ -26,13 +26,13 @@ func (i *Indexer) handleMessageReceivedEvent( "txHash", event.Raw.TxHash.Hex(), ) - // if the destinatio chain doesnt match, we dont process it in this indexer. - if new(big.Int).SetUint64(event.Message.DestChainId).Cmp(i.destChainId) != 0 { + // if the destination doesnt match our source chain, we dont want to handle this event. + if new(big.Int).SetUint64(event.Message.DestChainId).Cmp(i.srcChainId) != 0 { slog.Info("skipping event, wrong chainID", "messageDestChainID", event.Message.DestChainId, - "indexerDestChainID", - i.destChainId.Uint64(), + "indexerSrcChainID", + i.srcChainId.Uint64(), ) return nil diff --git a/packages/relayer/watchdog/watchdog.go b/packages/relayer/watchdog/watchdog.go index 813d4ea485..be8d54623c 100644 --- a/packages/relayer/watchdog/watchdog.go +++ b/packages/relayer/watchdog/watchdog.go @@ -285,14 +285,14 @@ func (w *Watchdog) checkMessage(ctx context.Context, msg queue.Message) error { } // check if the source chain sent this message - sent, err := w.srcBridge.IsMessageSent(nil, msgBody.Event.Message) + sent, err := w.destBridge.IsMessageSent(nil, msgBody.Event.Message) if err != nil { - return errors.Wrap(err, "w.srcBridge.IsMessageSent") + return errors.Wrap(err, "w.destBridge.IsMessageSent") } // if so, do nothing, acknowledge message if sent { - slog.Info("source bridge did send this message. returning early", + slog.Info("dest bridge did send this message. returning early", "msgHash", common.BytesToHash(msgBody.Event.MsgHash[:]).Hex(), "sent", sent, ) @@ -300,7 +300,7 @@ func (w *Watchdog) checkMessage(ctx context.Context, msg queue.Message) error { return nil } - data, err := encoding.BridgeABI.Pack("processMessage", [][32]byte{msgBody.Event.MsgHash}, true) + data, err := encoding.BridgeABI.Pack("suspendMessages", [][32]byte{msgBody.Event.MsgHash}, true) if err != nil { return errors.Wrap(err, "encoding.BridgeABI.Pack") } @@ -308,7 +308,7 @@ func (w *Watchdog) checkMessage(ctx context.Context, msg queue.Message) error { candidate := txmgr.TxCandidate{ TxData: data, Blobs: nil, - To: &w.cfg.DestBridgeAddress, + To: &w.cfg.SrcBridgeAddress, } receipt, err := w.txmgr.Send(ctx, candidate)