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

refactor: migrate bridge logic to frontend #4

Merged
merged 9 commits into from
Aug 2, 2024

Conversation

meeh0w
Copy link
Member

@meeh0w meeh0w commented Jul 26, 2024

Description

FAQ

  • WTF Michał?

    • 👀 The PR is huuge, but lots of the logic only changed places (i.e. from background handlers to context providers / hooks on the frontend).
  • Can you explain the changes a bit?

    • ℹ️ Below you can find some notes on how things used to work and how they work right now. Hopefully those will make the review easier. Do not lose faith 🙏

Migrating logic to the frontend

Our BridgeService and UnifiedBridgeService used to be responsible for constructing the transaction data.

We don't want that anymore.

The idea is that frontend should be responsible for constructing the transactions and only ask backend to sign them. As such, this PR migrates parts of the bridge backend logic to the frontend side of the extension:

🙃 avalanche_bridgeAsset.ts handler updates

This handler is used by Core Web to initiate bridge transactions in the extension. It used to heavily rely on BridgeService, but now it's using the Bridge SDK directly to construct the transactions.

✂️ BridgeService.transferAsset() removed

The logic that was there now lives in BridgeProvider.tsx file, in transferEVMAsset() function. This function uses the Bridge SDK to construct the transaction data and sends an eth_sendTransaction request to the backend for the transaction to be signed and dispatched.

✂️ BridgeService.transferBtcAsset() removed

The logic that was there is mostly removed. This method was mostly constructing a simple BTC send transaction, which we already have utils for in bitcoin_sendTransaction handler. So the useBtcBridge() now validates the input parameters and then re-uses the same utils we have in our Send flows to construct a transaction (based on the Bridge config & bridge addresses) and then sends a bitcoin_sendTransaction request to the backend.

BridgeService.estimateGas() left unchanged

This was left unchanged, because our avalanche_bridgeAsset request handler is still using that part. However, extension's frontend uses the Bridge SDK directly to estimate gas limit.

✂️ UnifiedBridgeService.getFee() removed

The logic that was there now lives in UnifiedBridgeProvider.tsx, as getFee() function.

✂️ UnifiedBridgeService.estimateGas() removed

The logic that was there now lives in UnifiedBridgeProvider.tsx, as estimateGas() function.

✂️ UnifiedBridgeService.transfer() removed

The logic that was there now lives in UnifiedBridgeProvider.tsx, as transferAsset() function.

✂️ Bunch of handlers removed

  • transferAsset.ts
  • getEthMaxTransferAmount.ts - logic moved to the useEthBridge() hook.
  • unifiedBridgeEstimateGas.ts
  • unifiedBridgeGetFee.ts
  • unifiedBridgeGetAssets.ts
  • unifiedBridgeTransferAsset.ts
  • unifiedBridgeEstimateGas.ts

🚀 One new handler

  • unifiedBridgeTrackTransfer.ts - since the transaction building now lives on the frontend, once tx is confirmed the frontend asks the backend to start tracking the transfer.

Changes to eth_sendTransaction and bitcoin_sendTransaction

Since those handlers are very generic and since bridge transactions cannot be simulated with Blockaid (they are cross-chain, use off-chain services), the approval windows for Bridge transactions could become pretty confusing (especially when they require two approvals).

As an idea to help with this a little bit, I added an optional parameter to eth_sendTransaction and bitcoin_sendTransaction handlers. This parameter is called TxDisplayOptions. Here's the breakdown:

  • parameter cannot be used by external dApps (backend will reject requests that include this parameter when the request is not coming from the extension itself)
  • parameter may include custom transaction header (i.e. Confirm Bridge) and also some notice (i.e. This bridge transfer requires two approvals, you will be ask for one more signature).
  • if present, this parameter is simply attached to the displayData object and can be used by SignTransaction.tsx / BitcoinSignTransaction.tsx screens.

Frontend component structure changes

How things used to work

  1. Previously we had one huge Bridge.tsx file, that called useBridge() hook, which in turn called all of the bridge adapter hooks (useEthBridge, useBtcBridge, useAvalancheBridge and useUnifiedBridge).
  2. Those adapter hooks then had to check wether they're being rendered in the correct context to prevent unnecessary computation (not all of which was prevented).
  3. useBridge() then decided which of the rendered hooks are relevant in the current state and merge them with the default values, then return back to Bridge.tsx.

Here is a simplified diagram:

Bridge Flowchart drawio

How things work now

As part of this PR, I changed the flow a little bit to prevent that unnecessary computation. Approach is very similar to the new Send flows. This is what it looks like right now:

  1. One shared BridgeForm component was extracted out of Bridge.tsx. It renders the form and accepts all of the state & state handlers returned by the specialised hooks (so called bridge adapters) that Bridge.tsx used to do.
  2. Bridge.tsx still calls useBridge(), but it only gets the data that is shared between all specialised flows in return (so things like: bridge provider (avalanche / cctp), current amount & amount setter, target chain id, etc.)
  3. Once Bridge.tsx has this data, it then decides which of the the specialised BridgeForm components to render. There are four: BridgeFormETH, BridgeFormBTC, BridgeFormAVAX, BridgeFormUnified. Those specialised components render their respective specialised hooks (e.g. useBtcBridge()) and then render the shared BridgeForm component.

Here is a simplified diagram:

New Bridge Flowchart drawio

Testing

  • Make sure all bridging still works

Screenshots:

I was not able to test ETH offboarding, as I don't have enough funds. I'm attaching screencast for some of the remaining scenarios below.

Ethereum.to.Avalanche.mov
Bitcoin.to.Avalanche.mov
Avalanche.to.Bitcoin.mov
CCTP.Ethereum.to.Avalanche.mov
CCTP.Avalanche.to.Ethereum.mov

Checklist for the author

  • I've covered new/modified business logic with Jest test cases.
  • I've tested the changes myself before sending it to code review and QA.

ryanml
ryanml previously approved these changes Jul 29, 2024
bferenc
bferenc previously approved these changes Aug 2, 2024
Copy link
Contributor

@bferenc bferenc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏 ✅

left a question below 👇

@meeh0w meeh0w merged commit 8385aea into main Aug 2, 2024
3 of 4 checks passed
@meeh0w meeh0w deleted the refactor/migrate-bridge-to-frontend branch August 2, 2024 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants