Skip to content

Update Scalus to 1.2 - #845

Open
nau wants to merge 3 commits into
MeshJS:mainfrom
nau:feat/scalus-provider-parity
Open

nau wants to merge 3 commits into
MeshJS:mainfrom
nau:feat/scalus-provider-parity

Conversation

@nau

@nau nau commented Sep 15, 2026

Copy link
Copy Markdown

Moves OfflineEvaluatorScalus and @meshsdk/scalus-emulator from Scalus 0.17 to 1.2.1.

Emulator

Scalus 1.2's JS emulator is a full provider backend, so the Mesh package drops its own CBOR decoding, protocol-parameter table and eval plumbing (src/index.ts: -301/+184):

  • evaluateTx with PV11 cost models, per-redeemer budgets
  • getUtxos(filter) - address, paymentCredential + paymentCredentialType (key/script), unit, txHash, outRefs, minLovelace, limit. Filtering runs in the ledger; returns decoded UTxOs, not CBOR
  • submitTx through the real ledger rules; SubmitResult carries errorRule and logs
  • getProtocolParameters, getDatum, getDelegation, getStakeDistribution, getStakeReward, getTransactionStatus
  • slot/time control: setSlot, setTime, tick, snapshot

Pure JS, no wasm. 2.82 MB raw, 627 KB gzipped. For comparison whisky-evaluator is 6.4 MB raw / 1.55 MB gzipped.

Emulator tests 20 -> 24: script spend, mint, validity intervals, collateral, metadata, queries by hash and by asset.

Evaluator

  • Dynamic import() inside evaluateTx, so the ESM and CJS builds work off one path (Scalus 1.x is ESM)
  • scalus declared in core-cst where it's imported; dropped from @meshsdk/core, which doesn't import it
  • Defaults to protocol major version 11; pass 10 for pre-van-Rossem budgets. The pinned budget is identical under both - explicit cost models, no version-gated builtin
  • Redeemer tags via a table typed on Scalus's tag union. Voting/Proposing map to VOTE/PROPOSE; a new upstream tag is a compile error
  • Uses top-level evalPlutusScripts; the Scalus namespace is deprecated

Tests

@meshsdk/core-cst        179 + 1
@meshsdk/scalus-emulator  24
test:scalus-packages      ESM, CJS, .d.ts, headless Chrome

test:scalus-packages packs and installs both packages and drives them as a consumer would, so publish-only breakage is caught. All wired into build.yml.

The Scalus test needs its own jest config: the default run is CJS, ts-jest rewrites import() to require(), and an ESM-only package can't load that way.

Node

No engines changes. Scalus 1.2.0 required >=20; I measured that it wasn't needed and released 1.2.1 with >=18.

nau added 3 commits September 14, 2026 21:03
OfflineEvaluatorScalus imported `scalus` at the top level, and core-cst had no
`scalus` dependency of its own - it resolved only by hoisting from
@meshsdk/core. Scalus 1.x is ESM-only, so a top-level import cannot work in the
CommonJS build.

The dependency is now declared where it is used, and Scalus loads through a
dynamic import() inside evaluateTx, which survives the CJS output. The call site
uses the top-level `evalPlutusScripts`; the `Scalus` namespace object that used
to carry it is a 0.x shape kept for backwards compatibility, and is deprecated.

The evaluator now defaults to protocol major version 11, the version mainnet
runs, instead of 10. Pass 10 explicitly to reproduce pre-van-Rossem budgets. The
figure the test pins does not move with the protocol version: cost models are
supplied explicitly and the script uses no version-gated builtin, so PV1 through
PV99 return the same budget.

Redeemer tags are mapped through a table keyed on Scalus's own tag union rather
than `string`, so a tag added upstream is a compile error here instead of a
runtime throw. The previous `.toUpperCase()` silently produced "VOTING" and
"PROPOSING", which are not valid RedeemerTagType values.
@meshsdk/scalus-emulator was written against Scalus 0.17 and pinned ^0.17.0, so
it never saw the 1.x line. Scalus 1.2 makes the JavaScript emulator a
self-sufficient provider backend: it answers protocol parameters, evaluates its
own transactions, serves indexed UTxO queries and returns decoded UTxOs.

The provider is rebuilt on that surface, which removes the CBOR decoding,
protocol-parameter table and evaluation plumbing it used to carry. Redeemer tags
are keyed on Scalus's tag union for the same reason as in core-cst.
The suites exercise the workspace sources. They would not catch a package that
is broken only once published: a missing dependency, an export map that does not
resolve, or an ESM-only bundle failing under require().

scripts/test-scalus-packages.mjs packs and installs the two packages and drives
them the way a consumer would, in Node and in headless Chrome, and CI runs it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant