Git Product home page Git Product logo

rainbow-bridge-frontend's Introduction

🌈 Rainbow Bridge Frontend 🌈

An app that moves assets between Ethereum and NEAR. You can use this as the starting point for your own app on the Rainbow Bridge.

Try it between Ethereum Goerli & NEAR Testnet: https://goerli.bridgetonear.org/

Deploy Lint

How it works

You can think of the Rainbow Bridge as having three main pieces:

  1. Clients. These get raw NEAR data into Ethereum and vice versa. These are light clients that run as smart contracts in each blockchain, with external relays to pipe the data in each direction.
  2. Provers. These are smart contracts that allow making assertions about data stored in the clients.
  3. Connectors. These are smart contract pairs, one on each chain, that provide an interface to apps that want to send certain kinds of data or calls from one blockchain to the other. They use the provers to ensure each operation is valid.

An app such as this one can then make calls to these various contracts to move assets between Ethereum and NEAR.

Right now, this app only moves a specific ERC20 fungible token from Ethereum to NEAR by making calls to a TokenLocker / MintableFungibleToken Connector contract pair. Here's how it looks:

UI showing sending 10 RAIN tokens from Ethereum to NEAR. Two confirmations from MetaMask pop up at the beginning of the transaction, then a notification area shows waiting for 25 blocks to sync, then the tokens are deposited on the NEAR side and the NEAR balance increases by 10

Above, we see someone sending tokens from their Ethereum wallet to their NEAR account. Here are the steps the app goes through:

  1. Make a call to the ERC20 contract to grant escrow access to a TokenLocker contract for the specified number of tokens (MetaMask pops up a confirmation here)
  2. Make a call to the TokenLocker to transfer these tokens from the user to itself (2nd MetaMask popup)
  3. TokenLocker contract emits Locked event
  4. This app waits for enough blocks to be mined on top of the one where this Locked event was emitted to feel confident that the transaction won't be reverted. This number could change based on the security needs of given Connector contracts.
  5. In the GIF above, it waits 25 blocks. These blocks need not only be mined in Ethereum, but also need to land in the EthOnNear Client contract. In the code, you'll see the app check progress by making calls to such a Client contract.
  6. This app makes a call to the MintableFungibleToken contract on NEAR to mint NEP141 fungible tokens on NEAR. Since NEAR contracts charge the contract owner for storage, this contract charges the user a small transaction fee, which is why you see a confirmation message on the NEAR side.
  7. The tokens have appeared in the user's NEAR wallet, and the app updates accordingly.

Here's a schematic representation, where "Transfer script" is this app's JavaScript:

TRANSFER SCRIPT calls 'approve' on ERC20 then 'lockToken' on LOCKER. LOCKER calls 'safeTransferFrom' on ERC20 then emits 'Locked' event. TRANSFER SCRIPT then notes the block of the 'Locked' event. TRANSFER SCRIPT then waits for this block to finalize over the bridge and extracts a proof. TRANSFER SCRIPT calls 'mint' on MINTABLE FUNGIBLE TOKEN. MINTABLE FUNGIBLE TOKEN checks that the event was not used before and that it's not too far in the past, then calls 'verify_log_entry' on PROVER. PROVER calls 'verify_trie_proof' on itself and then calls 'block_hash_safe' on ETH ON NEAR CLIENT. ETH ON NEAR CLIENT calls 'on_block_hash' on PROVER which calls 'finish_mint' on MINTABLE FUNGIBLE TOKEN

Getting started

  1. Clone this repository
  2. Make sure you've installed Node.js β‰₯ 12 and, optionally, yarn
  3. Install dependencies: npm install (or yarn install if you prefer yarn)
  4. Run the local development server: npm run start or yarn start (see package.json for a full list of scripts you can run)

This will start the app locally, connecting to smart contracts on the Ropsten test network for Ethereum and NEAR's Testnet. If you want to run everything locally, see below.

