From e787e6f17d1eb44af3d8d0013d3ac36775a847b6 Mon Sep 17 00:00:00 2001 From: Sebastian Koszuta Date: Wed, 11 Feb 2026 10:45:11 +0100 Subject: [PATCH 1/9] "start" command to spawn typeberry nodes --- bin/cli/index.ts | 2 + bin/cli/src/commands/start-command.ts | 82 +++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 bin/cli/src/commands/start-command.ts diff --git a/bin/cli/index.ts b/bin/cli/index.ts index e6814cc..f470baf 100755 --- a/bin/cli/index.ts +++ b/bin/cli/index.ts @@ -5,6 +5,7 @@ import { version } from "./package.json" with { type: "json" }; import { buildCommand } from "./src/commands/build-command"; import { createCommand } from "./src/commands/create-command"; import { deployCommand } from "./src/commands/deploy-command"; +import { startCommand } from "./src/commands/start-command"; import { testCommand } from "./src/commands/test-command"; program @@ -22,6 +23,7 @@ program.addCommand(createCommand); program.addCommand(buildCommand); program.addCommand(testCommand); program.addCommand(deployCommand); +program.addCommand(startCommand); // TODO: [MaSo] Display accual examples program.addHelpText( diff --git a/bin/cli/src/commands/start-command.ts b/bin/cli/src/commands/start-command.ts new file mode 100644 index 0000000..d8a5f5f --- /dev/null +++ b/bin/cli/src/commands/start-command.ts @@ -0,0 +1,82 @@ +import * as p from "@clack/prompts"; +import { Command } from "commander"; + +const DOCKER_IMAGE = "ghcr.io/fluffylabs/typeberry:latest"; + +/** + * Pull the latest Docker image + */ +export async function pullImage(): Promise { + const proc = Bun.spawn(["docker", "pull", "--platform=linux/amd64", DOCKER_IMAGE], { + stdout: "pipe", + stderr: "pipe", + cwd: process.cwd(), + }); + + const [stderr, exitCode] = await Promise.all([new Response(proc.stderr).text(), proc.exited]); + + if (exitCode !== 0) { + throw new Error(`Failed to pull image ${DOCKER_IMAGE} with exit code ${exitCode}: ${stderr}`); + } +} + +/** + * Spawn a Docker container to run a local Typeberry network. + */ +export async function startContainer(): Promise { + const dockerArgs: string[] = ["run", "--rm", "--entrypoint", "/bin/bash", DOCKER_IMAGE, "-c", "npm run tiny-network"]; + + const proc = Bun.spawn(["docker", ...dockerArgs], { + stdout: "inherit", + stderr: "inherit", + cwd: process.cwd(), + }); + + const cleanup = () => { + proc.kill(); + }; + + process.on("SIGINT", cleanup); + process.on("SIGTERM", cleanup); + process.on("exit", cleanup); + + await proc.exited; +} + +/** + * "Start" command definition + */ +export const startCommand = new Command("start") + .description("start a local JAM environment in a Docker container") + .addHelpText( + "after", + ` +Examples: + $ jammin start +`, + ) + .action(async () => { + p.intro("🚀 Starting local JAM network..."); + + const s = p.spinner(); + try { + s.start("Pulling latest Typeberry image..."); + await pullImage(); + s.stop("✅ Image up to date"); + + s.start("Spawning Docker container..."); + s.stop("Typeberry container output:"); + await startContainer(); + + p.outro("🏁 Local JAM network finished running."); + } catch (error) { + if (error instanceof Error) { + p.log.error(error.message); + } else { + p.log.error(String(error)); + } + + p.outro("❌ Start failed. See the output above for details."); + process.exit(1); + } + }); From f2ac410ba4086b4fbb9e46218cd08d67759708af Mon Sep 17 00:00:00 2001 From: Sebastian Koszuta Date: Fri, 20 Feb 2026 09:36:29 +0100 Subject: [PATCH 2/9] running tiny network with jammin-generated genesis.json --- bin/cli/src/commands/start-command.ts | 22 ++++++++++++++++--- .../jammin-sdk/genesis-state-generator.ts | 10 +++++---- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/bin/cli/src/commands/start-command.ts b/bin/cli/src/commands/start-command.ts index d8a5f5f..b018970 100644 --- a/bin/cli/src/commands/start-command.ts +++ b/bin/cli/src/commands/start-command.ts @@ -1,3 +1,4 @@ +import { mkdir } from "node:fs/promises"; import * as p from "@clack/prompts"; import { Command } from "commander"; @@ -8,8 +9,8 @@ const DOCKER_IMAGE = "ghcr.io/fluffylabs/typeberry:latest"; */ export async function pullImage(): Promise { const proc = Bun.spawn(["docker", "pull", "--platform=linux/amd64", DOCKER_IMAGE], { - stdout: "pipe", - stderr: "pipe", + stdout: "inherit", + stderr: "inherit", cwd: process.cwd(), }); @@ -24,7 +25,22 @@ export async function pullImage(): Promise { * Spawn a Docker container to run a local Typeberry network. */ export async function startContainer(): Promise { - const dockerArgs: string[] = ["run", "--rm", "--entrypoint", "/bin/bash", DOCKER_IMAGE, "-c", "npm run tiny-network"]; + const distPath = `${process.cwd()}/dist`; + const logsPath = `${process.cwd()}/logs`; + await mkdir(logsPath, { recursive: true }); + const dockerArgs: string[] = [ + "run", + "--rm", + "-v", + `${distPath}:/app/jammin`, + "-v", + `${logsPath}:/app/bin/jam/logs`, + "--entrypoint", + "/bin/bash", + DOCKER_IMAGE, + "-c", + "npm run tiny-network -- --config=dev --config=.chain_spec+=/app/jammin/genesis.json", + ]; const proc = Bun.spawn(["docker", ...dockerArgs], { stdout: "inherit", diff --git a/packages/jammin-sdk/genesis-state-generator.ts b/packages/jammin-sdk/genesis-state-generator.ts index 20ad724..5ac21ee 100644 --- a/packages/jammin-sdk/genesis-state-generator.ts +++ b/packages/jammin-sdk/genesis-state-generator.ts @@ -68,10 +68,12 @@ export function toJip4Schema(genesis: Genesis) { id: genesis.id, bootnodes: genesis.bootnodes, genesis_header: genesis.genesisHeader.toString().substring(2), - genesis_state: Array.from(genesis.genesisState.entries()).map(([key, value]) => [ - key.toString().substring(2), - value.toString().substring(2), - ]), + genesis_state: Object.fromEntries( + [...genesis.genesisState.entries()].map(([key, value]) => [ + key.toString().substring(2), + value.toString().substring(2), + ]), + ), // TODO: [MaSo] Update typeberry jip4Chainspec - add protocol_parameters }; } From f66b37d4fdadf08554533e322c8d0c3308c1ab87 Mon Sep 17 00:00:00 2001 From: Sebastian Koszuta Date: Fri, 20 Feb 2026 10:20:19 +0100 Subject: [PATCH 3/9] dropping validator data from genesis before passing to typeberry --- bin/cli/src/commands/start-command.ts | 55 ++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/bin/cli/src/commands/start-command.ts b/bin/cli/src/commands/start-command.ts index b018970..e79cb5a 100644 --- a/bin/cli/src/commands/start-command.ts +++ b/bin/cli/src/commands/start-command.ts @@ -1,9 +1,34 @@ -import { mkdir } from "node:fs/promises"; +import { access, mkdir, unlink } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join, resolve } from "node:path"; import * as p from "@clack/prompts"; import { Command } from "commander"; const DOCKER_IMAGE = "ghcr.io/fluffylabs/typeberry:latest"; +// note [seko]: genesis state keys to drop before passing to typeberry. this is needed to avoid overwriting dev node validator data +const GENESIS_STATE_DROP_KEYS: string[] = [ + "04000000000000000000000000000000000000000000000000000000000000", // next validator data + "07000000000000000000000000000000000000000000000000000000000000", // designated validator data + "08000000000000000000000000000000000000000000000000000000000000", // current validator data + "09000000000000000000000000000000000000000000000000000000000000", // previous validator data +]; + +export async function createFilteredGenesis(genesisPath: string): Promise { + const raw = await Bun.file(genesisPath).text(); + const genesis = JSON.parse(raw); + + if (genesis.genesis_state && GENESIS_STATE_DROP_KEYS.length > 0) { + for (const key of GENESIS_STATE_DROP_KEYS) { + delete genesis.genesis_state[key]; + } + } + + const tmpPath = join(tmpdir(), `jammin-genesis-${Date.now()}.json`); + await Bun.write(tmpPath, JSON.stringify(genesis, null, 2)); + return tmpPath; +} + /** * Pull the latest Docker image */ @@ -24,22 +49,21 @@ export async function pullImage(): Promise { /** * Spawn a Docker container to run a local Typeberry network. */ -export async function startContainer(): Promise { - const distPath = `${process.cwd()}/dist`; +export async function startContainer(filteredGenesisPath: string): Promise { const logsPath = `${process.cwd()}/logs`; await mkdir(logsPath, { recursive: true }); const dockerArgs: string[] = [ "run", "--rm", "-v", - `${distPath}:/app/jammin`, + `${filteredGenesisPath}:/app/genesis.json:ro`, "-v", `${logsPath}:/app/bin/jam/logs`, "--entrypoint", "/bin/bash", DOCKER_IMAGE, "-c", - "npm run tiny-network -- --config=dev --config=.chain_spec+=/app/jammin/genesis.json", + "npm run tiny-network -- --config=dev --config=.chain_spec+=/app/genesis.json", ]; const proc = Bun.spawn(["docker", ...dockerArgs], { @@ -74,15 +98,30 @@ Examples: .action(async () => { p.intro("🚀 Starting local JAM network..."); + const genesisPath = resolve(process.cwd(), "dist/genesis.json"); + try { + await access(genesisPath); + } catch { + p.log.error(`Genesis file not found at ${genesisPath}`); + p.log.info('Run "jammin deploy" first to generate the genesis state.'); + p.outro("❌ Start aborted."); + process.exit(1); + } + + let filteredGenesisPath: string | undefined; const s = p.spinner(); try { s.start("Pulling latest Typeberry image..."); await pullImage(); s.stop("✅ Image up to date"); + s.start("Preparing genesis state..."); + filteredGenesisPath = await createFilteredGenesis(genesisPath); + s.stop("✅ Genesis state ready"); + s.start("Spawning Docker container..."); s.stop("Typeberry container output:"); - await startContainer(); + await startContainer(filteredGenesisPath); p.outro("🏁 Local JAM network finished running."); } catch (error) { @@ -94,5 +133,9 @@ Examples: p.outro("❌ Start failed. See the output above for details."); process.exit(1); + } finally { + if (filteredGenesisPath) { + await unlink(filteredGenesisPath).catch(() => {}); + } } }); From 2ffe58e3b635aadfa8bbde8c4c8c61191cfcc5d7 Mon Sep 17 00:00:00 2001 From: Sebastian Koszuta Date: Fri, 20 Feb 2026 10:52:59 +0100 Subject: [PATCH 4/9] fixed unit test --- packages/jammin-sdk/utils/genesis-state-generator.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/jammin-sdk/utils/genesis-state-generator.test.ts b/packages/jammin-sdk/utils/genesis-state-generator.test.ts index 4fe455a..b377af4 100644 --- a/packages/jammin-sdk/utils/genesis-state-generator.test.ts +++ b/packages/jammin-sdk/utils/genesis-state-generator.test.ts @@ -35,10 +35,10 @@ describe("genesis-generator", () => { expect(genesis.bootnodes).toEqual([]); expect(genesis.genesis_header).toBeDefined(); expect(genesis.genesis_state).toBeDefined(); - expect(Array.isArray(genesis.genesis_state)).toBe(true); - expect(genesis.genesis_state.length).toBeGreaterThan(0); + expect(typeof genesis.genesis_state).toBe("object"); + expect(Object.keys(genesis.genesis_state).length).toBeGreaterThan(0); - const stateValues = genesis.genesis_state.map((entry) => entry[1]); + const stateValues = Object.values(genesis.genesis_state); const serviceCodeHex = services[0]?.code.toString().substring(2); const serviceCodeHex1 = services[1]?.code.toString().substring(2); From 24bab85eb665160ec6d31516c3341c3973250a6a Mon Sep 17 00:00:00 2001 From: Sebastian Koszuta Date: Mon, 23 Feb 2026 11:13:56 +0100 Subject: [PATCH 5/9] tests for start command --- bin/cli/src/commands/start-command.test.ts | 213 +++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 bin/cli/src/commands/start-command.test.ts diff --git a/bin/cli/src/commands/start-command.test.ts b/bin/cli/src/commands/start-command.test.ts new file mode 100644 index 0000000..ab7b1ca --- /dev/null +++ b/bin/cli/src/commands/start-command.test.ts @@ -0,0 +1,213 @@ +import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test"; +import { mkdir, unlink } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; + +describe("start-command", () => { + describe("createFilteredGenesis", () => { + const { createFilteredGenesis } = require("./start-command"); + + test("filters out genesis state drop keys from genesis data", async () => { + const genesisWithState = { + network: "testnet", + genesis_state: { + "04000000000000000000000000000000000000000000000000000000000000": { data: "next" }, + "07000000000000000000000000000000000000000000000000000000000000": { data: "designated" }, + "08000000000000000000000000000000000000000000000000000000000000": { data: "current" }, + "09000000000000000000000000000000000000000000000000000000000000": { data: "previous" }, + "05000000000000000000000000000000000000000000000000000000000000": { data: "keep this" }, + }, + }; + + const tmpGenesisPath = join(tmpdir(), `test-genesis-${Date.now()}.json`); + await Bun.write(tmpGenesisPath, JSON.stringify(genesisWithState)); + + const resultPath = await createFilteredGenesis(tmpGenesisPath); + const result = await Bun.file(resultPath).json(); + + expect(result.genesis_state).toBeDefined(); + expect(result.genesis_state["04000000000000000000000000000000000000000000000000000000000000"]).toBeUndefined(); + expect(result.genesis_state["07000000000000000000000000000000000000000000000000000000000000"]).toBeUndefined(); + expect(result.genesis_state["08000000000000000000000000000000000000000000000000000000000000"]).toBeUndefined(); + expect(result.genesis_state["09000000000000000000000000000000000000000000000000000000000000"]).toBeUndefined(); + expect(result.genesis_state["05000000000000000000000000000000000000000000000000000000000000"]).toEqual({ + data: "keep this", + }); + + await unlink(tmpGenesisPath).catch(() => {}); + await unlink(resultPath).catch(() => {}); + }); + + test("handles genesis without genesis_state field", async () => { + const genesisWithoutState = { + network: "testnet", + config: { chainId: 1 }, + }; + + const tmpGenesisPath = join(tmpdir(), `test-genesis-${Date.now()}.json`); + await Bun.write(tmpGenesisPath, JSON.stringify(genesisWithoutState)); + + const resultPath = await createFilteredGenesis(tmpGenesisPath); + const result = await Bun.file(resultPath).json(); + + expect(result.network).toBe("testnet"); + expect(result.config).toEqual({ chainId: 1 }); + expect(result.genesis_state).toBeUndefined(); + + await unlink(tmpGenesisPath).catch(() => {}); + await unlink(resultPath).catch(() => {}); + }); + + test("writes filtered genesis to temp directory", async () => { + const genesis = { genesis_state: {} }; + + const tmpGenesisPath = join(tmpdir(), `test-genesis-${Date.now()}.json`); + await Bun.write(tmpGenesisPath, JSON.stringify(genesis)); + + const resultPath = await createFilteredGenesis(tmpGenesisPath); + + expect(resultPath).toContain("jammin-genesis-"); + expect(resultPath).toContain(tmpdir()); + + await unlink(tmpGenesisPath).catch(() => {}); + await unlink(resultPath).catch(() => {}); + }); + }); + + describe("pullImage", () => { + let originalSpawn: typeof Bun.spawn; + let mockSpawn: ReturnType; + + beforeEach(() => { + originalSpawn = Bun.spawn; + mockSpawn = mock(() => ({ + stdout: new ReadableStream({ + start(controller) { + controller.close(); + }, + }), + stderr: new ReadableStream({ + start(controller) { + controller.close(); + }, + }), + exited: Promise.resolve(0), + })); + // biome-ignore lint/suspicious/noExplicitAny: Need to mock Bun.spawn for testing + (Bun as any).spawn = mockSpawn; + }); + + afterEach(() => { + Bun.spawn = originalSpawn; + }); + + test("pulls the correct Docker image with platform flag", async () => { + const { pullImage } = require("./start-command"); + await pullImage(); + + expect(mockSpawn).toHaveBeenCalledTimes(1); + const callArgs = mockSpawn.mock.calls[0]; + expect(callArgs?.[0]).toEqual([ + "docker", + "pull", + "--platform=linux/amd64", + "ghcr.io/fluffylabs/typeberry:latest", + ]); + }); + + test("throws error when pull fails with non-zero exit code", async () => { + const failingMockSpawn = mock(() => ({ + stdout: new ReadableStream({ + start(controller) { + controller.close(); + }, + }), + stderr: new ReadableStream({ + start(controller) { + controller.enqueue(new TextEncoder().encode("pull failed: network error")); + controller.close(); + }, + }), + exited: Promise.resolve(1), + })); + // biome-ignore lint/suspicious/noExplicitAny: Need to mock Bun.spawn for testing + (Bun as any).spawn = failingMockSpawn; + + const { pullImage } = require("./start-command"); + + expect(pullImage()).rejects.toThrow("Failed to pull image"); + expect(pullImage()).rejects.toThrow("exit code 1"); + }); + }); + + describe("startContainer", () => { + let originalSpawn: typeof Bun.spawn; + let mockSpawn: ReturnType; + let testCwd: string; + + beforeEach(async () => { + originalSpawn = Bun.spawn; + mockSpawn = mock(() => ({ + stdout: new ReadableStream({ + start(controller) { + controller.close(); + }, + }), + stderr: new ReadableStream({ + start(controller) { + controller.close(); + }, + }), + exited: Promise.resolve(0), + })); + // biome-ignore lint/suspicious/noExplicitAny: Need to mock Bun.spawn for testing + (Bun as any).spawn = mockSpawn; + + testCwd = join(tmpdir(), `jammin-test-${Date.now()}`); + await mkdir(testCwd, { recursive: true }); + await mkdir(join(testCwd, "logs"), { recursive: true }); + process.cwd = mock(() => testCwd); + }); + + afterEach(async () => { + Bun.spawn = originalSpawn; + process.cwd = () => "/"; + await unlink(testCwd).catch(() => {}); + }); + + test("spawns docker container with correct arguments in correct order", async () => { + const { startContainer } = require("./start-command"); + + await startContainer("/tmp/filtered-genesis.json"); + + expect(mockSpawn).toHaveBeenCalledTimes(1); + const callArgs = mockSpawn.mock.calls[0]; + const dockerArgs = callArgs?.[0] as string[]; + + expect(dockerArgs).toEqual([ + "docker", + "run", + "--rm", + "-v", + "/tmp/filtered-genesis.json:/app/genesis.json:ro", + "-v", + `${testCwd}/logs:/app/bin/jam/logs`, + "--entrypoint", + "/bin/bash", + "ghcr.io/fluffylabs/typeberry:latest", + "-c", + "npm run tiny-network -- --config=dev --config=.chain_spec+=/app/genesis.json", + ]); + }); + + test("passes cwd to docker spawn", async () => { + const { startContainer } = require("./start-command"); + + await startContainer("/tmp/filtered-genesis.json"); + + expect(mockSpawn).toHaveBeenCalledTimes(1); + const callArgs = mockSpawn.mock.calls[0]; + expect(callArgs?.[1]?.cwd).toBe(testCwd); + }); + }); +}); From 6022d522712f9e0d750175f8ed5a5aab4aa374f8 Mon Sep 17 00:00:00 2001 From: Sebastian Koszuta Date: Mon, 23 Feb 2026 14:38:27 +0100 Subject: [PATCH 6/9] fix as per code review --- bin/cli/src/commands/start-command.test.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bin/cli/src/commands/start-command.test.ts b/bin/cli/src/commands/start-command.test.ts index ab7b1ca..6b98f6c 100644 --- a/bin/cli/src/commands/start-command.test.ts +++ b/bin/cli/src/commands/start-command.test.ts @@ -135,8 +135,10 @@ describe("start-command", () => { const { pullImage } = require("./start-command"); - expect(pullImage()).rejects.toThrow("Failed to pull image"); - expect(pullImage()).rejects.toThrow("exit code 1"); + return Promise.all([ + expect(pullImage()).rejects.toThrow("Failed to pull image"), + expect(pullImage()).rejects.toThrow("exit code 1"), + ]); }); }); From 83726ff7c1b5ba98173202de15e86ba06707f012 Mon Sep 17 00:00:00 2001 From: Sebastian Koszuta Date: Mon, 23 Feb 2026 14:44:58 +0100 Subject: [PATCH 7/9] changes as per code review --- bin/cli/src/commands/start-command.test.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bin/cli/src/commands/start-command.test.ts b/bin/cli/src/commands/start-command.test.ts index 6b98f6c..e62a968 100644 --- a/bin/cli/src/commands/start-command.test.ts +++ b/bin/cli/src/commands/start-command.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test"; -import { mkdir, unlink } from "node:fs/promises"; +import { mkdir, rm, unlink } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; @@ -144,6 +144,7 @@ describe("start-command", () => { describe("startContainer", () => { let originalSpawn: typeof Bun.spawn; + let originalCwd: () => string; let mockSpawn: ReturnType; let testCwd: string; @@ -168,13 +169,14 @@ describe("start-command", () => { testCwd = join(tmpdir(), `jammin-test-${Date.now()}`); await mkdir(testCwd, { recursive: true }); await mkdir(join(testCwd, "logs"), { recursive: true }); + originalCwd = process.cwd; process.cwd = mock(() => testCwd); }); afterEach(async () => { Bun.spawn = originalSpawn; - process.cwd = () => "/"; - await unlink(testCwd).catch(() => {}); + process.cwd = originalCwd; + await rm(testCwd, { recursive: true }).catch(() => {}); }); test("spawns docker container with correct arguments in correct order", async () => { From 7c28e463027dc48c2f42ae845c05d35d4d86c89d Mon Sep 17 00:00:00 2001 From: Sebastian Koszuta Date: Wed, 25 Feb 2026 10:17:12 +0100 Subject: [PATCH 8/9] changes as per code review --- bin/cli/src/commands/start-command.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/bin/cli/src/commands/start-command.ts b/bin/cli/src/commands/start-command.ts index e79cb5a..79181a3 100644 --- a/bin/cli/src/commands/start-command.ts +++ b/bin/cli/src/commands/start-command.ts @@ -2,23 +2,26 @@ import { access, mkdir, unlink } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; import * as p from "@clack/prompts"; +import * as state_merkleization from "@typeberry/lib/state-merkleization"; import { Command } from "commander"; +const { StateKeyIdx, stateKeys } = state_merkleization; + const DOCKER_IMAGE = "ghcr.io/fluffylabs/typeberry:latest"; // note [seko]: genesis state keys to drop before passing to typeberry. this is needed to avoid overwriting dev node validator data const GENESIS_STATE_DROP_KEYS: string[] = [ - "04000000000000000000000000000000000000000000000000000000000000", // next validator data - "07000000000000000000000000000000000000000000000000000000000000", // designated validator data - "08000000000000000000000000000000000000000000000000000000000000", // current validator data - "09000000000000000000000000000000000000000000000000000000000000", // previous validator data -]; + StateKeyIdx.Gamma, + StateKeyIdx.Iota, + StateKeyIdx.Kappa, + StateKeyIdx.Lambda, +].map((stateKeyIdx) => stateKeys.index(stateKeyIdx).toString().slice(2, -2)); export async function createFilteredGenesis(genesisPath: string): Promise { const raw = await Bun.file(genesisPath).text(); const genesis = JSON.parse(raw); - if (genesis.genesis_state && GENESIS_STATE_DROP_KEYS.length > 0) { + if (genesis.genesis_state) { for (const key of GENESIS_STATE_DROP_KEYS) { delete genesis.genesis_state[key]; } @@ -135,7 +138,7 @@ Examples: process.exit(1); } finally { if (filteredGenesisPath) { - await unlink(filteredGenesisPath).catch(() => {}); + await unlink(filteredGenesisPath); } } }); From 0ca0d9a2190f94863a82b21f3ef99f787386cb91 Mon Sep 17 00:00:00 2001 From: Sebastian Koszuta Date: Wed, 25 Feb 2026 10:23:36 +0100 Subject: [PATCH 9/9] installed missing dep --- bin/cli/package.json | 1 + bun.lock | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/bin/cli/package.json b/bin/cli/package.json index c4e3fc4..39dc0b8 100644 --- a/bin/cli/package.json +++ b/bin/cli/package.json @@ -19,6 +19,7 @@ "dependencies": { "@clack/prompts": "^0.11.0", "@fluffylabs/jammin-sdk": "workspace:*", + "@typeberry/lib": "^0.5.8", "commander": "^14.0.2" }, "devDependencies": { diff --git a/bun.lock b/bun.lock index 466f497..e3e7e18 100644 --- a/bun.lock +++ b/bun.lock @@ -24,6 +24,7 @@ "dependencies": { "@clack/prompts": "^0.11.0", "@fluffylabs/jammin-sdk": "workspace:*", + "@typeberry/lib": "^0.5.8", "commander": "^14.0.2", }, "devDependencies": { @@ -90,7 +91,7 @@ "@typeberry/bandersnatch-native-linux-x64-gnu": ["@typeberry/bandersnatch-native-linux-x64-gnu@0.2.0-74dd7d7", "", { "os": "linux", "cpu": "x64" }, "sha512-kPTDJ6YYPghxMubhxMsn9wBea/aH9/hIaiG66PW7skRwDM9D5wNzZrmSD7BlpSKv9ayK2hIQiSL1amCiTS9mXQ=="], - "@typeberry/lib": ["@typeberry/lib@0.5.7", "", { "dependencies": { "@fluffylabs/anan-as": "^1.1.5", "@noble/ed25519": "2.2.3", "@opentelemetry/api": "1.9.0", "@typeberry/native": "0.2.0-74dd7d7", "eventemitter3": "^5.0.1", "hash-wasm": "4.12.0" } }, "sha512-q5g8jWeAeGBwh4Ywdjtc9R8R5xIkChD5uIpjvG8tEFIUGyN0/rf+e4wbrB71dRxJEojKK4ZPYt3gvuk9eWQI4w=="], + "@typeberry/lib": ["@typeberry/lib@0.5.8", "", { "dependencies": { "@fluffylabs/anan-as": "^1.1.5", "@noble/ed25519": "2.2.3", "@opentelemetry/api": "1.9.0", "@typeberry/native": "0.2.0-74dd7d7", "eventemitter3": "^5.0.1", "hash-wasm": "4.12.0" } }, "sha512-yB4ooIn1pxyCXKYp6gz0LzHOCLIXU/fm0exZA1hCsY/MHD1tHl27iaijd/fcmXkiekhNhQ9ejVa/pf5SV4ffpg=="], "@typeberry/native": ["@typeberry/native@0.2.0-74dd7d7", "", { "optionalDependencies": { "@typeberry/bandersnatch-native-darwin-arm64": "0.2.0-74dd7d7", "@typeberry/bandersnatch-native-linux-x64-gnu": "0.2.0-74dd7d7" } }, "sha512-b7qq7cIO30KKUVe2WISd+WmipurlzVePz7zFWFkZ2g8nqvfAt8l3upANC1Yxg+LPFLQLWUbEJ7vZ0reOX68Vqg=="], @@ -120,8 +121,14 @@ "zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], + "@fluffylabs/jammin-cli/@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="], + + "@fluffylabs/jammin-sdk/@typeberry/lib": ["@typeberry/lib@0.5.7", "", { "dependencies": { "@fluffylabs/anan-as": "^1.1.5", "@noble/ed25519": "2.2.3", "@opentelemetry/api": "1.9.0", "@typeberry/native": "0.2.0-74dd7d7", "eventemitter3": "^5.0.1", "hash-wasm": "4.12.0" } }, "sha512-q5g8jWeAeGBwh4Ywdjtc9R8R5xIkChD5uIpjvG8tEFIUGyN0/rf+e4wbrB71dRxJEojKK4ZPYt3gvuk9eWQI4w=="], + "@fluffylabs/jammin-sdk/@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="], + "@fluffylabs/jammin-cli/@types/bun/bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="], + "@fluffylabs/jammin-sdk/@types/bun/bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="], } }