reNFT Dev Diary #1

Hi frens!

This is our very first dev diary, and we can’t be more excited to share with you how things have been on the technical side!

Let me start with a little context. reNFT is the rental-infrastructure platform for the metaverse. Our primary mission is building the tools and infrastructure required for blockchain rentals. Currently, we provide contracts, an SDK, and marketplaces.

Our v2 marketplace launched earlier this year with support for two smart contracts: “Azreal”, our collateralized solution, and “Sylvester”, our non-collateralized solution. In the following months, we were working in secret on our Castle Crush integration, featuring our “Whoopie” reward-share contract on the Avalanche C-Chain, released in early September.

September for us didn’t turn out to be a conclusion of all the work put into our platform. Instead, you could say we were just getting started. We had, save for two members, a new team of developers which needed ramp-up to:

  1. support and continue development for our Castle Crush friends, and
  2. continue core platform work to support even more contracts and chains.

In the rush to launch our Castle Crush integration, we made some understandable, though less than ideal, choices in platform architecture! Things move fast in Web3, and our platform architecture was far removed from the flexible and scalable monster we need it to be to support the number of integrations coming next year. Meanwhile, our fresh dev team needed to tread carefully, taking care not to remove any fences but that had been put in place by our predecessors.

What followed were weeks of frustrations and celebrations. Truth be told, as a team, bending a legacy codebase to your will is one of the most satisfying and educational experiences you can have.

The stack and our challenges

Let’s quickly summarize what we’re working with at reNFT.

  • We have contracts deployed on Ethereum Mainnet and Avalanche, (and Polygon soon! ) and are using Foundry for local development and testing.
  • We use The Graph as our source for verifiable access to decentralized on-chain data. At reNFT, we compose subgraphs that transform low-level actions and blockchain state into robust, meaningful, and performant data for our platform and SDKs.
  • We maintain a TypeScript SDK which enables anyone to easily interface with our smart contracts and start creating their own rental platforms.
  • To service our application frontend, our team maintains a dedicated express backend which aggregates marketplace data provided by our subgraphs with NFT Metadata providers like OpenSea, NFTPort, and Alchemy to serve accurate NFT metadata fit for our application frontend.
  • Lastly, we maintain a frontend marketplace built with NextJS which enables users to seamlessly interact with on-chain rentals.

It’s a great stack to work in. Still, we had some gnarly issues surrounding our critical paths. Issues surrounding wallet connections, people unable to stop lendings, blockchain provider issues, batch-operation issues, and some UI/UX issues to top it off. Architecturally, on the frontend, there was a crisscross of code paths between our generic marketplace and our Castle Crush specific integration. And our Castle Crush users were, rightfully so, requesting features like shareable wallets and expansive collection filtering options.

Oh, and before we forget… we have our own platform to further as well! Polygon and other EVM-compatible chains to implement, improvements to our marketplace, SDK, subgraph mappings, backend caching model, more robust typing… The list goes on.

Climbing the stack

Users come first. Always.

Fixing their issues and getting the most requested features was top-priority. Unfortunately, our dev team had little experience in the current codebase. Fortunately, one of the best ways to grok a new codebase is by fixing bugs and getting your hands dirty. We did so diligently. We got to work.

Our main focus is to fix our Stop Lend feature on Castle Crush. Guild members offering the most powerful tokens needed a way to cancel their lendings before eager players snapped them up at the beginning of the next rental cycle. Additionally, we got a lot of reports of slow pages, assets rendering incorrectly, and faulty filter data.

We decided to each focus on fixing parts related to each developer’s expertise. Roughly we split up the effort into UI/UX and data. Of course, these things are usually closely-intertwined and you’ll end up in each other’s territory at some point, but this always happens during rapid iteration. Getting in each other’s way enforces communication.

In software engineering, getting the team’s mental models on the stack in sync is a critical ingredient for effective work.

Around the second half of October, we published our very first changelog which documented some of the most critical UX fixes and provided our users with an introduction to the Stop Lend feature.

