diff --git a/docs/guides/acquire-tokens.mdx b/docs/guides/acquire-tokens.mdx index 9142fca88..508da13e7 100644 --- a/docs/guides/acquire-tokens.mdx +++ b/docs/guides/acquire-tokens.mdx @@ -15,7 +15,7 @@ transaction. However, a supply of free tDUST is available for developers who want to experiment with Midnight DApps. :::tip -If you are using the local undeployed network, then use the [local network faucet](./midnight-local-network#fund-wallets) to fund your wallet and generate tDUST. +If you are using the local undeployed network, then use the [local network funding menu](./networks-and-environments#running-a-local-network) to fund your wallet and generate tDUST. ::: ## Get tNIGHT diff --git a/docs/guides/configure-providers.mdx b/docs/guides/configure-providers.mdx index 6cef9623a..c512833b2 100644 --- a/docs/guides/configure-providers.mdx +++ b/docs/guides/configure-providers.mdx @@ -55,7 +55,7 @@ export type MyProviders = MidnightProviders= 22.0.0 - -## Installation - -To get started, clone the [Midnight local network repository](https://github.com/midnightntwrk/midnight-local-dev): - -```bash -git clone https://github.com/midnightntwrk/midnight-local-dev.git -cd midnight-local-dev -``` - -Install the dependencies: - -```bash -npm install -``` - -## Network services - -The local network runs three Docker containers on the following ports: - -| Service | Container Name | Port | URL | -|:---:|:---:|:---:|:---:| -| **Midnight Node** | `midnight-node` | `9944` | `http://localhost:9944` | -| **Indexer** (GraphQL) | `midnight-indexer` | `8088` | `http://localhost:8088/api/v4/graphql` | -| **Indexer** (WebSocket) | `midnight-indexer` | `8088` | `ws://localhost:8088/api/v4/graphql/ws` | -| **Proof Server** | `midnight-proof-server` | `6300` | `http://localhost:6300` | - -All services use the `undeployed` network ID with the `dev` node preset. - -### Docker images - -The `standalone.yml` file in the root of the repository defines the Docker images and specific versions pulled when you start the local network. - -| Service | Image | Version | -|:---:|:---:|:---:| -| Node | `midnightntwrk/midnight-node` | `0.22.3` | -| Indexer | `midnightntwrk/indexer-standalone` | `4.0.1` | -| Proof Server | `midnightntwrk/proof-server` | `8.0.3` | - -### Wallet SDK packages - -The local network uses the following Wallet SDK packages: - -| Package | Version | -|:---:|:---:| -| `@midnight-ntwrk/wallet-sdk-facade` | 3.0.0 | -| `@midnight-ntwrk/wallet-sdk-abstractions` | 2.0.0 | -| `@midnight-ntwrk/wallet-sdk-shielded` | 2.1.0 | -| `@midnight-ntwrk/wallet-sdk-dust-wallet` | 3.0.0 | -| `@midnight-ntwrk/wallet-sdk-unshielded-wallet` | 2.1.0 | -| `@midnight-ntwrk/wallet-sdk-address-format` | 3.1.0 | -| `@midnight-ntwrk/wallet-sdk-hd` | 3.0.1 | -| `@midnight-ntwrk/ledger-v8` | 8.0.3 | -| `@midnight-ntwrk/midnight-js-network-id` | 4.0.2 | - -## Start the local network - -Once the installation is complete, start the local network by running the following command: - -```bash -npm start -``` - -This single command does the following: - -- **Pull** the latest Docker images for the Midnight node, indexer, and proof server. -- **Start** all three containers with health checks. -- **Initialize** the genesis master wallet (seed `0x00...001`) which holds all minted NIGHT tokens. -- **Register DUST** for the master wallet (required to pay transaction fees). -- **Display** the master wallet balance. -- **Present an interactive menu** for funding wallets in the undeployed network. - -Once running, you'll see: - -``` -Choose an option: - [1] Fund accounts from config file (NIGHT + DUST registration) - [2] Fund accounts by public key (NIGHT transfer only) - [3] Display master wallet balances - [4] Exit -> -``` - -## Fund wallets - -The local network provides two options for funding wallets: - -- Fund from a config file -- Fund by public key - -Each funding operation transfers _50,000 tNIGHT_ from the genesis master wallet. You can fund up to _10 accounts_ per operation. - -### Option 1: Fund from a config file - -The config option handles wallet operations such as generating the wallet seed from mnemonic, transferring tNIGHT to the unshielded address, syncing the wallet, and registering tNIGHT for DUST generation. - -It pulls wallet information from a config file, which is a JSON file with the following structure: - -```json -{ - "accounts": [ - { - "name": "Alice", - "mnemonic": "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art" - } - ] -} -``` -Here's a breakdown of the fields: - -| Field | Type | Description | -|:---:|:---:|:---:| -| `accounts` | `array` | List of accounts to fund (max 10) | -| `accounts[].name` | `string` | Display name for logging | -| `accounts[].mnemonic` | `string` | BIP39 mnemonic phrase (24 words) | - -An example file is provided at `accounts.example.json`. Copy the file to `accounts.json` and edit it to add your wallet mnemonics. - -```bash -cp accounts.example.json accounts.json -``` - -After editing the file, select option `[1] Fund accounts from config file (NIGHT + DUST registration)` from the interactive menu. - -You are prompted to enter the path to the config file. - -``` -> 1 -Path to accounts JSON file: ./accounts.json -``` - -The tool funds the wallets from the config file. - -### Option 2: Fund by public key - -The public key option allows you to fund wallets by their Bech32 addresses. You can fund up to 10 wallets at a time. - -Select option `[2] Fund accounts by public key (NIGHT transfer only)` from the interactive menu. - -You are prompted to enter the Bech32 addresses of the wallets you want to fund, separated by commas. - -``` -> 2 -Enter Bech32 addresses (comma-separated): mn1q..., mn1q... -``` - -Each address receives _50,000 tNIGHT_. Recipients must register for DUST generation themselves before they can pay transaction fees. - -## Connect a DApp - -Once the network is running, any Midnight DApp can connect using the standard localhost endpoints. - -Here's an example of how to connect a DApp to the local network: - -```typescript -import { setNetworkId } from '@midnight-ntwrk/midnight-js-network-id'; - -setNetworkId('undeployed'); - -const config = { - indexer: 'http://127.0.0.1:8088/api/v4/graphql', - indexerWS: 'ws://127.0.0.1:8088/api/v4/graphql/ws', - node: 'http://127.0.0.1:9944', - proofServer: 'http://127.0.0.1:6300', - networkId: 'undeployed', -}; - -// Use these endpoints with the Midnight wallet SDK, contract deployment, and other DApp operations -``` - -## Run the network standalone - -If you only need the Docker containers running without the interactive menu for wallet initialization or funding, then you can use Docker Compose directly: - -```bash -docker compose -f standalone.yml up -d -``` - -To check the status of the containers: - -```bash -docker compose -f standalone.yml ps -``` - -To view the logs: - -```bash -docker compose -f standalone.yml logs -f -``` - -This is useful when: -- Your DApp handles its own wallet initialization and funding. -- You want to keep the network running across multiple test sessions. -- You're debugging container-level issues. - -:::note -In this mode, you must handle genesis wallet funding and DUST registration yourself. -::: - -## Troubleshoot - -Below are some of the common issues that you might encounter and how to fix them. - -### Port already in use - -``` -Error: Bind for 0.0.0.0:9944 failed: port is already allocated -``` - -Another process or a previous run is using the port. Stop it: - -```bash -docker compose -f standalone.yml down -# or find and kill the process -lsof -i :9944 -``` - -### Invalid wallet address - -If you receive an error similar to this: - -``` -Operation failed: Expected undeployed address, got Preprod address -``` - -It means you're trying to fund a wallet with a Preprod address. You need to use the Undeployed network address instead. - -If you're using the Lace wallet, then you must configure the wallet to use the Undeployed network. - -1. In the Lace wallet extension, click the **Settings** icon and then select the **Network** tab. -2. Under the Midnight section, select the **Undeployed** network and then click **Confirm**. - -After that, you'll see your wallet addresses for the local Undeployed network. Make sure to use the Unshielded wallet address for the local Undeployed network. - -### Containers not starting - -Check Docker is running and you have access to the Midnight Docker registry: - -```bash -docker compose -f standalone.yml pull -docker compose -f standalone.yml up -``` - -Watch the logs for specific errors: - -```bash -docker compose -f standalone.yml logs -f node -docker compose -f standalone.yml logs -f indexer -docker compose -f standalone.yml logs -f proof-server -``` - -### Wallet sync takes too long - -The indexer needs time to catch up with the node after startup. If the sync seems stuck: - -1. Check the indexer logs: `docker compose -f standalone.yml logs -f indexer` -2. Verify the node is producing blocks: `curl http://localhost:9944/health` -3. Set `DEBUG_LEVEL=debug` in `.env` for more detailed wallet logs - -## Next steps - -Now that you have a local network running, you can start building your DApp. See our guide to learn how to [deploy a contract](./deploy-mn-app) to the Midnight blockchain. diff --git a/docs/guides/networks-and-environments.mdx b/docs/guides/networks-and-environments.mdx new file mode 100644 index 000000000..764cf1e5c --- /dev/null +++ b/docs/guides/networks-and-environments.mdx @@ -0,0 +1,466 @@ +--- +SPDX-License-Identifier: Apache-2.0 +copyright: This file is part of Midnight Docs. Copyright (C) Midnight Foundation. Licensed under the Apache License, Version 2.0 (the "License"); You may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +sidebar_label: Networks and environments +title: Networks and environments +description: "Understand Midnight's networks, choose the right one, connect a DApp with the correct network ID and endpoints, fund it, and prepare for mainnet." +sidebar_position: 04 +toc_max_heading_level: 2 +keywords: [midnight, networks, environments, endpoints, network id, mainnet, preprod, preview, undeployed, faucet] +tags: [midnight, networks, endpoints, dapp, mainnet] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Networks and environments + +Use this guide to understand the networks Midnight operates, pick the right one for the task in front of you, point your DApp at it, fund a wallet on it, and move to mainnet when you are ready. It explains the network landscape, gives you the exact endpoints and IDs to configure tools against, and walks through each task ending with a test you run to prove it worked. If you are starting from nothing, scaffold a project with the [quickstart](../getting-started/quickstart) first and return here when you need to choose or switch networks. + +## Prerequisites + +These apply to every procedure in this guide: + +- Node.js version 22 or higher installed. +- Docker installed and running, for the local network and the [proof server](./run-proof-server). +- [Vitest](https://vitest.dev/) and `@midnight-ntwrk/midnight-js-network-id` installed in your test workspace, for the verification tests. + +{/* _mod-docs-content-type: CONCEPT */} +## The Midnight networks + +Midnight operates one production network and maintains three environments for development. Every environment runs the same stack, so a DApp moves between them by changing configuration, not code. + +Four networks make up the landscape: + +- **`undeployed`** is the local development network: a Midnight node, indexer, and proof server running in Docker on your machine. Its genesis wallet is pre-funded, so you can deploy within minutes of starting it. See [Running a local network](#running-a-local-network). +- **`preview`** is a public test network for early development and experimentation, maintained by core engineering. +- **`preprod`** is a public test network for final validation before mainnet. Of the test networks, it tracks mainnet most closely. +- **`mainnet`** is the production network. Tokens on mainnet carry real value, and there is no faucet. + +Each public network identifies itself over RPC: the `system_chain` method returns `Midnight Preview`, `Midnight Preprod`, or `Midnight Mainnet`. Every network exposes the same three services your DApp talks to: a node (JSON-RPC over HTTPS and WebSocket), an indexer (GraphQL over HTTP and WebSocket), and a proof server. The node and indexer are network-specific; the proof server runs locally on port 6300 no matter which network you target, because it handles your private data. The [Environment reference](#environment-reference) lists every endpoint. + +:::note The testnet-02 name is retired + +Older articles and tools sometimes reference a network named `testnet-02`. That network has been retired and its endpoints no longer resolve. Use `preview` or `preprod` instead. + +::: + +{/* _mod-docs-content-type: REFERENCE */} +## Network selection at a glance + +Which network to target for a given task. Consult this before you configure anything; the setup and funding consequences of each choice are listed alongside. + +| Task | Network | Funding | Value at risk | +|---|---|---|---| +| Iterating on a contract, running tests, CI | `undeployed` | Genesis wallet is pre-funded, no faucet needed | None | +| Testing against shared public infrastructure early in development | `preview` | Free tNIGHT from the [Preview faucet](https://midnight-tmnight-preview.nethermind.dev/), rate limited | None | +| Final validation before a production launch | `preprod` | Free tNIGHT from the [Preprod faucet](https://midnight-tmnight-preprod.nethermind.dev/), rate limited | None | +| Running in production | `mainnet` | Real NIGHT, which generates DUST after registration | Real | + +Start on `undeployed` for speed, move to `preview` or `preprod` when you need shared infrastructure or a persistent chain, validate on `preprod` before launch, and treat `mainnet` as a deliberate final step. [Funding and transaction cost](#funding-and-transaction-cost) explains what each choice costs. + +{/* _mod-docs-content-type: REFERENCE */} +## Environment reference + +The endpoints, network ID, and funding source for each environment. Configure wallets, indexers, and tooling against these values; other pages link here rather than restating them. + + + + +The local development network, run via [midnight-local-dev](https://github.com/midnightntwrk/midnight-local-dev). All services run in Docker on your machine; set it up in [Running a local network](#running-a-local-network). + +| Service | Value | +|---|---| +| Network ID | `undeployed` | +| Node RPC | `http://localhost:9944` | +| Indexer (GraphQL) | `http://localhost:8088/api/v4/graphql` | +| Indexer (WebSocket) | `ws://localhost:8088/api/v4/graphql/ws` | +| Proof server | `http://localhost:6300` | +| Faucet | None. The genesis wallet is pre-funded and the funding menu transfers 50,000 tNIGHT per account. | +| Address prefixes | `mn_addr_undeployed`, `mn_shield-addr_undeployed`, `mn_dust_undeployed` | +| Block explorers | None | + + + + +Public test network for early development and experimentation. + +| Service | Value | +|---|---| +| Network ID | `preview` | +| Node RPC | `https://rpc.preview.midnight.network` | +| Node WebSocket | `wss://rpc.preview.midnight.network` | +| Indexer (GraphQL) | `https://indexer.preview.midnight.network/api/v4/graphql` | +| Indexer (WebSocket) | `wss://indexer.preview.midnight.network/api/v4/graphql/ws` | +| Proof server | `http://localhost:6300` (always local) | +| Faucet | [https://midnight-tmnight-preview.nethermind.dev/](https://midnight-tmnight-preview.nethermind.dev/) | +| Address prefixes | `mn_addr_preview`, `mn_shield-addr_preview`, `mn_dust_preview` | +| Block explorers | [Midnight Explorer](https://preview.midnightexplorer.com/), [Subscan](https://midnight-preview.subscan.io/), [1am](https://explorer.1am.xyz/?network=preview) | + + + + +Public test network for final validation before mainnet. + +| Service | Value | +|---|---| +| Network ID | `preprod` | +| Node RPC | `https://rpc.preprod.midnight.network` | +| Node WebSocket | `wss://rpc.preprod.midnight.network` | +| Indexer (GraphQL) | `https://indexer.preprod.midnight.network/api/v4/graphql` | +| Indexer (WebSocket) | `wss://indexer.preprod.midnight.network/api/v4/graphql/ws` | +| Proof server | `http://localhost:6300` (always local) | +| Faucet | [https://midnight-tmnight-preprod.nethermind.dev/](https://midnight-tmnight-preprod.nethermind.dev/) | +| Address prefixes | `mn_addr_preprod`, `mn_shield-addr_preprod`, `mn_dust_preprod` | +| Block explorers | [Midnight Explorer](https://preprod.midnightexplorer.com/), [Subscan](https://midnight-preprod.subscan.io/), [1am](https://explorer.1am.xyz/?network=preprod) | + + + + +The production network. + +| Service | Value | +|---|---| +| Network ID | `mainnet` | +| Node RPC | `https://rpc.mainnet.midnight.network` | +| Node WebSocket | `wss://rpc.mainnet.midnight.network` | +| Indexer (GraphQL) | `https://indexer.mainnet.midnight.network/api/v4/graphql` | +| Indexer (WebSocket) | `wss://indexer.mainnet.midnight.network/api/v4/graphql/ws` | +| Proof server | `http://localhost:6300` (always local) | +| Faucet | None. See [Funding and transaction cost](#funding-and-transaction-cost). | +| Address prefixes | `mn_addr`, `mn_shield-addr`, `mn_dust` | +| cNgD DApp | [https://midnight-dust-mainnet.nethermind.io/](https://midnight-dust-mainnet.nethermind.io/) | +| Block explorers | [Midnight Explorer](https://midnightexplorer.com/), [Subscan](https://midnight.subscan.io/), [1am](https://explorer.1am.xyz/) | + + + + +Addresses are Bech32m encoded, and the prefix names the address type and the network: `mainnet` uses the bare prefix, for example `mn_addr`, while every other network appends its name, for example `mn_addr_preprod`. Wallet viewing keys follow the same rule with the `mn_shield-esk` prefix. + +Midnight provides the public node and indexer endpoints for development and testing. For a production DApp, consider running your own [node](../nodes) or using a dedicated infrastructure provider. + +{/* _mod-docs-content-type: PROCEDURE */} +## Running a local network + +Run the full Midnight stack, a node, an indexer, and a proof server, in Docker on your machine with [midnight-local-dev](https://github.com/midnightntwrk/midnight-local-dev). The tool initializes a pre-funded genesis wallet and presents a funding menu, so you can deploy and transact within minutes, with no faucet and nothing at risk. + +### Procedure + +1. Clone the repository and install its dependencies: + + ```bash + git clone https://github.com/midnightntwrk/midnight-local-dev.git + cd midnight-local-dev + npm install + ``` + +2. Start the network: + + ```bash + npm start + ``` + + The command pulls the Docker images (versions are pinned in `standalone.yml`), starts the node, indexer, and proof server with health checks, initializes the genesis master wallet that holds the pre-mined NIGHT, registers it for DUST so it can pay fees, and then presents the funding menu: + + ```text + Choose an option: + [1] Fund accounts from config file (NIGHT + DUST registration) + [2] Fund accounts by public key (NIGHT transfer only) + [3] Display wallets + [4] Exit + ``` + +3. Fund the wallets you develop with. Option `1` reads a JSON file of accounts (copy `accounts.example.json` to `accounts.json` and add your 24-word mnemonics), transfers tNIGHT to each, and registers each account for DUST generation. Option `2` transfers tNIGHT to Bech32m addresses you paste, and the recipients register for DUST themselves. Either way, each account receives 50,000 tNIGHT, up to 10 accounts per operation. + +4. If you only need the containers, skip the wallet tooling and use Docker Compose directly. In this mode you handle genesis funding and DUST registration yourself: + + ```bash + docker compose -f standalone.yml up -d # start + docker compose -f standalone.yml ps # status + docker compose -f standalone.yml logs -f # logs + docker compose -f standalone.yml down # stop + ``` + +### Verification + +The local endpoints answer: the node reports the dev chain and serves its health check, the indexer serves blocks, and the proof server accepts connections. + +```typescript title="local-network.test.ts" +import { describe, it, expect } from 'vitest'; + +describe('local network', () => { + it('node is healthy', async () => { + const res = await fetch('http://localhost:9944/health').then((r) => r.json()); + expect(res.isSyncing).toBe(false); + }); + + it('indexer serves blocks', async () => { + const res = await fetch('http://localhost:8088/api/v4/graphql', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ query: '{ block { height } }' }), + }).then((r) => r.json()); + expect(res.data.block.height).toBeGreaterThan(0); + }); + + it('proof server reports ok', async () => { + const res = await fetch('http://localhost:6300/health').then((r) => r.json()); + expect(res.status).toBe('ok'); + }); +}); +``` + +```text + ✓ local-network.test.ts > local network > node is healthy + ✓ local-network.test.ts > local network > indexer serves blocks + ✓ local-network.test.ts > local network > proof server reports ok + + Test Files 1 passed (1) + Tests 3 passed (3) +``` + +{/* _mod-docs-content-type: REFERENCE */} +## Local network troubleshooting + +The failure modes you are most likely to hit with the local stack, and their fixes. + +| Symptom | Fix | +|---|---| +| `Bind for 0.0.0.0:9944 failed: port is already allocated` | A previous run still holds the port. Run `docker compose -f standalone.yml down`, or find the holder with `lsof -i :9944`. | +| Indexer exits on first start with `block number 1 not found` | A startup race on a fresh chain: the indexer asked for a block the node had not produced yet. Start it again with `docker start midnight-indexer`; it latches on once blocks exist. | +| `Operation failed: Expected undeployed address, got Preprod address` | The wallet is on the wrong network. In Lace, switch to the Undeployed network under **Settings**, then use that unshielded address. | +| Containers do not start | Confirm Docker is running, then run `docker compose -f standalone.yml pull` and `up`, and read `docker compose -f standalone.yml logs -f` for the failing service. | +| Wallet sync is slow after startup | The indexer is catching up with the node. Confirm the node produces blocks with `curl http://localhost:9944/health` and watch the indexer logs. | + +{/* _mod-docs-content-type: PROCEDURE */} +## Connecting a DApp to a network + +Point a DApp at a chosen network by setting the network ID and wiring the matching endpoints. The common trap is mixing values from different networks, for example a `preprod` network ID with a `preview` indexer URL; keep the ID and the endpoints together in one place so they cannot drift apart. + +### Procedure + +1. Choose the target network using [Network selection at a glance](#network-selection-at-a-glance). + +2. Set the network ID before initializing any providers. Midnight.js reads this value when it normalizes addresses and builds transactions (the `deployContract` and `callTx` paths), so it must be set before any contract operation: + + ```typescript + import { setNetworkId } from '@midnight-ntwrk/midnight-js-network-id'; + + setNetworkId('preprod'); + + /** Supported network IDs: 'mainnet', 'preview', 'preprod', 'undeployed' */ + ``` + + There is no default: `getNetworkId()` throws `Network ID has not been configured` until you call `setNetworkId`. The call stores the string as-is, so a misspelled network name does not fail here; it surfaces later, in the components that consume the ID. + +3. Keep the network ID and its endpoints together in one configuration object, using the values from the [Environment reference](#environment-reference). Note that the proof server URL stays local for every network: + + ```typescript + const NETWORKS = { + undeployed: { + node: 'http://localhost:9944', + indexer: 'http://localhost:8088/api/v4/graphql', + indexerWS: 'ws://localhost:8088/api/v4/graphql/ws', + proofServer: 'http://localhost:6300', + }, + preprod: { + node: 'https://rpc.preprod.midnight.network', + indexer: 'https://indexer.preprod.midnight.network/api/v4/graphql', + indexerWS: 'wss://indexer.preprod.midnight.network/api/v4/graphql/ws', + proofServer: 'http://localhost:6300', + }, + } as const; + + const network = NETWORKS['preprod']; + ``` + +4. Pass the endpoints to your providers. The full providers object, including private state, ZK configuration, and wallet providers, is covered in [How to configure providers](./configure-providers): + + ```typescript + import { indexerPublicDataProvider } from '@midnight-ntwrk/midnight-js-indexer-public-data-provider'; + + const publicDataProvider = indexerPublicDataProvider(network.indexer, network.indexerWS); + ``` + +5. In a project scaffolded with `create-mn-app` (the `hello-world` template), select the network with the setup script instead. The selection is sticky until you switch: + + ```bash + npm run setup -- --network preview # runs on preview and makes it active + npm run network preprod # switch the active network later + ``` + + The scaffold's network scripts accept `undeployed`, `preview`, and `preprod`. Mainnet is not a scaffold target; wire it through providers as shown above. + +### Verification + +Each network ID round-trips through the SDK, and the configured endpoints answer with the expected chain identity and a current block height. + +```typescript title="networks.test.ts" +import { describe, it, expect } from 'vitest'; +import { setNetworkId, getNetworkId } from '@midnight-ntwrk/midnight-js-network-id'; + +const rpc = (url: string, method: string) => + fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ jsonrpc: '2.0', method, params: [], id: 1 }), + }).then((r) => r.json()); + +const indexerBlock = (url: string) => + fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ query: '{ block { height } }' }), + }).then((r) => r.json()); + +const networks = [ + { + id: 'preview', + chain: 'Midnight Preview', + node: 'https://rpc.preview.midnight.network', + indexer: 'https://indexer.preview.midnight.network/api/v4/graphql', + }, + { + id: 'preprod', + chain: 'Midnight Preprod', + node: 'https://rpc.preprod.midnight.network', + indexer: 'https://indexer.preprod.midnight.network/api/v4/graphql', + }, + { + id: 'mainnet', + chain: 'Midnight Mainnet', + node: 'https://rpc.mainnet.midnight.network', + indexer: 'https://indexer.mainnet.midnight.network/api/v4/graphql', + }, +]; + +describe.each(networks)('$id', ({ id, chain, node, indexer }) => { + it('sets the network ID', () => { + setNetworkId(id); + expect(getNetworkId()).toBe(id); + }); + + it('reaches the node RPC', async () => { + const res = await rpc(node, 'system_chain'); + expect(res.result).toBe(chain); + }); + + it('reaches the indexer', async () => { + const res = await indexerBlock(indexer); + expect(res.data.block.height).toBeGreaterThan(0); + }); +}); +``` + +```text + ✓ networks.test.ts > 'preview' > sets the network ID + ✓ networks.test.ts > 'preview' > reaches the node RPC + ✓ networks.test.ts > 'preview' > reaches the indexer + ✓ networks.test.ts > 'preprod' > sets the network ID + ✓ networks.test.ts > 'preprod' > reaches the node RPC + ✓ networks.test.ts > 'preprod' > reaches the indexer + ✓ networks.test.ts > 'mainnet' > sets the network ID + ✓ networks.test.ts > 'mainnet' > reaches the node RPC + ✓ networks.test.ts > 'mainnet' > reaches the indexer + + Test Files 1 passed (1) + Tests 9 passed (9) +``` + +The `undeployed` network is not in the matrix because it only exists while your local containers run. With the [local network](#running-a-local-network) up, the same checks pass against `http://localhost:9944` and `http://localhost:8088/api/v4/graphql`. + +{/* _mod-docs-content-type: CONCEPT */} +## Funding and transaction cost + +Every transaction on Midnight consumes DUST, and where the DUST comes from is the main practical difference between the networks. Understanding the two-token model once saves you a confused hour on each network later. + +NIGHT is the native utility token; holding it is what entitles you to DUST. DUST is a shielded, non-transferable resource that fees are paid in. Registered NIGHT generates DUST over time up to a cap of about 5 DUST per NIGHT, refilling in roughly a week, so a funded wallet regenerates its capacity to transact rather than spending it away permanently. [Tokens on Midnight](../tokens/overview) introduces the model and [DUST architecture](../concepts/dust-architecture) covers generation, decay, and the protocol parameters. + +**On the local network**, the genesis wallet is pre-funded and already registered for DUST, and the funding menu transfers tNIGHT to your own test wallets. DUST generates in about 5 minutes. There is no faucet because none is needed; see [Running a local network](#running-a-local-network). + +**On `preview` and `preprod`**, request free tNIGHT from the network's faucet (the Preprod faucet sends 1,000 tNIGHT per request; both faucets are rate limited), then generate tDUST from it in your wallet. The [Get faucet tokens](./acquire-tokens) guide walks through the faucet and the Lace **Generate tDUST** flow, and [Generating DUST programmatically](./generating-dust-programmatically) does the same with the wallet SDK. Test tokens carry no real value. + +**On `mainnet`**, there is no faucet. Today most NIGHT is held on Cardano as cNIGHT, and DUST generation is cross-chain: you register your Cardano reward address together with a Midnight DUST public key (the [cNgD DApp](https://midnight-dust-mainnet.nethermind.io/) handles this), and your cNIGHT holdings then generate DUST on Midnight. The registration must finalize on Cardano and reach a Midnight node, which takes about 12 hours, so fund your production wallet well before launch day. + +{/* _mod-docs-content-type: PROCEDURE */} +## Preparing a DApp for mainnet + +Move a DApp that works on `preprod` to the production network. The mechanics are the same configuration change as any other network switch; what makes mainnet different is that funding is cross-chain and slow, mistakes cost real value, and public test infrastructure guarantees do not apply. + +### Prerequisites + +- A DApp deployed and validated on `preprod`, connected as in [Connecting a DApp to a network](#connecting-a-dapp-to-a-network). + +### Procedure + +1. Validate the full deploy and interaction flow on `preprod` first. It is the network closest to mainnet, so anything that fails there will fail in production. + +2. Fund the production wallet. Register your cNIGHT for DUST generation through the [cNgD DApp](https://midnight-dust-mainnet.nethermind.io/) and allow about 12 hours for the registration to take effect, as described in [Funding and transaction cost](#funding-and-transaction-cost). Confirm the wallet shows a DUST balance before you attempt a transaction. + +3. Point the configuration at mainnet. Set the network ID and swap the endpoints; nothing else in the DApp changes: + + ```typescript + import { setNetworkId } from '@midnight-ntwrk/midnight-js-network-id'; + + setNetworkId('mainnet'); + + const network = { + node: 'https://rpc.mainnet.midnight.network', + indexer: 'https://indexer.mainnet.midnight.network/api/v4/graphql', + indexerWS: 'wss://indexer.mainnet.midnight.network/api/v4/graphql/ws', + proofServer: 'http://localhost:6300', + }; + ``` + + The `create-mn-app` scaffold does not offer a mainnet target, so wire the providers yourself as in [How to configure providers](./configure-providers). + +4. Decide your infrastructure. The public endpoints are provided for development and testing; for production, run your own [node](../nodes) and indexer or use a dedicated infrastructure provider. + +5. Work through the [Mainnet readiness checklist](#mainnet-readiness-checklist) before announcing anything. + +### Verification + +The mainnet endpoints answer with the production chain identity and a current block height. Run the connection test from this guide filtered to mainnet: + +```bash +npx vitest run networks.test.ts -t mainnet +``` + +```text + ↓ networks.test.ts > 'preview' > sets the network ID + ↓ networks.test.ts > 'preview' > reaches the node RPC + ↓ networks.test.ts > 'preview' > reaches the indexer + ↓ networks.test.ts > 'preprod' > sets the network ID + ↓ networks.test.ts > 'preprod' > reaches the node RPC + ↓ networks.test.ts > 'preprod' > reaches the indexer + ✓ networks.test.ts > 'mainnet' > sets the network ID + ✓ networks.test.ts > 'mainnet' > reaches the node RPC + ✓ networks.test.ts > 'mainnet' > reaches the indexer + + Test Files 1 passed (1) + Tests 3 passed | 6 skipped (9) +``` + +{/* _mod-docs-content-type: REFERENCE */} +## Mainnet readiness checklist + +Work through this list before a production launch. Each item links to the page that explains it. + +- [ ] **The full flow is validated on `preprod`.** Deploy, interact, and observe state end to end on the network closest to mainnet. +- [ ] **The security checklist is complete.** Work through the [pre-deployment security checklist](./security-best-practices#pre-deployment-security-checklist) for the contract and the DApp around it. +- [ ] **The updatability decision is made.** Decide whether and how the contract can be upgraded before it holds real value. See [Making a decision on contract updatability](./making-decision-on-contract-updatability). +- [ ] **The production wallet generates DUST.** cNIGHT is registered, the roughly 12-hour registration delay has passed, and the wallet shows a DUST balance. See [Funding and transaction cost](#funding-and-transaction-cost). +- [ ] **Every endpoint in the configuration is a mainnet endpoint.** No `preview` or `preprod` URL remains. See the [Environment reference](#environment-reference). +- [ ] **The infrastructure decision is made.** You run your own node and indexer, or you have a dedicated provider; the public endpoints are for development and testing. +- [ ] **Key custody is settled.** The keys that control the contract and the funds have an owner, a backup, and a rotation path. See [Security and best practices](./security-best-practices). +- [ ] **You can observe the DApp in production.** You know which [block explorer](#environment-reference) and indexer queries you will use to confirm the deployment and watch activity. + +## Additional resources + +- [Environments and endpoints](../relnotes/network): the release-notes view of the per-network endpoints. +- [Node endpoints](../nodes/node-endpoints): RPC quickstart, common queries, and the Insomnia collection. +- [midnight-local-dev on GitHub](https://github.com/midnightntwrk/midnight-local-dev): the local network tool, its pinned image versions, and its README. +- [Run the proof server](./run-proof-server): the local proof server every network setup depends on. +- [How to configure providers](./configure-providers): the complete providers object a DApp passes to the SDK. +- [Get faucet tokens](./acquire-tokens): the faucet and tDUST generation walkthrough. +- [Security and best practices](./security-best-practices): hardening a contract and DApp before mainnet. diff --git a/docs/guides/security-best-practices.mdx b/docs/guides/security-best-practices.mdx index eddd3cc60..4425a5471 100644 --- a/docs/guides/security-best-practices.mdx +++ b/docs/guides/security-best-practices.mdx @@ -12,7 +12,7 @@ tags: [midnight, security, privacy, compact, smart-contracts, dapp] # Security and best practices -Use this guide to harden a Compact contract and the DApp around it. It groups its content into modules you can read in any order: concept modules explain a threat or mechanism, procedure modules walk through a single task and end with a test you run to prove it holds, and reference modules give you lookup tables. +Use this guide to harden a Compact contract and the DApp around it. You can read its sections in any order: some explain a threat or mechanism, some walk through a single task and end with a test you run to prove it holds, and some give you lookup tables. Three adversaries shape the decisions throughout. A **chain observer** reads the public ledger. A **malicious prover** controls their own frontend and supplies every witness value. An **operator of off-chain infrastructure**, such as an indexer or proof server, sees the data you route to them. For the language-level security model behind these patterns, read [Smart contract security](../compact/smart-contract-security). diff --git a/docs/nodes/node-endpoints.mdx b/docs/nodes/node-endpoints.mdx index 5ca68eaef..a0a05f088 100644 --- a/docs/nodes/node-endpoints.mdx +++ b/docs/nodes/node-endpoints.mdx @@ -102,7 +102,7 @@ async fn main() { ## Public network endpoints -Midnight currently maintains two active test networks for development and testing. +Midnight maintains public endpoints for two test networks, Preview and Preprod, and for the Mainnet production network. For the full per-network reference, including indexer, faucet, and proof server endpoints, see [Networks and environments](../guides/networks-and-environments). @@ -126,6 +126,17 @@ Pre-production environment for final testing before Mainnet deployment. | WebSocket | `wss://rpc.preprod.midnight.network/` | | Explorer | [https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frpc.preprod.midnight.network#/explorer](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frpc.preprod.midnight.network#/explorer) | + + + +The production network. + +| Service | URL | +| ------- | --- | +| RPC endpoint | `https://rpc.mainnet.midnight.network/` | +| WebSocket | `wss://rpc.mainnet.midnight.network/` | +| Explorer | [https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frpc.mainnet.midnight.network#/explorer](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frpc.mainnet.midnight.network#/explorer) | + :::important Network support diff --git a/docs/tutorials/bboard/bboard-cli-implementation.mdx b/docs/tutorials/bboard/bboard-cli-implementation.mdx index 7bdbcd521..03e99eb05 100644 --- a/docs/tutorials/bboard/bboard-cli-implementation.mdx +++ b/docs/tutorials/bboard/bboard-cli-implementation.mdx @@ -65,7 +65,7 @@ Each launcher script targets a different network: - `standalone`: Connects to a local Midnight network running on your machine using the genesis-mint wallet seed :::info -For more information on setting up a local Midnight network, see the [Midnight local network](../../../guides/midnight-local-network/) documentation. +For more information on setting up a local Midnight network, see [Running a local network](/guides/networks-and-environments#running-a-local-network). ::: ## Configure TypeScript @@ -1074,7 +1074,7 @@ await run(config, testEnvironment, logger); ``` :::info -The `standalone` launcher connects to a local Midnight network running on your machine. For more information, see [Midnight local network](../../../guides/midnight-local-network/). +The `standalone` launcher connects to a local Midnight network running on your machine. For more information, see [Running a local network](/guides/networks-and-environments#running-a-local-network). ::: diff --git a/docs/tutorials/zk-loan/attestation-api.mdx b/docs/tutorials/zk-loan/attestation-api.mdx index c00125330..1cccfe9e8 100644 --- a/docs/tutorials/zk-loan/attestation-api.mdx +++ b/docs/tutorials/zk-loan/attestation-api.mdx @@ -489,7 +489,7 @@ This creates a two-sided privacy guarantee: ## Set up Docker for the proof server :::note -If you are testing with [Midnight Local Dev](/guides/midnight-local-network) instead of Preprod, then skip this step. The local dev environment already includes a proof server on port `6300`. +If you are testing with [Midnight Local Dev](/guides/networks-and-environments#running-a-local-network) instead of Preprod, then skip this step. The local dev environment already includes a proof server on port `6300`. ::: The [proof server](/guides/run-proof-server) generates ZK proofs for every transaction that interacts with the smart contract. For Preprod, you run it locally via Docker while the blockchain node and indexer are remote (hosted by Midnight Network). diff --git a/docs/tutorials/zk-loan/cli.mdx b/docs/tutorials/zk-loan/cli.mdx index 4d37f282b..10781f843 100644 --- a/docs/tutorials/zk-loan/cli.mdx +++ b/docs/tutorials/zk-loan/cli.mdx @@ -101,7 +101,7 @@ export class LocalDevConfig implements Config { } ``` -This file covers both networks: `PreprodConfig` points the indexer and node at Midnight's remote infrastructure, while `LocalDevConfig` points them at a local stack. In both cases the proof server runs locally on port `6300` — the Docker container you started in [Part 2](./attestation-api) for Preprod, or the one bundled with [Midnight Local Dev](/guides/midnight-local-network). +This file covers both networks: `PreprodConfig` points the indexer and node at Midnight's remote infrastructure, while `LocalDevConfig` points them at a local stack. In both cases the proof server runs locally on port `6300` — the Docker container you started in [Part 2](./attestation-api) for Preprod, or the one bundled with [Midnight Local Dev](/guides/networks-and-environments#running-a-local-network). Key details: @@ -111,7 +111,7 @@ Key details: * The indexer provides two connections: HTTP for queries and WebSocket for real-time subscription to ledger state changes. -* `LocalDevConfig` connects to [Midnight Local Dev](/guides/midnight-local-network), a standalone Docker-based development environment that runs the Midnight node, indexer, and proof server locally. It uses the `undeployed` network ID, and all services run on `localhost`. +* `LocalDevConfig` connects to [Midnight Local Dev](/guides/networks-and-environments#running-a-local-network), a standalone Docker-based development environment that runs the Midnight node, indexer, and proof server locally. It uses the `undeployed` network ID, and all services run on `localhost`. ### Type definitions @@ -1736,7 +1736,7 @@ Edit `zkloan-credit-scorer-cli/.env` and set `MIDNIGHT_STORAGE_PASSWORD` to a va ## Run the CLI -The final part brings everything together by testing the complete flow using [Midnight Local Dev](/guides/midnight-local-network), a standalone Docker environment that runs the Midnight node, indexer, and proof server locally. Its `npm start` wizard can transfer NIGHT to any address you give it; the ZKLoan CLI then registers that NIGHT for DUST automatically, so the wallet is ready to submit transactions. +The final part brings everything together by testing the complete flow using [Midnight Local Dev](/guides/networks-and-environments#running-a-local-network), a standalone Docker environment that runs the Midnight node, indexer, and proof server locally. Its `npm start` wizard can transfer NIGHT to any address you give it; the ZKLoan CLI then registers that NIGHT for DUST automatically, so the wallet is ready to submit transactions. You need three terminal windows. diff --git a/packages/tests/pipelines-urls.json b/packages/tests/pipelines-urls.json index ad1cd440e..6ed52a7ec 100644 --- a/packages/tests/pipelines-urls.json +++ b/packages/tests/pipelines-urls.json @@ -11,6 +11,7 @@ "/getting-started/hello-world", "/guides/acquire-tokens", + "/guides/networks-and-environments", "/guides/deploy-mn-app", "/guides/security-best-practices", "/guides/compact-javascript-runtime", diff --git a/sdks/official/midnight-js.mdx b/sdks/official/midnight-js.mdx index 294c87461..51320b4fc 100644 --- a/sdks/official/midnight-js.mdx +++ b/sdks/official/midnight-js.mdx @@ -159,7 +159,7 @@ export const CONFIG = { :::note The undeployed network is a local network that is not deployed to the blockchain. It is used for testing and development purposes. -For more information, see the [Midnight local network](../../guides/midnight-local-network) guide. +For more information, see [Running a local network](/guides/networks-and-environments#running-a-local-network). ::: diff --git a/vercel.json b/vercel.json index 90c7a0758..0947df7c3 100644 --- a/vercel.json +++ b/vercel.json @@ -1431,7 +1431,12 @@ }, { "source": "/midnight-local-network", - "destination": "/guides/midnight-local-network", + "destination": "/guides/networks-and-environments", + "permanent": true + }, + { + "source": "/guides/midnight-local-network", + "destination": "/guides/networks-and-environments", "permanent": true }, {