feat(client): replace NetworkId with Chain descriptor#223
feat(client): replace NetworkId with Chain descriptor#223solidsnakedev wants to merge 25 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR replaces the loosely-typed network (+ separate slotConfig) client configuration with a required chain: Chain descriptor that bundles network identity, network magic, and slot timing parameters into a single object, and updates docs/examples/devnet tooling accordingly.
Changes:
- Introduces
Chain+defineChain, and exports built-inmainnet,preprod,previewconstants from the top-level package. - Updates
createClientand related client types to usechainand to source slot timing directly fromchain.slotConfig. - Adds devnet helpers (
getChain(cluster)andBOOTSTRAP_CHAIN) and migrates several devnet tests/docs/examples to the new API.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/evolution/src/sdk/client/ClientImpl.ts | Reworks createClient to require chain and wires chain.slotConfig into tx building. |
| packages/evolution/src/sdk/client/Client.ts | Updates public client types to expose chain instead of networkId where applicable and removes NetworkId type. |
| packages/evolution/src/sdk/client/Chain.ts | Adds the Chain model, defineChain, and built-in chain constants. |
| packages/evolution/src/index.ts | Re-exports chain utilities/constants from the package entrypoint. |
| packages/evolution-devnet/test/TxBuilder.VoteValidators.test.ts | Migrates devnet test setup to use Cluster.getChain(...) / BOOTSTRAP_CHAIN. |
| packages/evolution-devnet/test/TxBuilder.Validity.test.ts | Migrates validity-interval devnet tests to chain API. |
| packages/evolution-devnet/test/TxBuilder.SpendScriptRef.test.ts | Migrates script-ref devnet tests to chain API. |
| packages/evolution-devnet/test/TxBuilder.PlutusMint.test.ts | Migrates Plutus minting devnet tests to chain API. |
| packages/evolution-devnet/test/TxBuilder.Metadata.test.ts | Migrates metadata devnet tests to chain API. |
| packages/evolution-devnet/test/TxBuilder.Compose.test.ts | Migrates compose devnet tests to chain API. |
| packages/evolution-devnet/test/TxBuilder.Chain.test.ts | Migrates chainResult devnet tests to chain API. |
| packages/evolution-devnet/test/Client.Devnet.test.ts | Migrates devnet client test to chain API. |
| packages/evolution-devnet/src/Cluster.ts | Adds getChain(cluster) and BOOTSTRAP_CHAIN to produce Chain descriptors for devnet usage. |
| examples/with-vite-react/src/components/TransactionBuilder.tsx | Updates example app to select a Chain constant and pass it to createClient. |
| docs/content/docs/clients/providers.mdx | Updates provider docs snippets to pass chain: preprod. |
| docs/content/docs/clients/index.mdx | Updates overview docs to describe chain configuration. |
| docs/content/docs/clients/client-basics.mdx | Adds chain configuration section and updates examples to use built-in chain constants. |
| docs/content/docs/clients/architecture.mdx | Updates architecture examples to use chain: mainnet. |
| .changeset/chain-interface.md | Documents the chain migration and the devnet chain helpers. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Chain only → MinimalClient | ||
| export function createClient(config: { chain: Chain }): MinimalClient | ||
|
|
||
| // Implementation signature - handles all cases (all synchronous now) | ||
| export function createClient(config?: { | ||
| network?: NetworkId | ||
| export function createClient(config: { | ||
| chain: Chain | ||
| provider?: ProviderConfig |
There was a problem hiding this comment.
This change makes createClient require a chain and removes the optional/no-arg overloads, but there are still call sites in the repo using the old { network, slotConfig } shape and/or createClient() with no args (e.g. docs/app/(home)/page.tsx, packages/evolution-devnet/test/TxBuilder.AddSigner.test.ts, TxBuilder.Governance.test.ts, TxBuilder.Mint.test.ts, TxBuilder.NativeScript.test.ts, TxBuilder.Pool.test.ts, TxBuilder.RedeemerBuilder.test.ts, TxBuilder.ScriptStake.test.ts, TxBuilder.Stake.test.ts, TxBuilder.Vote.test.ts, and .specs/client-module-workflow.md). Those need to be migrated (or the old overload kept) or the build/tests/docs will fail.
.changeset/chain-interface.md
Outdated
| "@evolution-sdk/evolution": patch | ||
| "@evolution-sdk/devnet": patch |
There was a problem hiding this comment.
This changeset marks the release as a patch, but replacing network?: NetworkId with required chain: Chain (and removing createClient() / default-network behavior) is a breaking public API change. The changeset should be a major bump (or at least follow the repo’s documented semver policy for breaking changes).
| "@evolution-sdk/evolution": patch | |
| "@evolution-sdk/devnet": patch | |
| "@evolution-sdk/evolution": major | |
| "@evolution-sdk/devnet": major |
| @@ -58,13 +59,13 @@ export default function TransactionBuilder() { | |||
|
|
|||
| const providerConfig = { | |||
| type: "blockfrost" as const, | |||
| baseUrl: blockfrostUrls[networkId as keyof typeof blockfrostUrls], | |||
| baseUrl: blockfrostUrls[networkEnv as keyof typeof blockfrostUrls], | |||
| projectId: import.meta.env.VITE_BLOCKFROST_PROJECT_ID || "" | |||
There was a problem hiding this comment.
chain falls back to preprod when networkEnv is not one of the known keys, but providerConfig.baseUrl still indexes blockfrostUrls using networkEnv, which will be undefined in that fallback case. Use the same resolved key used for chain (or derive the URL from chain) so the provider config stays consistent with the chosen chain.
docs/content/docs/clients/index.mdx
Outdated
| ```typescript | ||
| import { mainnet, preprod, preview, defineChain } from "@evolution-sdk/evolution"; | ||
|
|
||
| createClient({ | ||
| network: "mainnet" | "preprod" | "preview", | ||
| provider?: ProviderConfig, // Optional | ||
| wallet?: WalletConfig // Optional | ||
| chain: mainnet | preprod | preview, // or a custom chain via defineChain(...) | ||
| provider?: ProviderConfig, // Optional | ||
| wallet?: WalletConfig // Optional | ||
| }) |
There was a problem hiding this comment.
This code sample calls createClient(...) but doesn’t import it (and also references ProviderConfig/WalletConfig without imports). The snippet should include createClient in the import (and either import the types or make the snippet explicitly schematic) so readers can copy/paste it without errors.
- Update wallet guide MDX files (api-wallet, private-key, seed-phrase) to use chain constants instead of network strings, fixing twoslash build errors (TS2769) - Migrate all 9 devnet test files from `network: 0` to `chain: Cluster.getChain(cluster)` / `Cluster.BOOTSTRAP_CHAIN`, fixing TypeError on `chain.id` - Update Cluster.getSlotConfig JSDoc example - Regenerate module reference docs
- Replace network: "preprod" / "mainnet" / "preview" with chain: preprod / mainnet / preview - Replace network: 0 with chain: Cluster.BOOTSTRAP_CHAIN / Cluster.getChain(cluster) - Add chain constant imports to all twoslash code blocks - Fix BOOTSTRAP_CHAIN epochLength type (number | undefined -> number) - Fix as const on chain references in provider-only-client.mdx - Update migration-from-lucid table and wallets/security guidance 52 docs files + 1 source file updated
Delete files superseded by the chain-interface refactor: - TxBuilderImpl.ts, SignBuilderImpl.ts, SubmitBuilderImpl.ts → replaced by modular internal/ architecture - EvaluationStateManager.ts → moved to sdk/builders/internal/ - phases/utils.ts → renamed to phases/Calculations.ts - provider/internal/HttpUtils.ts → renamed to Http.ts - sdk/wallet/WalletNew.ts → replaced by typed Wallet.ts - NativeScriptsOLD.ts → old duplicate removed - sdk/index.ts → empty barrel, no longer needed
- Address.ts: add helpers for the new chain-interface patterns - UTxO.ts: extend UTxO type surface - FeeValidation.ts: add fee validation utilities extracted from builder - index.ts: export EvalRedeemer module
Replace WalletNew.ts with a properly typed Wallet.ts: - ReadOnlyWallet, SigningWallet, ApiWallet types with Effect interface - makeReadOnlyWalletEffect, makeSigningWalletEffect, makePrivateKeyWalletEffect, makeApiWalletEffect factories - Derivation.ts updated to align with new wallet types
- Move implementation details into internal/ directory: TxAssembly, SignBuilderImpl, SubmitBuilderImpl, EvaluationStateManager, UtxoAnalysis, TxOutput - Rename phases/utils.ts → phases/Calculations.ts - Rename UtxoUtils.ts → UtxoAnalysis.ts, OutputUtils.ts → TxOutput.ts - Rename allRedeemersEvaluated → areAllRedeemersEvaluated - Rename attachScriptToState → createAttachScriptProgram - Remove leaked SignBuilderImpl/SubmitBuilderImpl from public index - TransactionBuilder.ts: add makeCapabilityTxBuilder alongside legacy makeTxBuilder - SignBuilder, SubmitBuilder: thin public wrappers over internal impls
New pattern: client(chain).with(provider).with(wallet).newTx() - Capabilities.ts: QueryUtxos, Signable, Addressable, Submittable types - attachCapabilities.ts: auto-derives Promise methods from Effect interface - Per-provider modules: Blockfrost.ts, Koios.ts, Kupmios.ts, Maestro.ts - Client.ts: client() factory, provider/wallet attachment, newTx() - Chain.ts: extend with slotConfig and helpers
- Extract types to ClientLegacy.ts (clean type-only module) - Add Wallets.ts for wallet construction helpers - ClientImpl.ts: rename WalletNew → Wallet, KoiosProvider, add @deprecated JSDoc - createClient overloads preserved for backward compatibility
- HttpUtils.ts → Http.ts (cleaner name, no utils anti-pattern) - Update all provider effect files to import from Http.ts - Rename Koios class → KoiosProvider for consistency with BlockfrostProvider, MaestroProvider, KupmiosProvider
- Wallet.test.ts: new tests for Effect-based wallet factories - TxBuilder.SlotConfig.test.ts: rewrite using newTx(client(chain)) pattern - providers.test.ts: update KoiosProvider rename - All TxBuilder tests: align imports with new modular structure - Add sdk/ test directory for composable client tests
- Cluster.ts: add getChain helper and BOOTSTRAP_CHAIN constant - Add Client.WatchUtxos.test.ts integration test - Migrate TxBuilder.Governance.test.ts: add missing Cardano import - All devnet tests: align with new client(chain).with(provider) pattern
SigningClient and other legacy types were missing from the public index after moving them to ClientLegacy.ts. Docs twoslash blocks import them via @evolution-sdk/evolution, causing CI build failure TS2305.
- TxBuilder.Vote.test.ts: restore 4th account in beforeAll setup; addressHexes[3] was undefined causing GenesisError on cluster start - TxBuilder.NativeScript.test.ts: pass referenceUtxos explicitly to client2.signTx() for reference-script tests; composable client does not auto-fetch reference UTxOs unlike the legacy SigningClient
- Add getUtxosWithUnit and getUtxoByUnit to all four provider constructors - Add getWalletDelegation to seedWallet and privateKeyWallet (auto-resolves reward address) - Auto-fetch reference UTxOs in signTx for both seedWallet and privateKeyWallet when a provider with getUtxosByOutRef is present — fixes phase-1 native script validation with reference scripts
…pt test Auto-fetch now handles this in seedWallet signTx
The
network?: stringfield oncreateClientcarried a string identifier but left slot timing, network magic, and chain identity as separate concerns that callers had to assemble manually. There was no type that encoded all of these together, and theslotConfigtop-level parameter was easy to omit or misconfigure.This replaces
networkwith a requiredchain: Chainfield. Three built-in constants —mainnet,preprod,preview— are exported from the top-level package. Each constant carries the chain name, id, network magic, slot config, and epoch length in one object. AdefineChainhelper allows custom chains for local devnets and private forks. ThenetworkIdproperty on returned client objects is replaced withchain. The@evolution-sdk/devnetpackage gainsgetChain(cluster)andBOOTSTRAP_CHAINfor test setup.