Exploring the code

  1. Start in package.json

    • Note the (relatively) short list of dependencies. If you prefer to use React, Vue, Svelte, Angular, or some other framework, this app should still be an easy starting point.
    • You'll see that the start script loads environment variables from the .config.js file. Anytime you see process.env in the code, you can check .config.js to see the value. This is also where you'll want to update settings to point at your own contracts.
    • After loading environment variables, the start script runs a development server using Parcel, a zero-config bundler.
  2. Next, explore index.html. Some interesting parts:

    • global.css – just as with JavaScript, this app is lightly opinionated about CSS. The global CSS file imports some more specific stylesheets using Parcel, but other than that strives to be as minimal as possible. Feel free to swap out the approach for whatever CSS framework you prefer.
    • data-behavior attributes are the main way that JavaScript hooks in, except for some CSS+JS widget-type UI elements like .dropdown.
    • aria-live="polite": this is for all the screen readers out there. It's how you make accessible dropdowns.
    • You'll see three main sections: 1. a nav element with the stuff that shows up in the top right, 2. the UI that shows up when you're signed out (note the authEthereum and authNear buttons), and 3. a main section, which is the UI you see when authenticated with both Ethereum and NEAR
    • Finally, at the bottom, you'll see the JS import
  3. index.js: deceptively simple?

    • Note the imports of files named authEthereum & authNear. These imports have side effects, adding behavior to the buttons with matching data-behavior attributes. The Ethereum- and NEAR-specific stuff is mostly contained within these files, so you can compare the authentication & contract-initialization code side-by-side.
    • initDOMHandlers is a function that needs to be called once after page load, to add behavior like dropdown toggling & form submission. Check out domHelpers.js to see the simple setup here.
    • render is a function which doesn't truly render, if you're used to thinking about rendering from a framework like React. Instead, this function procedurally updates the DOM based on current app state. Open render.js to see everything it does. This function gets called again in both authEthereum and authNear after login.

Run everything locally (todo)

In package.json you may have noticed a local command. This will let you run the app in "full local" mode, with a locally-running Ethereum network, NEAR network, NEAR Wallet (frontend & backend), Rainbow Bridge contracts, and an ERC20 contract.

This is difficult and error-prone, but could be streamlined if there's interest. Please get in touch if you want this.

To run this project locally:

  1. Prerequisites: Make sure you've installed Node.js β‰₯ 12

  2. Install dependencies: yarn install

  3. Follow the instructions for rainbow-bridge-cli to run an Ethereum network, a NEAR network, and the bridge all locally

  4. Run near-contract-helper locally on the default port (3000)

  5. Run near-wallet locally (this PR streamlines it). Run it on port 4000 & set node's --max-http-header-size to 16000 (default is 8kb):

    yarn update:static; node --max-http-header-size=16000 ./node_modules/.bin/parcel -p 4000 src/index.html
    
  6. Run the local development server: yarn local (see package.json for a full list of scripts you can run with yarn; see .config.js to see how environment variables are loaded in)

Contributing

You want to contribute to rainbow-bridge-frontend itself? Thank you!

To get started:

  1. Fork & clone the repository
  2. Make sure you've installed Node.js β‰₯ 12 and yarn
  3. Install dependencies: yarn install
  4. Make your changes, send a pull request!

Gotcha: commit messages

rainbow-bridge-frontend uses semantic versioning and auto-generates nice release notes & a changelog all based off of the commits. We do this by enforcing Conventional Commits. In general the pattern looks like:

type(scope?): subject  #scope is optional; multiple scopes are supported (current delimiter options: "/", "\" and ",")

Real world examples can look like this:

chore: run tests on travis ci
fix(server): send cors headers
feat(blog): add comment section

If your change should show up in release notes as a feature, use feat:. If it should show up as a fix, use fix:. Otherwise, you probably want refactor: or chore:. More info

Release the repository

Update the repository CHANGELOG:

yarn changelog

Commit and push master:

git commit -m "chore: Release v2.0.0."
git tag v2.0.0

rainbow-bridge-frontend's People

Contributors

chadoh avatar dependabot-preview[bot] avatar mikedotexe avatar paouvrard avatar semantic-release-bot avatar sept-en avatar thisisjoshford avatar unix avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rainbow-bridge-frontend's Issues

