My React Plugin Journey: Embarking on an Epic Adventure

Week 1: Setting the stage and building foundations

Welcome to this series, where I will share my journey with you as I attempt to build a bridging aggregator react plugin alongside my mentor and the boys. Before we dive deep into the first week's activities, grab a glass of water and join me as I quickly brief you on how the first week went.

Some weeks back, I reached out to my mentor on Whatsapp, requesting we build a product together as I was in significant doubt about my technical skill after applying for some roles and getting turned down. After cheering me up, he proposed inviting friends for a wholesome experience. My boys got super excited about the opportunity and opted in. We're four and counting down to the start date.

On the day of onboarding, we went from four to six as two builders joined us from India. We introduced ourselves and got assigned some tasks to assess our skill level with the basic stacks we'd be using. Upon submission of the assignments, another meeting got scheduled to decide on a project so we could get things started officially.

We were allowed to choose between building a React component or a plugin. While the former would expose us to gaining knowledge of how components like the React Data Table Component are made, he informed us the latter is more complex and would encompass a practical understanding of building a React component and a plugin. Trust boys, we opted for the latter! We'll dedicate the next couple of weeks to this course and have it published as an NPM package.

Setting Things Up

We aim at building a replicate of the Socket Plugin, a public NPM package that helps bring the seamless bridging user experience from Bungee into any DApp. A long journey it is, but we must begin from somewhere.

For the first time, I didn't create my React app using the traditional create-react-app approach; instead, only react and react-dom dependencies were added, with no room for the extra stuff that comes with the default boilerplate. If you care to read more on this, Nikhil talked about setting up your own React.Js boilerplate and examined the pros and cons of this approach.

To separate the business logic from the application's UI, we adopted a Component Driven Development (CDD) approach to help us build, test, and document components in isolation using Storybook.Js. We followed the installation guide and added Storybook to our project.

We added tailwindcss to our React project using the installation guide. However, the styles didn't work on the test component due to Storybook requiring extra configurations to work with tailwindcss. This led us to our first configuration task. After searching for solutions online, we found a promising guide to integrating tailwindcss and Storybook. Despite following the guide, we couldn't get it to work until our mentor shared a tip involving adjusting the tailwind.config.js file to work with our project structure.

Familiarizing with Storybook

During the live coding session, we watched and coded along as our mentor showed us how to create a button component with its stories/states/variants. At first, everything looked strange; I later realized that the idea involved creating a simple/complex UI component and then having this component exist in different states or variants. The button component had a primary and secondary variant, a small size state, a full-width state, a disabled state, and a loading state. Creating different stories for different states of the component made it possible to conditionally effect styles on the button based on its current state, which may change due to user interaction with the component.

To better understand working with Storybook, we were tasked with building four (two complex and two easy) components per person alongside their relevant stories. I went on Carbon Design System for inspiration and made a modal, an accordion, a link, and a search component. I created my design system for the application, specifying what can and can't happen to the components when a user interacts with them. Felt good!

Of the four components I built, the modal came with more headache as I took things a step further to make it customizable - a team member who works with the component can pass a custom style object into the component as prop to override the default styles of the modal. The snippet below shows the technique I used to achieve this:

// Expected prop is an object whose key/value pairs are tailwindcss classes. The idea is to spread out the style classes into the component' ClassName when passed in.
[...Object.values(customStyles.cancelBtnStyles)].join(" ")

After having our components reviewed during the last meeting, which was held on Friday, 26th May 2023, we are now tasked with building the following components:

  • User input/output: this component will take and display the input. Passing a specified prop disables user input for the output variant.

  • Network dropdown: this component will display the active chain. Clicking on the component shows a dropdown of all available chains.

  • Token selector: this will be a modal component that shows all the tokens, their balances, and a search bar. It would be a complex one.

I'll be sure to brief you on how building these components went in the next episode of this series.

Choosing a Bridging Flow

In bridging, either a single or multi-transaction flow can be used. With the former, bridging and swapping are done at the sending chain, with no extra transactions done at the receiving chain. The reverse is the case for the latter, as other transactions can occur at the receiving chain.

We have chosen to use the single transaction bridge flow as our adopted method. To implement this, we will be utilizing the V2 of Socket API. See the flow below for a better understanding.

  1. The user selects sending and destination chain.

  2. Check tokens that can be bridged based on the previous step.

  3. Populate the from-token-list and to-token-list components with supported tokens for bridging.

  4. The user selects the token to be sent and received.

  5. Fetch and display available routes between selected chains using the quote endpoint.

  6. The user selects a route.

  7. Check if the selected token is an ERC-20 token.

  8. Request allowance of spending sending token from the user using the check-allowance endpoint.

  9. If the selected token isn't ERC-20, skip step seven and continue.

  10. If the user does not provide a receiving address, the sender's address will be used as the receiving address on the selected chain. If a receiving address is provided by the user, that address will be used instead.

  11. Fetch the callData for the route from /server/build-tx endpoint to get transaction data.

  12. Initiate a contract call to send callData to Socket contracts.

  13. Socket contract bridges and swaps.

  14. Track transaction status using Socket Bridge Status APIs.

Conclusion

The first week was mainly focused on project setup and configurations, familiarizing ourselves with Storybook, and deciding on a flow for our bridging application. Now we'll begin building components used in the application, using Socket or Uniswap plugin as a case study.

Also, we have been tasked with researching different topics, with each person assigned two issues. Mine is State Management using Redux and an overview of Web3 bridging. I'll be sure to share my findings with you in the next episode of this series.

To access my Github repository for this project, please follow this link.

That would be all for now. To catch the upcoming episodes of this series, kindly follow my Hashnode profile and connect with me on LinkedIn. Stay growing!