Merge pull request #9 from aiken-lang/KtorZ-patch-1
Update Discord link and add IntelliJ integration
Update Discord link and add IntelliJ integration
chore: downgrade `blockfrost-tests` to make the CI green
CI failure on the previous push exposed two issues with my initial pin to .87: 1. **Smoke test "libsodium not initialized"**: pinning Mesh to `.87` pulled in different `@cardano-sdk/*` transitive versions than preprod's known- good lockfile, and the resulting libsodium-wrappers-sumo / libsodium-sumo combination fails WASM init under Node 20 in CI. Preprod runs Mesh `.102` for `core/core-csl/core-cst`, `.100` for `provider`, `-40` for `react`, and its smoke test passes — so pin to those exact versions. 2. **Pin alone doesn't fix the user**: with `.102` we're back on the same CBOR-encoding Mesh that broke their wallet's signature in the first place. The verify guard added in the previous commit converts that into a friendly error, but the user still can't vote. Extended `mergeSignerWitnesses`: when the wallet returns a full signed Transaction (not just a witness set), and its body bytes differ from ours, and we have no pre-existing witnesses to invalidate, *use the wallet's body*. The wallet's vkey signature was made over its body, so adopting it makes the signature verify and lets the submit succeed. This handles the first-signer case — which is the typical case for "I clicked Approve & Sign and it failed" — without changing behaviour for multi-signer flows where prior witnesses would be invalidated. Also dropped the libsodium override commit's package.json entry — it's not needed once we match preprod's exact Mesh versions, and trying to pin `libsodium-sumo` to 0.7.10 broke Node 22's WASM loader. Added unit test covering the body-swap recovery path; existing 3 tests still pass (4 total). Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
The 0.7.16 release ships `dist/modules-sumo-esm/libsodium-wrappers.mjs` with
a relative `import "./libsodium-sumo.mjs"` whose target file isn't in the
package — the actual sumo binary lives in the separate `libsodium-sumo`
package and is wired up via package.json `exports`. Node's strict ESM
resolver (used by `tsx` in the CI smoke runner, and by Next.js at build
time) doesn't follow the cross-package indirection and throws
`ERR_MODULE_NOT_FOUND` before any Mesh helper has a chance to run.
Preprod's pre-existing lockfile pinned 0.7.10, which works. Regenerating the
lockfile to land the Mesh pin pulled 0.7.16 (the latest in the ^0.7.5 range
the cardano-sdk transitively allows), breaking both `multisig-v1-smoke` and
the Vercel build. Override to 0.7.10 forces all `@cardano-sdk/crypto`
copies onto the working version.
Verified: `node --input-type=module -e "import('@meshsdk/core')"` now
succeeds (failed before the override). Unit tests still pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Adds an alternative component builder that runs `cabal v2-build` inside a slice derivation and emits a cabal-store layout rather than going through Setup.hs, alongside the existing Setup-based v1 builder. Selected per-project via the new `builderVersion` option (default `1` for now; flip to `2` to opt in on a per-project basis). What the v2 builder provides: * Per-component cabal-store slices that compose into a single `~/.cabal/store/ghc-<version>/` layout via `composeStore`. Each slice's UnitId matches what a downstream `cabal v2-build` would compute against the real compiler, so a v2 store can be reused by interactive cabal invocations without recomputation. * Public sublibrary support (`library <n>` stanzas) end-to-end — not currently supported by v1's Setup-based path. * A v2 dev shell (`shell-for-v2.nix`) wired through `project.shellFor` whenever `builderVersion = 2`. Two exposure modes: `cabal-store` (default) pre-populates `~/.cabal/store` so plain `cabal v2-build` reuses the slice's units; `ghc-pkg` mode wraps `ghc` / `ghc-pkg` with `GHC_ENVIRONMENT` / `GHC_PACKAGE_PATH` so `ghc -e` and similar see the composed store directly. * A shared ghc shim (`ghc-shim.nix`) used by both the slice's `cabal v2-build` and the v2 shell so the user-facing compiler matches the slice compiler. Adds cabal near-compiler aliases, patches the ghcjs `ar command` setting (drops missing `.o`s for backpack-on-ghcjs), and adds native-musl `unlit` / `ghc-iserv[-dyn|-prof]` aliases. Plumbing changes: * `builder/default.nix` + `builder/hspkg-builder.nix` dispatch on `builderVersion`. v2-specific helpers (`buildCabalStoreSlice`, `composeStore`, `makeGhcShim`, the patched `v2CabalInstall`) live in `builder/default.nix`. * `modules/project-common.nix` adds `builderVersion`. `modules/component-driver.nix` propagates it (plus `crossTemplateHaskellSupport` and `cabalProjectLocal`) into the pkg-set config. `modules/stack-project.nix` forces v1 for stack projects (stack-to-nix doesn't produce the plan-json shapes v2 consumes). * `modules/package-options.nix` adds round-trip options (`configureOptions`, `extraLibDirs`, `extraIncludeDirs`, `programOptions`) that v2 emits back into each slice's cabal.project. * `modules/install-plan/configure-args.nix` extracts those round-trip options from plan.json's configure-args, and filters `-hide-all-packages` for v2 (cabal injects it on every Setup configure call; round-tripping it would fork UnitId hashes between plan-nix and slice cabal). * `modules/install-plan/non-reinstallable.nix` skips the ghcjs/wasm boot-package hiding on v2 (v2 follows cabal's plan literally rather than overlaying haskell.nix's exclusions). * `modules/shell.nix` adds the `exposePackagesVia` option. * `lib/check.nix` adds a v2-slice branch that runs the installed exe under the platform's testWrapper, mirroring the v1 check semantics for slice derivations. * `overlays/haskell.nix` propagates `builderVersion` / `cabalProjectLocal` through `addProjectAndPackageAttrs`, dispatches `shellFor` on `builderVersion`, and rebuilds iserv-proxy as both a non-profiled and profiled variant — v2 reads the prof variant from `package iserv-proxy profiling: True` in cabal.project rather than `enableProfiling = true` on the .override (which v2 doesn't honour). * `overlays/linux-cross.nix` + `overlays/mingw_w64.nix` add a `wrapGhc` derivation that bakes `-fexternal-interpreter -pgmi <iserv-wrapper>` into ghc itself — v2 can't put those into per-package `ghc-options:` (UnitId divergence), so it wraps the compiler instead. The `compilerSelection` chain picks the wrapped ghc on cross targets. Internal projects pin v1: * `compiler/ghc/default.nix` (hadrian) and `overlays/bootstrap.nix` (hscolour) set `builderVersion = 1` explicitly so v2 evolution doesn't churn GHC builds while v2 is still settling. `overlays/tools.nix` defaults `haskell-nix.tool` invocations to v1 for the same reason. Tests are NOT migrated in this commit — the existing tests run under v1 (the default) and exercise master's behaviour as before. A follow-up will migrate or duplicate them under v2 once we know which expectations need adjusting.
A user submitting a "Ballot Vote" on a 2-of-3 DRep multisig hit
`ConwayUtxowFailure (InvalidWitnessesUTXOW [VKey ce7cbe8f...])`. Decoding the
failing tx with this repo's CSL showed the witness's vkey hashes to a *valid*
script signer, but its Ed25519 signature does not verify against the tx body
hash. The body itself is byte-stable across CSL round-trips, so the wallet
must have signed a different (re-canonicalised) body.
Cause: package.json had `^1.9.0-beta.87` on @meshsdk/core/core-csl/core-cst/
provider/react; the lockfile had drifted to 1.9.0-beta.102. Some patch in
those 15 betas changed how Mesh emits CBOR (likely voting_procedures), so
app-built bodies no longer match what the wallet's encoder produces — the
wallet's signature verifies against its body but not ours.
Fix:
- Pin Mesh deps to exact .87 (.86 for provider) — no more silent patch drift.
- `mergeSignerWitnesses` returns `{ txHex, invalidVkeyPubKeysHex }`,
verifying each newly-merged vkey's signature against the merged tx body
hash. Witnesses already on the tx are not re-verified.
- transaction-card.signTx() and useTransaction.newTransaction() abort with a
destructive toast (and skip submission + persistence) when the wallet
returns a witness that doesn't verify. Offending pubkey is logged for
debugging. The wallet user gets an actionable message instead of a chain
rejection.
- jest.config.mjs: one-line moduleNameMapper for libsodium-wrappers-sumo's
broken relative `./libsodium-sumo.mjs` import (pre-existing CI gap).
- .gitattributes: mark package-lock.json as linguist-generated so diff
reviewers can skip the lockfile churn.
Test plan:
- New unit test `mergeSignerWitnesses.test.ts`: 3 cases (happy, mismatched
body, pre-existing witness preserved) — all pass.
- `npx tsc --noEmit` on touched files: clean.
- Manual: decoded the user-shared failing txCbor; confirmed
`blake2b-224(vkey) == 'f6ed79ef...'` (valid signer) but
`pk.verify(body, sig)` is false. The new guard catches exactly this case
before submit.
- Pre-existing test failures on preprod (proxyCiPreflight, proxyDRepInfo,
signTransaction mock missing isBotJwt, pendingTransactions, apiSecurity)
are in files unrelated to this fix.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
step) Signed-off-by: Roland Kuhn <[email protected]>
The onlyOne() method in Pluto threw a generic Error("something wrong") with no context about what was being looked up or why it failed.
Changes:
- Accept optional context string to identify the caller and query
- Distinguish between empty results (arr.length === 0) and null item
- Report the actual count when multiple results found
- Pass context from getPairByDID() and getPairByName() callers
Fixes #648
Signed-off-by: A-Chronicle <[email protected]>
Flake lock file updates:
• Updated input 'advisory-db':
'github:rustsec/advisory-db/f2ae5fc' (2026-05-16)
→ 'github:rustsec/advisory-db/831c50f' (2026-05-23)
• Updated input 'blockfrost-tests':
'github:blockfrost/blockfrost-tests/7c8dfa8' (2026-05-15)
→ 'github:blockfrost/blockfrost-tests/72316a2' (2026-05-20)
• Updated input 'crane':
'github:ipetkov/crane/6d015ea' (2026-05-06)
→ 'github:ipetkov/crane/edb3889' (2026-05-18)
• Updated input 'fenix':
'github:nix-community/fenix/ecd6d4f' (2026-05-16)
→ 'github:nix-community/fenix/4f37db7' (2026-05-23)
• Updated input 'fenix/rust-analyzer-src':
'github:rust-lang/rust-analyzer/1a68212' (2026-05-15)
→ 'github:rust-lang/rust-analyzer/56dc60d' (2026-05-22)
• Updated input 'nixpkgs':
'github:nixos/nixpkgs/d7a713c' (2026-05-14)
→ 'github:nixos/nixpkgs/687f05a' (2026-05-18)
Adds an alternative component builder that runs `cabal v2-build` inside a slice derivation and emits a cabal-store layout rather than going through Setup.hs, alongside the existing Setup-based v1 builder. Selected per-project via the new `builderVersion` option (default `1` for now; flip to `2` to opt in on a per-project basis). What the v2 builder provides: * Per-component cabal-store slices that compose into a single `~/.cabal/store/ghc-<version>/` layout via `composeStore`. Each slice's UnitId matches what a downstream `cabal v2-build` would compute against the real compiler, so a v2 store can be reused by interactive cabal invocations without recomputation. * Public sublibrary support (`library <n>` stanzas) end-to-end — not currently supported by v1's Setup-based path. * A v2 dev shell (`shell-for-v2.nix`) wired through `project.shellFor` whenever `builderVersion = 2`. Two exposure modes: `cabal-store` (default) pre-populates `~/.cabal/store` so plain `cabal v2-build` reuses the slice's units; `ghc-pkg` mode wraps `ghc` / `ghc-pkg` with `GHC_ENVIRONMENT` / `GHC_PACKAGE_PATH` so `ghc -e` and similar see the composed store directly. * A shared ghc shim (`ghc-shim.nix`) used by both the slice's `cabal v2-build` and the v2 shell so the user-facing compiler matches the slice compiler. Adds cabal near-compiler aliases, patches the ghcjs `ar command` setting (drops missing `.o`s for backpack-on-ghcjs), and adds native-musl `unlit` / `ghc-iserv[-dyn|-prof]` aliases. Plumbing changes: * `builder/default.nix` + `builder/hspkg-builder.nix` dispatch on `builderVersion`. v2-specific helpers (`buildCabalStoreSlice`, `composeStore`, `makeGhcShim`, the patched `v2CabalInstall`) live in `builder/default.nix`. * `modules/project-common.nix` adds `builderVersion`. `modules/component-driver.nix` propagates it (plus `crossTemplateHaskellSupport` and `cabalProjectLocal`) into the pkg-set config. `modules/stack-project.nix` forces v1 for stack projects (stack-to-nix doesn't produce the plan-json shapes v2 consumes). * `modules/package-options.nix` adds round-trip options (`configureOptions`, `extraLibDirs`, `extraIncludeDirs`, `programOptions`) that v2 emits back into each slice's cabal.project. * `modules/install-plan/configure-args.nix` extracts those round-trip options from plan.json's configure-args, and filters `-hide-all-packages` for v2 (cabal injects it on every Setup configure call; round-tripping it would fork UnitId hashes between plan-nix and slice cabal). * `modules/install-plan/non-reinstallable.nix` skips the ghcjs/wasm boot-package hiding on v2 (v2 follows cabal's plan literally rather than overlaying haskell.nix's exclusions). * `modules/shell.nix` adds the `exposePackagesVia` option. * `lib/check.nix` adds a v2-slice branch that runs the installed exe under the platform's testWrapper, mirroring the v1 check semantics for slice derivations. * `overlays/haskell.nix` propagates `builderVersion` / `cabalProjectLocal` through `addProjectAndPackageAttrs`, dispatches `shellFor` on `builderVersion`, and rebuilds iserv-proxy as both a non-profiled and profiled variant — v2 reads the prof variant from `package iserv-proxy profiling: True` in cabal.project rather than `enableProfiling = true` on the .override (which v2 doesn't honour). * `overlays/linux-cross.nix` + `overlays/mingw_w64.nix` add a `wrapGhc` derivation that bakes `-fexternal-interpreter -pgmi <iserv-wrapper>` into ghc itself — v2 can't put those into per-package `ghc-options:` (UnitId divergence), so it wraps the compiler instead. The `compilerSelection` chain picks the wrapped ghc on cross targets. Internal projects pin v1: * `compiler/ghc/default.nix` (hadrian) and `overlays/bootstrap.nix` (hscolour) set `builderVersion = 1` explicitly so v2 evolution doesn't churn GHC builds while v2 is still settling. `overlays/tools.nix` defaults `haskell-nix.tool` invocations to v1 for the same reason. Tests are NOT migrated in this commit — the existing tests run under v1 (the default) and exercise master's behaviour as before. A follow-up will migrate or duplicate them under v2 once we know which expectations need adjusting.
Bake `--optimistic-linking` into iserv-proxy / iserv-proxy-interpreter at link time via `-with-rtsopts`. `GHC/Linker/Executable.hs` emits this into the generated `main.c` as `__conf.rts_opts`, which `setupRtsFlags` processes with `RtsOptsAll` — bypassing the `OPTION_UNSAFE` gate that `+RTS --optimistic-linking -RTS` on the command line is subject to. Makes the runtime linker tolerate undefined symbols when loading object files at TH-eval time; splices that don't actually reference the missing symbol then resolve fine instead of aborting the load. `-rtsopts=all` is kept so wrapper scripts / GHCRTS can still override at invocation. `--optimistic-linking` is only available in GHC's RTS from 9.14 onwards; gated on the Nix side since cabal.project doesn't allow `if` inside a `package` stanza. Refactor `cabalProjectLocal` for the iserv-proxy project from `//`-chained `optionalAttrs` blocks to a single string built via `optionalString` concatenation so the new directive can compose with the existing aarch64+<9.8 threaded gate without the last `//` clobbering it. Also drop the previous `allow-newer: *:base, *:bytestring` block on GHC > 9.10. The bounds in iserv-proxy.cabal (`base < 5`, `bytestring < 0.13`, etc.) already accommodate current GHCs; if a transitive package needs relaxation we'll re-add a more targeted allow-newer once we know which one. Pulled out of #2504 (`hkm/builder-v2`).
Flake lock file updates:
• Updated input 'haskell-nix':
'github:input-output-hk/haskell.nix/131f8cc' (2026-05-16)
→ 'github:input-output-hk/haskell.nix/ddc0742' (2026-05-23)
• Updated input 'haskell-nix/hackage':
'github:input-output-hk/hackage.nix/a482aef' (2026-05-16)
→ 'github:input-output-hk/hackage.nix/ed56358' (2026-05-23)
• Updated input 'haskell-nix/hackage-for-stackage':
'github:input-output-hk/hackage.nix/ab71329' (2026-05-16)
→ 'github:input-output-hk/hackage.nix/ba0ca9b' (2026-05-23)
• Updated input 'haskell-nix/stackage':
'github:input-output-hk/stackage.nix/c1f217f' (2026-05-16)
→ 'github:input-output-hk/stackage.nix/acd47a6' (2026-05-23)
Flake lock file updates:
• Updated input 'haskellNix':
'github:input-output-hk/haskell.nix/cc939d0' (2026-02-23)
→ 'github:input-output-hk/haskell.nix/ddc0742' (2026-05-23)
• Removed input 'haskellNix/cabal-32'
• Updated input 'haskellNix/hackage':
'github:input-output-hk/hackage.nix/06f38c7' (2026-02-23)
→ 'github:input-output-hk/hackage.nix/ed56358' (2026-05-23)
• Updated input 'haskellNix/hackage-for-stackage':
'github:input-output-hk/hackage.nix/2d5bbb1' (2026-02-23)
→ 'github:input-output-hk/hackage.nix/ba0ca9b' (2026-05-23)
• Updated input 'haskellNix/iserv-proxy':
'github:stable-haskell/iserv-proxy/91ef7ff' (2026-02-04)
→ 'github:stable-haskell/iserv-proxy/3f7b281' (2026-04-08)
• Updated input 'haskellNix/nixpkgs-2511':
'github:NixOS/nixpkgs/b0924ea' (2025-12-01)
→ 'github:NixOS/nixpkgs/74b8795' (2026-04-09)
• Updated input 'haskellNix/nixpkgs-unstable':
'github:NixOS/nixpkgs/c1cb7d0' (2025-12-01)
→ 'github:NixOS/nixpkgs/1304392' (2026-04-11)
• Updated input 'haskellNix/stackage':
'github:input-output-hk/stackage.nix/862226e' (2026-02-23)
→ 'github:input-output-hk/stackage.nix/acd47a6' (2026-05-23)
• Updated input 'iohk-nix':
'github:input-output-hk/iohk-nix/a704b93' (2025-11-12)
→ 'github:input-output-hk/iohk-nix/9de0011' (2026-05-05)
• Updated input 'iohk-nix/blst':
'github:supranational/blst/8c7db7f' (2025-02-12)
→ 'github:supranational/blst/6d960cd' (2025-06-06)