send novel ERC20 to NEAR

  • UI for searching for a whitelist of ERC20 tokens, set by environment variables
  • allow setting unlisted ERC20 via URL param (show warning for these)
  • if user selects ERC20 that has no matching ERC20-as-NEP21 deployed via Token Factory in NEAR
    • UI explains situation
    • user can pay tx / storage fee to deploy NEP21 Wrapper

send novel NEP21 to Eth

  • UI for searching for a whitelist of NEP21 tokens, set by environment variables
  • allow setting unlisted NEP21 via URL param (show warning for these)
  • if user selects NEP21 that has no matching NEP21-as-ERC20 deployed via Token Factory in Ethereum
    • UI explains situation
    • user can pay tx / storage fee to deploy ERC20 Wrapper

Dropdown to change between different bridges.

There will be several bridges running at the same time between different networks (Near mainnet, Near testnet, Ethereum Mainnet, Rinkeby and Ropsten).

The relevant difference between them from the frontend point of view, are the addresses of deployment and endpoint RPC. We should have a dropdown on the UI that allows user to change between bridges, (similar to how it is done in the explorer)

Improve balance display on eth accountsChanged

On a new transfer page, if the user changes Ethereum account, the balances should be queried again.

  • Ethereum -> Near: update "Available to transfer"
    image

  • Near -> Ethereum: update "Current balance" in To (destination)
    image

send wrapped ERC20 back to Eth

When, as shown above, someone has existing balance on NEAR of an ERC20 that has been wrapped as an NEP21 on NEAR, they should be able to send some balance from NEAR back to Ethereum. In the view below, there should be arrows pointing in both directions.

Screen Shot 2020-10-21 at 21.33.58.png

This should be done in the same way as rainbow-bridge-cli

Determine how to transform token icons when they're bridged to NEAR

Currently bridged tokens use the same token icons in the withdrawal dropdown. This can be enhanced by an approach to modifying existing ERC-20 tokens in similarly.
The main goal is to give a user a visual confirmation of two facts:

  1. Bridged token is different from the source token
  2. Bridge token is a representation of the source token on NEAR (has a 1:1 exchange ratio)

CC @chadoh

Consider using the same token names between networks

Currently, the bridge, and perhaps the wallet, display ERC-20 tokens as the Ethereum name, prefixed with an "n", e.g. "nALCX". This exposes in the UI the underlying mechanics of what's happening, i.e. that the token they are using on NEAR is a different token than what they had on Ethereum.

