{"version":3,"file":"index.cjs","names":["fs","TypedError","TypedError","fs","spawnWithArgsAndVersion","DEFAULT_NEAR_SANDBOX_VERSION","spawnWithArgsAndVersion","TypedError","initConfigsWithVersion"],"sources":["../../src/sandbox/config.ts","../../src/sandbox/sandboxUtils.ts","../../src/sandbox/Sandbox.ts"],"sourcesContent":["import * as fs from 'fs/promises';\nimport { apply } from 'json-merge-patch';\nimport { join } from 'path';\nimport { SandboxErrors, TypedError } from '../errors';\n\n/*\n * Network-specific configurations used to modify behavior inside a chain.\n * This is so far only useable with sandbox networks since it would require\n * direct access to a node to change the config. Each network like mainnet\n * and testnet already have pre-configured settings; meanwhile sandbox can\n * have additional settings on top of them to facilitate custom behavior\n * such as sending large requests to the sandbox network.\n */\n\nexport const DEFAULT_ACCOUNT_ID = 'sandbox';\nexport const DEFAULT_PUBLIC_KEY = 'ed25519:5BGSaf6YjVm7565VzWQHNxoyEjwr3jUpRJSGjREvU9dB';\nexport const DEFAULT_PRIVATE_KEY =\n  'ed25519:3tgdk2wPraJzT4nsTuf86UX41xgPNk3MHnq8epARMdBNs29AFEztAuaQ7iHddDfXG9F2RzV1XNQYgJyAyoW51UBB';\n/**\n * 10,000 NEAR\n */\nexport const DEFAULT_BALANCE = 10000000000000000000000000000n;\n\n/*\n * Represents a genesis account in the NEAR sandbox.\n * Means it will saved as starting account in the genesis.json file.\n * accountId - The unique identifier for the account, it`s can be top-level account or sub-account.(e.g. \"alice.near\", \"alice\")\n * publicKey - The public part of the privateKey that will control the account.\n * privateKey - The private key used to sign transactions for the account.\n * balance - The initial balance of the account in yoctoNEAR.\n */\nexport class GenesisAccount {\n  accountId: string;\n  publicKey: string;\n  privateKey: string;\n  balance: bigint;\n\n  constructor(accountId: string, publicKey: string, privateKey: string, balance: bigint) {\n    this.accountId = accountId;\n    this.publicKey = publicKey;\n    this.privateKey = privateKey;\n    this.balance = balance;\n  }\n\n  /**\n   * Creates a default genesis account with predefined values.\n   * This is useful for testing and development purposes.\n   *\n   * @param accountId Optional custom account ID, defaults to DEFAULT_ACCOUNT_ID.\n   * @returns A GenesisAccount instance with default values.\n   */\n  static createDefault(accountId?: string): GenesisAccount {\n    return new GenesisAccount(\n      accountId ?? DEFAULT_ACCOUNT_ID,\n      DEFAULT_PUBLIC_KEY,\n      DEFAULT_PRIVATE_KEY,\n      DEFAULT_BALANCE,\n    );\n  }\n}\n\n/**\n * Configuration options for the NEAR sandbox environment.\n * This interface allows customization of the sandbox's behavior.\n * @property rpcPort - Port that RPC will be bound to. Will be picked randomly if not set.\n * @property netPort - Port that the network will be bound to. Will be picked randomly if not set.\n * @property additionalConfig - Additional JSON configuration to merge with the default config. Ensure that the additional properties are correct.\n * @property additionalGenesis - Additional genesis parameters to modify the genesis.json.\n * @property additionalAccounts - Additional accounts to be passed in the sandbox genesis. By default, it will create a default account with 10,000 NEAR.\n * @property nodeKey - Node key to be used by the sandbox node. If not provided, a default key will be used. Should match up with node key in genesis.json.\n * @property validatorKey - Validator key to be used by the validator. Should match up with validator key in genesis.json.\n */\nexport interface SandboxConfig {\n  rpcPort?: number;\n  netPort?: number;\n  additionalConfig?: Record<string, any>;\n  additionalGenesis?: Record<string, any>;\n  additionalAccounts?: GenesisAccount[];\n  nodeKey?: Record<string, any>;\n  validatorKey?: Record<string, any>;\n}\n\nexport async function overrideConfigs(homeDir: string, config?: SandboxConfig): Promise<void> {\n  await setSandboxGenesis(homeDir, config);\n\n  await setSandboxConfig(homeDir, config);\n  if (config?.nodeKey) {\n    await fs.writeFile(\n      join(homeDir, 'node_key.json'),\n      JSON.stringify(config.nodeKey, null, 2),\n      'utf-8',\n    );\n  }\n  if (config?.validatorKey) {\n    await fs.writeFile(\n      join(homeDir, 'validator_key.json'),\n      JSON.stringify(config.validatorKey, null, 2),\n      'utf-8',\n    );\n  }\n}\nexport async function setSandboxGenesis(homeDir: string, config?: SandboxConfig): Promise<void> {\n  // This function modifies the genesis.json file in the specified homeDir\n  await overwriteGenesis(homeDir, config);\n\n  const additionalAccountsWithDefault: GenesisAccount[] = [\n    GenesisAccount.createDefault(),\n    ...(config?.additionalAccounts ?? []),\n  ];\n  // This function create an {accountId}.json file in the homeDir for each account\n  await saveAccountsKeys(homeDir, additionalAccountsWithDefault);\n}\n\nexport async function setSandboxConfig(homeDir: string, config?: SandboxConfig): Promise<void> {\n  // get NEAR_SANDBOX_MAX_PAYLOAD_SIZE and NEAR_SANDBOX_MAX_OPEN_FILES from config or environment variables\n  // If not provided, use default values\n  const maxPayloadSize = config?.additionalGenesis?.['maxPayloadSize'] ?? 1024 * 1024 * 1024;\n\n  const maxOpenFiles = config?.additionalGenesis?.['maxOpenFiles'] ?? 3000;\n\n  // create a json with these values\n  let newJsonConfig: Record<string, any> = {\n    rpc: {\n      limits_config: {\n        json_payload_max_size: maxPayloadSize,\n      },\n    },\n    store: {\n      max_open_files: maxOpenFiles,\n    },\n  };\n\n  // if there is additionalConfig, merge it with the json\n  if (config?.additionalConfig) {\n    newJsonConfig = apply(newJsonConfig, config?.additionalConfig);\n  }\n\n  // overwrite the sandbox.json file in the homeDir\n  await overwriteSandboxConfigJson(homeDir, newJsonConfig);\n}\n\nasync function overwriteGenesis(homeDir: string, config?: SandboxConfig): Promise<void> {\n  const genesisPath = join(homeDir, 'genesis.json');\n  const genesisRaw = await fs.readFile(genesisPath, 'utf-8');\n  const genesisObj = JSON.parse(genesisRaw);\n\n  let totalSupply = BigInt(genesisObj['total_supply']);\n  if (totalSupply === null || totalSupply === undefined) {\n    throw new TypedError(\n      'Total supply not found in default genesis.json',\n      SandboxErrors.InvalidConfig,\n    );\n  }\n\n  const accountsToAdd: GenesisAccount[] = [\n    GenesisAccount.createDefault(),\n    ...(config?.additionalAccounts ?? []),\n  ];\n\n  for (const account of accountsToAdd) {\n    totalSupply += account.balance;\n  }\n  genesisObj['total_supply'] = totalSupply.toString();\n\n  if (!Array.isArray(genesisObj['records'])) {\n    throw new TypedError(\n      \"Expected 'records' to be an array in default genesis.json\",\n      SandboxErrors.InvalidConfig,\n    );\n  }\n\n  for (const acc of accountsToAdd) {\n    genesisObj['records'].push({\n      Account: {\n        account_id: acc.accountId,\n        account: {\n          amount: acc.balance.toString(),\n          locked: '0',\n          code_hash: '11111111111111111111111111111111',\n          storage_usage: 182,\n        },\n      },\n    });\n\n    genesisObj['records'].push({\n      AccessKey: {\n        account_id: acc.accountId,\n        public_key: acc.publicKey,\n        access_key: {\n          nonce: 0,\n          permission: 'FullAccess',\n        },\n      },\n    });\n  }\n\n  if (config?.additionalGenesis) {\n    apply(genesisObj, config?.additionalGenesis);\n  }\n  await fs.writeFile(genesisPath, JSON.stringify(genesisObj), 'utf-8');\n}\n\nasync function saveAccountsKeys(homeDir: string, additionalAccountsWithDefault: GenesisAccount[]) {\n  for (const account of additionalAccountsWithDefault) {\n    const keyJson = {\n      account_id: account.accountId,\n      public_key: account.publicKey,\n      private_key: account.privateKey,\n    };\n\n    const fileName = `${account.accountId}.json`;\n    const filePath = join(homeDir, fileName);\n    const keyContent = JSON.stringify(keyJson, null, 2);\n\n    await fs.writeFile(filePath, keyContent, 'utf-8');\n  }\n}\n\nasync function overwriteSandboxConfigJson(homeDir: string, jsonConfig: Record<string, any>) {\n  const sandboxPath = join(homeDir, 'config.json');\n  const sandboxRaw = await fs.readFile(sandboxPath, 'utf-8');\n  const sandboxObj = JSON.parse(sandboxRaw);\n\n  apply(sandboxObj, jsonConfig);\n  await fs.writeFile(sandboxPath, JSON.stringify(sandboxObj), 'utf-8');\n}\n","import { existsSync } from 'fs';\nimport * as fs from 'fs/promises';\nimport { readFile } from 'fs/promises';\nimport * as net from 'net';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\nimport { lock } from 'proper-lockfile';\nimport { dir } from 'tmp-promise';\nimport { spawnWithArgsAndVersion } from '../binary/binaryExecution';\nimport { DEFAULT_NEAR_SANDBOX_VERSION } from '../constants';\nimport { TcpAndLockErrors, TypedError } from '../errors';\n\nconst DEFAULT_RPC_HOST = '127.0.0.1';\n\nexport function rpcSocket(port: number): string {\n  return `${DEFAULT_RPC_HOST}:${port}`;\n}\n\nexport async function acquireOrLockPort(\n  port?: number,\n): Promise<{ port: number; lockFilePath: string }> {\n  return port ? tryAcquireSpecificPort(port) : acquireUnusedPort();\n}\n\nasync function tryAcquireSpecificPort(\n  port: number,\n): Promise<{ port: number; lockFilePath: string }> {\n  const checkedPort = await resolveAvailablePort({ port, host: DEFAULT_RPC_HOST });\n\n  if (checkedPort !== port) {\n    throw new TypedError(`Port ${port} is not available`, TcpAndLockErrors.PortNotAvailable);\n  }\n\n  const lockFilePath = await createLockFileForPort(port);\n\n  try {\n    await lock(lockFilePath);\n    return { port, lockFilePath };\n  } catch {\n    throw new TypedError(\n      `Failed to lock port ${port}. It may already be in use.`,\n      TcpAndLockErrors.LockFailed,\n    );\n  }\n}\n\nasync function acquireUnusedPort(): Promise<{ port: number; lockFilePath: string }> {\n  const errors: string[] = [];\n  const MAX_ATTEMPTS = 10;\n\n  for (let i = 0; i < MAX_ATTEMPTS; i++) {\n    try {\n      const port = await resolveAvailablePort({ port: 0, host: DEFAULT_RPC_HOST });\n      const lockFilePath = await createLockFileForPort(port);\n      await lock(lockFilePath);\n      return { port, lockFilePath };\n    } catch (error) {\n      errors.push(error instanceof Error ? error.message : String(error));\n    }\n  }\n  throw new TypedError(\n    `Failed to acquire an unused port after ${MAX_ATTEMPTS} attempts`,\n    TcpAndLockErrors.PortAcquisitionFailed,\n    new Error(errors.map((msg, i) => `Attempt ${i + 1}: ${msg}`).join('\\n')),\n  );\n}\n\n// options takes the port and host, if port is 0 os will find an available port\nasync function resolveAvailablePort(options: net.ListenOptions): Promise<number> {\n  return new Promise((resolve, reject) => {\n    const server = net.createServer();\n    server.unref();\n    server.on('error', (err) => reject(err));\n\n    server.listen(options, () => {\n      const addr = server.address();\n\n      if (typeof addr === 'object' && addr !== null && typeof addr.port === 'number') {\n        const { port } = addr;\n        server.close(() => resolve(port));\n      } else {\n        server.close();\n        reject(\n          new TypedError(\n            'Could not determine assigned port.',\n            TcpAndLockErrors.PortAcquisitionFailed,\n          ),\n        );\n      }\n    });\n  });\n}\n\nasync function createLockFileForPort(port: number): Promise<string> {\n  const lockFilePath = join(tmpdir(), `near-sandbox-port-${port}.lock`);\n\n  if (!existsSync(lockFilePath)) {\n    await fs.writeFile(lockFilePath, '');\n  }\n\n  return lockFilePath;\n}\n\nexport async function dumpStateFromPath(pathToState: string): Promise<{\n  config: Record<string, unknown>;\n  genesis: Record<string, unknown>;\n  nodeKey: Record<string, unknown>;\n  validatorKey: Record<string, unknown>;\n}> {\n  await new Promise<void>(async (resolve, reject) => {\n    const proc = await spawnWithArgsAndVersion(DEFAULT_NEAR_SANDBOX_VERSION, [\n      '--home',\n      pathToState,\n      'view-state',\n      'dump-state',\n      '--stream',\n    ]);\n    proc.on('error', reject);\n    proc.on('exit', (code) => {\n      if (code === 0) {\n        resolve();\n      } else {\n        reject(new Error(`Process exited with code ${code}`));\n      }\n    });\n  });\n\n  const [genesis, config, nodeKey, validatorKey, records] = await Promise.all([\n    readFile(join(pathToState, 'output/genesis.json'), 'utf-8').then(JSON.parse),\n    readFile(join(pathToState, 'output/config.json'), 'utf-8').then(JSON.parse),\n    readFile(join(pathToState, 'output/node_key.json'), 'utf-8').then(JSON.parse),\n    readFile(join(pathToState, 'output/validator_key.json'), 'utf-8').then(JSON.parse),\n    readFile(join(pathToState, 'output/records.json'), 'utf-8').then(JSON.parse),\n  ]);\n\n  if (!Array.isArray(genesis.records)) genesis.records = [];\n\n  genesis.records.push(...records);\n  return {\n    config,\n    genesis,\n    nodeKey,\n    validatorKey,\n  };\n}\n\nexport async function createTmpDir() {\n  const now = new Date();\n  const timestamp = `${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}_${String(now.getHours()).padStart(2, '0')}-${String(now.getMinutes()).padStart(2, '0')}`;\n  const random = Math.random().toString(36).substring(2, 8);\n  const name = `near-sandbox-${timestamp}-${random}`;\n\n  return dir({ unsafeCleanup: true, name });\n}\n","import { ChildProcess } from 'child_process';\nimport { rm } from 'fs/promises';\nimport got from 'got';\nimport { unlock } from 'proper-lockfile';\nimport { DirectoryResult } from 'tmp-promise';\nimport { initConfigsWithVersion, spawnWithArgsAndVersion } from '../binary/binaryExecution';\nimport { DEFAULT_NEAR_SANDBOX_VERSION } from '../constants';\nimport { SandboxErrors, TypedError } from '../errors';\nimport { overrideConfigs, SandboxConfig } from './config';\nimport { acquireOrLockPort, createTmpDir, dumpStateFromPath, rpcSocket } from './sandboxUtils';\n\n// Re-export for backwards compatibility\nexport { DEFAULT_NEAR_SANDBOX_VERSION };\n\ninterface StartParams {\n  config?: SandboxConfig;\n  version?: string;\n}\n/**\n * `Sandbox` provides an isolated, ephemeral NEAR blockchain environment for local testing.\n *\n * Internally, it wraps the execution of the `near-sandbox` binary with configuration options,\n * port locking, and lifecycle management. It ensures proper startup and teardown for reliable testing.\n *\n * @example\n * ```ts\n * import { Sandbox } from './sandbox';\n *\n * const sandbox = await Sandbox.start({\n *   config: {\n *     rpcPort: 3030,\n *     additionalGenesis: { epoch_length: 250 },\n *   }\n * });\n *\n * console.log('Sandbox running at', sandbox.rpcUrl);\n * // Use the sandbox...\n * await sandbox.tearDown(true); // Cleans up temp dir and releases ports\n * ```\n *\n * @property rpcUrl - The URL of the running sandbox's RPC endpoint.(e.g. \"http://127.0.0.1:{port}\")\n * @property homeDir - The path to the temporary home directory used by the sandbox.\n * This directory contains all the sandbox state, configuration and accounts keys.\n * @property rpcPortLockPath - Path to the lock file that prevents other processes from using the same RPC port until this sandbox is started.\n * @property netPortLockPath - Path to the lock file for the network port.\n */\nexport class Sandbox {\n  public readonly rpcUrl: string;\n  public readonly homeDir: string;\n  public readonly rpcPortLockPath: string;\n  public readonly netPortLockPath: string;\n  private childProcess: ChildProcess;\n\n  private constructor(\n    rpcUrl: string,\n    homeDir: string,\n    childProcess: ChildProcess,\n    rpcPortLock: string,\n    netPortLock: string,\n  ) {\n    this.rpcUrl = rpcUrl;\n    this.homeDir = homeDir;\n    this.rpcPortLockPath = rpcPortLock;\n    this.netPortLockPath = netPortLock;\n    this.childProcess = childProcess;\n  }\n\n  /**\n   * Launch a sandbox environment.\n   *\n   * Downloads the appropriate binary version (if not cached), locks two available ports (RPC & network),\n   * generates a temporary home directory, and spawns the `neard-sandbox` binary with runtime args.\n   *\n   * @param params Configuration options:\n   *   - `config` - Optional sandbox configuration like RPC port, additional genesis data, accounts etc.\n   *   - `version` - Optional NEAR sandbox binary version.\n   *\n   * @returns A ready-to-use `Sandbox` instance with `.rpcUrl` and `.homeDir` available.\n   *\n   * @throws {TypedError} if the sandbox fails to start, ports cannot be locked, or config setup fails.\n   */\n  static async start(params: StartParams): Promise<Sandbox> {\n    const config: SandboxConfig = params.config || {};\n    const version: string = params.version || DEFAULT_NEAR_SANDBOX_VERSION;\n    // Ensure Binary downloaded with specified version\n    // Initialize tmp directory with the specified version\n    // get tmp directory with default configs\n    const tmpDir = await this.initConfigsWithVersion(version);\n    // get ports\n    const { port: rpcPort, lockFilePath: rpcPortLock } = await acquireOrLockPort(config?.rpcPort);\n    const { port: netPort, lockFilePath: netPortLock } = await acquireOrLockPort(config?.netPort);\n\n    const rpcAddr = rpcSocket(rpcPort);\n    const netAddr = rpcSocket(netPort);\n    // set sandbox configs\n    await overrideConfigs(tmpDir.path, config);\n    // create options and args to spawn the process\n    const args = ['--home', tmpDir.path, 'run', '--rpc-addr', rpcAddr, '--network-addr', netAddr];\n    // spawn sandbox with the specified version and arguments, get ChildProcess\n    const childProcess = await spawnWithArgsAndVersion(version, args);\n\n    const rpcUrl = `http://${rpcAddr}`;\n\n    // Ping rpcUrl to ensure the process is ready\n    await this.waitUntilReady(rpcUrl);\n\n    return new Sandbox(rpcUrl, tmpDir.path, childProcess, rpcPortLock, netPortLock);\n  }\n\n  /**\n   * Dumps the current state of the sandbox environment.\n   * Parses next files from dumped dir: the genesis, records(that will merge to genesis), config, node_key, and validator_key.\n   *\n   * Returned files such as `genesis`, `nodeKey`, and `validatorKey` are intended to be used\n   * when running the sandbox with a specific state. These files contain the necessary configuration and keys\n   * to restore or replicate the sandbox environment.\n   * @returns An object containing the genesis, config, node key, and validator key as json files.\n   */\n  async dump(): Promise<{\n    config: Record<string, unknown>;\n    genesis: Record<string, unknown>;\n    nodeKey: Record<string, unknown>;\n    validatorKey: Record<string, unknown>;\n  }> {\n    return dumpStateFromPath(this.homeDir);\n  }\n\n  /**\n   * Destroys the running sandbox environment by:\n   * - Killing the child process, waiting for it to exit\n   * - Unlocking the previously locked ports\n   */\n  async stop(): Promise<void> {\n    this.childProcess.kill();\n\n    await new Promise((resolve) => this.childProcess.once('exit', resolve));\n    await Promise.allSettled([unlock(this.rpcPortLockPath), unlock(this.netPortLockPath)]);\n  }\n  /**\n   * Calls `stop()` to terminate the sandbox and then cleans up the home directory.\n   */\n  async tearDown(): Promise<void> {\n    await this.stop();\n    await rm(this.homeDir, { recursive: true, force: true }).catch((error) => {\n      throw new TypedError(\n        `Sandbox teardown encountered errors`,\n        SandboxErrors.TearDownFailed,\n        error instanceof Error ? error : new Error(String(error)),\n      );\n    });\n  }\n\n  private static async initConfigsWithVersion(version: string): Promise<DirectoryResult> {\n    const tmpDir = await createTmpDir();\n    await initConfigsWithVersion(version, tmpDir.path);\n    return tmpDir;\n  }\n\n  private static async waitUntilReady(rpcUrl: string) {\n    const timeoutSecs = parseInt(process.env['NEAR_RPC_TIMEOUT_SECS'] || '10');\n    const attempts = timeoutSecs * 2;\n    let lastError: unknown = null;\n    for (let i = 0; i < attempts; i++) {\n      try {\n        const response = await got(`${rpcUrl}/status`, { throwHttpErrors: false });\n        if (response.statusCode >= 200 && response.statusCode < 300) {\n          return;\n        }\n      } catch (error) {\n        lastError = error;\n      }\n      await new Promise((resolve) => setTimeout(resolve, 500));\n    }\n    throw new TypedError(\n      'Sandbox failed to become ready within the timeout period.',\n      SandboxErrors.RunFailed,\n      lastError instanceof Error ? lastError : new Error(String(lastError)),\n    );\n  }\n}\n"],"mappings":"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"}