From fd8f433a3674d339b4481ac872fa6fa41b82b3bf Mon Sep 17 00:00:00 2001 From: redshift <213178690+1ftredsh@users.noreply.github.com> Date: Sat, 16 May 2026 16:22:16 +0800 Subject: [PATCH 1/3] feat: add Docker dev environment and fix logging/cashu-ts - Add Dockerfile, docker-compose.yml, and .dockerignore for Bun dev container - Fix sdkLogger to use logger.warn instead of logger.log for warnings - Add proper warn method to logger (writes to file instead of console) - Use console.log for daemon startup messages to keep them visible - Update cashu-ts getDecodedToken call with explicit well-known-pubkeys - Use proof.amount.toNumber() for updated cashu-ts Amount type --- .dockerignore | 12 ++++++++++++ Dockerfile | 3 +++ docker-compose.yml | 14 ++++++++++++++ src/daemon/http/index.ts | 2 +- src/daemon/index.ts | 2 +- src/daemon/wallet/index.ts | 6 +++--- src/start-daemon.ts | 10 +++++----- src/utils/logger.ts | 6 +++--- 8 files changed, 42 insertions(+), 13 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ae43c2a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +node_modules/ +dist/ +.git/ +.worktrees/ +.pi/ +logs/ +tmp/ +temp/ +*.log +.env +.env.* +.DS_Store diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..03afcaa --- /dev/null +++ b/Dockerfile @@ -0,0 +1,3 @@ +FROM oven/bun:1-slim +WORKDIR /app +CMD ["/bin/bash"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..3f278a5 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +services: + bun: + build: . + container_name: routstrd-bun + working_dir: /app + volumes: + - .:/app + - bun_home:/root/.bun + stdin_open: true + tty: true + command: /bin/bash + +volumes: + bun_home: diff --git a/src/daemon/http/index.ts b/src/daemon/http/index.ts index f12da28..d40c82d 100644 --- a/src/daemon/http/index.ts +++ b/src/daemon/http/index.ts @@ -271,7 +271,7 @@ function makeSdkLogger(prefix?: string): SdkLogger { const fmt = (...args: unknown[]) => (tag ? [tag, ...args] : args); return { log: (...args: unknown[]) => logger.log(...fmt(...args)), - warn: (...args: unknown[]) => logger.log(...fmt(...args)), + warn: (...args: unknown[]) => logger.warn(...fmt(...args)), error: (...args: unknown[]) => logger.error(...fmt(...args)), debug: (...args: unknown[]) => logger.debug(...fmt(...args)), child: (p: string) => makeSdkLogger(prefix ? `${prefix}:${p}` : p), diff --git a/src/daemon/index.ts b/src/daemon/index.ts index 1280cd4..4a4f9c7 100644 --- a/src/daemon/index.ts +++ b/src/daemon/index.ts @@ -17,7 +17,7 @@ function makeSdkLogger(prefix?: string): SdkLogger { const fmt = (...args: unknown[]) => (tag ? [tag, ...args] : args); return { log: (...args: unknown[]) => logger.log(...fmt(...args)), - warn: (...args: unknown[]) => logger.log(...fmt(...args)), + warn: (...args: unknown[]) => logger.warn(...fmt(...args)), error: (...args: unknown[]) => logger.error(...fmt(...args)), debug: (...args: unknown[]) => logger.debug(...fmt(...args)), child: (p: string) => makeSdkLogger(prefix ? `${prefix}:${p}` : p), diff --git a/src/daemon/wallet/index.ts b/src/daemon/wallet/index.ts index 6a64d0a..a1480f6 100644 --- a/src/daemon/wallet/index.ts +++ b/src/daemon/wallet/index.ts @@ -1,4 +1,4 @@ -import { getDecodedToken } from "@cashu/cashu-ts"; +import { getDecodedToken, Amount } from "@cashu/cashu-ts"; import { InsufficientBalanceError } from "@routstr/sdk"; import { logger } from "../../utils/logger"; import { createCocodClient, type CocodClient } from "./cocod-client"; @@ -7,9 +7,9 @@ export function decodeCashuTokenAmount(token: string): { amount: number; unit: "sat" | "msat"; } { - const decoded = getDecodedToken(token); + const decoded = getDecodedToken(token, []); const amount = - decoded?.proofs?.reduce((sum, proof) => sum + proof.amount, 0) ?? 0; + decoded?.proofs?.reduce((sum, proof) => sum + proof.amount.toNumber(), 0) ?? 0; const unit = decoded?.unit === "msat" ? "msat" : "sat"; return { amount, unit }; } diff --git a/src/start-daemon.ts b/src/start-daemon.ts index ac50ade..9d9ea8f 100644 --- a/src/start-daemon.ts +++ b/src/start-daemon.ts @@ -28,7 +28,7 @@ async function startDaemonUnlocked( const startupTimeoutMs = 10 * 60 * 1000; if (await isDaemonHealthy(port)) { - logger.log(`Routstr daemon already running on http://localhost:${port}/v1`); + console.log(`Routstr daemon already running on http://localhost:${port}/v1`); return; } @@ -43,8 +43,8 @@ async function startDaemonUnlocked( const shellCmd = `bun run "${daemonScript}" ${args.map((a) => `'${a}'`).join(" ")}`; const proc = Bun.spawn(["sh", "-c", shellCmd], { - stdout: "inherit", - stderr: "inherit", + stdout: "ignore", + stderr: "ignore", stdin: "ignore", detached: true, }); @@ -67,7 +67,7 @@ async function startDaemonUnlocked( } if (await isDaemonHealthy(port)) { - logger.log(`Routstr daemon started (PID: ${proc.pid}).`); + console.log(`Routstr daemon started (PID: ${proc.pid}).`); return; } } @@ -84,7 +84,7 @@ export async function startDaemon( const startupTimeoutMs = 10 * 60 * 1000; if (await isDaemonHealthy(port)) { - logger.log(`Routstr daemon already running on http://localhost:${port}/v1`); + console.log(`Routstr daemon already running on http://localhost:${port}/v1`); return; } diff --git a/src/utils/logger.ts b/src/utils/logger.ts index af8b9c0..cc317e0 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -48,18 +48,18 @@ async function writeLog(level: string, ...args: unknown[]) { export const logger = { log: (...args: unknown[]) => { - console.log(...args); writeLog("INFO", ...args); }, debug: (...args: unknown[]) => { writeLog("DEBUG", ...args); }, + warn: (...args: unknown[]) => { + writeLog("WARN", ...args); + }, error: (...args: unknown[]) => { - console.error(...args); writeLog("ERROR", ...args); }, info: (...args: unknown[]) => { - console.log(...args); writeLog("INFO", ...args); }, }; From 390701b5ea1da5f33ef8dc7230de67c5121c8f61 Mon Sep 17 00:00:00 2001 From: redshift <213178690+1ftredsh@users.noreply.github.com> Date: Sat, 16 May 2026 14:20:26 +0530 Subject: [PATCH 2/3] chore: bump @routstr/sdk to ^0.3.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e87a724..287d326 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@cashu/cashu-ts": "^4.3.0", - "@routstr/sdk": "^0.3.6", + "@routstr/sdk": "^0.3.7", "applesauce-core": "^5.1.0", "applesauce-relay": "^5.1.0", "commander": "^14.0.2", From 5069fcac4306d22bc20861926c546af62d0c7edb Mon Sep 17 00:00:00 2001 From: redshift <213178690+1ftredsh@users.noreply.github.com> Date: Sat, 16 May 2026 16:47:20 +0530 Subject: [PATCH 3/3] bumpd version --- bun.lock | 17 +++++++++-------- package.json | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) mode change 100644 => 100755 bun.lock diff --git a/bun.lock b/bun.lock old mode 100644 new mode 100755 index a80766c..33d39de --- a/bun.lock +++ b/bun.lock @@ -1,11 +1,10 @@ { - "lockfileVersion": 1, + "lockfileVersion": 0, "workspaces": { "": { - "name": "routstrd", "dependencies": { - "@cashu/cashu-ts": "^3.1.1", - "@routstr/sdk": "^0.3.6", + "@cashu/cashu-ts": "^4.3.0", + "@routstr/sdk": "^0.3.8", "applesauce-core": "^5.1.0", "applesauce-relay": "^5.1.0", "commander": "^14.0.2", @@ -24,7 +23,7 @@ }, }, "packages": { - "@cashu/cashu-ts": ["@cashu/cashu-ts@3.7.0", "", { "dependencies": { "@noble/curves": "^2.2.0", "@noble/hashes": "^2.2.0", "@scure/base": "^2.2.0", "@scure/bip32": "^2.2.0" } }, "sha512-Jy4Hek+Wouh94xS4InmTJRLpBPXA6fddVOAHR5lfNyTsCk9r3desY0vnwUGvOZBZWsSKZXedqdD/YpjWb3zngQ=="], + "@cashu/cashu-ts": ["@cashu/cashu-ts@4.3.0", "", { "dependencies": { "@noble/curves": "^2.2.0", "@noble/hashes": "^2.2.0", "@scure/base": "^2.2.0", "@scure/bip32": "^2.2.0" } }, "sha512-YUkqKDN/8edtZi0f6O4wymRkVvr24A/ysxZYhaInr/1PFrBlrBbxi1dmdkf9MK14mwBMkWtAQutJm/vCfMePGQ=="], "@noble/ciphers": ["@noble/ciphers@2.1.1", "", {}, "sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw=="], @@ -32,7 +31,7 @@ "@noble/hashes": ["@noble/hashes@2.2.0", "", {}, "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg=="], - "@routstr/sdk": ["@routstr/sdk@0.3.6", "", { "dependencies": { "@cashu/cashu-ts": "^3.1.1", "applesauce-core": "^5.1.0", "applesauce-relay": "^5.1.0", "rxjs": "^7.8.1", "zustand": "^5.0.5" }, "optionalDependencies": { "better-sqlite3": "^11.7.2" }, "peerDependencies": { "typescript": ">=5.0.0" } }, "sha512-QYHhudkQQUX59NA51GBZHJOcVPZVbTDG3F1tX1E+WzXVNEbARXzI1a1DH3D19dsHfWntZjzikNz3ZQGeWQWb/A=="], + "@routstr/sdk": ["@routstr/sdk@0.3.8", "", { "dependencies": { "@cashu/cashu-ts": "^3.1.1", "applesauce-core": "^5.1.0", "applesauce-relay": "^5.1.0", "rxjs": "^7.8.1", "zustand": "^5.0.5" }, "optionalDependencies": { "better-sqlite3": "^11.7.2" }, "peerDependencies": { "typescript": ">=5.0.0" } }, "sha512-5wQh+SPfBQBgWZq4VJSpOlpp3EWKDPBQ3lFAwQpvTdJ9Ds/IpkAvPbIAtS2ZLqTY7oN95GtlZps5TMOtyCDwGA=="], "@scure/base": ["@scure/base@2.2.0", "", {}, "sha512-b8XEupJibegiXV+tDUseI8oLQc8ei3d/4Jkb2RpbHh3MfE054ov3uIz2dhFkB3FI8iwYkEh0gGCApkrYggkPNg=="], @@ -42,7 +41,7 @@ "@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="], - "@types/node": ["@types/node@25.7.0", "", { "dependencies": { "undici-types": "~7.21.0" } }, "sha512-z+pdZyxE+RTQE9AcboAZCb4otwcrvgHD+GlBpPgn0emDVt0ohrTMhAwlr2Wd9nZ+nihhYFxO2pThz3C5qSu2Eg=="], + "@types/node": ["@types/node@25.8.0", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ=="], "@types/qrcode": ["@types/qrcode@1.5.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw=="], @@ -194,7 +193,7 @@ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], - "undici-types": ["undici-types@7.21.0", "", {}, "sha512-w9IMgQrz4O0YN1LtB7K5P63vhlIOvC7opSmouCJ+ZywlPAlO9gIkJ+otk6LvGpAs2wg4econaCz3TvQ9xPoyuQ=="], + "undici-types": ["undici-types@7.24.6", "", {}, "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg=="], "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], @@ -212,6 +211,8 @@ "zustand": ["zustand@5.0.13", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-efI2tVaVQPqtOh114loML/Z80Y4NP3yc+Ff0fYiZJPauNeWZeIp/bRFD7I9bfmCOYBh/PHxlglQ9+wvlwnPikQ=="], + "@routstr/sdk/@cashu/cashu-ts": ["@cashu/cashu-ts@3.7.0", "", { "dependencies": { "@noble/curves": "^2.2.0", "@noble/hashes": "^2.2.0", "@scure/base": "^2.2.0", "@scure/bip32": "^2.2.0" } }, "sha512-Jy4Hek+Wouh94xS4InmTJRLpBPXA6fddVOAHR5lfNyTsCk9r3desY0vnwUGvOZBZWsSKZXedqdD/YpjWb3zngQ=="], + "@scure/bip39/@noble/hashes": ["@noble/hashes@2.0.1", "", {}, "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw=="], "@scure/bip39/@scure/base": ["@scure/base@2.0.0", "", {}, "sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w=="], diff --git a/package.json b/package.json index 287d326..33bec94 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "routstrd", - "version": "0.2.21", + "version": "0.2.22", "module": "src/index.ts", "type": "module", "private": false, @@ -24,7 +24,7 @@ }, "dependencies": { "@cashu/cashu-ts": "^4.3.0", - "@routstr/sdk": "^0.3.7", + "@routstr/sdk": "^0.3.8", "applesauce-core": "^5.1.0", "applesauce-relay": "^5.1.0", "commander": "^14.0.2",