From 2186c323e949cd7b627f71408b823489165dfd91 Mon Sep 17 00:00:00 2001
From: Owen
Date: Mon, 10 Nov 2025 16:36:08 -0500
Subject: [PATCH 1/7] wizard draft
---
.../console/layer-1/AvalancheGoDockerL1.tsx | 618 ++++++++++++------
.../toolbox/console/layer-1/node-config.ts | 192 ++++++
2 files changed, 612 insertions(+), 198 deletions(-)
create mode 100644 components/toolbox/console/layer-1/node-config.ts
diff --git a/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx b/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx
index 4f3a63f29ea..8372e3b0869 100644
--- a/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx
+++ b/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx
@@ -7,18 +7,13 @@ import { Container } from "../../components/Container";
import { getBlockchainInfo, getSubnetInfo } from "../../coreViem/utils/glacier";
import InputSubnetId from "../../components/InputSubnetId";
import BlockchainDetailsDisplay from "../../components/BlockchainDetailsDisplay";
-import { Steps, Step } from "fumadocs-ui/components/steps";
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
import { Button } from "../../components/Button";
-import { Success } from "../../components/Success";
-import { DockerInstallation } from "../../components/DockerInstallation";
-import { NodeBootstrapCheck } from "../../components/NodeBootstrapCheck";
-import { ReverseProxySetup } from "../../components/ReverseProxySetup";
-import { AddToWalletStep } from "../../components/AddToWalletStep";
-import { ConfigureNodeType } from "../../components/ConfigureNodeType";
-import { generateDockerCommand } from "./create/config";
+import { Steps, Step } from "fumadocs-ui/components/steps";
+import { SyntaxHighlightedJSON } from "../../components/genesis/SyntaxHighlightedJSON";
import { SUBNET_EVM_VM_ID } from "@/constants/console";
+import { generateChainConfig, generateDockerCommand, generateConfigFileCommand } from "./node-config";
export default function AvalanchegoDocker() {
const [chainId, setChainId] = useState("");
@@ -27,38 +22,58 @@ export default function AvalanchegoDocker() {
const [blockchainInfo, setBlockchainInfo] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [nodeType, setNodeType] = useState<"validator" | "public-rpc">("validator");
- const [rpcCommand, setRpcCommand] = useState("");
const [domain, setDomain] = useState("");
const [enableDebugTrace, setEnableDebugTrace] = useState(false);
const [pruningEnabled, setPruningEnabled] = useState(true);
const [subnetIdError, setSubnetIdError] = useState(null);
- const [chainAddedToWallet, setChainAddedToWallet] = useState(null);
- const [nodeIsReady, setNodeIsReady] = useState(false);
const [selectedRPCBlockchainId, setSelectedRPCBlockchainId] = useState("");
const [minDelayTarget, setMinDelayTarget] = useState(250);
+ const [configJson, setConfigJson] = useState("");
+
+ // Advanced cache settings
+ const [trieCleanCache, setTrieCleanCache] = useState(512);
+ const [trieDirtyCache, setTrieDirtyCache] = useState(512);
+ const [snapshotCache, setSnapshotCache] = useState(256);
+ const [commitInterval, setCommitInterval] = useState(4096);
+
+ // API settings
+ const [rpcGasCap, setRpcGasCap] = useState(50000000);
+ const [apiMaxBlocksPerRequest, setApiMaxBlocksPerRequest] = useState(0);
+ const [allowUnfinalizedQueries, setAllowUnfinalizedQueries] = useState(false);
+
+ // Show advanced settings
+ const [showAdvancedSettings, setShowAdvancedSettings] = useState(false);
const { avalancheNetworkID } = useWalletStore();
const isRPC = nodeType === "public-rpc";
+ // Generate Subnet-EVM chain configuration JSON when parameters change
useEffect(() => {
+ if (!subnetId || !chainId || !blockchainInfo) {
+ setConfigJson("");
+ return;
+ }
+
try {
- const vmId = blockchainInfo?.vmId || SUBNET_EVM_VM_ID;
- setRpcCommand(generateDockerCommand(
- [subnetId],
- isRPC,
- avalancheNetworkID,
- chainId,
- vmId,
+ const config = generateChainConfig(
+ nodeType,
enableDebugTrace,
pruningEnabled,
- false, // isPrimaryNetwork = false
- isRPC ? null : minDelayTarget // Pass minDelayTarget only for validators
- ));
+ minDelayTarget,
+ trieCleanCache,
+ trieDirtyCache,
+ snapshotCache,
+ commitInterval,
+ rpcGasCap,
+ apiMaxBlocksPerRequest,
+ allowUnfinalizedQueries
+ );
+ setConfigJson(JSON.stringify(config, null, 2));
} catch (error) {
- setRpcCommand((error as Error).message);
+ setConfigJson(`Error: ${(error as Error).message}`);
}
- }, [subnetId, isRPC, avalancheNetworkID, enableDebugTrace, chainId, pruningEnabled, blockchainInfo, minDelayTarget]);
+ }, [subnetId, chainId, nodeType, enableDebugTrace, pruningEnabled, blockchainInfo, minDelayTarget, trieCleanCache, trieDirtyCache, snapshotCache, commitInterval, rpcGasCap, apiMaxBlocksPerRequest, allowUnfinalizedQueries]);
useEffect(() => {
if (nodeType === "validator") {
@@ -140,57 +155,38 @@ export default function AvalanchegoDocker() {
setSubnet(null);
setBlockchainInfo(null);
setNodeType("validator");
- setChainAddedToWallet(null);
- setRpcCommand("");
setDomain("");
setEnableDebugTrace(false);
setPruningEnabled(true);
setSubnetIdError(null);
- setNodeIsReady(false);
setSelectedRPCBlockchainId("");
setMinDelayTarget(250);
+ setConfigJson("");
+ setTrieCleanCache(512);
+ setTrieDirtyCache(512);
+ setSnapshotCache(256);
+ setCommitInterval(4096);
+ setRpcGasCap(50000000);
+ setApiMaxBlocksPerRequest(0);
+ setAllowUnfinalizedQueries(false);
+ setShowAdvancedSettings(false);
};
// Check if this blockchain uses a custom VM
const isCustomVM = blockchainInfo && blockchainInfo.vmId !== SUBNET_EVM_VM_ID;
return (
- <>
- Set up Instance
- Set up a linux server with any cloud provider, like AWS, GCP, Azure, or Digital Ocean. Low specs (e.g. 2 vCPUs, 4GB RAM, 20GB storage) are sufficient for basic tests. For more extensive test and production L1s use a larger instance with appropriate resources (e.g. 8 vCPUs, 16GB RAM, 1 TB storage).
-
- If you do not have access to a server, you can also run a node for educational purposes locally. Simply select the "RPC Node (Local)" option in the next step.
-
-
-
-
-
-
- If you do not want to use Docker, you can follow the instructions{" "}
-
- here
-
- .
-
-
-
-
- Select L1
- Enter the Avalanche Subnet ID of the L1 you want to run a node for.
+ Select L1
+
+ Enter the Avalanche Subnet ID of the L1 you want to run a node for
+
- {/* Show subnet details if available */}
{subnet && subnet.blockchains && subnet.blockchains.length > 0 && (
-
+
{subnet.blockchains.map((blockchain: { blockchainId: string; blockchainName: string; createBlockTimestamp: number; createBlockNumber: string; vmId: string; subnetId: string; evmChainId: number }) => (
-
- {/* Blockchain selection for multiple blockchains */}
- {nodeType === "public-rpc" && subnet && subnet.blockchains && subnet.blockchains.length > 1 && (
-
+
Configure Node Settings
+
+
+
+
+
+ Node Type
+
+ setNodeType(e.target.value as "validator" | "public-rpc")}
+ className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
+ >
+ Validator Node
+ Public RPC Node
+
+
+
+ {nodeType === "public-rpc" && (
+ <>
+
+
+ setEnableDebugTrace(e.target.checked)}
+ className="rounded"
+ />
+ Enable Debug Trace
+
+
+
+
+
+ setPruningEnabled(e.target.checked)}
+ className="rounded"
+ />
+ Enable Pruning
+
+
+
+ {subnet && subnet.blockchains && subnet.blockchains.length > 1 && (
+
Select Blockchain for RPC Endpoint
@@ -251,9 +280,26 @@ export default function AvalanchegoDocker() {
)}
- {/* Min delay target for validator nodes */}
+
+
+ Domain (optional)
+
+
setDomain(e.target.value)}
+ placeholder="example.com"
+ className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
+ />
+
+ If you plan to expose this RPC publicly, enter your domain name.
+
+
+ >
+ )}
+
{nodeType === "validator" && (
-
+
Min Delay Target (ms)
@@ -269,20 +315,307 @@ export default function AvalanchegoDocker() {
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
/>
- The minimum delay between blocks (in milliseconds) that this node will attempt to use when creating blocks. Maximum: 2000ms. Default for L1: 250ms.
+ The minimum delay between blocks (in milliseconds). Maximum: 2000ms. Default: 250ms.
)}
-
+
+ {/* Advanced Settings */}
+
+
setShowAdvancedSettings(!showAdvancedSettings)}
+ className="flex items-center justify-between w-full text-left"
+ >
+
+ Advanced Settings
+
+
+
+
+
+
+ {showAdvancedSettings && (
+
+
+
+
+
Performance Settings
+
+
+
+
+ Commit Interval (blocks)
+
+
setCommitInterval(Math.max(1, parseInt(e.target.value) || 1))}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Interval to persist EVM and atomic tries
+
+
+
+
+
+ RPC Gas Cap
+
+
setRpcGasCap(Math.max(0, parseInt(e.target.value) || 0))}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Maximum gas limit for RPC calls
+
+
+
+
+
+ {isRPC && (
+
+
RPC Settings
+
+
+
+
+ API Max Blocks Per Request
+
+
setApiMaxBlocksPerRequest(Math.max(0, parseInt(e.target.value) || 0))}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ 0 = no limit. Limits blocks per getLogs request
+
+
+
+
+
+ setAllowUnfinalizedQueries(e.target.checked)}
+ className="rounded"
+ />
+
+ Allow Unfinalized Queries
+
+
+
+ Allows queries for unfinalized blocks
+
+
+
+
+ )}
+
+ )}
+
+
+
+ {/* Configuration Preview */}
+
+
+
+
Configuration Preview
+
+
+ {configJson && !configJson.startsWith("Error:") ? (
+
+ ) : (
+
+ {configJson.startsWith("Error:") ? configJson : "Configure your node to see the Subnet-EVM chain config"}
+
+ )}
+
+
+
+
- Start AvalancheGo Node
- Run the following Docker command to start your node:
+ Create Configuration File
+
+ Run this command on your server to create the Subnet-EVM chain configuration file:
+
+
+ {
+ try {
+ const config = JSON.parse(configJson);
+ return generateConfigFileCommand(chainId, config);
+ } catch {
+ return "# Error generating config file command";
+ }
+ })()}
+ />
+
+
+ This creates the configuration file at ~/.avalanchego/configs/chains/{chainId}/config.json
+
+
+
+
+
+
Basic Settings:
+
+ pruning-enabled: Enables state pruning to save disk space
+ log-level: Logging level (trace, debug, info, warn, error, crit)
+ min-delay-target: Minimum delay between blocks in milliseconds
+ warp-api-enabled: Enables the Warp API for cross-chain messaging (ICM)
+
+
+
Cache Settings:
+
+ trie-clean-cache: Size of the trie clean cache in MB (default: 512)
+ trie-dirty-cache: Size of the trie dirty cache in MB (default: 512)
+ snapshot-cache: Size of the snapshot disk layer clean cache in MB (default: 256)
+
-
+
Performance Settings:
+
+ commit-interval: Interval at which to persist EVM and atomic tries (blocks, default: 4096)
+ rpc-gas-cap: Maximum gas limit for RPC calls (default: 50,000,000)
+
+
+ {isRPC && (
+ <>
+
RPC-Specific Settings:
+
+ api-max-blocks-per-request: Maximum blocks per getLogs request (0 = no limit)
+ allow-unfinalized-queries: Allows queries for unfinalized blocks
+
+ >
+ )}
+
+ {enableDebugTrace && (
+ <>
+
Debug Settings:
+
+ eth-apis: Extended list of Ethereum APIs including debug and tracing capabilities
+ admin-api-enabled: Enables administrative operations API
+
+ >
+ )}
+
+
+
+ {isCustomVM && (
+
+
+ This blockchain uses a non-standard Virtual Machine ID. The Docker command includes VM aliases mapping.
+
+
+ VM ID: {blockchainInfo.vmId}
+ Aliases to: {SUBNET_EVM_VM_ID}
+
+
+ )}
+
+
+
+
+ Run Docker Command
+
+ Start the node using Docker:
+
+
+ {
+ try {
+ const config = JSON.parse(configJson);
+ const vmId = blockchainInfo?.vmId || SUBNET_EVM_VM_ID;
+ return generateDockerCommand(
+ subnetId,
+ chainId,
+ config,
+ nodeType,
+ avalancheNetworkID,
+ vmId
+ );
+ } catch {
+ return "# Error generating Docker command";
+ }
+ })()}
+ />
+ The container will read the config from ~/.avalanchego/configs/chains/{chainId}/config.json via the mounted volume.
+
+
+
+
+ To run multiple nodes on the same machine, ensure each node has:
+
+ Unique container name (change --name parameter)
+ Different ports (modify port mappings)
+ Separate data directories (change ~/.avalanchego path)
+
+
+
+
+ Monitor your node with:
+
+
+
+
+
For advanced node configuration options, see the{" "}
.
-
- {isCustomVM && (
-
-
-
- This blockchain uses a non-standard Virtual Machine ID. The Docker command automatically includes the AVAGO_VM_ALIASES_FILE_CONTENT environment variable with base64 encoded VM aliases configuration.
-
-
- VM ID: {blockchainInfo.vmId}
- Aliases to: {SUBNET_EVM_VM_ID}
-
-
-
- )}
-
-
-
- To run multiple validator nodes on the same machine, ensure each node has:
-
- Unique container name (change --name parameter)
- Different ports (modify AVAGO_HTTP_PORT and AVAGO_STAKING_PORT)
- Separate data directories (change the local volume path ~/.avalanchego to a unique directory)
-
- Example for second node: Use ports 9652/9653 (HTTP/staking), container name "avago2", and data directory "~/.avalanchego2"
-
-
- {/* Conditional steps based on nodeType */}
- {nodeType === "public-rpc" && (
-
-
-
- )}
- {((nodeType === "public-rpc" && !!domain)) && (
-
-
-
- )}
-
- {nodeType === "validator" && (
-
- Wait for the Node to Bootstrap
- Your node will now bootstrap and sync the P-Chain and your L1. This process should take a few minutes . You can follow the process by checking the logs with the following command:
-
-
-
-
-
- The bootstrapping has three phases:
-
-
-
- Fetching the blocks of the P-Chain:
- The node fetches all the P-Chain blocks. The eta field is giving the estimated remaining time for the fetching process.
-
-
-
- Executing the blocks of the P-Chain:
- The node will sync the P-Chain and your L1.
-
-
-
- After the P-Chain is fetched and executed the process is repeated for the tracked Subnet.
-
-
-
- setNodeIsReady(checked)}
- />
-
- )}
-
- {/* Show success message when node is ready for validator mode */}
- {nodeIsReady && nodeType === "validator" && (
-
- Node Setup Complete
- Your AvalancheGo node is now fully bootstrapped and ready to be used as a validator node.
-
-
-
-
-
-
- Node is ready for validation
-
-
- Your node has successfully synced with the network and is ready to be added as a validator.
-
-
-
-
-
- )}
- >)}
-
-
-
-
- {chainAddedToWallet && (
- <>
-
-
Reset
>
)}
-
-
- >
+
+
+ {configJson && !configJson.startsWith("Error:") && (
+
+
+ Start Over
+
+
+ )}
+
);
};
diff --git a/components/toolbox/console/layer-1/node-config.ts b/components/toolbox/console/layer-1/node-config.ts
new file mode 100644
index 00000000000..f559d5cf086
--- /dev/null
+++ b/components/toolbox/console/layer-1/node-config.ts
@@ -0,0 +1,192 @@
+// Node configuration generation for L1 Docker setup
+import { SUBNET_EVM_VM_ID } from '@/constants/console';
+import { getContainerVersions } from '@/components/toolbox/utils/containerVersions';
+
+/**
+ * Generates the Subnet-EVM chain configuration
+ * This configuration is saved to ~/.avalanchego/configs/chains/
/config.json
+ */
+export const generateChainConfig = (
+ nodeType: 'validator' | 'public-rpc',
+ enableDebugTrace: boolean = false,
+ pruningEnabled: boolean = true,
+ minDelayTarget: number = 250,
+ trieCleanCache: number = 512,
+ trieDirtyCache: number = 512,
+ snapshotCache: number = 256,
+ commitInterval: number = 4096,
+ rpcGasCap: number = 50000000,
+ apiMaxBlocksPerRequest: number = 0,
+ allowUnfinalizedQueries: boolean = false
+) => {
+ const isRPC = nodeType === 'public-rpc';
+
+ // Base configuration for all nodes
+ const config: any = {
+ "pruning-enabled": pruningEnabled,
+ "commit-interval": commitInterval,
+ "trie-clean-cache": trieCleanCache,
+ "trie-dirty-cache": trieDirtyCache,
+ "snapshot-cache": snapshotCache,
+ "rpc-gas-cap": rpcGasCap,
+ "log-level": enableDebugTrace ? "debug" : "info",
+ "metrics-expensive-enabled": true,
+ "accepted-cache-size": 32,
+ "min-delay-target": minDelayTarget
+ };
+
+ // Add warp API for cross-chain messaging (enabled by default for L1s)
+ config["warp-api-enabled"] = true;
+
+ // Configure APIs based on node type
+ if (enableDebugTrace) {
+ config["eth-apis"] = [
+ "eth",
+ "eth-filter",
+ "net",
+ "admin",
+ "web3",
+ "internal-eth",
+ "internal-blockchain",
+ "internal-transaction",
+ "internal-debug",
+ "internal-account",
+ "internal-personal",
+ "debug",
+ "debug-tracer",
+ "debug-file-tracer",
+ "debug-handler"
+ ];
+ config["admin-api-enabled"] = true;
+ } else {
+ // Standard APIs
+ config["eth-apis"] = ["eth", "eth-filter", "net", "web3"];
+ }
+
+ // RPC-specific settings
+ if (isRPC) {
+ config["api-max-duration"] = 0; // No time limit
+ config["api-max-blocks-per-request"] = apiMaxBlocksPerRequest;
+ config["allow-unfinalized-queries"] = allowUnfinalizedQueries;
+ }
+
+ return config;
+};
+
+/**
+ * Metadata object to store deployment information (separate from chain config)
+ */
+export const generateDeploymentMetadata = (
+ subnetId: string,
+ blockchainId: string,
+ nodeType: 'validator' | 'public-rpc',
+ networkID: number,
+ vmId: string = SUBNET_EVM_VM_ID,
+ domain?: string
+) => {
+ const isTestnet = networkID === 5;
+ const isCustomVM = vmId !== SUBNET_EVM_VM_ID;
+
+ return {
+ "deployment": {
+ "network": isTestnet ? "fuji" : "mainnet",
+ "networkID": networkID,
+ "subnetId": subnetId,
+ "blockchainId": blockchainId,
+ "vmId": vmId,
+ "isCustomVM": isCustomVM,
+ "nodeType": nodeType,
+ "domain": domain || null,
+ "timestamp": new Date().toISOString()
+ }
+ };
+};
+
+/**
+ * Generates base64-encoded chain config for environment variable
+ */
+export const encodeChainConfig = (
+ blockchainId: string,
+ chainConfig: any
+) => {
+ const chainConfigMap: Record = {};
+ chainConfigMap[blockchainId] = {
+ "Config": btoa(JSON.stringify(chainConfig)),
+ "Upgrade": null
+ };
+ return btoa(JSON.stringify(chainConfigMap));
+};
+
+/**
+ * Generates a command to create the chain config file in the correct location
+ */
+export const generateConfigFileCommand = (
+ blockchainId: string,
+ chainConfig: any
+) => {
+ const configJson = JSON.stringify(chainConfig, null, 2);
+ const configPath = `~/.avalanchego/configs/chains/${blockchainId}`;
+
+ // Escape single quotes in the JSON for the shell command
+ const escapedJson = configJson.replace(/'/g, "'\\''");
+
+ return `# Create the chain config directory and file
+mkdir -p ${configPath} && cat > ${configPath}/config.json << 'EOF'
+${configJson}
+EOF`;
+};
+
+/**
+ * Generates the complete Docker command
+ * The chain config is read from the mounted volume at ~/.avalanchego/configs/chains//config.json
+ */
+export const generateDockerCommand = (
+ subnetId: string,
+ blockchainId: string,
+ chainConfig: any,
+ nodeType: 'validator' | 'public-rpc',
+ networkID: number,
+ vmId: string = SUBNET_EVM_VM_ID
+) => {
+ const isRPC = nodeType === 'public-rpc';
+ const isTestnet = networkID === 5; // Fuji
+ const isCustomVM = vmId !== SUBNET_EVM_VM_ID;
+ const versions = getContainerVersions(isTestnet);
+
+ const env: Record = {
+ AVAGO_PUBLIC_IP_RESOLUTION_SERVICE: "opendns",
+ AVAGO_HTTP_HOST: "0.0.0.0",
+ AVAGO_PARTIAL_SYNC_PRIMARY_NETWORK: "true",
+ AVAGO_TRACK_SUBNETS: subnetId
+ };
+
+ // Set network ID
+ if (networkID === 5) {
+ env.AVAGO_NETWORK_ID = "fuji";
+ }
+
+ // Configure RPC settings
+ if (isRPC) {
+ env.AVAGO_HTTP_ALLOWED_HOSTS = '"*"';
+ }
+
+ // Add VM aliases if custom VM
+ if (isCustomVM) {
+ const vmAliases = {
+ [vmId]: [SUBNET_EVM_VM_ID]
+ };
+ env.AVAGO_VM_ALIASES_FILE_CONTENT = btoa(JSON.stringify(vmAliases, null, 2));
+ }
+
+ const chunks = [
+ "docker run -it -d",
+ `--name avago`,
+ `-p ${isRPC ? "" : "127.0.0.1:"}9650:9650 -p 9651:9651`,
+ `-v ~/.avalanchego:/root/.avalanchego`,
+ ...Object.entries(env).map(([key, value]) => `-e ${key}=${value}`),
+ `avaplatform/subnet-evm_avalanchego:${versions['avaplatform/subnet-evm_avalanchego']}`
+ ];
+
+ return chunks.map(chunk => ` ${chunk}`).join(" \\\n").trim();
+};
+
From 134a1980e276df8ecaf4fb04d2f329fcfcb3ba93 Mon Sep 17 00:00:00 2001
From: Owen
Date: Mon, 10 Nov 2025 18:48:57 -0500
Subject: [PATCH 2/7] fixes
---
.../toolbox/components/ReverseProxySetup.tsx | 2 +-
.../console/layer-1/AvalancheGoDockerL1.tsx | 107 +++++++++++++-----
.../toolbox/console/layer-1/node-config.ts | 26 ++++-
3 files changed, 103 insertions(+), 32 deletions(-)
diff --git a/components/toolbox/components/ReverseProxySetup.tsx b/components/toolbox/components/ReverseProxySetup.tsx
index 74eec54b48d..b15b572aca0 100644
--- a/components/toolbox/components/ReverseProxySetup.tsx
+++ b/components/toolbox/components/ReverseProxySetup.tsx
@@ -50,7 +50,7 @@ const generateHealthCheckCommand = (domain: string, chainId: string) => {
const processedDomain = nipify(domain);
return `curl -X POST --data '{
- "jsonrpc":"2.0", "method":"eth_chainId", "params":[], "id":1
+ "jsonrpc":"2.0", "method":"eth_blockNumber", "params":[], "id":1
}' -H 'content-type:application/json;' \\
https://${processedDomain}/ext/bc/${chainId}/rpc`;
};
diff --git a/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx b/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx
index 8372e3b0869..fbe4dcc6b2e 100644
--- a/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx
+++ b/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx
@@ -12,6 +12,7 @@ import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
import { Button } from "../../components/Button";
import { Steps, Step } from "fumadocs-ui/components/steps";
import { SyntaxHighlightedJSON } from "../../components/genesis/SyntaxHighlightedJSON";
+import { ReverseProxySetup } from "../../components/ReverseProxySetup";
import { SUBNET_EVM_VM_ID } from "@/constants/console";
import { generateChainConfig, generateDockerCommand, generateConfigFileCommand } from "./node-config";
@@ -41,6 +42,10 @@ export default function AvalanchegoDocker() {
const [apiMaxBlocksPerRequest, setApiMaxBlocksPerRequest] = useState(0);
const [allowUnfinalizedQueries, setAllowUnfinalizedQueries] = useState(false);
+ // State and history
+ const [acceptedCacheSize, setAcceptedCacheSize] = useState(32);
+ const [transactionHistory, setTransactionHistory] = useState(0);
+
// Show advanced settings
const [showAdvancedSettings, setShowAdvancedSettings] = useState(false);
@@ -67,20 +72,39 @@ export default function AvalanchegoDocker() {
commitInterval,
rpcGasCap,
apiMaxBlocksPerRequest,
- allowUnfinalizedQueries
+ allowUnfinalizedQueries,
+ acceptedCacheSize,
+ transactionHistory
);
setConfigJson(JSON.stringify(config, null, 2));
} catch (error) {
setConfigJson(`Error: ${(error as Error).message}`);
}
- }, [subnetId, chainId, nodeType, enableDebugTrace, pruningEnabled, blockchainInfo, minDelayTarget, trieCleanCache, trieDirtyCache, snapshotCache, commitInterval, rpcGasCap, apiMaxBlocksPerRequest, allowUnfinalizedQueries]);
+ }, [subnetId, chainId, nodeType, enableDebugTrace, pruningEnabled, blockchainInfo, minDelayTarget, trieCleanCache, trieDirtyCache, snapshotCache, commitInterval, rpcGasCap, apiMaxBlocksPerRequest, allowUnfinalizedQueries, acceptedCacheSize, transactionHistory]);
useEffect(() => {
if (nodeType === "validator") {
+ // Validator node defaults - optimized for block production
setDomain("");
setEnableDebugTrace(false);
setPruningEnabled(true);
- setMinDelayTarget(250); // Reset to default for L1
+ setMinDelayTarget(250); // Fast block times for L1
+ setAllowUnfinalizedQueries(false);
+ // Standard cache sizes for validators
+ setTrieCleanCache(512);
+ setTrieDirtyCache(512);
+ setSnapshotCache(256);
+ setAcceptedCacheSize(32);
+ setTransactionHistory(0); // Keep all tx history by default
+ } else if (nodeType === "public-rpc") {
+ // RPC node defaults - optimized for query performance
+ setAllowUnfinalizedQueries(true); // Enable real-time queries
+ // Larger caches for better RPC performance
+ setTrieCleanCache(1024); // 2x for better read performance
+ setTrieDirtyCache(1024);
+ setSnapshotCache(512); // 2x for snapshot queries
+ setAcceptedCacheSize(64); // Larger for more recent history
+ setTransactionHistory(0); // Keep all tx history by default for getLogs
}
}, [nodeType]);
@@ -169,6 +193,8 @@ export default function AvalanchegoDocker() {
setRpcGasCap(50000000);
setApiMaxBlocksPerRequest(0);
setAllowUnfinalizedQueries(false);
+ setAcceptedCacheSize(32);
+ setTransactionHistory(0);
setShowAdvancedSettings(false);
};
@@ -278,23 +304,7 @@ export default function AvalanchegoDocker() {
This blockchain will be used for the RPC endpoint URL generation.
- )}
-
-
-
- Domain (optional)
-
-
setDomain(e.target.value)}
- placeholder="example.com"
- className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
- />
-
- If you plan to expose this RPC publicly, enter your domain name.
-
-
+ )}
>
)}
@@ -381,6 +391,21 @@ export default function AvalanchegoDocker() {
className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
/>
+
+
+
+ Accepted Cache Size (blocks)
+
+
setAcceptedCacheSize(Math.max(1, parseInt(e.target.value) || 1))}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Depth of accepted headers and logs cache
+
+
@@ -417,6 +442,21 @@ export default function AvalanchegoDocker() {
Maximum gas limit for RPC calls
+
+
+
+ Transaction History (blocks)
+
+
setTransactionHistory(Math.max(0, parseInt(e.target.value) || 0))}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Maximum blocks from head to keep tx indices. 0 = no limit (archive mode)
+
+
@@ -518,27 +558,31 @@ export default function AvalanchegoDocker() {
log-level: Logging level (trace, debug, info, warn, error, crit)
min-delay-target: Minimum delay between blocks in milliseconds
warp-api-enabled: Enables the Warp API for cross-chain messaging (ICM)
+ eth-apis: List of enabled Ethereum API namespaces
Cache Settings:
- trie-clean-cache: Size of the trie clean cache in MB (default: 512)
- trie-dirty-cache: Size of the trie dirty cache in MB (default: 512)
- snapshot-cache: Size of the snapshot disk layer clean cache in MB (default: 256)
+ trie-clean-cache: Size of the trie clean cache in MB (validator: 512, RPC: 1024)
+ trie-dirty-cache: Size of the trie dirty cache in MB (validator: 512, RPC: 1024)
+ snapshot-cache: Size of the snapshot disk layer clean cache in MB (validator: 256, RPC: 512)
+ accepted-cache-size: Depth to keep in accepted headers/logs cache (validator: 32, RPC: 64)
Performance Settings:
- commit-interval: Interval at which to persist EVM and atomic tries (blocks, default: 4096)
+ commit-interval: Interval to persist EVM and atomic tries in blocks (default: 4096)
rpc-gas-cap: Maximum gas limit for RPC calls (default: 50,000,000)
+ transaction-history: Max blocks from head to keep tx indices. 0 = archive mode (all history)
{isRPC && (
<>
RPC-Specific Settings:
+ api-max-duration: Maximum duration for API calls (0 = no limit)
api-max-blocks-per-request: Maximum blocks per getLogs request (0 = no limit)
- allow-unfinalized-queries: Allows queries for unfinalized blocks
+ allow-unfinalized-queries: Allows queries for unfinalized/pending blocks
>
)}
@@ -547,7 +591,7 @@ export default function AvalanchegoDocker() {
<>
Debug Settings:
- eth-apis: Extended list of Ethereum APIs including debug and tracing capabilities
+ eth-apis: Extended APIs including debug-tracer, debug-file-tracer, internal-* APIs
admin-api-enabled: Enables administrative operations API
>
@@ -629,6 +673,17 @@ export default function AvalanchegoDocker() {
+
+ {nodeType === "public-rpc" && (
+
+
+
+ )}
>
)}
diff --git a/components/toolbox/console/layer-1/node-config.ts b/components/toolbox/console/layer-1/node-config.ts
index f559d5cf086..b5c52b741e5 100644
--- a/components/toolbox/console/layer-1/node-config.ts
+++ b/components/toolbox/console/layer-1/node-config.ts
@@ -17,7 +17,9 @@ export const generateChainConfig = (
commitInterval: number = 4096,
rpcGasCap: number = 50000000,
apiMaxBlocksPerRequest: number = 0,
- allowUnfinalizedQueries: boolean = false
+ allowUnfinalizedQueries: boolean = false,
+ acceptedCacheSize: number = 32,
+ transactionHistory: number = 0
) => {
const isRPC = nodeType === 'public-rpc';
@@ -31,7 +33,7 @@ export const generateChainConfig = (
"rpc-gas-cap": rpcGasCap,
"log-level": enableDebugTrace ? "debug" : "info",
"metrics-expensive-enabled": true,
- "accepted-cache-size": 32,
+ "accepted-cache-size": acceptedCacheSize,
"min-delay-target": minDelayTarget
};
@@ -59,8 +61,16 @@ export const generateChainConfig = (
];
config["admin-api-enabled"] = true;
} else {
- // Standard APIs
- config["eth-apis"] = ["eth", "eth-filter", "net", "web3"];
+ // Standard APIs (includes internal APIs required for basic eth methods)
+ config["eth-apis"] = [
+ "eth",
+ "eth-filter",
+ "net",
+ "web3",
+ "internal-eth",
+ "internal-blockchain",
+ "internal-transaction"
+ ];
}
// RPC-specific settings
@@ -70,6 +80,11 @@ export const generateChainConfig = (
config["allow-unfinalized-queries"] = allowUnfinalizedQueries;
}
+ // Transaction history (0 = no limit, keeps all tx indices)
+ if (transactionHistory > 0) {
+ config["transaction-history"] = transactionHistory;
+ }
+
return config;
};
@@ -157,7 +172,8 @@ export const generateDockerCommand = (
AVAGO_PUBLIC_IP_RESOLUTION_SERVICE: "opendns",
AVAGO_HTTP_HOST: "0.0.0.0",
AVAGO_PARTIAL_SYNC_PRIMARY_NETWORK: "true",
- AVAGO_TRACK_SUBNETS: subnetId
+ AVAGO_TRACK_SUBNETS: subnetId,
+ AVAGO_CHAIN_CONFIG_DIR: "/root/.avalanchego/configs/chains"
};
// Set network ID
From b77de9ef55388f276cc77efc2cef9b052f10f597 Mon Sep 17 00:00:00 2001
From: Owen
Date: Mon, 10 Nov 2025 19:47:28 -0500
Subject: [PATCH 3/7] code highlighting + nits
---
.../console/layer-1/AvalancheGoDockerL1.tsx | 655 +++++++++++++-----
.../toolbox/console/layer-1/node-config.ts | 59 +-
.../layer-1/useNodeConfigHighlighting.ts | 78 +++
3 files changed, 626 insertions(+), 166 deletions(-)
create mode 100644 components/toolbox/console/layer-1/useNodeConfigHighlighting.ts
diff --git a/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx b/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx
index fbe4dcc6b2e..fcfbfdf6f3d 100644
--- a/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx
+++ b/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx
@@ -13,10 +13,13 @@ import { Button } from "../../components/Button";
import { Steps, Step } from "fumadocs-ui/components/steps";
import { SyntaxHighlightedJSON } from "../../components/genesis/SyntaxHighlightedJSON";
import { ReverseProxySetup } from "../../components/ReverseProxySetup";
+import { GenesisHighlightProvider, useGenesisHighlight } from "../../components/genesis/GenesisHighlightContext";
import { SUBNET_EVM_VM_ID } from "@/constants/console";
import { generateChainConfig, generateDockerCommand, generateConfigFileCommand } from "./node-config";
+import { useNodeConfigHighlighting } from "./useNodeConfigHighlighting";
-export default function AvalanchegoDocker() {
+function AvalanchegoDockerInner() {
+ const { setHighlightPath, clearHighlight, highlightPath } = useGenesisHighlight();
const [chainId, setChainId] = useState("");
const [subnetId, setSubnetId] = useState("");
const [subnet, setSubnet] = useState(null);
@@ -30,22 +33,42 @@ export default function AvalanchegoDocker() {
const [selectedRPCBlockchainId, setSelectedRPCBlockchainId] = useState("");
const [minDelayTarget, setMinDelayTarget] = useState(250);
const [configJson, setConfigJson] = useState("");
-
+
// Advanced cache settings
const [trieCleanCache, setTrieCleanCache] = useState(512);
const [trieDirtyCache, setTrieDirtyCache] = useState(512);
+ const [trieDirtyCommitTarget, setTrieDirtyCommitTarget] = useState(20);
+ const [triePrefetcherParallelism, setTriePrefetcherParallelism] = useState(16);
const [snapshotCache, setSnapshotCache] = useState(256);
const [commitInterval, setCommitInterval] = useState(4096);
-
+ const [stateSyncServerTrieCache, setStateSyncServerTrieCache] = useState(64);
+
// API settings
const [rpcGasCap, setRpcGasCap] = useState(50000000);
+ const [rpcTxFeeCap, setRpcTxFeeCap] = useState(100);
const [apiMaxBlocksPerRequest, setApiMaxBlocksPerRequest] = useState(0);
const [allowUnfinalizedQueries, setAllowUnfinalizedQueries] = useState(false);
-
+ const [batchRequestLimit, setBatchRequestLimit] = useState(1000);
+ const [batchResponseMaxSize, setBatchResponseMaxSize] = useState(25000000);
+
// State and history
const [acceptedCacheSize, setAcceptedCacheSize] = useState(32);
const [transactionHistory, setTransactionHistory] = useState(0);
-
+ const [stateSyncEnabled, setStateSyncEnabled] = useState(false);
+ const [skipTxIndexing, setSkipTxIndexing] = useState(false);
+
+ // Transaction settings
+ const [preimagesEnabled, setPreimagesEnabled] = useState(false);
+ const [localTxsEnabled, setLocalTxsEnabled] = useState(false);
+
+ // Gossip settings (validator specific)
+ const [pushGossipNumValidators, setPushGossipNumValidators] = useState(100);
+ const [pushGossipPercentStake, setPushGossipPercentStake] = useState(0.9);
+
+ // Profiling
+ const [continuousProfilerDir, setContinuousProfilerDir] = useState("");
+ const [continuousProfilerFrequency, setContinuousProfilerFrequency] = useState("15m");
+
// Show advanced settings
const [showAdvancedSettings, setShowAdvancedSettings] = useState(false);
@@ -53,6 +76,9 @@ export default function AvalanchegoDocker() {
const isRPC = nodeType === "public-rpc";
+ // Get highlighted lines for JSON preview
+ const highlightedLines = useNodeConfigHighlighting(highlightPath, configJson);
+
// Generate Subnet-EVM chain configuration JSON when parameters change
useEffect(() => {
if (!subnetId || !chainId || !blockchainInfo) {
@@ -68,19 +94,33 @@ export default function AvalanchegoDocker() {
minDelayTarget,
trieCleanCache,
trieDirtyCache,
+ trieDirtyCommitTarget,
+ triePrefetcherParallelism,
snapshotCache,
commitInterval,
+ stateSyncServerTrieCache,
rpcGasCap,
+ rpcTxFeeCap,
apiMaxBlocksPerRequest,
allowUnfinalizedQueries,
+ batchRequestLimit,
+ batchResponseMaxSize,
acceptedCacheSize,
- transactionHistory
+ transactionHistory,
+ stateSyncEnabled,
+ skipTxIndexing,
+ preimagesEnabled,
+ localTxsEnabled,
+ pushGossipNumValidators,
+ pushGossipPercentStake,
+ continuousProfilerDir,
+ continuousProfilerFrequency
);
setConfigJson(JSON.stringify(config, null, 2));
} catch (error) {
setConfigJson(`Error: ${(error as Error).message}`);
}
- }, [subnetId, chainId, nodeType, enableDebugTrace, pruningEnabled, blockchainInfo, minDelayTarget, trieCleanCache, trieDirtyCache, snapshotCache, commitInterval, rpcGasCap, apiMaxBlocksPerRequest, allowUnfinalizedQueries, acceptedCacheSize, transactionHistory]);
+ }, [subnetId, chainId, nodeType, enableDebugTrace, pruningEnabled, blockchainInfo, minDelayTarget, trieCleanCache, trieDirtyCache, trieDirtyCommitTarget, triePrefetcherParallelism, snapshotCache, commitInterval, stateSyncServerTrieCache, rpcGasCap, rpcTxFeeCap, apiMaxBlocksPerRequest, allowUnfinalizedQueries, batchRequestLimit, batchResponseMaxSize, acceptedCacheSize, transactionHistory, stateSyncEnabled, skipTxIndexing, preimagesEnabled, localTxsEnabled, pushGossipNumValidators, pushGossipPercentStake, continuousProfilerDir, continuousProfilerFrequency]);
useEffect(() => {
if (nodeType === "validator") {
@@ -188,13 +228,27 @@ export default function AvalanchegoDocker() {
setConfigJson("");
setTrieCleanCache(512);
setTrieDirtyCache(512);
+ setTrieDirtyCommitTarget(20);
+ setTriePrefetcherParallelism(16);
setSnapshotCache(256);
setCommitInterval(4096);
+ setStateSyncServerTrieCache(64);
setRpcGasCap(50000000);
+ setRpcTxFeeCap(100);
setApiMaxBlocksPerRequest(0);
setAllowUnfinalizedQueries(false);
+ setBatchRequestLimit(1000);
+ setBatchResponseMaxSize(25000000);
setAcceptedCacheSize(32);
setTransactionHistory(0);
+ setStateSyncEnabled(false);
+ setSkipTxIndexing(false);
+ setPreimagesEnabled(false);
+ setLocalTxsEnabled(false);
+ setPushGossipNumValidators(100);
+ setPushGossipPercentStake(0.9);
+ setContinuousProfilerDir("");
+ setContinuousProfilerFrequency("15m");
setShowAdvancedSettings(false);
};
@@ -202,44 +256,44 @@ export default function AvalanchegoDocker() {
const isCustomVM = blockchainInfo && blockchainInfo.vmId !== SUBNET_EVM_VM_ID;
return (
-
-
-
+ githubUrl="https://github.com/ava-labs/builders-hub/edit/master/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx"
+ >
+
+
Select L1
Enter the Avalanche Subnet ID of the L1 you want to run a node for
-
+
- {subnet && subnet.blockchains && subnet.blockchains.length > 0 && (
+ {subnet && subnet.blockchains && subnet.blockchains.length > 0 && (
- {subnet.blockchains.map((blockchain: { blockchainId: string; blockchainName: string; createBlockTimestamp: number; createBlockNumber: string; vmId: string; subnetId: string; evmChainId: number }) => (
-
- ))}
-
- )}
-
+ {subnet.blockchains.map((blockchain: { blockchainId: string; blockchainName: string; createBlockTimestamp: number; createBlockNumber: string; vmId: string; subnetId: string; evmChainId: number }) => (
+
+ ))}
+
+ )}
+
- {subnetId && blockchainInfo && (
- <>
-
+ {subnetId && blockchainInfo && (
+ <>
+
Configure Node Settings
@@ -260,7 +314,7 @@ export default function AvalanchegoDocker() {
{nodeType === "public-rpc" && (
<>
-
+
setHighlightPath('ethApis')} onMouseLeave={clearHighlight}>
-
+
setHighlightPath('pruning')} onMouseLeave={clearHighlight}>
1 && (
-
- Select Blockchain for RPC Endpoint
-
-
setSelectedRPCBlockchainId(e.target.value)}
- className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
- >
- {subnet.blockchains.map((blockchain: { blockchainId: string; blockchainName: string }) => (
-
- {blockchain.blockchainName} ({blockchain.blockchainId})
-
- ))}
-
-
- This blockchain will be used for the RPC endpoint URL generation.
-
-
+
+ Select Blockchain for RPC Endpoint
+
+ setSelectedRPCBlockchainId(e.target.value)}
+ className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
+ >
+ {subnet.blockchains.map((blockchain: { blockchainId: string; blockchainName: string }) => (
+
+ {blockchain.blockchainName} ({blockchain.blockchainId})
+
+ ))}
+
+
+ This blockchain will be used for the RPC endpoint URL generation.
+
+
)}
>
)}
{nodeType === "validator" && (
-
+
setHighlightPath('minDelayTarget')} onMouseLeave={clearHighlight}>
Min Delay Target (ms)
@@ -320,6 +374,8 @@ export default function AvalanchegoDocker() {
const value = Math.min(2000, Math.max(0, parseInt(e.target.value) || 0));
setMinDelayTarget(value);
}}
+ onFocus={() => setHighlightPath('minDelayTarget')}
+ onBlur={clearHighlight}
min="0"
max="2000"
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
@@ -352,11 +408,31 @@ export default function AvalanchegoDocker() {
{showAdvancedSettings && (
+
+ For advanced configuration options, see the{" "}
+
+ AvalancheGo configuration
+ {" "}
+ and{" "}
+
+ Subnet-EVM configuration
+ documentation.
+
Cache Settings
-
+
-
+
setHighlightPath('trieCleanCache')} onMouseLeave={clearHighlight}>
Trie Clean Cache (MB)
@@ -364,11 +440,13 @@ export default function AvalanchegoDocker() {
type="number"
value={trieCleanCache}
onChange={(e) => setTrieCleanCache(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('trieCleanCache')}
+ onBlur={clearHighlight}
className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
/>
-
+
setHighlightPath('trieDirtyCache')} onMouseLeave={clearHighlight}>
Trie Dirty Cache (MB)
@@ -376,11 +454,13 @@ export default function AvalanchegoDocker() {
type="number"
value={trieDirtyCache}
onChange={(e) => setTrieDirtyCache(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('trieDirtyCache')}
+ onBlur={clearHighlight}
className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
/>
-
+
setHighlightPath('snapshotCache')} onMouseLeave={clearHighlight}>
Snapshot Cache (MB)
@@ -388,11 +468,13 @@ export default function AvalanchegoDocker() {
type="number"
value={snapshotCache}
onChange={(e) => setSnapshotCache(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('snapshotCache')}
+ onBlur={clearHighlight}
className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
/>
-
+
setHighlightPath('acceptedCacheSize')} onMouseLeave={clearHighlight}>
Accepted Cache Size (blocks)
@@ -400,20 +482,73 @@ export default function AvalanchegoDocker() {
type="number"
value={acceptedCacheSize}
onChange={(e) => setAcceptedCacheSize(Math.max(1, parseInt(e.target.value) || 1))}
+ onFocus={() => setHighlightPath('acceptedCacheSize')}
+ onBlur={clearHighlight}
className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
/>
Depth of accepted headers and logs cache
+
+
setHighlightPath('trieDirtyCommitTarget')} onMouseLeave={clearHighlight}>
+
+ Trie Dirty Commit Target (MB)
+
+
setTrieDirtyCommitTarget(Math.max(1, parseInt(e.target.value) || 1))}
+ onFocus={() => setHighlightPath('trieDirtyCommitTarget')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Memory limit before commit
+
+
+
+
setHighlightPath('triePrefetcherParallelism')} onMouseLeave={clearHighlight}>
+
+ Trie Prefetcher Parallelism
+
+
setTriePrefetcherParallelism(Math.max(1, parseInt(e.target.value) || 1))}
+ onFocus={() => setHighlightPath('triePrefetcherParallelism')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Max concurrent disk reads
+
+
+
+
setHighlightPath('stateSyncServerTrieCache')} onMouseLeave={clearHighlight}>
+
+ State Sync Server Trie Cache (MB)
+
+
setStateSyncServerTrieCache(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('stateSyncServerTrieCache')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Trie cache for state sync server
+
+
Performance Settings
-
+
-
+
setHighlightPath('commitInterval')} onMouseLeave={clearHighlight}>
Commit Interval (blocks)
@@ -421,6 +556,8 @@ export default function AvalanchegoDocker() {
type="number"
value={commitInterval}
onChange={(e) => setCommitInterval(Math.max(1, parseInt(e.target.value) || 1))}
+ onFocus={() => setHighlightPath('commitInterval')}
+ onBlur={clearHighlight}
className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
/>
@@ -428,7 +565,7 @@ export default function AvalanchegoDocker() {
-
+
setHighlightPath('rpcGasCap')} onMouseLeave={clearHighlight}>
RPC Gas Cap
@@ -436,6 +573,8 @@ export default function AvalanchegoDocker() {
type="number"
value={rpcGasCap}
onChange={(e) => setRpcGasCap(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('rpcGasCap')}
+ onBlur={clearHighlight}
className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
/>
@@ -443,7 +582,70 @@ export default function AvalanchegoDocker() {
-
+
setHighlightPath('rpcTxFeeCap')} onMouseLeave={clearHighlight}>
+
+ RPC Tx Fee Cap (AVAX)
+
+
setRpcTxFeeCap(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('rpcTxFeeCap')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Maximum transaction fee cap
+
+
+
+
+
+
+
API Limits
+
+
+
setHighlightPath('batchRequestLimit')} onMouseLeave={clearHighlight}>
+
+ Batch Request Limit
+
+
setBatchRequestLimit(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('batchRequestLimit')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Max batched requests (0 = no limit)
+
+
+
+
setHighlightPath('batchResponseMaxSize')} onMouseLeave={clearHighlight}>
+
+ Batch Response Max Size (bytes)
+
+
setBatchResponseMaxSize(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('batchResponseMaxSize')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Max batch response size (default: 25MB)
+
+
+
+
+
+
+
Transaction & State
+
+
+
setHighlightPath('transactionHistory')} onMouseLeave={clearHighlight}>
Transaction History (blocks)
@@ -451,21 +653,144 @@ export default function AvalanchegoDocker() {
type="number"
value={transactionHistory}
onChange={(e) => setTransactionHistory(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('transactionHistory')}
+ onBlur={clearHighlight}
className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
/>
- Maximum blocks from head to keep tx indices. 0 = no limit (archive mode)
+ Max blocks to keep tx indices. 0 = archive mode (all history)
+
+
+
+
setHighlightPath('skipTxIndexing')} onMouseLeave={clearHighlight}>
+
+ setSkipTxIndexing(e.target.checked)}
+ onFocus={() => setHighlightPath('skipTxIndexing')}
+ onBlur={clearHighlight}
+ className="rounded"
+ />
+
+ Skip Transaction Indexing
+
+
+
+ Disable tx indexing entirely (saves disk space)
+
+
+
+
setHighlightPath('stateSyncEnabled')} onMouseLeave={clearHighlight}>
+
+ setStateSyncEnabled(e.target.checked)}
+ onFocus={() => setHighlightPath('stateSyncEnabled')}
+ onBlur={clearHighlight}
+ className="rounded"
+ />
+
+ Enable State Sync
+
+
+
+ Fast sync from state summary
+
+
+
+
setHighlightPath('preimagesEnabled')} onMouseLeave={clearHighlight}>
+
+ setPreimagesEnabled(e.target.checked)}
+ onFocus={() => setHighlightPath('preimagesEnabled')}
+ onBlur={clearHighlight}
+ className="rounded"
+ />
+
+ Enable Preimages
+
+
+
+ Record preimages (uses more disk)
+
+
+
+
setHighlightPath('localTxsEnabled')} onMouseLeave={clearHighlight}>
+
+ setLocalTxsEnabled(e.target.checked)}
+ onFocus={() => setHighlightPath('localTxsEnabled')}
+ onBlur={clearHighlight}
+ className="rounded"
+ />
+
+ Enable Local Transactions
+
+
+
+ Treat local account txs as local
+ {nodeType === "validator" && (
+
+
Gossip Settings (Validator)
+
+
+
setHighlightPath('pushGossipNumValidators')} onMouseLeave={clearHighlight}>
+
+ Push Gossip Num Validators
+
+
setPushGossipNumValidators(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('pushGossipNumValidators')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Number of validators to push gossip to
+
+
+
+
setHighlightPath('pushGossipPercentStake')} onMouseLeave={clearHighlight}>
+
+ Push Gossip Percent Stake
+
+
setPushGossipPercentStake(Math.min(1, Math.max(0, parseFloat(e.target.value) || 0)))}
+ onFocus={() => setHighlightPath('pushGossipPercentStake')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Percentage of total stake to gossip to (0-1)
+
+
+
+
+ )}
+
{isRPC && (
-
RPC Settings
-
+
RPC-Specific Settings
+
-
+
setHighlightPath('apiMaxBlocksPerRequest')} onMouseLeave={clearHighlight}>
API Max Blocks Per Request
@@ -473,6 +798,8 @@ export default function AvalanchegoDocker() {
type="number"
value={apiMaxBlocksPerRequest}
onChange={(e) => setApiMaxBlocksPerRequest(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('apiMaxBlocksPerRequest')}
+ onBlur={clearHighlight}
className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
/>
@@ -480,12 +807,14 @@ export default function AvalanchegoDocker() {
-
)}
+
+
+
Profiling (Optional)
+
+
+
setHighlightPath('continuousProfilerDir')} onMouseLeave={clearHighlight}>
+
+ Continuous Profiler Directory
+
+
setContinuousProfilerDir(e.target.value)}
+ onFocus={() => setHighlightPath('continuousProfilerDir')}
+ onBlur={clearHighlight}
+ placeholder="./profiles (leave empty to disable)"
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Directory for continuous profiler output
+
+
+
+ {continuousProfilerDir && (
+
setHighlightPath('continuousProfilerFrequency')} onMouseLeave={clearHighlight}>
+
+ Profiler Frequency
+
+
setContinuousProfilerFrequency(e.target.value)}
+ onFocus={() => setHighlightPath('continuousProfilerFrequency')}
+ onBlur={clearHighlight}
+ placeholder="15m"
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ How often to create profiles (e.g., 15m, 1h)
+
+
+ )}
+
+
)}
@@ -514,7 +887,7 @@ export default function AvalanchegoDocker() {
{configJson && !configJson.startsWith("Error:") ? (
) : (
@@ -525,16 +898,16 @@ export default function AvalanchegoDocker() {
-
+
-
+
Create Configuration File
Run this command on your server to create the Subnet-EVM chain configuration file:
- {
try {
const config = JSON.parse(configJson);
@@ -542,63 +915,33 @@ export default function AvalanchegoDocker() {
} catch {
return "# Error generating config file command";
}
- })()}
+ })()}
/>
-
+
This creates the configuration file at ~/.avalanchego/configs/chains/{chainId}/config.json
-
+
+ Read the documentation for more information on the configuration options. {" "}
+
+ AvalancheGo configuration
+
+ {" "}and{" "}
+
+ Subnet-EVM configuration
+
+
-
-
-
Basic Settings:
-
- pruning-enabled: Enables state pruning to save disk space
- log-level: Logging level (trace, debug, info, warn, error, crit)
- min-delay-target: Minimum delay between blocks in milliseconds
- warp-api-enabled: Enables the Warp API for cross-chain messaging (ICM)
- eth-apis: List of enabled Ethereum API namespaces
-
-
-
Cache Settings:
-
- trie-clean-cache: Size of the trie clean cache in MB (validator: 512, RPC: 1024)
- trie-dirty-cache: Size of the trie dirty cache in MB (validator: 512, RPC: 1024)
- snapshot-cache: Size of the snapshot disk layer clean cache in MB (validator: 256, RPC: 512)
- accepted-cache-size: Depth to keep in accepted headers/logs cache (validator: 32, RPC: 64)
-
-
-
Performance Settings:
-
- commit-interval: Interval to persist EVM and atomic tries in blocks (default: 4096)
- rpc-gas-cap: Maximum gas limit for RPC calls (default: 50,000,000)
- transaction-history: Max blocks from head to keep tx indices. 0 = archive mode (all history)
-
-
- {isRPC && (
- <>
-
RPC-Specific Settings:
-
- api-max-duration: Maximum duration for API calls (0 = no limit)
- api-max-blocks-per-request: Maximum blocks per getLogs request (0 = no limit)
- allow-unfinalized-queries: Allows queries for unfinalized/pending blocks
-
- >
- )}
-
- {enableDebugTrace && (
- <>
-
Debug Settings:
-
- eth-apis: Extended APIs including debug-tracer, debug-file-tracer, internal-* APIs
- admin-api-enabled: Enables administrative operations API
-
- >
- )}
-
-
-
{isCustomVM && (
@@ -619,8 +962,8 @@ export default function AvalanchegoDocker() {
Start the node using Docker:
- {
try {
const config = JSON.parse(configJson);
@@ -636,10 +979,10 @@ export default function AvalanchegoDocker() {
} catch {
return "# Error generating Docker command";
}
- })()}
+ })()}
/>
-
+
The container will read the config from ~/.avalanchego/configs/chains/{chainId}/config.json via the mounted volume.
@@ -657,33 +1000,19 @@ export default function AvalanchegoDocker() {
Monitor your node with:
+
+
-
-
- For advanced node configuration options, see the{" "}
-
- AvalancheGo configuration flags documentation
- .
-
-
-
-
-
- {nodeType === "public-rpc" && (
-
-
+
-
- )}
+ showHealthCheck={true}
+ />
+
+ )}
>
)}
@@ -697,4 +1026,12 @@ export default function AvalanchegoDocker() {
)}
);
-};
+}
+
+export default function AvalanchegoDocker() {
+ return (
+
+
+
+ );
+}
diff --git a/components/toolbox/console/layer-1/node-config.ts b/components/toolbox/console/layer-1/node-config.ts
index b5c52b741e5..3adae6e9bd7 100644
--- a/components/toolbox/console/layer-1/node-config.ts
+++ b/components/toolbox/console/layer-1/node-config.ts
@@ -13,13 +13,27 @@ export const generateChainConfig = (
minDelayTarget: number = 250,
trieCleanCache: number = 512,
trieDirtyCache: number = 512,
+ trieDirtyCommitTarget: number = 20,
+ triePrefetcherParallelism: number = 16,
snapshotCache: number = 256,
commitInterval: number = 4096,
+ stateSyncServerTrieCache: number = 64,
rpcGasCap: number = 50000000,
+ rpcTxFeeCap: number = 100,
apiMaxBlocksPerRequest: number = 0,
allowUnfinalizedQueries: boolean = false,
+ batchRequestLimit: number = 1000,
+ batchResponseMaxSize: number = 25000000,
acceptedCacheSize: number = 32,
- transactionHistory: number = 0
+ transactionHistory: number = 0,
+ stateSyncEnabled: boolean = false,
+ skipTxIndexing: boolean = false,
+ preimagesEnabled: boolean = false,
+ localTxsEnabled: boolean = false,
+ pushGossipNumValidators: number = 100,
+ pushGossipPercentStake: number = 0.9,
+ continuousProfilerDir: string = "",
+ continuousProfilerFrequency: string = "15m"
) => {
const isRPC = nodeType === 'public-rpc';
@@ -29,17 +43,41 @@ export const generateChainConfig = (
"commit-interval": commitInterval,
"trie-clean-cache": trieCleanCache,
"trie-dirty-cache": trieDirtyCache,
+ "trie-dirty-commit-target": trieDirtyCommitTarget,
+ "trie-prefetcher-parallelism": triePrefetcherParallelism,
"snapshot-cache": snapshotCache,
+ "state-sync-server-trie-cache": stateSyncServerTrieCache,
"rpc-gas-cap": rpcGasCap,
+ "rpc-tx-fee-cap": rpcTxFeeCap,
"log-level": enableDebugTrace ? "debug" : "info",
"metrics-expensive-enabled": true,
"accepted-cache-size": acceptedCacheSize,
- "min-delay-target": minDelayTarget
+ "min-delay-target": minDelayTarget,
+ "batch-request-limit": batchRequestLimit,
+ "batch-response-max-size": batchResponseMaxSize
};
// Add warp API for cross-chain messaging (enabled by default for L1s)
config["warp-api-enabled"] = true;
+ // State sync configuration
+ config["state-sync-enabled"] = stateSyncEnabled;
+
+ // Transaction indexing
+ if (skipTxIndexing) {
+ config["skip-tx-indexing"] = true;
+ } else if (transactionHistory > 0) {
+ config["transaction-history"] = transactionHistory;
+ }
+
+ // Transaction settings
+ if (preimagesEnabled) {
+ config["preimages-enabled"] = true;
+ }
+ if (localTxsEnabled) {
+ config["local-txs-enabled"] = true;
+ }
+
// Configure APIs based on node type
if (enableDebugTrace) {
config["eth-apis"] = [
@@ -80,9 +118,16 @@ export const generateChainConfig = (
config["allow-unfinalized-queries"] = allowUnfinalizedQueries;
}
- // Transaction history (0 = no limit, keeps all tx indices)
- if (transactionHistory > 0) {
- config["transaction-history"] = transactionHistory;
+ // Gossip settings (primarily for validators)
+ if (nodeType === 'validator') {
+ config["push-gossip-num-validators"] = pushGossipNumValidators;
+ config["push-gossip-percent-stake"] = pushGossipPercentStake;
+ }
+
+ // Continuous profiling (if enabled)
+ if (continuousProfilerDir) {
+ config["continuous-profiler-dir"] = continuousProfilerDir;
+ config["continuous-profiler-frequency"] = continuousProfilerFrequency;
}
return config;
@@ -141,10 +186,10 @@ export const generateConfigFileCommand = (
) => {
const configJson = JSON.stringify(chainConfig, null, 2);
const configPath = `~/.avalanchego/configs/chains/${blockchainId}`;
-
+
// Escape single quotes in the JSON for the shell command
const escapedJson = configJson.replace(/'/g, "'\\''");
-
+
return `# Create the chain config directory and file
mkdir -p ${configPath} && cat > ${configPath}/config.json << 'EOF'
${configJson}
diff --git a/components/toolbox/console/layer-1/useNodeConfigHighlighting.ts b/components/toolbox/console/layer-1/useNodeConfigHighlighting.ts
new file mode 100644
index 00000000000..3cdba795c99
--- /dev/null
+++ b/components/toolbox/console/layer-1/useNodeConfigHighlighting.ts
@@ -0,0 +1,78 @@
+import { useMemo } from 'react';
+
+export function useNodeConfigHighlighting(highlightPath: string | null, configJson: string) {
+ return useMemo(() => {
+ if (!highlightPath || !configJson) return [];
+
+ const lines = configJson.split('\n');
+ const highlighted: number[] = [];
+
+ // Map of highlight paths to their JSON keys
+ const fieldMap: Record
= {
+ 'pruning': 'pruning-enabled',
+ 'minDelayTarget': 'min-delay-target',
+ 'trieCleanCache': 'trie-clean-cache',
+ 'trieDirtyCache': 'trie-dirty-cache',
+ 'trieDirtyCommitTarget': 'trie-dirty-commit-target',
+ 'triePrefetcherParallelism': 'trie-prefetcher-parallelism',
+ 'snapshotCache': 'snapshot-cache',
+ 'acceptedCacheSize': 'accepted-cache-size',
+ 'stateSyncServerTrieCache': 'state-sync-server-trie-cache',
+ 'commitInterval': 'commit-interval',
+ 'rpcGasCap': 'rpc-gas-cap',
+ 'rpcTxFeeCap': 'rpc-tx-fee-cap',
+ 'transactionHistory': 'transaction-history',
+ 'apiMaxBlocksPerRequest': 'api-max-blocks-per-request',
+ 'allowUnfinalizedQueries': 'allow-unfinalized-queries',
+ 'batchRequestLimit': 'batch-request-limit',
+ 'batchResponseMaxSize': 'batch-response-max-size',
+ 'skipTxIndexing': 'skip-tx-indexing',
+ 'stateSyncEnabled': 'state-sync-enabled',
+ 'preimagesEnabled': 'preimages-enabled',
+ 'localTxsEnabled': 'local-txs-enabled',
+ 'pushGossipNumValidators': 'push-gossip-num-validators',
+ 'pushGossipPercentStake': 'push-gossip-percent-stake',
+ 'continuousProfilerDir': 'continuous-profiler-dir',
+ 'continuousProfilerFrequency': 'continuous-profiler-frequency',
+ 'logLevel': 'log-level',
+ 'warpApi': 'warp-api-enabled',
+ 'ethApis': 'eth-apis',
+ 'adminApi': 'admin-api-enabled',
+ 'metricsExpensive': 'metrics-expensive-enabled',
+ // Additional fields that might be in config
+ 'apiMaxDuration': 'api-max-duration'
+ };
+
+ const fieldName = fieldMap[highlightPath];
+ if (fieldName) {
+ const searchKey = typeof fieldName === 'string' ? fieldName : fieldName[0];
+ const idx = lines.findIndex(line => line.includes(`"${searchKey}"`));
+ if (idx >= 0) {
+ highlighted.push(idx + 1);
+
+ // For arrays, highlight multiple lines
+ if (searchKey === 'eth-apis') {
+ let bracketCount = 0;
+ let inArray = false;
+ for (let i = idx; i < lines.length && i < idx + 30; i++) {
+ const line = lines[i];
+ if (line.includes('[')) {
+ inArray = true;
+ bracketCount++;
+ }
+ if (inArray) {
+ highlighted.push(i + 1);
+ if (line.includes(']')) {
+ bracketCount--;
+ if (bracketCount === 0) break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return [...new Set(highlighted)];
+ }, [highlightPath, configJson]);
+}
+
From 360b8d80492570384ac3776d620825c8443deb5b Mon Sep 17 00:00:00 2001
From: Owen
Date: Mon, 17 Nov 2025 17:00:40 -0500
Subject: [PATCH 4/7] update config defaults
---
.../console/layer-1/AvalancheGoDockerL1.tsx | 4 +-
.../toolbox/console/layer-1/node-config.ts | 128 ++++++++++++++----
2 files changed, 100 insertions(+), 32 deletions(-)
diff --git a/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx b/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx
index fcfbfdf6f3d..c9ed95c543a 100644
--- a/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx
+++ b/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx
@@ -48,7 +48,7 @@ function AvalanchegoDockerInner() {
const [rpcTxFeeCap, setRpcTxFeeCap] = useState(100);
const [apiMaxBlocksPerRequest, setApiMaxBlocksPerRequest] = useState(0);
const [allowUnfinalizedQueries, setAllowUnfinalizedQueries] = useState(false);
- const [batchRequestLimit, setBatchRequestLimit] = useState(1000);
+ const [batchRequestLimit, setBatchRequestLimit] = useState(0); // 0 = no limit (default)
const [batchResponseMaxSize, setBatchResponseMaxSize] = useState(25000000);
// State and history
@@ -237,7 +237,7 @@ function AvalanchegoDockerInner() {
setRpcTxFeeCap(100);
setApiMaxBlocksPerRequest(0);
setAllowUnfinalizedQueries(false);
- setBatchRequestLimit(1000);
+ setBatchRequestLimit(0);
setBatchResponseMaxSize(25000000);
setAcceptedCacheSize(32);
setTransactionHistory(0);
diff --git a/components/toolbox/console/layer-1/node-config.ts b/components/toolbox/console/layer-1/node-config.ts
index 3adae6e9bd7..e2de06162e9 100644
--- a/components/toolbox/console/layer-1/node-config.ts
+++ b/components/toolbox/console/layer-1/node-config.ts
@@ -2,8 +2,35 @@
import { SUBNET_EVM_VM_ID } from '@/constants/console';
import { getContainerVersions } from '@/components/toolbox/utils/containerVersions';
+// Subnet-EVM default configuration values
+// Reference: https://build.avax.network/docs/nodes/chain-configs/subnet-evm
+const SUBNET_EVM_DEFAULTS = {
+ "pruning-enabled": true,
+ "commit-interval": 4096,
+ "trie-clean-cache": 512,
+ "trie-dirty-cache": 512,
+ "trie-dirty-commit-target": 20,
+ "trie-prefetcher-parallelism": 16,
+ "snapshot-cache": 256,
+ "state-sync-server-trie-cache": 64,
+ "rpc-gas-cap": 50000000,
+ "rpc-tx-fee-cap": 100,
+ "log-level": "info",
+ "metrics-expensive-enabled": false,
+ "accepted-cache-size": 32,
+ "batch-request-limit": 0,
+ "batch-response-max-size": 25000000,
+ "state-sync-enabled": false,
+ "allow-unfinalized-queries": false,
+ "api-max-duration": 0,
+ "api-max-blocks-per-request": 0,
+ // Default eth-apis
+ "eth-apis": ["eth", "eth-filter", "net", "web3", "internal-eth", "internal-blockchain", "internal-transaction"],
+};
+
/**
* Generates the Subnet-EVM chain configuration
+ * Only includes values that differ from defaults
* This configuration is saved to ~/.avalanchego/configs/chains//config.json
*/
export const generateChainConfig = (
@@ -22,7 +49,7 @@ export const generateChainConfig = (
rpcTxFeeCap: number = 100,
apiMaxBlocksPerRequest: number = 0,
allowUnfinalizedQueries: boolean = false,
- batchRequestLimit: number = 1000,
+ batchRequestLimit: number = 0,
batchResponseMaxSize: number = 25000000,
acceptedCacheSize: number = 32,
transactionHistory: number = 0,
@@ -36,41 +63,74 @@ export const generateChainConfig = (
continuousProfilerFrequency: string = "15m"
) => {
const isRPC = nodeType === 'public-rpc';
+ const config: any = {};
- // Base configuration for all nodes
- const config: any = {
- "pruning-enabled": pruningEnabled,
- "commit-interval": commitInterval,
- "trie-clean-cache": trieCleanCache,
- "trie-dirty-cache": trieDirtyCache,
- "trie-dirty-commit-target": trieDirtyCommitTarget,
- "trie-prefetcher-parallelism": triePrefetcherParallelism,
- "snapshot-cache": snapshotCache,
- "state-sync-server-trie-cache": stateSyncServerTrieCache,
- "rpc-gas-cap": rpcGasCap,
- "rpc-tx-fee-cap": rpcTxFeeCap,
- "log-level": enableDebugTrace ? "debug" : "info",
- "metrics-expensive-enabled": true,
- "accepted-cache-size": acceptedCacheSize,
- "min-delay-target": minDelayTarget,
- "batch-request-limit": batchRequestLimit,
- "batch-response-max-size": batchResponseMaxSize
+ // Helper function to add config only if it differs from default
+ const addIfNotDefault = (key: string, value: any, defaultValue?: any) => {
+ const defaultVal = defaultValue !== undefined ? defaultValue : SUBNET_EVM_DEFAULTS[key as keyof typeof SUBNET_EVM_DEFAULTS];
+
+ // For arrays, do a deep comparison
+ if (Array.isArray(value) && Array.isArray(defaultVal)) {
+ if (JSON.stringify(value) !== JSON.stringify(defaultVal)) {
+ config[key] = value;
+ }
+ } else if (value !== defaultVal) {
+ config[key] = value;
+ }
};
- // Add warp API for cross-chain messaging (enabled by default for L1s)
+ // Always include pruning-enabled for explicitness in L1 node setup
+ config["pruning-enabled"] = pruningEnabled;
+
+ // Cache settings - only add if different from defaults
+ addIfNotDefault("trie-clean-cache", trieCleanCache);
+ addIfNotDefault("trie-dirty-cache", trieDirtyCache);
+ addIfNotDefault("trie-dirty-commit-target", trieDirtyCommitTarget);
+ addIfNotDefault("trie-prefetcher-parallelism", triePrefetcherParallelism);
+ addIfNotDefault("snapshot-cache", snapshotCache);
+ addIfNotDefault("state-sync-server-trie-cache", stateSyncServerTrieCache);
+ addIfNotDefault("accepted-cache-size", acceptedCacheSize);
+ addIfNotDefault("commit-interval", commitInterval);
+
+ // Performance settings
+ addIfNotDefault("rpc-gas-cap", rpcGasCap);
+ addIfNotDefault("rpc-tx-fee-cap", rpcTxFeeCap);
+
+ // Logging - only add if debug is enabled
+ if (enableDebugTrace) {
+ config["log-level"] = "debug";
+ }
+
+ // Metrics - only add if enabled (default is false)
+ if (true) { // We always want expensive metrics enabled
+ config["metrics-expensive-enabled"] = true;
+ }
+
+ // Min delay target - only add if non-zero (default is 0, meaning no minimum delay)
+ if (minDelayTarget > 0) {
+ config["min-delay-target"] = minDelayTarget;
+ }
+
+ // Batch limits - only add if different from defaults
+ addIfNotDefault("batch-request-limit", batchRequestLimit);
+ addIfNotDefault("batch-response-max-size", batchResponseMaxSize);
+
+ // Warp API - typically enabled for L1s, but not a default for all Subnet-EVM chains
config["warp-api-enabled"] = true;
- // State sync configuration
- config["state-sync-enabled"] = stateSyncEnabled;
+ // State sync - only add if enabled
+ if (stateSyncEnabled) {
+ config["state-sync-enabled"] = true;
+ }
- // Transaction indexing
+ // Transaction indexing - only add if non-default
if (skipTxIndexing) {
config["skip-tx-indexing"] = true;
} else if (transactionHistory > 0) {
config["transaction-history"] = transactionHistory;
}
- // Transaction settings
+ // Transaction settings - only add if enabled
if (preimagesEnabled) {
config["preimages-enabled"] = true;
}
@@ -79,6 +139,7 @@ export const generateChainConfig = (
}
// Configure APIs based on node type
+ // Always include eth-apis for explicitness in L1 node setup
if (enableDebugTrace) {
config["eth-apis"] = [
"eth",
@@ -99,7 +160,8 @@ export const generateChainConfig = (
];
config["admin-api-enabled"] = true;
} else {
- // Standard APIs (includes internal APIs required for basic eth methods)
+ // Include standard APIs explicitly for L1 nodes (even though these are defaults)
+ // This makes the configuration more explicit and easier to understand
config["eth-apis"] = [
"eth",
"eth-filter",
@@ -113,18 +175,24 @@ export const generateChainConfig = (
// RPC-specific settings
if (isRPC) {
- config["api-max-duration"] = 0; // No time limit
- config["api-max-blocks-per-request"] = apiMaxBlocksPerRequest;
- config["allow-unfinalized-queries"] = allowUnfinalizedQueries;
+ // api-max-duration: 0 is default (no time limit), already default so we don't need to add
+ // api-max-blocks-per-request: 0 is default (no limit)
+ addIfNotDefault("api-max-blocks-per-request", apiMaxBlocksPerRequest);
+
+ // Only add if enabled (default is false)
+ if (allowUnfinalizedQueries) {
+ config["allow-unfinalized-queries"] = true;
+ }
}
- // Gossip settings (primarily for validators)
+ // Gossip settings (primarily for validators) - only add if non-default
if (nodeType === 'validator') {
+ // These don't have documented defaults, so we always add them for validators
config["push-gossip-num-validators"] = pushGossipNumValidators;
config["push-gossip-percent-stake"] = pushGossipPercentStake;
}
- // Continuous profiling (if enabled)
+ // Continuous profiling - only add if enabled
if (continuousProfilerDir) {
config["continuous-profiler-dir"] = continuousProfilerDir;
config["continuous-profiler-frequency"] = continuousProfilerFrequency;
From 1377f54dea34b536898a8c43fb5e913c037ea99e Mon Sep 17 00:00:00 2001
From: Owen
Date: Tue, 18 Nov 2025 14:28:41 -0500
Subject: [PATCH 5/7] nits
---
.../console/layer-1/AvalancheGoDockerL1.tsx | 155 ++++++++++++------
.../toolbox/console/layer-1/node-config.ts | 18 +-
2 files changed, 119 insertions(+), 54 deletions(-)
diff --git a/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx b/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx
index c9ed95c543a..b7fa57934f6 100644
--- a/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx
+++ b/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx
@@ -28,7 +28,9 @@ function AvalanchegoDockerInner() {
const [nodeType, setNodeType] = useState<"validator" | "public-rpc">("validator");
const [domain, setDomain] = useState("");
const [enableDebugTrace, setEnableDebugTrace] = useState(false);
+ const [adminApiEnabled, setAdminApiEnabled] = useState(false);
const [pruningEnabled, setPruningEnabled] = useState(true);
+ const [logLevel, setLogLevel] = useState("info");
const [subnetIdError, setSubnetIdError] = useState(null);
const [selectedRPCBlockchainId, setSelectedRPCBlockchainId] = useState("");
const [minDelayTarget, setMinDelayTarget] = useState(250);
@@ -90,7 +92,9 @@ function AvalanchegoDockerInner() {
const config = generateChainConfig(
nodeType,
enableDebugTrace,
+ adminApiEnabled,
pruningEnabled,
+ logLevel,
minDelayTarget,
trieCleanCache,
trieDirtyCache,
@@ -120,14 +124,16 @@ function AvalanchegoDockerInner() {
} catch (error) {
setConfigJson(`Error: ${(error as Error).message}`);
}
- }, [subnetId, chainId, nodeType, enableDebugTrace, pruningEnabled, blockchainInfo, minDelayTarget, trieCleanCache, trieDirtyCache, trieDirtyCommitTarget, triePrefetcherParallelism, snapshotCache, commitInterval, stateSyncServerTrieCache, rpcGasCap, rpcTxFeeCap, apiMaxBlocksPerRequest, allowUnfinalizedQueries, batchRequestLimit, batchResponseMaxSize, acceptedCacheSize, transactionHistory, stateSyncEnabled, skipTxIndexing, preimagesEnabled, localTxsEnabled, pushGossipNumValidators, pushGossipPercentStake, continuousProfilerDir, continuousProfilerFrequency]);
+ }, [subnetId, chainId, nodeType, enableDebugTrace, adminApiEnabled, pruningEnabled, logLevel, blockchainInfo, minDelayTarget, trieCleanCache, trieDirtyCache, trieDirtyCommitTarget, triePrefetcherParallelism, snapshotCache, commitInterval, stateSyncServerTrieCache, rpcGasCap, rpcTxFeeCap, apiMaxBlocksPerRequest, allowUnfinalizedQueries, batchRequestLimit, batchResponseMaxSize, acceptedCacheSize, transactionHistory, stateSyncEnabled, skipTxIndexing, preimagesEnabled, localTxsEnabled, pushGossipNumValidators, pushGossipPercentStake, continuousProfilerDir, continuousProfilerFrequency]);
useEffect(() => {
if (nodeType === "validator") {
// Validator node defaults - optimized for block production
setDomain("");
setEnableDebugTrace(false);
+ setAdminApiEnabled(false);
setPruningEnabled(true);
+ setLogLevel("info");
setMinDelayTarget(250); // Fast block times for L1
setAllowUnfinalizedQueries(false);
// Standard cache sizes for validators
@@ -138,6 +144,8 @@ function AvalanchegoDockerInner() {
setTransactionHistory(0); // Keep all tx history by default
} else if (nodeType === "public-rpc") {
// RPC node defaults - optimized for query performance
+ setPruningEnabled(false); // RPC nodes typically need full history
+ setLogLevel("info");
setAllowUnfinalizedQueries(true); // Enable real-time queries
// Larger caches for better RPC performance
setTrieCleanCache(1024); // 2x for better read performance
@@ -221,7 +229,9 @@ function AvalanchegoDockerInner() {
setNodeType("validator");
setDomain("");
setEnableDebugTrace(false);
+ setAdminApiEnabled(false);
setPruningEnabled(true);
+ setLogLevel("info");
setSubnetIdError(null);
setSelectedRPCBlockchainId("");
setMinDelayTarget(250);
@@ -312,6 +322,85 @@ function AvalanchegoDockerInner() {
+
setHighlightPath('logLevel')} onMouseLeave={clearHighlight}>
+
+ Log Level
+
+
setLogLevel(e.target.value)}
+ onFocus={() => setHighlightPath('logLevel')}
+ onBlur={clearHighlight}
+ className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
+ >
+ Off - No logs
+ Fatal - Only fatal errors
+ Error - Recoverable errors
+ Warn - Warnings
+ Info - Status updates (default)
+ Trace - Container job results
+ Debug - Debugging information
+ Verbo - Verbose output
+
+
+ Controls the verbosity of node logs
+
+
+ {nodeType === "validator" && (
+
setHighlightPath('minDelayTarget')} onMouseLeave={clearHighlight}>
+
+ Min Delay Target (ms)
+
+
{
+ const value = Math.min(2000, Math.max(0, parseInt(e.target.value) || 0));
+ setMinDelayTarget(value);
+ }}
+ onFocus={() => setHighlightPath('minDelayTarget')}
+ onBlur={clearHighlight}
+ min="0"
+ max="2000"
+ className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
+ />
+
+ The minimum delay between blocks (in milliseconds). Maximum: 2000ms. Default: 250ms.
+
+
+ )}
+
setHighlightPath('pruning')} onMouseLeave={clearHighlight}>
+
+ setPruningEnabled(e.target.checked)}
+ className="rounded"
+ />
+ Enable Pruning
+
+
+ {nodeType === "validator"
+ ? "Recommended for validators. Reduces disk usage by removing old state data."
+ : "Not recommended for RPC nodes that need full historical data."}
+
+
+
+
setHighlightPath('adminApi')} onMouseLeave={clearHighlight}>
+
+ setAdminApiEnabled(e.target.checked)}
+ className="rounded"
+ />
+ Enable Admin API
+
+
+ Enables administrative APIs. Only enable if needed and secured.
+
+
+
{nodeType === "public-rpc" && (
<>
setHighlightPath('ethApis')} onMouseLeave={clearHighlight}>
@@ -324,18 +413,9 @@ function AvalanchegoDockerInner() {
/>
Enable Debug Trace
-
-
-
setHighlightPath('pruning')} onMouseLeave={clearHighlight}>
-
- setPruningEnabled(e.target.checked)}
- className="rounded"
- />
- Enable Pruning
-
+
+ Enables debug APIs and detailed tracing capabilities
+
{subnet && subnet.blockchains && subnet.blockchains.length > 1 && (
@@ -362,30 +442,6 @@ function AvalanchegoDockerInner() {
>
)}
- {nodeType === "validator" && (
-
setHighlightPath('minDelayTarget')} onMouseLeave={clearHighlight}>
-
- Min Delay Target (ms)
-
-
{
- const value = Math.min(2000, Math.max(0, parseInt(e.target.value) || 0));
- setMinDelayTarget(value);
- }}
- onFocus={() => setHighlightPath('minDelayTarget')}
- onBlur={clearHighlight}
- min="0"
- max="2000"
- className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
- />
-
- The minimum delay between blocks (in milliseconds). Maximum: 2000ms. Default: 250ms.
-
-
- )}
-
{/* Advanced Settings */}
-
- {isCustomVM && (
-
-
- This blockchain uses a non-standard Virtual Machine ID. The Docker command includes VM aliases mapping.
-
-
- VM ID: {blockchainInfo.vmId}
- Aliases to: {SUBNET_EVM_VM_ID}
-
-
- )}
-
@@ -986,7 +1029,19 @@ function AvalanchegoDockerInner() {
The container will read the config from ~/.avalanchego/configs/chains/{chainId}/config.json via the mounted volume.
+
+ {isCustomVM && (
+
+
+ This blockchain uses a non-standard Virtual Machine ID. The Docker command includes VM aliases mapping.
+
+
+ VM ID: {blockchainInfo.vmId}
+ Aliases to: {SUBNET_EVM_VM_ID}
+
+
+ )}
To run multiple nodes on the same machine, ensure each node has:
diff --git a/components/toolbox/console/layer-1/node-config.ts b/components/toolbox/console/layer-1/node-config.ts
index e2de06162e9..3edb708bbb1 100644
--- a/components/toolbox/console/layer-1/node-config.ts
+++ b/components/toolbox/console/layer-1/node-config.ts
@@ -36,7 +36,9 @@ const SUBNET_EVM_DEFAULTS = {
export const generateChainConfig = (
nodeType: 'validator' | 'public-rpc',
enableDebugTrace: boolean = false,
+ adminApiEnabled: boolean = false,
pruningEnabled: boolean = true,
+ logLevel: string = "info",
minDelayTarget: number = 250,
trieCleanCache: number = 512,
trieDirtyCache: number = 512,
@@ -96,9 +98,9 @@ export const generateChainConfig = (
addIfNotDefault("rpc-gas-cap", rpcGasCap);
addIfNotDefault("rpc-tx-fee-cap", rpcTxFeeCap);
- // Logging - only add if debug is enabled
- if (enableDebugTrace) {
- config["log-level"] = "debug";
+ // Logging - only add if different from default (info)
+ if (logLevel !== "info") {
+ config["log-level"] = logLevel;
}
// Metrics - only add if enabled (default is false)
@@ -158,7 +160,6 @@ export const generateChainConfig = (
"debug-file-tracer",
"debug-handler"
];
- config["admin-api-enabled"] = true;
} else {
// Include standard APIs explicitly for L1 nodes (even though these are defaults)
// This makes the configuration more explicit and easier to understand
@@ -173,6 +174,15 @@ export const generateChainConfig = (
];
}
+ // Admin API - only enable if explicitly requested
+ if (adminApiEnabled) {
+ config["admin-api-enabled"] = true;
+ // Add admin to eth-apis if not already present (when debug is disabled)
+ if (!enableDebugTrace && !config["eth-apis"].includes("admin")) {
+ config["eth-apis"].push("admin");
+ }
+ }
+
// RPC-specific settings
if (isRPC) {
// api-max-duration: 0 is default (no time limit), already default so we don't need to add
From 1774b3c5f27658ed41465bcc4f7a5255ecc8e149 Mon Sep 17 00:00:00 2001
From: Owen
Date: Tue, 25 Nov 2025 15:12:01 -0600
Subject: [PATCH 6/7] expand wizard to primary network / remove target block
time from genesis wizard
---
.../toolbox/components/genesis/FeeConfig.tsx | 33 +-
.../console/layer-1/AvalancheGoDockerL1.tsx | 26 +-
.../AvalancheGoDockerPrimaryNetwork.tsx | 872 ++++++++++++++++--
components/toolbox/stores/createChainStore.ts | 2 +-
4 files changed, 821 insertions(+), 112 deletions(-)
diff --git a/components/toolbox/components/genesis/FeeConfig.tsx b/components/toolbox/components/genesis/FeeConfig.tsx
index e8871e3159c..e4acaf762f3 100644
--- a/components/toolbox/components/genesis/FeeConfig.tsx
+++ b/components/toolbox/components/genesis/FeeConfig.tsx
@@ -80,7 +80,6 @@ function FeeConfigBase({
gasLimit,
setGasLimit,
targetBlockRate,
- setTargetBlockRate,
feeConfig,
onFeeConfigChange,
validationMessages,
@@ -97,7 +96,6 @@ function FeeConfigBase({
// Local string state for smooth typing
const [gasLimitInput, setGasLimitInput] = useState(gasLimit.toString());
- const [targetBlockRateInput, setTargetBlockRateInput] = useState(targetBlockRate.toString());
const [minBaseFeeInput, setMinBaseFeeInput] = useState((feeConfig.minBaseFee / 1000000000).toString());
const [baseFeeChangeDenominatorInput, setBaseFeeChangeDenominatorInput] = useState(feeConfig.baseFeeChangeDenominator.toString());
const [minBlockGasCostInput, setMinBlockGasCostInput] = useState(feeConfig.minBlockGasCost.toString());
@@ -109,9 +107,6 @@ function FeeConfigBase({
useEffect(() => {
if (focusedField !== 'gasLimit') setGasLimitInput(gasLimit.toString());
}, [gasLimit, focusedField]);
- useEffect(() => {
- if (focusedField !== 'targetBlockRate') setTargetBlockRateInput(targetBlockRate.toString());
- }, [targetBlockRate, focusedField]);
useEffect(() => {
if (focusedField !== 'minBaseFee') setMinBaseFeeInput((feeConfig.minBaseFee / 1000000000).toString());
}, [feeConfig.minBaseFee, focusedField]);
@@ -140,14 +135,6 @@ function FeeConfigBase({
}
}, [setGasLimit]);
- const handleTargetBlockRateChange = useCallback((value: string) => {
- setTargetBlockRateInput(value);
- const parsed = parseInt(value);
- if (!isNaN(parsed)) {
- setTargetBlockRate(parsed);
- }
- }, [setTargetBlockRate]);
-
const handleMinBaseFeeChange = useCallback((value: string) => {
setMinBaseFeeInput(value);
const parsed = parseFloat(value);
@@ -181,11 +168,6 @@ function FeeConfigBase({
if (gasLimitInput === '' || isNaN(parsed)) setGasLimitInput(gasLimit.toString());
break;
}
- case 'targetBlockRate': {
- const parsed = parseInt(targetBlockRateInput);
- if (targetBlockRateInput === '' || isNaN(parsed)) setTargetBlockRateInput(targetBlockRate.toString());
- break;
- }
case 'minBaseFee': {
const parsed = parseFloat(minBaseFeeInput);
if (minBaseFeeInput === '' || isNaN(parsed)) setMinBaseFeeInput((feeConfig.minBaseFee / 1000000000).toString());
@@ -218,7 +200,7 @@ function FeeConfigBase({
}
}
setFocusedField(null);
- }, [gasLimitInput, gasLimit, targetBlockRateInput, targetBlockRate, minBaseFeeInput, feeConfig, baseFeeChangeDenominatorInput, minBlockGasCostInput, maxBlockGasCostInput, blockGasCostStepInput, targetGasInput]);
+ }, [gasLimitInput, gasLimit, minBaseFeeInput, feeConfig, baseFeeChangeDenominatorInput, minBlockGasCostInput, maxBlockGasCostInput, blockGasCostStepInput, targetGasInput]);
return (
@@ -239,19 +221,6 @@ function FeeConfigBase({
warning={validationMessages.warnings.gasLimit}
/>
-
- handleFocus('targetBlockRate')}
- onBlur={() => normalizeOnBlur('targetBlockRate')}
- placeholder="2"
- error={validationMessages.errors.blockRate}
- warning={validationMessages.warnings.blockRate}
- />
-
("info");
const [subnetIdError, setSubnetIdError] = useState(null);
const [selectedRPCBlockchainId, setSelectedRPCBlockchainId] = useState("");
- const [minDelayTarget, setMinDelayTarget] = useState(250);
+ const [minDelayTarget, setMinDelayTarget] = useState(500);
const [configJson, setConfigJson] = useState("");
// Advanced cache settings
@@ -134,7 +135,7 @@ function AvalanchegoDockerInner() {
setAdminApiEnabled(false);
setPruningEnabled(true);
setLogLevel("info");
- setMinDelayTarget(250); // Fast block times for L1
+ setMinDelayTarget(500); // Default block time for L1
setAllowUnfinalizedQueries(false);
// Standard cache sizes for validators
setTrieCleanCache(512);
@@ -234,7 +235,7 @@ function AvalanchegoDockerInner() {
setLogLevel("info");
setSubnetIdError(null);
setSelectedRPCBlockchainId("");
- setMinDelayTarget(250);
+ setMinDelayTarget(500);
setConfigJson("");
setTrieCleanCache(512);
setTrieDirtyCache(512);
@@ -272,6 +273,23 @@ function AvalanchegoDockerInner() {
githubUrl="https://github.com/ava-labs/builders-hub/edit/master/components/toolbox/console/layer-1/AvalancheGoDockerL1.tsx"
>
+
+
+
+
+ If you do not want to use Docker, you can follow the instructions{" "}
+
+ here
+
+ .
+
+
+
Select L1
@@ -365,7 +383,7 @@ function AvalanchegoDockerInner() {
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
/>
- The minimum delay between blocks (in milliseconds). Maximum: 2000ms. Default: 250ms.
+ The minimum delay between blocks (in milliseconds). Maximum: 2000ms. Default: 500ms.
)}
diff --git a/components/toolbox/console/primary-network/AvalancheGoDockerPrimaryNetwork.tsx b/components/toolbox/console/primary-network/AvalancheGoDockerPrimaryNetwork.tsx
index d4aa532151a..5afbbf8c63c 100644
--- a/components/toolbox/console/primary-network/AvalancheGoDockerPrimaryNetwork.tsx
+++ b/components/toolbox/console/primary-network/AvalancheGoDockerPrimaryNetwork.tsx
@@ -9,56 +9,203 @@ import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
import { DockerInstallation } from "@/components/toolbox/components/DockerInstallation";
import { NodeBootstrapCheck } from "@/components/toolbox/components/NodeBootstrapCheck";
import { ReverseProxySetup } from "@/components/toolbox/components/ReverseProxySetup";
-import { ConfigureNodeType } from "@/components/toolbox/components/ConfigureNodeType";
+import { Button } from "@/components/toolbox/components/Button";
+import { SyntaxHighlightedJSON } from "@/components/toolbox/components/genesis/SyntaxHighlightedJSON";
+import { GenesisHighlightProvider, useGenesisHighlight } from "@/components/toolbox/components/genesis/GenesisHighlightContext";
+import { generateChainConfig } from "@/components/toolbox/console/layer-1/node-config";
+import { useNodeConfigHighlighting } from "@/components/toolbox/console/layer-1/useNodeConfigHighlighting";
import { C_CHAIN_ID, generateDockerCommand } from "@/components/toolbox/console/layer-1/create/config";
-export default function AvalancheGoDockerPrimaryNetwork() {
+function AvalancheGoDockerPrimaryNetworkInner() {
+ const { setHighlightPath, clearHighlight, highlightPath } = useGenesisHighlight();
const [nodeType, setNodeType] = useState<"validator" | "public-rpc">("validator");
- const [rpcCommand, setRpcCommand] = useState("");
const [domain, setDomain] = useState("");
const [enableDebugTrace, setEnableDebugTrace] = useState(false);
+ const [adminApiEnabled, setAdminApiEnabled] = useState(false);
const [pruningEnabled, setPruningEnabled] = useState(true);
+ const [logLevel, setLogLevel] = useState("info");
+ const [minDelayTarget, setMinDelayTarget] = useState(1200);
+ const [configJson, setConfigJson] = useState("");
const [nodeIsReady, setNodeIsReady] = useState(false);
- const [minDelayTarget, setMinDelayTarget] = useState(null);
- const [enableMinDelay, setEnableMinDelay] = useState(false);
+
+ // Advanced cache settings
+ const [trieCleanCache, setTrieCleanCache] = useState(512);
+ const [trieDirtyCache, setTrieDirtyCache] = useState(512);
+ const [trieDirtyCommitTarget, setTrieDirtyCommitTarget] = useState(20);
+ const [triePrefetcherParallelism, setTriePrefetcherParallelism] = useState(16);
+ const [snapshotCache, setSnapshotCache] = useState(256);
+ const [commitInterval, setCommitInterval] = useState(4096);
+ const [stateSyncServerTrieCache, setStateSyncServerTrieCache] = useState(64);
+
+ // API settings
+ const [rpcGasCap, setRpcGasCap] = useState(50000000);
+ const [rpcTxFeeCap, setRpcTxFeeCap] = useState(100);
+ const [apiMaxBlocksPerRequest, setApiMaxBlocksPerRequest] = useState(0);
+ const [allowUnfinalizedQueries, setAllowUnfinalizedQueries] = useState(false);
+ const [batchRequestLimit, setBatchRequestLimit] = useState(0);
+ const [batchResponseMaxSize, setBatchResponseMaxSize] = useState(25000000);
+
+ // State and history
+ const [acceptedCacheSize, setAcceptedCacheSize] = useState(32);
+ const [transactionHistory, setTransactionHistory] = useState(0);
+ const [stateSyncEnabled, setStateSyncEnabled] = useState(false);
+ const [skipTxIndexing, setSkipTxIndexing] = useState(false);
+
+ // Transaction settings
+ const [preimagesEnabled, setPreimagesEnabled] = useState(false);
+ const [localTxsEnabled, setLocalTxsEnabled] = useState(false);
+
+ // Gossip settings (validator specific)
+ const [pushGossipNumValidators, setPushGossipNumValidators] = useState(100);
+ const [pushGossipPercentStake, setPushGossipPercentStake] = useState(0.9);
+
+ // Profiling
+ const [continuousProfilerDir, setContinuousProfilerDir] = useState("");
+ const [continuousProfilerFrequency, setContinuousProfilerFrequency] = useState("15m");
+
+ // Show advanced settings
+ const [showAdvancedSettings, setShowAdvancedSettings] = useState(false);
const { avalancheNetworkID } = useWalletStore();
const isRPC = nodeType === "public-rpc";
+ // Get highlighted lines for JSON preview
+ const highlightedLines = useNodeConfigHighlighting(highlightPath, configJson);
+
+ // Generate chain configuration JSON when parameters change
useEffect(() => {
try {
- setRpcCommand(generateDockerCommand(
- [], // No subnets for Primary Network
- isRPC,
- avalancheNetworkID,
- C_CHAIN_ID,
- "", // No custom VM ID for Primary Network
+ const config = generateChainConfig(
+ nodeType,
enableDebugTrace,
+ adminApiEnabled,
pruningEnabled,
- true, // isPrimaryNetwork = true
- isRPC ? null : (enableMinDelay ? minDelayTarget : null) // Pass minDelayTarget only for validators when enabled
- ));
+ logLevel,
+ minDelayTarget,
+ trieCleanCache,
+ trieDirtyCache,
+ trieDirtyCommitTarget,
+ triePrefetcherParallelism,
+ snapshotCache,
+ commitInterval,
+ stateSyncServerTrieCache,
+ rpcGasCap,
+ rpcTxFeeCap,
+ apiMaxBlocksPerRequest,
+ allowUnfinalizedQueries,
+ batchRequestLimit,
+ batchResponseMaxSize,
+ acceptedCacheSize,
+ transactionHistory,
+ stateSyncEnabled,
+ skipTxIndexing,
+ preimagesEnabled,
+ localTxsEnabled,
+ pushGossipNumValidators,
+ pushGossipPercentStake,
+ continuousProfilerDir,
+ continuousProfilerFrequency
+ );
+ setConfigJson(JSON.stringify(config, null, 2));
} catch (error) {
- setRpcCommand((error as Error).message);
+ setConfigJson(`Error: ${(error as Error).message}`);
}
- }, [isRPC, avalancheNetworkID, enableDebugTrace, pruningEnabled, minDelayTarget, enableMinDelay]);
+ }, [nodeType, enableDebugTrace, adminApiEnabled, pruningEnabled, logLevel, minDelayTarget, trieCleanCache, trieDirtyCache, trieDirtyCommitTarget, triePrefetcherParallelism, snapshotCache, commitInterval, stateSyncServerTrieCache, rpcGasCap, rpcTxFeeCap, apiMaxBlocksPerRequest, allowUnfinalizedQueries, batchRequestLimit, batchResponseMaxSize, acceptedCacheSize, transactionHistory, stateSyncEnabled, skipTxIndexing, preimagesEnabled, localTxsEnabled, pushGossipNumValidators, pushGossipPercentStake, continuousProfilerDir, continuousProfilerFrequency]);
useEffect(() => {
if (nodeType === "validator") {
+ // Validator node defaults
setDomain("");
setEnableDebugTrace(false);
+ setAdminApiEnabled(false);
setPruningEnabled(true);
- setMinDelayTarget(500); // Default value when enabled
- setEnableMinDelay(false); // Reset to disabled
+ setLogLevel("info");
+ setMinDelayTarget(1200);
+ setAllowUnfinalizedQueries(false);
+ setTrieCleanCache(512);
+ setTrieDirtyCache(512);
+ setSnapshotCache(256);
+ setAcceptedCacheSize(32);
+ setTransactionHistory(0);
+ } else if (nodeType === "public-rpc") {
+ // RPC node defaults
+ setPruningEnabled(false);
+ setLogLevel("info");
+ setAllowUnfinalizedQueries(true);
+ setTrieCleanCache(1024);
+ setTrieDirtyCache(1024);
+ setSnapshotCache(512);
+ setAcceptedCacheSize(64);
+ setTransactionHistory(0);
}
}, [nodeType]);
+ useEffect(() => {
+ if (!isRPC) {
+ setDomain("");
+ }
+ }, [isRPC]);
+
+ const handleReset = () => {
+ setNodeType("validator");
+ setDomain("");
+ setEnableDebugTrace(false);
+ setAdminApiEnabled(false);
+ setPruningEnabled(true);
+ setLogLevel("info");
+ setMinDelayTarget(1200);
+ setConfigJson("");
+ setTrieCleanCache(512);
+ setTrieDirtyCache(512);
+ setTrieDirtyCommitTarget(20);
+ setTriePrefetcherParallelism(16);
+ setSnapshotCache(256);
+ setCommitInterval(4096);
+ setStateSyncServerTrieCache(64);
+ setRpcGasCap(50000000);
+ setRpcTxFeeCap(100);
+ setApiMaxBlocksPerRequest(0);
+ setAllowUnfinalizedQueries(false);
+ setBatchRequestLimit(0);
+ setBatchResponseMaxSize(25000000);
+ setAcceptedCacheSize(32);
+ setTransactionHistory(0);
+ setStateSyncEnabled(false);
+ setSkipTxIndexing(false);
+ setPreimagesEnabled(false);
+ setLocalTxsEnabled(false);
+ setPushGossipNumValidators(100);
+ setPushGossipPercentStake(0.9);
+ setContinuousProfilerDir("");
+ setContinuousProfilerFrequency("15m");
+ setShowAdvancedSettings(false);
+ setNodeIsReady(false);
+ };
+
+ // Generate Docker command for Primary Network
+ const getDockerCommand = () => {
+ try {
+ return generateDockerCommand(
+ [], // No subnets for Primary Network
+ isRPC,
+ avalancheNetworkID,
+ C_CHAIN_ID,
+ "", // No custom VM ID for Primary Network
+ enableDebugTrace,
+ pruningEnabled,
+ true, // isPrimaryNetwork = true
+ nodeType === "validator" ? minDelayTarget : null
+ );
+ } catch (error) {
+ return `# Error: ${(error as Error).message}`;
+ }
+ };
+
return (
- <>
@@ -69,8 +216,7 @@ export default function AvalancheGoDockerPrimaryNetwork() {
Minimum specs: 8 vCPUs, 16GB RAM, 1TB storage
Recommended specs: 16 vCPUs, 32GB RAM, 2TB NVMe SSD
-
- If you do not have access to a server, you can also run a node for educational purposes locally. Simply select the "RPC Node (Local)" option in the next step.
+ If you do not have access to a server, you can also run a node for educational purposes locally. Simply select the "Public RPC Node" option in the next step.
@@ -91,82 +237,648 @@ export default function AvalancheGoDockerPrimaryNetwork() {
-
- {/* Min delay target for validator nodes */}
- {nodeType === "validator" && (
-
-
- {
- setEnableMinDelay(e.target.checked);
- if (e.target.checked && minDelayTarget === null) {
- setMinDelayTarget(500); // Set default when enabling
- }
- }}
- className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
- />
-
- Configure Min Delay Target
-
-
+
Configure Node Settings
- {enableMinDelay && (
-
+
+
+
+
+ Node Type
+
+ setNodeType(e.target.value as "validator" | "public-rpc")}
+ className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
+ >
+ Validator Node
+ Public RPC Node
+
+
+
+
setHighlightPath('logLevel')} onMouseLeave={clearHighlight}>
+
+ Log Level
+
+
setLogLevel(e.target.value)}
+ onFocus={() => setHighlightPath('logLevel')}
+ onBlur={clearHighlight}
+ className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
+ >
+ Off - No logs
+ Fatal - Only fatal errors
+ Error - Recoverable errors
+ Warn - Warnings
+ Info - Status updates (default)
+ Trace - Container job results
+ Debug - Debugging information
+ Verbo - Verbose output
+
+
+ Controls the verbosity of node logs
+
+
+
+ {nodeType === "validator" && (
+
setHighlightPath('minDelayTarget')} onMouseLeave={clearHighlight}>
Min Delay Target (ms)
{
const value = Math.min(2000, Math.max(0, parseInt(e.target.value) || 0));
setMinDelayTarget(value);
}}
+ onFocus={() => setHighlightPath('minDelayTarget')}
+ onBlur={clearHighlight}
min="0"
max="2000"
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
/>
-
- The minimum delay between blocks (in milliseconds) that this node will attempt to use when creating blocks. Maximum: 2000ms. Leave empty to keep default.
-
+
+ The minimum delay between blocks (in milliseconds). Maximum: 2000ms. Default: 1200ms.
+
+
+ )}
+
+
setHighlightPath('pruning')} onMouseLeave={clearHighlight}>
+
+ setPruningEnabled(e.target.checked)}
+ className="rounded"
+ />
+ Enable Pruning
+
+
+ {nodeType === "validator"
+ ? "Recommended for validators. Reduces disk usage by removing old state data."
+ : "Not recommended for RPC nodes that need full historical data."}
+
+
+
+ {nodeType === "public-rpc" && (
+
setHighlightPath('ethApis')} onMouseLeave={clearHighlight}>
+
+ setEnableDebugTrace(e.target.checked)}
+ className="rounded"
+ />
+ Enable Debug Trace
+
+
+ Enables debug APIs and detailed tracing capabilities
+
+
+ )}
+
+ {/* Advanced Settings */}
+
+
setShowAdvancedSettings(!showAdvancedSettings)}
+ className="flex items-center justify-between w-full text-left"
+ >
+
+ Advanced Settings
+
+
+
+
+
+
+ {showAdvancedSettings && (
+
+
+ For advanced configuration options, see the{" "}
+
+ AvalancheGo configuration
+ {" "}
+ and{" "}
+
+ C-Chain configuration
+ documentation.
+
+
+
+
Cache Settings
+
+
+
setHighlightPath('trieCleanCache')} onMouseLeave={clearHighlight}>
+
+ Trie Clean Cache (MB)
+
+ setTrieCleanCache(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('trieCleanCache')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+
+
setHighlightPath('trieDirtyCache')} onMouseLeave={clearHighlight}>
+
+ Trie Dirty Cache (MB)
+
+ setTrieDirtyCache(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('trieDirtyCache')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+
+
setHighlightPath('snapshotCache')} onMouseLeave={clearHighlight}>
+
+ Snapshot Cache (MB)
+
+ setSnapshotCache(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('snapshotCache')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+
+
setHighlightPath('acceptedCacheSize')} onMouseLeave={clearHighlight}>
+
+ Accepted Cache Size (blocks)
+
+
setAcceptedCacheSize(Math.max(1, parseInt(e.target.value) || 1))}
+ onFocus={() => setHighlightPath('acceptedCacheSize')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Depth of accepted headers and logs cache
+
+
+
+
setHighlightPath('trieDirtyCommitTarget')} onMouseLeave={clearHighlight}>
+
+ Trie Dirty Commit Target (MB)
+
+
setTrieDirtyCommitTarget(Math.max(1, parseInt(e.target.value) || 1))}
+ onFocus={() => setHighlightPath('trieDirtyCommitTarget')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Memory limit before commit
+
+
+
+
setHighlightPath('triePrefetcherParallelism')} onMouseLeave={clearHighlight}>
+
+ Trie Prefetcher Parallelism
+
+
setTriePrefetcherParallelism(Math.max(1, parseInt(e.target.value) || 1))}
+ onFocus={() => setHighlightPath('triePrefetcherParallelism')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Max concurrent disk reads
+
+
+
+
setHighlightPath('stateSyncServerTrieCache')} onMouseLeave={clearHighlight}>
+
+ State Sync Server Trie Cache (MB)
+
+
setStateSyncServerTrieCache(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('stateSyncServerTrieCache')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Trie cache for state sync server
+
+
+
+
+
+
+
Performance Settings
+
+
+
setHighlightPath('commitInterval')} onMouseLeave={clearHighlight}>
+
+ Commit Interval (blocks)
+
+
setCommitInterval(Math.max(1, parseInt(e.target.value) || 1))}
+ onFocus={() => setHighlightPath('commitInterval')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Interval to persist EVM and atomic tries
+
+
+
+
setHighlightPath('rpcGasCap')} onMouseLeave={clearHighlight}>
+
+ RPC Gas Cap
+
+
setRpcGasCap(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('rpcGasCap')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Maximum gas limit for RPC calls
+
+
+
+
setHighlightPath('rpcTxFeeCap')} onMouseLeave={clearHighlight}>
+
+ RPC Tx Fee Cap (AVAX)
+
+
setRpcTxFeeCap(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('rpcTxFeeCap')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Maximum transaction fee cap
+
+
+
+
+
+
+
API Limits
+
+
+
setHighlightPath('batchRequestLimit')} onMouseLeave={clearHighlight}>
+
+ Batch Request Limit
+
+
setBatchRequestLimit(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('batchRequestLimit')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Max batched requests (0 = no limit)
+
+
+
+
setHighlightPath('batchResponseMaxSize')} onMouseLeave={clearHighlight}>
+
+ Batch Response Max Size (bytes)
+
+
setBatchResponseMaxSize(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('batchResponseMaxSize')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Max batch response size (default: 25MB)
+
+
+
+
+
+
+
Transaction & State
+
+
+
setHighlightPath('transactionHistory')} onMouseLeave={clearHighlight}>
+
+ Transaction History (blocks)
+
+
setTransactionHistory(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('transactionHistory')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Max blocks to keep tx indices. 0 = archive mode (all history)
+
+
+
+
setHighlightPath('skipTxIndexing')} onMouseLeave={clearHighlight}>
+
+ setSkipTxIndexing(e.target.checked)}
+ onFocus={() => setHighlightPath('skipTxIndexing')}
+ onBlur={clearHighlight}
+ className="rounded"
+ />
+
+ Skip Transaction Indexing
+
+
+
+ Disable tx indexing entirely (saves disk space)
+
+
+
+
setHighlightPath('stateSyncEnabled')} onMouseLeave={clearHighlight}>
+
+ setStateSyncEnabled(e.target.checked)}
+ onFocus={() => setHighlightPath('stateSyncEnabled')}
+ onBlur={clearHighlight}
+ className="rounded"
+ />
+
+ Enable State Sync
+
+
+
+ Fast sync from state summary
+
+
+
+
setHighlightPath('preimagesEnabled')} onMouseLeave={clearHighlight}>
+
+ setPreimagesEnabled(e.target.checked)}
+ onFocus={() => setHighlightPath('preimagesEnabled')}
+ onBlur={clearHighlight}
+ className="rounded"
+ />
+
+ Enable Preimages
+
+
+
+ Record preimages (uses more disk)
+
+
+
+
setHighlightPath('localTxsEnabled')} onMouseLeave={clearHighlight}>
+
+ setLocalTxsEnabled(e.target.checked)}
+ onFocus={() => setHighlightPath('localTxsEnabled')}
+ onBlur={clearHighlight}
+ className="rounded"
+ />
+
+ Enable Local Transactions
+
+
+
+ Treat local account txs as local
+
+
+
+
+
+ {nodeType === "validator" && (
+
+
Gossip Settings (Validator)
+
+
+
setHighlightPath('pushGossipNumValidators')} onMouseLeave={clearHighlight}>
+
+ Push Gossip Num Validators
+
+
setPushGossipNumValidators(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('pushGossipNumValidators')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Number of validators to push gossip to
+
+
+
+
setHighlightPath('pushGossipPercentStake')} onMouseLeave={clearHighlight}>
+
+ Push Gossip Percent Stake
+
+
setPushGossipPercentStake(Math.min(1, Math.max(0, parseFloat(e.target.value) || 0)))}
+ onFocus={() => setHighlightPath('pushGossipPercentStake')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Percentage of total stake to gossip to (0-1)
+
+
+
+
+ )}
+
+ {isRPC && (
+
+
RPC-Specific Settings
+
+
+
setHighlightPath('apiMaxBlocksPerRequest')} onMouseLeave={clearHighlight}>
+
+ API Max Blocks Per Request
+
+
setApiMaxBlocksPerRequest(Math.max(0, parseInt(e.target.value) || 0))}
+ onFocus={() => setHighlightPath('apiMaxBlocksPerRequest')}
+ onBlur={clearHighlight}
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ 0 = no limit. Limits blocks per getLogs request
+
+
+
+
setHighlightPath('allowUnfinalizedQueries')} onMouseLeave={clearHighlight}>
+
+ setAllowUnfinalizedQueries(e.target.checked)}
+ onFocus={() => setHighlightPath('allowUnfinalizedQueries')}
+ onBlur={clearHighlight}
+ className="rounded"
+ />
+
+ Allow Unfinalized Queries
+
+
+
+ Allows queries for unfinalized/pending blocks
+
+
+
+
+ )}
+
+
+
Profiling (Optional)
+
+
+
setHighlightPath('continuousProfilerDir')} onMouseLeave={clearHighlight}>
+
+ Continuous Profiler Directory
+
+
setContinuousProfilerDir(e.target.value)}
+ onFocus={() => setHighlightPath('continuousProfilerDir')}
+ onBlur={clearHighlight}
+ placeholder="./profiles (leave empty to disable)"
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ Directory for continuous profiler output
+
+
+
+ {continuousProfilerDir && (
+
setHighlightPath('continuousProfilerFrequency')} onMouseLeave={clearHighlight}>
+
+ Profiler Frequency
+
+
setContinuousProfilerFrequency(e.target.value)}
+ onFocus={() => setHighlightPath('continuousProfilerFrequency')}
+ onBlur={clearHighlight}
+ placeholder="15m"
+ className="w-full px-2 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-md dark:bg-gray-700 dark:text-white"
+ />
+
+ How often to create profiles (e.g., 15m, 1h)
+
+
+ )}
+
+
+
+ )}
+
+
+
+ {/* Configuration Preview */}
+
+
+
+
Configuration Preview
+
+
+ {configJson && !configJson.startsWith("Error:") ? (
+
+ ) : (
+
+ {configJson.startsWith("Error:") ? configJson : "Configure your node to see the chain config"}
)}
- )}
-
+
+
+
- Start AvalancheGo Node
- Run the following Docker command to start your Primary Network node:
+ Run Docker Command
+
+ Run the following Docker command to start your Primary Network node:
+
-
+
-
+
- To run multiple validator nodes on the same machine, ensure each node has:
-
+ To run multiple nodes on the same machine, ensure each node has:
+
Unique container name (change --name parameter)
- Different ports (modify -p parameters)
- Separate data directories (change the local volume path ~/.avalanchego to a unique directory)
+ Different ports (modify port mappings)
+ Separate data directories (change ~/.avalanchego path)
- Example for second node: Use ports 9652/9653, container name "avago2", and data directory "~/.avalanchego2"
+ Example for second node: Use ports 9652/9653, container name "avago2", and data directory "~/.avalanchego2"
+
+
+
+ Monitor your node with:
+
- {/* Conditional steps based on node type */}
{nodeType === "public-rpc" && (
)}
-
-
{nodeType === "validator" && (
- Wait for the Node to Bootstrap
+ Wait for the Node to Bootstrap
Your node will now bootstrap and sync the Primary Network (P-Chain, X-Chain, and C-Chain). This process can take several hours to days depending on your hardware and network connection.
You can follow the process by checking the logs with the following command:
@@ -219,7 +929,6 @@ export default function AvalancheGoDockerPrimaryNetwork() {
)}
- {/* Show success message when node is ready for validator mode */}
{nodeIsReady && nodeType === "validator" && (
Node Setup Complete
@@ -246,8 +955,21 @@ export default function AvalancheGoDockerPrimaryNetwork() {
)}
-
+ {configJson && !configJson.startsWith("Error:") && (
+
+
+ Start Over
+
+
+ )}
- >
+ );
+}
+
+export default function AvalancheGoDockerPrimaryNetwork() {
+ return (
+
+
+
);
}
diff --git a/components/toolbox/stores/createChainStore.ts b/components/toolbox/stores/createChainStore.ts
index 128cb32900a..c98ce36d91d 100644
--- a/components/toolbox/stores/createChainStore.ts
+++ b/components/toolbox/stores/createChainStore.ts
@@ -9,7 +9,7 @@ const createChainInitialState = {
chainName: "",
managerAddress: "0xfacade0000000000000000000000000000000000",
genesisData: "",
- targetBlockRate: 2,
+ targetBlockRate: 1,
gasLimit: 12000000,
evmChainId: Math.floor(Math.random() * (999999 - 100000 + 1)) + 100000,
convertToL1TxId: "",
From 3df4ba72aabd7278c00a589b0a16d8c546431cd2 Mon Sep 17 00:00:00 2001
From: Owen
Date: Tue, 25 Nov 2025 15:41:58 -0600
Subject: [PATCH 7/7] dont use AVAGO_CHAIN_CONFIG_CONTENT for primary network
---
.../AvalancheGoDockerPrimaryNetwork.tsx | 96 ++++++++++++++++---
1 file changed, 81 insertions(+), 15 deletions(-)
diff --git a/components/toolbox/console/primary-network/AvalancheGoDockerPrimaryNetwork.tsx b/components/toolbox/console/primary-network/AvalancheGoDockerPrimaryNetwork.tsx
index 5afbbf8c63c..5fbda2b8d42 100644
--- a/components/toolbox/console/primary-network/AvalancheGoDockerPrimaryNetwork.tsx
+++ b/components/toolbox/console/primary-network/AvalancheGoDockerPrimaryNetwork.tsx
@@ -12,9 +12,10 @@ import { ReverseProxySetup } from "@/components/toolbox/components/ReverseProxyS
import { Button } from "@/components/toolbox/components/Button";
import { SyntaxHighlightedJSON } from "@/components/toolbox/components/genesis/SyntaxHighlightedJSON";
import { GenesisHighlightProvider, useGenesisHighlight } from "@/components/toolbox/components/genesis/GenesisHighlightContext";
-import { generateChainConfig } from "@/components/toolbox/console/layer-1/node-config";
+import { generateChainConfig, generateConfigFileCommand } from "@/components/toolbox/console/layer-1/node-config";
import { useNodeConfigHighlighting } from "@/components/toolbox/console/layer-1/useNodeConfigHighlighting";
-import { C_CHAIN_ID, generateDockerCommand } from "@/components/toolbox/console/layer-1/create/config";
+import { C_CHAIN_ID } from "@/components/toolbox/console/layer-1/create/config";
+import { getContainerVersions } from "@/components/toolbox/utils/containerVersions";
function AvalancheGoDockerPrimaryNetworkInner() {
const { setHighlightPath, clearHighlight, highlightPath } = useGenesisHighlight();
@@ -183,25 +184,53 @@ function AvalancheGoDockerPrimaryNetworkInner() {
setNodeIsReady(false);
};
- // Generate Docker command for Primary Network
+ // Generate Docker command for Primary Network (using file-based config)
const getDockerCommand = () => {
try {
- return generateDockerCommand(
- [], // No subnets for Primary Network
- isRPC,
- avalancheNetworkID,
- C_CHAIN_ID,
- "", // No custom VM ID for Primary Network
- enableDebugTrace,
- pruningEnabled,
- true, // isPrimaryNetwork = true
- nodeType === "validator" ? minDelayTarget : null
- );
+ const isTestnet = avalancheNetworkID === 5;
+ const versions = getContainerVersions(isTestnet);
+
+ const env: Record = {
+ AVAGO_PUBLIC_IP_RESOLUTION_SERVICE: "opendns",
+ AVAGO_HTTP_HOST: "0.0.0.0",
+ AVAGO_CHAIN_CONFIG_DIR: "/root/.avalanchego/configs/chains"
+ };
+
+ // Set network ID
+ if (avalancheNetworkID === 5) {
+ env.AVAGO_NETWORK_ID = "fuji";
+ }
+
+ // Configure RPC settings
+ if (isRPC) {
+ env.AVAGO_HTTP_ALLOWED_HOSTS = '"*"';
+ }
+
+ const chunks = [
+ "docker run -it -d",
+ "--name avago",
+ `-p ${isRPC ? "" : "127.0.0.1:"}9650:9650 -p 9651:9651`,
+ "-v ~/.avalanchego:/root/.avalanchego",
+ ...Object.entries(env).map(([key, value]) => `-e ${key}=${value}`),
+ `avaplatform/avalanchego:${versions['avaplatform/avalanchego']}`
+ ];
+
+ return chunks.map(chunk => ` ${chunk}`).join(" \\\n").trim();
} catch (error) {
return `# Error: ${(error as Error).message}`;
}
};
+ // Generate the config file command
+ const getConfigFileCommand = () => {
+ try {
+ const config = JSON.parse(configJson);
+ return generateConfigFileCommand(C_CHAIN_ID, config);
+ } catch {
+ return "# Error generating config file command";
+ }
+ };
+
return (
+
+ Create Configuration File
+
+ Run this command on your server to create the C-Chain configuration file:
+
+
+
+
+
+ This creates the configuration file at ~/.avalanchego/configs/chains/{C_CHAIN_ID}/config.json
+
+
+ Read the documentation for more information on the configuration options. {" "}
+
+ AvalancheGo configuration
+
+ {" "}and{" "}
+
+ C-Chain configuration
+
+
+
+
Run Docker Command
- Run the following Docker command to start your Primary Network node:
+ Start the node using Docker:
+
+ The container will read the config from ~/.avalanchego/configs/chains/{C_CHAIN_ID}/config.json via the mounted volume.
+
+
To run multiple nodes on the same machine, ensure each node has: