Thanks for your interest in contributing to Rivet! Please take a moment to review this document before submitting a pull request. If you want to contribute, but aren't sure where to start, you can create a new discussion.
Note Please ask first before starting work on any significant new features.
It's never a fun experience to have your pull request declined after investing time and effort into a new feature. To avoid this from happening, we request that contributors create a feature request to first discuss any API changes or significant new ideas.
Here is a great primer on Web Extensions. The rest of the Chrome Developers guides are pretty good too.
Rivet has four isolated contexts:
- Wallet app:
- A Single Page Application (SPA).
- The main UI of Rivet (a React app).
- It is exposed to the global Web Extension APIs (ie.
chrome.runtime
).
- Background service worker:
- A service worker that runs in isolation in the background. The Background context is responsible for: handling RPC requests, external network requests, initializing the extension context menu, registering content scripts, etc.
- It is also exposed to the global Web Extension APIs (ie.
chrome.runtime
).
- Content Script:
- Executes JavaScript in the context of the current webpage. The Content Script context is mainly responsible for injecting the Wallet app into the current webpage.
- It is exposed to only a subset of the global Web Extension APIs (ie.
chrome.runtime
). - Its
window
instance is not the same as the current webpage'swindow
instance.
- Inpage:
- Similar to the Content Script and executes JavaScript in the context of the current webpage. The Inpage context is mainly responsible for injecting the
window.ethereum
provider into the current webpage. - Unlike the Content Script, it is not exposed to the global Web Extension APIs (ie.
chrome.runtime
). - Its
window
instance is the same as the current webpage'swindow
instance.
- Similar to the Content Script and executes JavaScript in the context of the current webpage. The Inpage context is mainly responsible for injecting the
Below is a diagram which visualizes these four contexts.
We can utilize a combination of the chrome.runtime.sendMessage
/chrome.tabs.sendMessage
APIs and window.postMessage
API to communicate between contexts.
It is important to note that the Inpage context does not have access to Web Extension APIs, and the Background/Wallet contexts do not have access to the window
instance, which makes messaging between these contexts non-trivial. To make this possible, we need to set up a "bridge relay" in the Content Script context which has access to window
and the Web Extension APIs.
To make this communication easier, we have created a "Messenger" abstraction so you don't have to think about what transport (window.postMessage
vs. chrome.runtime.sendMessage
vs. chrome.tabs.sendMessage
) to use, setting up a bridge relay, and dealing their synchronous nature.
example.ts
(Wallet context)
import { getMessenger } from '~/messengers';
const messenger = getMessenger('background:wallet');
async function example() {
const result = await messenger.send('ping', { foo: 'bar' });
console.log(result); // "pong and bar"
}
background.ts
(Background context)
import { getMessenger } from '~/messengers';
const messenger = getMessenger('background:wallet');
messenger.reply('ping', (args) => {
return `pong and ${args.foo}`;
});
This guide is intended to help you get started with contributing. By following these steps, you will understand the development process and workflow.
- Cloning the repository
- Installing Node.js and pnpm
- Installing Anvil
- Installing dependencies
- Running the Web Extension
- Installing the Web Extension
- Submitting a pull request
To start contributing to the project, clone it to your local machine using git:
git clone https://github.com/paradigmxyz/rivet.git
Or the GitHub CLI:
gh repo clone paradigmxyz/rivet
Rivet uses pnpm. You need to install Node.js v18 or higher and pnpm v8 or higher.
You can run the following commands in your terminal to check your local Node.js and pnpm versions:
node -v
pnpm -v
If the versions are not correct or you don't have Node.js or pnpm installed, download and follow their setup instructions:
- Install Node.js using fnm or from the official website
- Install pnpm
Rivet uses Anvil to spin up a forked Ethereum node.
Install Anvil using the following command:
curl -L https://foundry.paradigm.xyz | bash
Once in the project's root directory, run the following command to install the project's dependencies:
pnpm install
After you have installed dependencies, you are ready to run the Web Extension. To do so, run the following:
pnpm dev # start dev server
This will run a script that will build the Web Extension and start a dev server for the Test Dapp, it will also open the Test Dapp in a new browser tab. The Web Extension also utilizes Hot Module Replacement (HMR), so you can make changes to the code and see them reflected in the extension without having to reload the extension itself.
Once you have your dev server running, you can install the Web Extension in your browser. To do so, follow these steps:
- Open your browser's Extensions page
- Enable "Developer mode" in the top right corner
- Click "Load unpacked" in the top left corner
- Select the
dist/dev
folder in Rivet's root directory - You're good to go! Don't forget to pin the Extension to your browser's toolbar for easy access. 🎉
When you're ready to submit a pull request, you can follow these naming conventions:
- Pull request titles use the Imperative Mood (e.g.,
Add something
,Fix something
). - Changesets use past tense verbs (e.g.,
Added something
,Fixed something
).
When you submit a pull request, GitHub will automatically lint, build, and test your changes. If you see an ❌, it's most likely a bug in your code. Please, inspect the logs through the GitHub UI to find the cause.