justfile 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. alias b := build
  2. alias c := check
  3. alias t := test
  4. default:
  5. @just --list
  6. # Create a new SQL migration file
  7. new-migration target name:
  8. #!/usr/bin/env bash
  9. set -euo pipefail
  10. if [ "{{target}}" != "mint" ] && [ "{{target}}" != "wallet" ]; then
  11. echo "Error: target must be either 'mint' or 'wallet'"
  12. exit 1
  13. fi
  14. timestamp=$(date +%Y%m%d%H%M%S)
  15. migration_path="./crates/cdk-sql-common/src/{{target}}/migrations/${timestamp}_{{name}}.sql"
  16. # Create the file
  17. mkdir -p "$(dirname "$migration_path")"
  18. touch "$migration_path"
  19. echo "Created new migration: $migration_path"
  20. final-check: typos format clippy test
  21. # run `cargo build` on everything
  22. build *ARGS="--workspace --all-targets":
  23. #!/usr/bin/env bash
  24. set -euo pipefail
  25. if [ ! -f Cargo.toml ]; then
  26. cd {{invocation_directory()}}
  27. fi
  28. cargo build {{ARGS}}
  29. # run `cargo check` on everything
  30. check *ARGS="--workspace --all-targets":
  31. #!/usr/bin/env bash
  32. set -euo pipefail
  33. if [ ! -f Cargo.toml ]; then
  34. cd {{invocation_directory()}}
  35. fi
  36. cargo check {{ARGS}}
  37. # run code formatters
  38. format:
  39. #!/usr/bin/env bash
  40. set -euo pipefail
  41. if [ ! -f Cargo.toml ]; then
  42. cd {{invocation_directory()}}
  43. fi
  44. cargo fmt --all
  45. nixpkgs-fmt $(echo **.nix)
  46. # run doc tests
  47. test:
  48. #!/usr/bin/env bash
  49. set -euo pipefail
  50. if [ ! -f Cargo.toml ]; then
  51. cd {{invocation_directory()}}
  52. fi
  53. cargo test --lib --workspace --exclude cdk-postgres
  54. # Run pure integration tests
  55. cargo test -p cdk-integration-tests --test mint
  56. # run doc tests
  57. test-pure db="memory":
  58. #!/usr/bin/env bash
  59. set -euo pipefail
  60. if [ ! -f Cargo.toml ]; then
  61. cd {{invocation_directory()}}
  62. fi
  63. # Run pure integration tests (cargo test will only build what's needed for the test)
  64. CDK_TEST_DB_TYPE={{db}} cargo test -p cdk-integration-tests --test integration_tests_pure -- --test-threads 1
  65. # Run swap flow tests (detailed testing of swap operation)
  66. CDK_TEST_DB_TYPE={{db}} cargo test -p cdk-integration-tests --test test_swap_flow -- --test-threads 1
  67. test-all db="memory":
  68. #!/usr/bin/env bash
  69. set -euo pipefail
  70. just test {{db}}
  71. ./misc/itests.sh "{{db}}"
  72. ./misc/fake_itests.sh "{{db}}" external_signatory
  73. ./misc/fake_itests.sh "{{db}}"
  74. # Mutation Testing Commands
  75. # Run mutation tests on a specific crate
  76. # Usage: just mutants <crate-name>
  77. # Example: just mutants cashu
  78. mutants CRATE:
  79. #!/usr/bin/env bash
  80. set -euo pipefail
  81. echo "Running mutation tests on crate: {{CRATE}}"
  82. cargo mutants --package {{CRATE}} -vV
  83. # Run mutation tests on the cashu crate
  84. mutants-cashu:
  85. #!/usr/bin/env bash
  86. set -euo pipefail
  87. echo "Running mutation tests on cashu crate..."
  88. cargo mutants --package cashu -vV
  89. # Run mutation tests on the cdk crate
  90. mutants-cdk:
  91. #!/usr/bin/env bash
  92. set -euo pipefail
  93. echo "Running mutation tests on cdk crate..."
  94. cargo mutants --package cdk -vV
  95. # Run mutation tests on entire workspace (WARNING: very slow)
  96. mutants-all:
  97. #!/usr/bin/env bash
  98. set -euo pipefail
  99. echo "Running mutation tests on entire workspace..."
  100. echo "WARNING: This may take a very long time!"
  101. cargo mutants -vV
  102. # Quick mutation test for current work (alias for mutants-diff)
  103. mutants-quick:
  104. #!/usr/bin/env bash
  105. set -euo pipefail
  106. echo "Running mutations on changed files since HEAD..."
  107. cargo mutants --in-diff HEAD -vV
  108. # Run mutation tests only on changed code since HEAD
  109. mutants-diff:
  110. #!/usr/bin/env bash
  111. set -euo pipefail
  112. echo "Running mutation tests on changed code..."
  113. cargo mutants --in-diff HEAD -vV
  114. # Run mutation tests and save output to log file
  115. # Usage: just mutants-log <crate-name> <log-suffix>
  116. # Example: just mutants-log cashu baseline
  117. mutants-log CRATE SUFFIX:
  118. #!/usr/bin/env bash
  119. set -euo pipefail
  120. if [ ! -f Cargo.toml ]; then
  121. cd {{invocation_directory()}}
  122. fi
  123. LOG_FILE="mutants-{{CRATE}}-{{SUFFIX}}.log"
  124. echo "Running mutation tests on {{CRATE}}, saving to $LOG_FILE..."
  125. cargo mutants --package {{CRATE}} -vV 2>&1 | tee "$LOG_FILE"
  126. echo "Results saved to $LOG_FILE"
  127. # Mutation test with baseline comparison
  128. # Usage: just mutants-check <crate-name>
  129. # Example: just mutants-check cashu
  130. mutants-check CRATE:
  131. #!/usr/bin/env bash
  132. set -euo pipefail
  133. BASELINE="mutants-{{CRATE}}-baseline.log"
  134. if [ ! -f "$BASELINE" ]; then
  135. echo "ERROR: No baseline found at $BASELINE"
  136. echo "Run: just mutants-log {{CRATE}} baseline"
  137. exit 1
  138. fi
  139. cargo mutants --package {{CRATE}} -vV | tee mutants-{{CRATE}}-current.log
  140. # Compare results
  141. echo "=== Baseline vs Current ==="
  142. diff <(grep "^CAUGHT\|^MISSED" "$BASELINE" | wc -l) \
  143. <(grep "^CAUGHT\|^MISSED" mutants-{{CRATE}}-current.log | wc -l) || true
  144. test-nutshell:
  145. #!/usr/bin/env bash
  146. set -euo pipefail
  147. # Function to cleanup docker containers
  148. cleanup() {
  149. echo "Cleaning up docker containers..."
  150. docker stop nutshell 2>/dev/null || true
  151. docker rm nutshell 2>/dev/null || true
  152. unset CDK_ITESTS_DIR
  153. }
  154. # Trap to ensure cleanup happens on exit (success or failure)
  155. trap cleanup EXIT
  156. docker run -d -p 3338:3338 --name nutshell -e MINT_LIGHTNING_BACKEND=FakeWallet -e MINT_LISTEN_HOST=0.0.0.0 -e MINT_LISTEN_PORT=3338 -e MINT_PRIVATE_KEY=TEST_PRIVATE_KEY -e MINT_INPUT_FEE_PPK=100 cashubtc/nutshell:latest poetry run mint
  157. export CDK_ITESTS_DIR=$(mktemp -d)
  158. # Wait for the Nutshell service to be ready
  159. echo "Waiting for Nutshell to start..."
  160. max_attempts=30
  161. attempt=0
  162. while ! curl -s http://127.0.0.1:3338/v1/info > /dev/null; do
  163. attempt=$((attempt+1))
  164. if [ $attempt -ge $max_attempts ]; then
  165. echo "Nutshell failed to start after $max_attempts attempts"
  166. exit 1
  167. fi
  168. echo "Waiting for Nutshell to start (attempt $attempt/$max_attempts)..."
  169. sleep 1
  170. done
  171. echo "Nutshell is ready!"
  172. # Set environment variables and run tests
  173. export CDK_TEST_MINT_URL=http://127.0.0.1:3338
  174. export LN_BACKEND=FAKEWALLET
  175. # Track test results
  176. test_exit_code=0
  177. # Run first test and capture exit code
  178. echo "Running happy_path_mint_wallet test..."
  179. if ! cargo test -p cdk-integration-tests --test happy_path_mint_wallet; then
  180. echo "ERROR: happy_path_mint_wallet test failed"
  181. test_exit_code=1
  182. fi
  183. # Run second test and capture exit code
  184. echo "Running test_fees test..."
  185. if ! cargo test -p cdk-integration-tests --test test_fees; then
  186. echo "ERROR: test_fees test failed"
  187. test_exit_code=1
  188. fi
  189. unset CDK_TEST_MINT_URL
  190. unset LN_BACKEND
  191. # Exit with error code if any test failed
  192. if [ $test_exit_code -ne 0 ]; then
  193. echo "One or more tests failed"
  194. exit $test_exit_code
  195. fi
  196. echo "All tests passed successfully"
  197. # run `cargo clippy` on everything
  198. clippy *ARGS="--workspace --all-targets":
  199. cargo clippy {{ARGS}} -- -D warnings
  200. # run `cargo clippy --fix` on everything
  201. clippy-fix *ARGS="--workspace --all-targets":
  202. cargo clippy {{ARGS}} --fix
  203. typos:
  204. typos
  205. # fix all typos
  206. [no-exit-message]
  207. typos-fix:
  208. just typos -w
  209. # Goose AI Recipe Commands
  210. # Update changelog from staged changes using Goose AI
  211. goose-git-msg:
  212. #!/usr/bin/env bash
  213. set -euo pipefail
  214. goose run --recipe ./misc/recipes/git-commit-message.yaml --interactive
  215. # Create git message from staged changes using Goose AI
  216. goose-changelog-staged:
  217. #!/usr/bin/env bash
  218. set -euo pipefail
  219. goose run --recipe ./misc/recipes/changelog-update.yaml --interactive
  220. # Update changelog from recent commits using Goose AI
  221. # Usage: just goose-changelog-commits [number_of_commits]
  222. goose-changelog-commits *COMMITS="5":
  223. #!/usr/bin/env bash
  224. set -euo pipefail
  225. COMMITS={{COMMITS}} goose run --recipe ./misc/recipes/changelog-from-commits.yaml --interactive
  226. itest db:
  227. #!/usr/bin/env bash
  228. set -euo pipefail
  229. ./misc/itests.sh "{{db}}"
  230. fake-mint-itest db:
  231. #!/usr/bin/env bash
  232. set -euo pipefail
  233. ./misc/fake_itests.sh "{{db}}"
  234. ./misc/fake_itests.sh "{{db}}" external_signatory
  235. itest-payment-processor ln:
  236. #!/usr/bin/env bash
  237. set -euo pipefail
  238. ./misc/mintd_payment_processor.sh "{{ln}}"
  239. fake-auth-mint-itest db openid_discovery:
  240. #!/usr/bin/env bash
  241. set -euo pipefail
  242. ./misc/fake_auth_itests.sh "{{db}}" "{{openid_discovery}}"
  243. nutshell-wallet-itest:
  244. #!/usr/bin/env bash
  245. set -euo pipefail
  246. ./misc/nutshell_wallet_itest.sh
  247. # Start interactive regtest environment (Bitcoin + 4 LN nodes + 2 CDK mints)
  248. regtest db="sqlite":
  249. #!/usr/bin/env bash
  250. set -euo pipefail
  251. ./misc/interactive_regtest_mprocs.sh {{db}}
  252. # Lightning Network Commands (require regtest environment to be running)
  253. # Get CLN node 1 info
  254. ln-cln1 *ARGS:
  255. #!/usr/bin/env bash
  256. set -euo pipefail
  257. ./misc/regtest_helper.sh ln-cln1 {{ARGS}}
  258. # Get CLN node 2 info
  259. ln-cln2 *ARGS:
  260. #!/usr/bin/env bash
  261. set -euo pipefail
  262. ./misc/regtest_helper.sh ln-cln2 {{ARGS}}
  263. # Get LND node 1 info
  264. ln-lnd1 *ARGS:
  265. #!/usr/bin/env bash
  266. set -euo pipefail
  267. ./misc/regtest_helper.sh ln-lnd1 {{ARGS}}
  268. # Get LND node 2 info
  269. ln-lnd2 *ARGS:
  270. #!/usr/bin/env bash
  271. set -euo pipefail
  272. ./misc/regtest_helper.sh ln-lnd2 {{ARGS}}
  273. # Bitcoin regtest commands
  274. btc *ARGS:
  275. #!/usr/bin/env bash
  276. set -euo pipefail
  277. ./misc/regtest_helper.sh btc {{ARGS}}
  278. # Mine blocks in regtest
  279. btc-mine blocks="10":
  280. #!/usr/bin/env bash
  281. set -euo pipefail
  282. ./misc/regtest_helper.sh btc-mine {{blocks}}
  283. # Show mint information
  284. mint-info:
  285. #!/usr/bin/env bash
  286. set -euo pipefail
  287. ./misc/regtest_helper.sh mint-info
  288. # Run integration tests against regtest environment
  289. mint-test:
  290. #!/usr/bin/env bash
  291. set -euo pipefail
  292. ./misc/regtest_helper.sh mint-test
  293. # Restart mints after recompiling (useful for development)
  294. restart-mints:
  295. #!/usr/bin/env bash
  296. set -euo pipefail
  297. ./misc/regtest_helper.sh restart-mints
  298. # Show regtest environment status
  299. regtest-status:
  300. #!/usr/bin/env bash
  301. set -euo pipefail
  302. ./misc/regtest_helper.sh show-status
  303. # Show regtest environment logs
  304. regtest-logs:
  305. #!/usr/bin/env bash
  306. set -euo pipefail
  307. ./misc/regtest_helper.sh show-logs
  308. run-examples:
  309. cargo r --example p2pk
  310. cargo r --example mint-token
  311. cargo r --example melt-token
  312. cargo r --example proof_selection
  313. cargo r --example wallet
  314. check-wasm *ARGS="--target wasm32-unknown-unknown":
  315. #!/usr/bin/env bash
  316. set -euo pipefail
  317. if [ ! -f Cargo.toml ]; then
  318. cd {{invocation_directory()}}
  319. fi
  320. buildargs=(
  321. "-p cdk"
  322. "-p cdk --no-default-features"
  323. "-p cdk --no-default-features --features wallet"
  324. "-p cdk --no-default-features --features mint"
  325. )
  326. for arg in "${buildargs[@]}"; do
  327. echo "Checking '$arg'"
  328. cargo check $arg {{ARGS}}
  329. echo
  330. done
  331. release m="":
  332. #!/usr/bin/env bash
  333. set -euo pipefail
  334. args=(
  335. "-p cashu"
  336. "-p cdk-prometheus"
  337. "-p cdk-common"
  338. "-p cdk-sql-common"
  339. "-p cdk-sqlite"
  340. "-p cdk-postgres"
  341. "-p cdk-redb"
  342. "-p cdk-signatory"
  343. "-p cdk"
  344. "-p cdk-ffi"
  345. "-p cdk-axum"
  346. "-p cdk-mint-rpc"
  347. "-p cdk-cln"
  348. "-p cdk-lnd"
  349. "-p cdk-lnbits"
  350. "-p cdk-ldk-node"
  351. "-p cdk-fake-wallet"
  352. "-p cdk-payment-processor"
  353. "-p cdk-cli"
  354. "-p cdk-mintd"
  355. )
  356. for arg in "${args[@]}";
  357. do
  358. echo "Publishing '$arg'"
  359. cargo publish $arg {{m}}
  360. echo
  361. done
  362. # Extract version from the cdk-ffi crate
  363. VERSION=$(cargo metadata --format-version 1 --no-deps | jq -r '.packages[] | select(.name == "cdk-ffi") | .version')
  364. # Trigger Swift package release after Rust crates are published
  365. echo "📦 Triggering Swift package release for version $VERSION..."
  366. just ffi-release-swift $VERSION
  367. check-docs:
  368. #!/usr/bin/env bash
  369. set -euo pipefail
  370. args=(
  371. "-p cashu"
  372. "-p cdk-common"
  373. "-p cdk-sql-common"
  374. "-p cdk"
  375. "-p cdk-redb"
  376. "-p cdk-sqlite"
  377. "-p cdk-axum"
  378. "-p cdk-cln"
  379. "-p cdk-lnd"
  380. "-p cdk-lnbits"
  381. "-p cdk-fake-wallet"
  382. "-p cdk-mint-rpc"
  383. "-p cdk-payment-processor"
  384. "-p cdk-signatory"
  385. "-p cdk-cli"
  386. "-p cdk-mintd"
  387. )
  388. for arg in "${args[@]}"; do
  389. echo "Checking '$arg' docs"
  390. cargo doc $arg --all-features
  391. echo
  392. done
  393. # Build docs for all crates and error on warnings
  394. docs-strict:
  395. #!/usr/bin/env bash
  396. set -euo pipefail
  397. args=(
  398. "-p cashu"
  399. "-p cdk-common"
  400. "-p cdk-sql-common"
  401. "-p cdk"
  402. "-p cdk-redb"
  403. "-p cdk-sqlite"
  404. "-p cdk-axum"
  405. "-p cdk-cln"
  406. "-p cdk-lnd"
  407. "-p cdk-lnbits"
  408. "-p cdk-fake-wallet"
  409. "-p cdk-mint-rpc"
  410. "-p cdk-payment-processor"
  411. "-p cdk-signatory"
  412. "-p cdk-cli"
  413. "-p cdk-mintd"
  414. )
  415. for arg in "${args[@]}"; do
  416. echo "Building docs for $arg with strict warnings"
  417. RUSTDOCFLAGS="-D warnings" cargo doc $arg --all-features --no-deps
  418. echo
  419. done
  420. # =============================================================================
  421. # FFI Commands - CDK Foreign Function Interface bindings
  422. # =============================================================================
  423. # Helper function to get library extension based on platform
  424. _ffi-lib-ext:
  425. #!/usr/bin/env bash
  426. if [[ "$OSTYPE" == "darwin"* ]]; then
  427. echo "dylib"
  428. else
  429. echo "so"
  430. fi
  431. # Build the FFI library
  432. ffi-build *ARGS="--release":
  433. cargo build {{ARGS}} --package cdk-ffi --features postgres
  434. # Generate bindings for a specific language
  435. ffi-generate LANGUAGE *ARGS="--release": ffi-build
  436. #!/usr/bin/env bash
  437. set -euo pipefail
  438. LANG="{{LANGUAGE}}"
  439. # Validate language
  440. case "$LANG" in
  441. python|swift|kotlin)
  442. ;;
  443. *)
  444. echo "❌ Unsupported language: $LANG"
  445. echo "Supported languages: python, swift, kotlin"
  446. exit 1
  447. ;;
  448. esac
  449. # Set emoji and build type
  450. case "$LANG" in
  451. python) EMOJI="🐍" ;;
  452. swift) EMOJI="🍎" ;;
  453. kotlin) EMOJI="🎯" ;;
  454. esac
  455. # Determine build type and library path
  456. if [[ "{{ARGS}}" == *"--release"* ]] || [[ "{{ARGS}}" == "" ]]; then
  457. BUILD_TYPE="release"
  458. else
  459. BUILD_TYPE="debug"
  460. cargo build --package cdk-ffi --features postgres
  461. fi
  462. LIB_EXT=$(just _ffi-lib-ext)
  463. echo "$EMOJI Generating $LANG bindings..."
  464. mkdir -p target/bindings/$LANG
  465. cargo run --bin uniffi-bindgen generate \
  466. --library target/$BUILD_TYPE/libcdk_ffi.$LIB_EXT \
  467. --language $LANG \
  468. --out-dir target/bindings/$LANG
  469. echo "✅ $LANG bindings generated in target/bindings/$LANG/"
  470. # Generate Python bindings (shorthand)
  471. ffi-generate-python *ARGS="--release":
  472. just ffi-generate python {{ARGS}}
  473. # Generate Swift bindings (shorthand)
  474. ffi-generate-swift *ARGS="--release":
  475. just ffi-generate swift {{ARGS}}
  476. # Generate Kotlin bindings (shorthand)
  477. ffi-generate-kotlin *ARGS="--release":
  478. just ffi-generate kotlin {{ARGS}}
  479. # Generate bindings for all supported languages
  480. ffi-generate-all *ARGS="--release": ffi-build
  481. @echo "🔧 Generating UniFFI bindings for all languages..."
  482. just ffi-generate python {{ARGS}}
  483. just ffi-generate swift {{ARGS}}
  484. just ffi-generate kotlin {{ARGS}}
  485. @echo "✅ All bindings generated successfully!"
  486. # Build debug version and generate Python bindings quickly (for development)
  487. ffi-dev-python:
  488. #!/usr/bin/env bash
  489. set -euo pipefail
  490. # Generate Python bindings first
  491. just ffi-generate python --debug
  492. # Copy library to Python bindings directory
  493. LIB_EXT=$(just _ffi-lib-ext)
  494. echo "📦 Copying library to Python bindings directory..."
  495. cp target/debug/libcdk_ffi.$LIB_EXT target/bindings/python/
  496. # Launch Python REPL with CDK FFI loaded
  497. cd target/bindings/python
  498. echo "🐍 Launching Python REPL with CDK FFI library loaded..."
  499. echo "💡 The 'cdk_ffi' module is pre-imported and ready to use!"
  500. python3 -i -c "from cdk_ffi import *; print('✅ CDK FFI library loaded successfully!');"
  501. # Test language bindings with a simple import
  502. ffi-test-bindings LANGUAGE: (ffi-generate LANGUAGE "--debug")
  503. #!/usr/bin/env bash
  504. set -euo pipefail
  505. LANG="{{LANGUAGE}}"
  506. LIB_EXT=$(just _ffi-lib-ext)
  507. echo "📦 Copying library to $LANG bindings directory..."
  508. cp target/debug/libcdk_ffi.$LIB_EXT target/bindings/$LANG/
  509. cd target/bindings/$LANG
  510. echo "🧪 Testing $LANG bindings..."
  511. case "$LANG" in
  512. python)
  513. python3 -c "import cdk_ffi; print('✅ Python bindings work!')"
  514. ;;
  515. *)
  516. echo "✅ $LANG bindings generated (manual testing required)"
  517. ;;
  518. esac
  519. # Test Python bindings (shorthand)
  520. ffi-test-python:
  521. just ffi-test-bindings python
  522. # Trigger Swift Package release workflow
  523. ffi-release-swift VERSION:
  524. #!/usr/bin/env bash
  525. set -euo pipefail
  526. echo "🚀 Triggering Publish Swift Package workflow..."
  527. echo " Version: {{VERSION}}"
  528. echo " CDK Ref: v{{VERSION}}"
  529. # Trigger the workflow using GitHub CLI
  530. gh workflow run "Publish Swift Package" \
  531. --repo cashubtc/cdk-swift \
  532. --field version="{{VERSION}}" \
  533. --field cdk_repo="cashubtc/cdk" \
  534. --field cdk_ref="v{{VERSION}}"
  535. echo "✅ Workflow triggered successfully!"