The issues surrounding our handling of wallet connections were still pressing; in some rare cases, some users couldn’t reconnect wallets properly! The frontend had a lot of custom coupling between ethers, @walletconnect, web3modal and react. Instead of having a lot of code-surface to manage ourselves, we implemented wagmi and @rainbow-me/rainbowkit to manage our wallet connections. This trimmed our codebase greatly, whilst simultaneously making wallet interactions in our frontend far simpler to reason about.

Our time spent migrating the codebase to using industry-standard tools for Web3 in React helped pave the way toward the release of the Lending Share Page feature our users had been requesting.

Work on this revealed a hard-coupling between a Collection (e.g. a group of NFTs like the contents of a user’s wallet, or the child tokens of an ERC721 or ERC1155) and the currently selected chain in the user’s connected wallet.

We would love to highlight every detail of the refactoring we did. Let’s just say it was quite the rabbit hole!

Unfortunately, we couldn’t make a big release at the end of October, shipping some UI improvements and a (much asked-for) update to our whitelisting feature. We had a lot to untangle still.

☕️

There’s one quality I find fascinating in developers. We have this borderline masochistic desire to write things the right (read: our) way, whatever that may be. This mood can be triggered by the tiniest of things: a linter preference, an improperly modeled property, or a function having one argument too many. What follows is a multi-day, obsessive grind. Yaks shaved and magnum opi written. The mood is only expelled when the mind feels a calm warmth radiating from the pull-request.

The main goal for our core platform was preparing for the deployment of our marketplaces on Polygon. For Polygon, we needed to deploy our contracts, update our indexers and block explorers in the API and tie these together logically on our frontend. We were happy to have this on the list alongside features because we had code-path overlap, as it allowed us to do some thorough work on the reNFT engine. This is also where the ☕️ came in handy.

Aside from this, we also needed to work on the much-requested wallet URLs and Castle Crush filters. It all involved a lot of moving parts.

For the frontend, the bulk of the work required refactoring how we dealt with page layouts in our application. In an application like NextJS pages are made up of a layout “frame” and a content “slot”. Having the correct data dependencies set up for both types of components is critical for application performance. On the backend, the Polygon support was ready, but serving payloads were still bottlenecked by a lack of pagination and lack of a NFT metadata cache.

These were the most stressful weeks. From the outside, it looked like things were stagnant. The team, however, was hard-pressed to wire up the changes in the stack. The new wallet integrations were deployed and tested on our staging environment, as well as the feature work on the frontend. We really started to feel the gnaw of not delivering to our users.

Things worked. Things actually worked… Of course, things worked!

At the end of November, we had a huge release. From the outside, our application now had shareable wallet URLs, filter options for Castle Crush wallets, and a lot of performance optimizations, bug fixes, and UI tweaks. Under the hood, however, we managed to make changes so the team could ship much faster. This felt like a great moment; it really felt like we reached a summit, and the exciting things we plan to do in the future felt within our reach.

Also, testing in production gets everyone going.

The next summit

Things move fast in space and so do we.

Polygon is coming. The earlier mentioned engine work will allow us to more easily integrate arbitrary EVM chains and improved contract versions, our Polygon marketplace being first. Once our thorough internal testing is complete, these improvements will be made available to everyone in the next major release of our SDK.

We’ve been working incredibly hard to better support large collections and “phat” wallets. Implementing image caching and edge availability is going to make sure that we’re serving NFT previews to everyone, everywhere fast. We’re also excited about our virtualized collection views, meaning only assets in view will be rendered. Your batteries will thank us.

Looking into next year, our team will begin streamlining third-party integrations by implementing an exhaustive and extensible GraphQL gateway for our subgraphs, custom integrations, and NFT metadata. We want to lower the barrier significantly for anyone who wishes to create their own decentralized rental marketplace. At the same time, we are going to further increase our release confidence and frequency thanks to an overhauled CI/CD pipeline.

Stay tuned.