-
Notifications
You must be signed in to change notification settings - Fork 421
docs: add popkins (sepolia + celestia mocha) and local OP Stack & Nitro devnet guides #2395
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
Open
jcstein
wants to merge
22
commits into
main
Choose a base branch
from
jcstein/op-stack-local-devnet
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
7bdb8c8
docs: add guide for popkins + popsigner op stack
bc6ec49
docs: add local OP Stack devnet guide
3b8a142
docs: add placeholder for upcoming Popkins UI features
bdbd9c4
docs: replace emdashes with hyphens
95e6ccc
docs: address review comments on popkins-popsigner guide
65d4c5f
Update page.mdx
jcstein 6ad31dc
Merge branch 'main' into jcstein/op-stack-local-devnet
jcstein 196d881
docs: move around existing contents into 1 dir
jcstein 3401530
docs: rearrange guide
jcstein deda4dd
docs: fix links
jcstein 8ad2dd3
docs: add nitro guide
jcstein 15d0446
docs: add smart contract example
jcstein 9d324cd
docs: add detailed port mappings and funded accounts info for Nitro l…
jcstein 5b39055
docs: add type
jcstein 2361166
docs: add clone step on nitro
jcstein d63fc4b
docs: edit
jcstein 33bd575
docs: add popkins ui steps for local networks
jcstein adf96af
Merge branch 'main' into jcstein/op-stack-local-devnet
jcstein 7715111
docs: add nitro guide for popsigner
jcstein 86d60d2
docs: nitro deployment edits
jcstein a808295
fix: scrot
jcstein e5736ea
Merge remote-tracking branch 'origin/main' into jcstein/op-stack-loca…
jcstein File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| const meta = { | ||
| "nitro-das-server": "Nitro DAS server", | ||
| "op-alt-da": "OP alt DA", | ||
| "optimism": "Optimism", | ||
| }; | ||
|
|
||
| export default meta; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| const meta = { | ||
| "op-alt-da": "OP alt DA", | ||
| "popkins-popsigner": | ||
| "Deploying OP alt DA with Popkins, Popsigner, and Docker", | ||
| "local-devnet": "Local OP Stack Devnet", | ||
| }; | ||
|
|
||
| export default meta; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| # Local OP Stack Devnet | ||
|
|
||
| Spin up a complete local OP Stack rollup with Celestia DA for testing. | ||
|
|
||
| ```bash | ||
| # Build the bundle generator | ||
| cd control-plane/cmd/pop-deployer | ||
| go build -o pop-deployer . | ||
|
|
||
| # Generate the pre-deployed bundle | ||
| ./pop-deployer | ||
|
|
||
| # Extract and run | ||
| tar xzf opstack-local-devnet-bundle.tar.gz | ||
| cd bundle | ||
| docker compose up -d | ||
| ``` | ||
|
|
||
| Verify it's running: | ||
|
|
||
| ```bash | ||
| cast block-number --rpc-url http://localhost:8545 | ||
| # 55 | ||
| ``` | ||
|
|
||
| This starts: | ||
| - **Anvil** - L1 chain with pre-deployed OP Stack contracts | ||
| - **OP-Geth** - L2 execution client | ||
| - **OP-Node** - L2 consensus/derivation | ||
| - **Localestia** - Mock Celestia DA layer | ||
| - **POPSigner-Lite** - Local signing service | ||
|
|
||
| The bundle comes with all contracts already deployed and configured—just extract and run. | ||
|
|
||
| **What `pop-deployer` does:** It spins up a temporary Anvil instance, deploys all OP Stack contracts (SystemConfig, L1CrossDomainMessenger, OptimismPortal, etc.), captures the chain state to a snapshot, then packages everything into a tarball. When you run the bundle, Anvil loads the pre-deployed state instantly—no waiting for contract deployments. |
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,325 @@ | ||
| # How to deploy an OP Stack rollup with Docker, Popsigner, and Popkins | ||
|
|
||
| ## Overview | ||
|
|
||
| OP Stack, the stack behind Optimism, allows you to run rollups that post data to Celestia instead of Ethereum by using op-alt-da. Learn more in [the overview of op-alt-da](https://docs.celestia.org/build/stacks/op-alt-da/). In this tutorial, you’ll learn how to run an OP stack rollup using: | ||
|
|
||
| - **[Popsigner](https://github.com/celestiaorg/popsigner)** for key management. Popsigner is a great way to create, manage, and revoke keys, or even export them if you’d like. | ||
| - **[Popkins](https://popkins.popsigner.com/)** for deploying contracts and chain setup. Popkins sets up your keys from Popsigner for rollup deployment, deploys your contracts, and gives you the bundle to run your rollup locally. | ||
| - **Docker** for the devops of running your rollup bundle. | ||
|
|
||
| In order to get started, you will need a basic understanding of a few components with accounts you will create that make up this stack: | ||
|
|
||
| 1. **deployer**: Deploys and configures L1 contracts. Needs most ETH for gas. | ||
| 2. **batcher**: This account submits L2 transaction batches to L1. Needs ongoing ETH. | ||
| 3. **proposer**: Submits L2 state roots to L1 for withdrawals. | ||
| 4. **celestia**: This account posts data to Celestia’s Mocha testnet | ||
|
|
||
| With these four components and accounts combined, you will be able to run an OP Stack rollup that posts to Celestia for data availability! Let’s get started. | ||
|
|
||
| ## Environment setup | ||
|
|
||
| This tutorial has been tested on MacOS and Linux (Ubuntu 24.04). | ||
|
|
||
| Before you run OP stack, you’ll need: | ||
|
|
||
| 1. Docker installed and running locally. | ||
| 2. An Ethereum Sepolia RPC endpoint from a provider like [Quicknode](https://www.quicknode.com/), [Alchemy](https://www.alchemy.com/), or [Infura](https://www.infura.io/) | ||
| 3. A Celestia Mocha testnet RPC and gRPC endpoint from [Quicknode](https://www.quicknode.com/) for posting and retrieving blobs | ||
|
|
||
| That’s it for now! Let’s get everything else set up. | ||
|
|
||
| import { Steps } from "nextra/components"; | ||
|
|
||
| <Steps> | ||
|
|
||
| ## Setting up keys on Popsigner | ||
|
|
||
| First, you’ll set up the keys for the batcher, deployer, proposer, and Celestia. This will allow us to deploy the rollup through Popkins and then start it locally, posting blobs to Celestia. | ||
|
|
||
| 1. Go to [https://popsigner.com/](https://popsigner.com/) and make an account by clicking “Deploy”: | ||
|
|
||
|  | ||
|
|
||
| 2. Once you’re logged in, click “CREATE_KEY” in the top right: | ||
|
|
||
|  | ||
|
|
||
| 3. Make 4 keys, all universal for simplicity: | ||
| 1. deploy-1 | ||
| 2. batcher-1 | ||
| 3. proposer-1 | ||
| 4. celestia-1 | ||
|
|
||
|  | ||
|
|
||
| ## Funding keys | ||
|
|
||
| Now that you’ve set the keys up, you need to fund 3 of the addresses accordingly. | ||
|
|
||
| 1. Find the addresses in your dashboard, for Ethereum Sepolia keys, copy the 0x address: | ||
|
|
||
|  | ||
|
|
||
| and click “VIEW” to see the Celestia address: | ||
|
|
||
|  | ||
| 2. Deployer key: `deploy-1` (or whatever you named this) | ||
| 1. Here’s my example address: `0x7C7ece049b23b68D8c4a087f5252040B61F9fAe8` | ||
| 2. Fund the `deploy-1` with at least 1 sepoliaETH | ||
| 3. Batcher key: `batcher-1` | ||
| 1. Here’s my example address: `0xDB00E7dfd960bD8C497807f07fa161016a4900F3` | ||
|
jcstein marked this conversation as resolved.
Outdated
|
||
| 2. Fund the `batcher-1` with at least 0.5 sepoliaETH | ||
| 4. Proposer key: `proposer-1` | ||
| 1. Here’s my example address: `0xd66a3047fcFd200b36F8c8Da1a4B1d4Ddb497c6C` | ||
| 2. You only need to fund this key if you plan to make withdrawals from the L2 to L1. | ||
| 5. Celestia key: | ||
| 1. Here’s my example address: `celestia1su2l6v5a0cj6yg05gp9cuvfen74t8u8rvck836` | ||
| 2. Fund the `celestia-1` address with 10 Mocha TIA from the [faucet](https://celenium.io/faucet) | ||
|
|
||
| ## Setting up deployment on Popkins | ||
|
|
||
| Next, you’re ready to sign in to [Popkins](https://popkins.popsigner.com/deployments) and begin your first rollup deployment with an OP Stack chain. | ||
|
|
||
| 1. Click “+ NEW CHAIN” button in the top right corner and select OP Stack as the stack. | ||
|
|
||
|  | ||
|
|
||
| 2. Set up your config for the new chain! Pick a rollup name and ID that you want to use. This is where you’ll also put in the Ethereum Sepolia RPC URL from the environment setup. | ||
|
|
||
|  | ||
|
|
||
| 3. Click “CONTINUE”, then assign keys accordingly: | ||
| 1. Deployer key: `deploy-1` (or whatever you setup for this) | ||
| 2. Batcher key: `batcher-1` | ||
| 3. Proposer key: `proposer-1` | ||
| 4. You’ll set the Celestia key up later in the `.env` | ||
|
|
||
| Then click “CONTINUE” again: | ||
|
|
||
|  | ||
|
|
||
| 4. Once you’ve set up the config, double-check the values before proceeding! Make sure you have 1 sepoliaETH in the deploy key and 0.5 sepoliaETH in the batcher key, and 10 mochaTIA in your Celestia account. | ||
| 1. Click “🚀 DEPLOY CHAIN” | ||
|
|
||
|  | ||
|
|
||
| 5. Keep an eye out on the process as it completes. Once it’s finished, you will be able to download the config to run your rollup with Docker compose. | ||
|
|
||
|  | ||
|
|
||
| 6. Click “BACK TO MY CHAINS” | ||
|
|
||
|  | ||
|
|
||
| 7. Go to the chain you just set up. Download the bundle by clicking “DOWNLOAD ARTIFACTS” | ||
|
|
||
|  | ||
|
|
||
| ## Running locally with Docker | ||
|
|
||
| Now that you’ve set the rollup up by deploying contracts and downloading the artifacts, you’re ready to run it on your own and start producing blocks! Let’s start by making some config changes. | ||
|
|
||
| 1. Set up API key on [Popsigner.com](http://Popsigner.com). This is different than creating a key for a blockchain account. Save this for the next step in your clipboard. You’ll only be able to see it once, for safe security practice. | ||
|
jcstein marked this conversation as resolved.
Outdated
|
||
|
|
||
|  | ||
|
|
||
| 2. Copy `.env.example` into `.env` to put in your environment variables: | ||
| 1. Fill in the Popsigner API key in your `.env` after copying it in step 1: | ||
|
|
||
| ``` | ||
| # Your POPSigner API key (get from dashboard.popsigner.com) | ||
| POPSIGNER_API_KEY=<REQUIRED> | ||
| ``` | ||
|
|
||
| Here’s what mine looks like: | ||
|
|
||
| ``` | ||
| POPSIGNER_API_KEY=bbr_live_7Kp3xM9nR2bQ4sL8wXy6Zv1a | ||
| ``` | ||
|
|
||
| 2. Next, fill in the Celestia information: | ||
| 1. To find your Key ID, go to the Celestia key in Popsigner, click “View”, and copy the “KEY_ID”: | ||
|
|
||
| ``` | ||
| # Your Celestia key ID from POPSigner (UUID format) | ||
| CELESTIA_KEY_ID=<your-celestia-key-uuid> | ||
| ``` | ||
|
|
||
| Here’s what mine looks like: | ||
|
|
||
| ``` | ||
| CELESTIA_KEY_ID=7f4a8c21-b9e3-4d6e-ac52-1e8f9d3c7b65 | ||
| ``` | ||
|
|
||
| 2. For the bridge/light node RPC, use Quicknode: | ||
|
|
||
| ``` | ||
| # Celestia Bridge/Light Node RPC (for reading blobs) | ||
| # Example: https://your-provider.celestia-mocha.quiknode.pro/your-token/ | ||
| CELESTIA_BRIDGE_ADDR=<REQUIRED> | ||
| CELESTIA_BRIDGE_AUTH_TOKEN= | ||
| ``` | ||
|
|
||
| Here’s what mine looks like: | ||
|
|
||
| ``` | ||
| CELESTIA_BRIDGE_ADDR=https://delicate-sleek-lambo.celestia-mocha.quiknode.pro/8d7f3e5a9b2c4f1e6d8c9a5b7e4f2c1a6d3b9e5f/ | ||
| CELESTIA_BRIDGE_AUTH_TOKEN= | ||
| ``` | ||
|
|
||
| 3. For the core gRPC, use the same Quicknode endpoint, constructed slightly differently — no `https://`, add port 9090: | ||
|
|
||
| ``` | ||
| # Celestia Core gRPC (for submitting blobs) | ||
| # Example: your-provider.celestia-mocha.quiknode.pro:9090 | ||
| CELESTIA_GRPC_ADDR=<REQUIRED> | ||
| CELESTIA_GRPC_AUTH_TOKEN=<your-token-if-required> | ||
| ``` | ||
|
|
||
| Here’s what mine looks like: | ||
|
|
||
| ``` | ||
| CELESTIA_GRPC_ADDR=delicate-sleek-lambo.celestia-mocha.quiknode.pro:9090 | ||
| CELESTIA_GRPC_AUTH_TOKEN=8d7f3e5a9b2c4f1e6d8c9a5b7e4f2c1a6d3b9e5f | ||
| ``` | ||
|
jcstein marked this conversation as resolved.
|
||
|
|
||
| 4. Lastly, the namespace will need to be set to something with this format. You’ll need to remove the `0x` prefix and use a 29 byte namespace ID: | ||
|
|
||
| ``` | ||
| # Celestia namespace (auto-generated from chain ID) | ||
| CELESTIA_NAMESPACE=0000000000000000000000000000000000000009d94e20cae97add6d34 | ||
| ``` | ||
|
|
||
| 5. You can autogenerate a random namespace with: | ||
|
|
||
| ``` | ||
| export CELESTIA_NAMESPACE=00000000000000000000000000000000000000$(openssl rand -hex 10) && echo $CELESTIA_NAMESPACE | ||
| ``` | ||
|
jcstein marked this conversation as resolved.
Outdated
|
||
|
|
||
| 3. Lastly, change the Popsigner RPC URL to: | ||
|
|
||
| ``` | ||
| # POPSigner RPC endpoint (for op-node, op-batcher signing) | ||
| POPSIGNER_RPC_URL=https://rpc.popsigner.com | ||
| ``` | ||
|
|
||
| 3. Open up `config.toml` and set the variables accordingly: | ||
| 1. For namespace, update from: | ||
|
|
||
| ``` | ||
| [celestia] | ||
| # Celestia namespace (29 bytes hex, version 0 requires 18 leading zeros) | ||
| namespace = "0x706f7000000000016942" | ||
| ``` | ||
|
|
||
| To this, the same way you did in `.env`: | ||
|
|
||
| ``` | ||
| [celestia] | ||
| # Celestia namespace (29 bytes hex, version 0 requires 18 leading zeros) | ||
| namespace = "0000000000000000000000000000000000000009d94e20cae97add6d34" | ||
| ``` | ||
|
|
||
| 2. For bridge node for reading blobs, update from: | ||
|
|
||
| ``` | ||
| # ------------------------------------------------------------------------------ | ||
| # Bridge Node (for reading blobs) | ||
| # ------------------------------------------------------------------------------ | ||
| bridge_addr = "${CELESTIA_BRIDGE_ADDR}" | ||
| bridge_auth_token = "${CELESTIA_BRIDGE_AUTH_TOKEN}" | ||
| bridge_tls_enabled = false | ||
| ``` | ||
|
|
||
| To your Quicknode endpoint, similarly to how you did in `.env`: | ||
|
|
||
| ``` | ||
| # ------------------------------------------------------------------------------ | ||
| # Bridge Node (for reading blobs) | ||
| # ------------------------------------------------------------------------------ | ||
| bridge_addr = "https://delicate-sleek-lambo.celestia-mocha.quiknode.pro/8d7f3e5a9b2c4f1e6d8c9a5b7e4f2c1a6d3b9e5f/" | ||
| bridge_auth_token = "" | ||
| bridge_tls_enabled = true | ||
| ``` | ||
|
|
||
| 3. For core gRPC node for submitting blobs, update from: | ||
|
|
||
| ``` | ||
| # ------------------------------------------------------------------------------ | ||
| # Core gRPC (for submitting blobs) | ||
| # ------------------------------------------------------------------------------ | ||
| core_grpc_addr = "${CELESTIA_GRPC_ADDR}" | ||
| core_grpc_auth_token = "${CELESTIA_GRPC_AUTH_TOKEN}" | ||
| core_grpc_tls_enabled = true | ||
| ``` | ||
|
|
||
| To your Quicknode endpoint, similarly to how you did in `.env`: | ||
|
|
||
| ``` | ||
| # ------------------------------------------------------------------------------ | ||
| # Core gRPC (for submitting blobs) | ||
| # ------------------------------------------------------------------------------ | ||
| core_grpc_addr = "delicate-sleek-lambo.celestia-mocha.quiknode.pro:9090" | ||
| core_grpc_auth_token = "8d7f3e5a9b2c4f1e6d8c9a5b7e4f2c1a6d3b9e5f" | ||
| core_grpc_tls_enabled = true | ||
| ``` | ||
|
|
||
| 4. For POPSigner configuration update from: | ||
|
|
||
| ``` | ||
| # ------------------------------------------------------------------------------ | ||
| # POPSigner Configuration | ||
| # ------------------------------------------------------------------------------ | ||
| # Keys remain remote. You remain sovereign. | ||
|
|
||
| [celestia.signer.popsigner] | ||
| api_key = "${POPSIGNER_API_KEY}" | ||
| key_id = "${CELESTIA_KEY_ID}" | ||
| base_url = "https://api.popsigner.com/" | ||
| ``` | ||
|
|
||
| To your API key and Key ID for your POPSigner keys, similarly to how you did in `.env`: | ||
|
|
||
| ``` | ||
| # ------------------------------------------------------------------------------ | ||
| # POPSigner Configuration | ||
| # ------------------------------------------------------------------------------ | ||
| # Keys remain remote. You remain sovereign. | ||
|
|
||
| [celestia.signer.popsigner] | ||
| api_key = "bbr_live_7Kp3xM9nR2bQ4sL8wXy6Zv1a" | ||
| key_id = "7f4a8c21-b9e3-4d6e-ac52-1e8f9d3c7b65" | ||
| base_url = "https://api.popsigner.com/" | ||
| ``` | ||
|
jcstein marked this conversation as resolved.
|
||
|
|
||
| 4. Now you’re ready to run this with Docker! | ||
| 1. If you are on ARM/MacOS, update the image in `docker-compose.yaml` to: | ||
|
|
||
| ``` | ||
| image: rg.nl-ams.scw.cloud/banhbao/op-alt-da:v0.10.1 | ||
| ``` | ||
|
|
||
| 2. If you are on Linux/AMD64, update the image in `docker-compose.yaml` to: | ||
|
|
||
| ``` | ||
| image: rg.nl-ams.scw.cloud/banhbao/op-alt-da:v0.10.1-amd64 | ||
| ``` | ||
|
|
||
| 5. Just run `docker-compose up` and watch the magic happen 😎 | ||
| 1. On Linux, use `docker-compose --env-file .env up` to load the `.env` | ||
| 1. Else, you will have many missing variables: | ||
|
|
||
| ```bash | ||
| WARNING: The L1_RPC_URL variable is not set. Defaulting to a blank string. | ||
| WARNING: The L1_BEACON_URL variable is not set. Defaulting to a blank string. | ||
| WARNING: The POPSIGNER_RPC_URL variable is not set. Defaulting to a blank string. | ||
| WARNING: The BATCHER_ADDRESS variable is not set. Defaulting to a blank string. | ||
| WARNING: The POPSIGNER_API_KEY variable is not set. Defaulting to a blank string. | ||
| WARNING: The DISPUTE_GAME_FACTORY_ADDRESS variable is not set. Defaulting to a blank string. | ||
| WARNING: The PROPOSER_ADDRESS variable is not set. Defaulting to a blank string. | ||
| ``` | ||
|
|
||
| </Steps> | ||
|
|
||
| Congratulations! You’re now running your first OP Stack rollup with Celestia for DA. | ||
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.