An alternative, currently in use by BSC and Terra, would be to use the original name of the token, e.g. just "ALCX". This has some benefits:

  • We hide the underlying mechanics from the user, and reinforce that "transferring" across the bridge is actually "moving" their tokens.
  • Interacting on NEAR has some familiarity (they're using the same tokens they are used to).
  • The UI of the Rainbow Bridge could be simplified, dropping the "Received as" row.

Remove withdraw/lock access keys

The withdraw() function of the BridgeToken should be #[payable] like the ft_transfer() of NEP141 and require a near deposit so that it is not possible to transact with an access key to that token contract. Instead the user should always sign a withdraw/lock transaction via the near wallet.

Minting/unlocking on near can be done safely with access keys as the receiver and amount are determined at lock/burn.

Once the change has been made and NEP141 is applied, this rainbow-bridge-frontend interface will have to be updated since it currently uses access keys for withdraw/lock on the near side.

A user is unable to send 1e18 tokens (big numbers problem)

Screenshot 2021-02-03 at 10 06 22

index.ts:205 :

Uncaught (in promise) Error: overflow (fault="overflow", operation="BigNumber.from", value=1000000000000000000, code=NUMERIC_FAULT, version=bignumber/5.0.8)
at l.makeError (index.ts:205)
at l.throwError (index.ts:217)
at m (bignumber.ts:335)
at Function.from (bignumber.ts:226)
at r.encode (number.js:13)
at array.js:41
at Array.forEach ()
at l (array.js:27)
at t.encode (tuple.js:19)
at C.encode (abi-coder.js:82)

ERC-20 -> NEP-4 not syncing the blocks

During the TST token transfer from Ropsten to TestNet, the front-end stales at the syncing stage, though the transaction was included in the block already.

Transaction: 0xbafee58f33a7d2441026e0e05272d1a0d8eb7396793e9331d930a5867af8471f

Screenshot 2021-02-03 at 10 04 18

Screenshot 2021-02-03 at 10 04 03

send wrapped NEP21 back to NEAR

When someone has existing balance on Ethereum of an NEP21 that has been wrapped as an ERC20, they should be able to send some balance from NEAR back to Ethereum. This is the inverse of near/rainbow-bridge#394

This should be done in the same way as rainbow-bridge-cli

Critical Path: Rainbow Bridge v0

While Job Stories (being defined for this project in #42) are useful for collecting a list of the granular motivations and decisions that users will be making as they interact with our product, it's also important to keep in mind the higher-level user journey.

Unlike job stories, a critical path can be illustrated in a number of ways (text, flowcharts, other diagrams). It's up to the author. The ultimate goal is to illustrated a single primary/critical path (ignoring major divergences) that a user will take from the point at which they enter the application, to the point at which they have achieved their primary goal, and all the steps in between (in our case: from sign in to the successful exchange of a certain amount of a single ERC20 to its NEAR equivalent).

As a design reference for how we envision a user traveling between points A > B > C, let's define the Critical Path that a user is most likely to traverse during their initial encounter with our MVP.

Tracking issue for final changes before the Q1 2021 release

  • #149
  • #136 (functionality only, may be without nice-looking UI) + PR#10 PR#11
  • Update the list of tokens according to #112 (comment)
  • #105 (comment)
  • Change on the login screen 'Don’t have a NEAR account? Create one here.' -> 'Need a NEAR account? Create one here.'
  • Change the links to the URLs according to #105 (comment) when switching between the networks
  • During scheduling the deployBridgeToken transaction change the appropriate amount for contract storage
  • Change everywhere the NEAR-side token names from DAI^n to nDAI
  • Update the wording for the transfer steps:
    • Approve transfer of 5.1 TST from Ethereum
    • Convert 5.1 TST to nTST
    • Wait for 20 Ethereum confirmations for security
    • Deposit 5.1 nTST on NEAR

    • Withdraw 0.1 nDAI from NEAR
    • Convert 0.1 nDAI to DAI
    • Sync withdrawal transaction to Ethereum (up to 24 hours)
    • Deposit 0.1 DAI in Ethereum

checkMint() may give the wrong result

checkMint() gives a failed transfer status if balanceBefore + transfer.amount != balanceAfter.
But the user may be doing other transfers (via bridge or regular token transfer) so checkMint() may give a failed status even though the mint transaction was successful.

The same problem can occur when the near.wallet informs : Error: send_tx_commit has timed out (balanceAfter queried before the tx is executed ?)

Host frontend in custom domain

The bridge frontend should be served at *.near.org url rather than in *.github.io for production.

We can keep *.github.io for staging, testing and iterating fast on new changes, but ultimately the stable and trusted deployment of the bridge should be at bridge.near.org.

After #104 we can have different url for different bridges, such that is clear for the user reading at the URL which bridge they are using. (Example https://bridge.rinkeby-testnet.near.org / https://bridge.ropsten-testnet.near.org)

Bug: Recovery from Failed Block Syncing (and other polling related bugs)

I was syncing blocks on the frontend and it got to 25/30.

Said "Failed" and the UI went red.

I clicked retry.

It is now orange, but still stuck at 25/30 block.

Now my TST isn't minted on the receiving side.

It's been several minutes now. Nothing on explorer.

Not sure what appropriate course of action is?

Perhaps we need some sort of unlocking if tokens are stuck and not minted?

image

image

Handle eth tx canceled/ speed up / replaced

From metamask a user may speed up an approve or lock transaction. Since the dapp frontend has no knowledge of this, it will keep checking the status of a transaction which has already been replaced and will never be mined. This is common behavior on eth mainnet especially with recent gas price variations. For dapps like uniswap this is not an issue as nothing depends on the execution result of the swap. But for the bridge:

  • If this happens on an approve tx, the user will never be able to create another transfer to Near due to the double approval override safety
  • If this happens on a lock tx, the dapp frontend will keep waiting for that lock tx and never be able to build a lock proof to mint the tokens on Near.

Discussions on the topic:
web3/web3.js#3585
web3/web3.js#3723
https://eips.ethereum.org/EIPS/eip-2831

Also there doesn't seem to be a good way to check transaction statuses with the account nonce since that would require an indexing service such as etherscan.

cc @djsatok

Update `getNep21Balance` with the usage of view method `get_bridge_token_account_id` of a bridge factory

Currently, in getNep21Balance function we use the following code:

const nep21Address =
    transfer.sourceToken.replace('0x', '').toLowerCase() +
    '.' +
    process.env.nearTokenFactoryAccount

Though at the moment this is correct, a connector might change the way how it maps addresses of the tokens on both sides. For the consistency, we should use get_bridge_token_account_id view method of the bridge factory

"Approve" TX must be sent even if the vault is already approved

Overview

I started an "Approve" TX, then used the MetaMask "speed up" feature to get the TX mined quicker. By doing this, the frontend never detected my successful TX (likely due to the TX having a different hash than the original), and there was no way for me to advance in the flow. I had to send another "Approve" TX, even though I'd just approved the contract.

Expected Behavior

If I've approved the vault for a token at any time, I shouldn't have to re-approve.

Steps to Reproduce

  1. Click "Approve Transfer"
  2. Authorize the TX in MetaMask
  3. Either click "Speed Up" in MetaMask, or leave the page and clear the browser cache
  4. The only path forward is to click "Approve" again and sign another, redundant TX

Choosing a custom token does not closes the dropdown

In case a user would like to manually enter the token contract address, the FE does not close the dropdown dialog after hitting enter. If manually close it, the displayed info in the transfer form is correct. This might be misleading for a user.

Desired behavior: once a user entered an address of his token in the field and hit enter, the dialog should be closed.

Job Stories: Rainbow Bridge v0

When designing an MVP, it's beneficial to lay out user stories at the outset of a project as a means to comprehensively survey the various user tasks and motivations.

In contrast to user stories, I actually favor Job Stories to fill this role. Job stories tend to be less prescriptive of user actions or solutions, and tend to provide more information about a user's context and motivations, which help to frame the problems we're solving more effectively.

The job story format looks like the following:

When I [situation], I want to [motivation] so I can [outcome/benefit].

In preparation for designing the front-end for the rainbow bridge, let's go through and define our job stories for our v0, making sure to focus not on prescribing specific solutions (eg "we need a button for..."), but rather our users' context, motivations, and outcomes. This list should be focused only on the stories we will be solving for for the MVP. These stories will be used to set and maintain context for decision making during the UX and UI design process.

Job Stories

A few examples to start:

- [x] When I first set out to transfer tokens from my Ethereum wallet to my NEAR wallet, I want to know which ERC20 tokens are available to transfer, so I can ensure I have the correct ERC20 tokens available in my Ethereum wallet.

  • After I initiate a transfer, I want to follow the progress of my transfer every step of the way, so that I can stay informed about the state of the transfer and any significant events that occur during processing.

- [ ] When a transfer I initiated is successful, I want to be notified about its completion, so I know when my transferred tokens are available to use.

  • When a transfer I initiated encounters a problem, I want to be notified of and be given context about the issue, so I can make an informed decision about what I might need do to resolve it.

Issue with erc20 token approvals

Currently for locking a token, it's allowance needs to be set so that the lock contract can pull the tokens.
This allowance is currently set by calling erc20Contract.methods.approve().
If a user initiates two eth -> near transfers, then the allowance will not have been increased by the 2nd transfer (because approve only sets approval and simply overrides the previous approval) and the erc20Contract.methods.lock() will fail.

Possible solutions:

  • Increase the allowance instead of setting it. But some erc20 tokens implement increaseAllowance() and others increaseApproval().
  • Prevent the user from initiating a transfer while the previous one is not locked.
  • Give the maximum allowance to the lock contract.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.