From f97a59bd42816c128aba005fe0cd3e6613e43f3c Mon Sep 17 00:00:00 2001 From: Taras Shchybovyk Date: Thu, 19 Mar 2026 12:55:28 -0700 Subject: [PATCH] feat(sdk): add local development environment Adds a "local" environment entry that points all HTTP APIs at localhost:4399, enabling end-to-end local development with a fake EigenCloud server and an Anvil Sepolia fork instead of real infrastructure. - LOCAL_CHAIN_ID (31337) constant for anvil - "local" environment config reusing sepolia-dev contract addresses - "local" included in available environments for dev builds - KMS keys for "local" reuse sepolia dev keys (fake server skips verification) - Environment type union in browser.ts includes "local" --- packages/sdk/src/browser.ts | 2 +- .../src/client/common/config/environment.ts | 28 +++++++++++++++++-- packages/sdk/src/client/common/utils/keys.ts | 8 ++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/packages/sdk/src/browser.ts b/packages/sdk/src/browser.ts index b381faa9..c9a8486c 100644 --- a/packages/sdk/src/browser.ts +++ b/packages/sdk/src/browser.ts @@ -251,4 +251,4 @@ export { getKMSKeysForEnvironment } from "./client/common/utils/keys"; // ============================================================================= // Re-export common types // ============================================================================= -export type Environment = "sepolia" | "sepolia-dev" | "mainnet-alpha"; +export type Environment = "sepolia" | "sepolia-dev" | "mainnet-alpha" | "local"; diff --git a/packages/sdk/src/client/common/config/environment.ts b/packages/sdk/src/client/common/config/environment.ts index 5fdfe9a6..fa03b10c 100644 --- a/packages/sdk/src/client/common/config/environment.ts +++ b/packages/sdk/src/client/common/config/environment.ts @@ -8,6 +8,7 @@ import { BillingEnvironmentConfig, EnvironmentConfig } from "../types"; // Chain IDs export const SEPOLIA_CHAIN_ID = 11155111; export const MAINNET_CHAIN_ID = 1; +export const LOCAL_CHAIN_ID = 31337; // anvil default // Common addresses across all chains export const CommonAddresses: Record = { @@ -36,6 +37,26 @@ const BILLING_ENVIRONMENTS: Record<"dev" | "prod", BillingEnvironmentConfig> = { // Chain environment configurations const ENVIRONMENTS: Record> = { + /** + * Local development environment. + * Points all HTTP APIs at localhost:4399 — run a fake EigenCloud API server + * that implements the UserAPI and BuildAPI endpoints locally. + * + * Uses the same contract addresses as sepolia-dev so that an Anvil Sepolia + * fork works out of the box: + * anvil --fork-url https://ethereum-sepolia-rpc.publicnode.com + */ + local: { + name: "local", + build: "dev", + appControllerAddress: "0xa86DC1C47cb2518327fB4f9A1627F51966c83B92" as Address, + permissionControllerAddress: ChainAddresses[SEPOLIA_CHAIN_ID].PermissionController, + erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator, + kmsServerURL: "http://localhost:4399", + userApiServerURL: "http://localhost:4399", + defaultRPCURL: "http://localhost:8545", + usdcCreditsAddress: "0xbdA3897c3A428763B59015C64AB766c288C97376" as Address, + }, "sepolia-dev": { name: "sepolia", build: "dev", @@ -103,12 +124,13 @@ export function getEnvironmentConfig(environment: string, chainID?: bigint): Env } // Determine chain ID from environment if not provided - // Both "sepolia" and "sepolia-dev" use Sepolia chain ID const resolvedChainID = chainID || (environment === "sepolia" || environment === "sepolia-dev" ? SEPOLIA_CHAIN_ID - : MAINNET_CHAIN_ID); + : environment === "local" + ? LOCAL_CHAIN_ID + : MAINNET_CHAIN_ID); return { ...env, @@ -170,7 +192,7 @@ export function getAvailableEnvironments(): string[] { const buildType = getBuildType(); if (buildType === "dev") { - return ["sepolia-dev"]; + return ["sepolia-dev", "local"]; } // prod build diff --git a/packages/sdk/src/client/common/utils/keys.ts b/packages/sdk/src/client/common/utils/keys.ts index 2d026690..368a040c 100644 --- a/packages/sdk/src/client/common/utils/keys.ts +++ b/packages/sdk/src/client/common/utils/keys.ts @@ -14,6 +14,14 @@ type BuildType = "dev" | "prod"; type KeyPair = { encryption: string; signing: string }; const KEYS = { + // Local development — reuses sepolia dev keys since the fake EigenCloud server + // does not perform KMS verification. These keys are not security-sensitive here. + local: { + dev: { + encryption: sepoliaDevEncryption, + signing: sepoliaDevSigning, + }, + }, "mainnet-alpha": { prod: { encryption: mainnetAlphaProdEncryption,