Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .changeset/chain-interface.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
"@evolution-sdk/evolution": patch
"@evolution-sdk/devnet": patch
Comment on lines +2 to +3
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Suggested change
"@evolution-sdk/evolution": patch
"@evolution-sdk/devnet": patch
"@evolution-sdk/evolution": major
"@evolution-sdk/devnet": major

Copilot uses AI. Check for mistakes.
---

`createClient` now requires an explicit `chain` field instead of the optional `network?: string` field.

Previously, selecting a network required passing a string identifier and, separately, a `slotConfig` object for slot/time conversions. There was no single source of truth that tied network identity, magic number, and timing parameters together:

```ts
// Before
createClient({
network: "preprod",
slotConfig: { zeroTime: 1655769600000n, zeroSlot: 86400n, slotLength: 1000 },
provider: { ... },
wallet: { ... }
})
```

Now the `chain` field is a rich descriptor that carries all of this together. Three built-in constants are exported from the top-level package:

```ts
// After
import { createClient, preprod } from "@evolution-sdk/evolution"

createClient({
chain: preprod,
provider: { ... },
wallet: { ... }
})
```

For custom networks — local devnets, private chains, or future forks — use `defineChain`:

```ts
import { defineChain } from "@evolution-sdk/evolution"

const devnet = defineChain({
name: "Devnet",
id: 0,
networkMagic: 42,
slotConfig: { zeroTime: 0n, zeroSlot: 0n, slotLength: 1000 },
epochLength: 432000,
})
```

The `networkId: number | string` property on client objects is replaced with `chain: Chain`. The `@evolution-sdk/devnet` package adds `getChain(cluster)` and `BOOTSTRAP_CHAIN` for constructing a `Chain` from a running local devnet.
4 changes: 2 additions & 2 deletions docs/content/docs/addresses/construction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ const bech32 = Address.toBech32(address)
## Getting Your Wallet Address

```typescript twoslash
import { createClient } from "@evolution-sdk/evolution"
import { createClient, preprod} from "@evolution-sdk/evolution"

const client = createClient({
network: "preprod",
chain: preprod,
wallet: { type: "seed", mnemonic: process.env.WALLET_MNEMONIC!, accountIndex: 0 }
})

Expand Down
6 changes: 3 additions & 3 deletions docs/content/docs/advanced/custom-providers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ interface ProviderEffect {
## Using a Provider

```typescript twoslash
import { createClient } from "@evolution-sdk/evolution"
import { createClient, preprod} from "@evolution-sdk/evolution"

// Blockfrost
const blockfrostClient = createClient({
network: "preprod",
chain: preprod,
provider: {
type: "blockfrost",
baseUrl: "https://cardano-preprod.blockfrost.io/api/v0",
Expand All @@ -52,7 +52,7 @@ const blockfrostClient = createClient({

// Kupo/Ogmios
const kupmiosClient = createClient({
network: "preprod",
chain: preprod,
provider: {
type: "kupmios",
kupoUrl: "http://localhost:1442",
Expand Down
12 changes: 6 additions & 6 deletions docs/content/docs/advanced/error-handling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ Evolution SDK is built on Effect, providing structured error handling with typed
The standard `.build()`, `.sign()`, `.submit()` methods return Promises. Errors throw as exceptions:

```typescript twoslash
import { Address, Assets, createClient } from "@evolution-sdk/evolution"
import { Address, Assets, createClient, preprod} from "@evolution-sdk/evolution"

const client = createClient({
network: "preprod",
chain: preprod,
provider: { type: "blockfrost", baseUrl: "https://cardano-preprod.blockfrost.io/api/v0", projectId: process.env.BLOCKFROST_API_KEY! },
wallet: { type: "seed", mnemonic: process.env.WALLET_MNEMONIC!, accountIndex: 0 }
})
Expand All @@ -50,10 +50,10 @@ Use `.buildEffect()` for composable error handling with Effect:

```typescript twoslash
import { Effect } from "effect"
import { Address, Assets, createClient } from "@evolution-sdk/evolution"
import { Address, Assets, createClient, preprod} from "@evolution-sdk/evolution"

const client = createClient({
network: "preprod",
chain: preprod,
provider: { type: "blockfrost", baseUrl: "https://cardano-preprod.blockfrost.io/api/v0", projectId: process.env.BLOCKFROST_API_KEY! },
wallet: { type: "seed", mnemonic: process.env.WALLET_MNEMONIC!, accountIndex: 0 }
})
Expand All @@ -76,10 +76,10 @@ const program = client
Use `.buildEither()` for explicit success/failure without exceptions:

```typescript twoslash
import { Address, Assets, createClient } from "@evolution-sdk/evolution"
import { Address, Assets, createClient, preprod} from "@evolution-sdk/evolution"

const client = createClient({
network: "preprod",
chain: preprod,
provider: { type: "blockfrost", baseUrl: "https://cardano-preprod.blockfrost.io/api/v0", projectId: process.env.BLOCKFROST_API_KEY! },
wallet: { type: "seed", mnemonic: process.env.WALLET_MNEMONIC!, accountIndex: 0 }
})
Expand Down
8 changes: 4 additions & 4 deletions docs/content/docs/advanced/performance.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ Evolution SDK provides several configuration options to optimize transaction bui
The default algorithm is `"largest-first"`. You can also provide a custom coin selection function:

```typescript twoslash
import { Address, Assets, createClient } from "@evolution-sdk/evolution"
import { Address, Assets, createClient, preprod} from "@evolution-sdk/evolution"

const client = createClient({
network: "preprod",
chain: preprod,
provider: { type: "blockfrost", baseUrl: "https://cardano-preprod.blockfrost.io/api/v0", projectId: process.env.BLOCKFROST_API_KEY! },
wallet: { type: "seed", mnemonic: process.env.WALLET_MNEMONIC!, accountIndex: 0 }
})
Expand All @@ -40,10 +40,10 @@ const tx = await client
The `unfrack` option optimizes your wallet's UTxO structure during transaction building:

```typescript twoslash
import { Address, Assets, createClient } from "@evolution-sdk/evolution"
import { Address, Assets, createClient, preprod} from "@evolution-sdk/evolution"

const client = createClient({
network: "preprod",
chain: preprod,
provider: { type: "blockfrost", baseUrl: "https://cardano-preprod.blockfrost.io/api/v0", projectId: process.env.BLOCKFROST_API_KEY! },
wallet: { type: "seed", mnemonic: process.env.WALLET_MNEMONIC!, accountIndex: 0 }
})
Expand Down
6 changes: 3 additions & 3 deletions docs/content/docs/advanced/typescript.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,17 @@ const addr = Address.fromBech32("addr_test1vrm9x2dgvdau8vckj4duc89m638t8djmluqw5
The client type narrows based on configuration:

```typescript twoslash
import { createClient } from "@evolution-sdk/evolution"
import { createClient, preprod} from "@evolution-sdk/evolution"

// Provider-only client (no wallet) — can query but not sign
const queryClient = createClient({
network: "preprod",
chain: preprod,
provider: { type: "blockfrost", baseUrl: "", projectId: "" }
})

// Signing client (wallet + provider) — full capabilities
const signingClient = createClient({
network: "preprod",
chain: preprod,
provider: { type: "blockfrost", baseUrl: "", projectId: "" },
wallet: { type: "seed", mnemonic: "", accountIndex: 0 }
})
Expand Down
8 changes: 4 additions & 4 deletions docs/content/docs/assets/metadata.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ Transaction metadata lets you attach arbitrary data to transactions without affe
## Attach a Message (CIP-20)

```typescript twoslash
import { Address, Assets, TransactionMetadatum, createClient } from "@evolution-sdk/evolution"
import { Address, Assets, TransactionMetadatum, createClient, preprod} from "@evolution-sdk/evolution"

const client = createClient({
network: "preprod",
chain: preprod,
provider: { type: "blockfrost", baseUrl: "https://cardano-preprod.blockfrost.io/api/v0", projectId: process.env.BLOCKFROST_API_KEY! },
wallet: { type: "seed", mnemonic: process.env.WALLET_MNEMONIC!, accountIndex: 0 }
})
Expand Down Expand Up @@ -49,10 +49,10 @@ await signed.submit()
Chain multiple `attachMetadata` calls for different labels:

```typescript twoslash
import { Address, Assets, TransactionMetadatum, createClient } from "@evolution-sdk/evolution"
import { Address, Assets, TransactionMetadatum, createClient, preprod} from "@evolution-sdk/evolution"

const client = createClient({
network: "preprod",
chain: preprod,
provider: { type: "blockfrost", baseUrl: "https://cardano-preprod.blockfrost.io/api/v0", projectId: process.env.BLOCKFROST_API_KEY! },
wallet: { type: "seed", mnemonic: process.env.WALLET_MNEMONIC!, accountIndex: 0 }
})
Expand Down
30 changes: 15 additions & 15 deletions docs/content/docs/clients/architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ interface ReadOnlyWalletConfig {
### Backend Transaction Building

```typescript twoslash
import { Address, Assets, Transaction, createClient } from "@evolution-sdk/evolution";
import { Address, Assets, Transaction, createClient, mainnet } from "@evolution-sdk/evolution";

// Backend: Create provider client, then attach read-only wallet
const providerClient = createClient({
network: "mainnet",
chain: mainnet,
provider: {
type: "blockfrost",
baseUrl: "https://cardano-mainnet.blockfrost.io/api/v0",
Expand Down Expand Up @@ -87,15 +87,15 @@ Frontend applications connect to user wallets through CIP-30 but never have prov
### Implementation

```typescript
import { Address, Assets, Transaction, createClient } from "@evolution-sdk/evolution";
import { Address, Assets, Transaction, createClient, mainnet } from "@evolution-sdk/evolution";

// 1. Connect wallet
declare const cardano: any;
const walletApi = await cardano.eternl.enable();

// 2. Create signing-only client
const client = createClient({
network: "mainnet",
chain: mainnet,
wallet: { type: "api", api: walletApi }
});

Expand Down Expand Up @@ -138,13 +138,13 @@ Backend services use read-only wallets configured with user addresses to build u
### Implementation

```typescript
import { Address, Assets, Transaction, createClient } from "@evolution-sdk/evolution";
import { Address, Assets, Transaction, createClient, mainnet } from "@evolution-sdk/evolution";

// Backend endpoint
export async function buildTransaction(userAddress: string) {
// Create read-only client with user's address
const client = createClient({
network: "mainnet",
chain: mainnet,
provider: {
type: "blockfrost",
baseUrl: "https://cardano-mainnet.blockfrost.io/api/v0",
Expand Down Expand Up @@ -193,7 +193,7 @@ export type BuildPaymentResponse = { txCbor: string };

// @filename: frontend.ts
// ===== Frontend (Browser) =====
import { Address, Assets, Transaction, createClient } from "@evolution-sdk/evolution";
import { Address, Assets, Transaction, createClient, mainnet } from "@evolution-sdk/evolution";
import type { BuildPaymentResponse } from "./shared";

declare const cardano: any;
Expand All @@ -202,7 +202,7 @@ async function sendPayment(recipientAddress: string, lovelace: bigint) {
// 1. Connect user wallet
const walletApi = await cardano.eternl.enable();
const walletClient = createClient({
network: "mainnet",
chain: mainnet,
wallet: { type: "api", api: walletApi }
});

Expand Down Expand Up @@ -232,7 +232,7 @@ async function sendPayment(recipientAddress: string, lovelace: bigint) {

// @filename: backend.ts
// ===== Backend (Server) =====
import { Address, Assets, Transaction, createClient } from "@evolution-sdk/evolution";
import { Address, Assets, Transaction, createClient, mainnet } from "@evolution-sdk/evolution";

export async function buildPayment(
userAddressBech32: string,
Expand All @@ -244,7 +244,7 @@ export async function buildPayment(

// Create provider client first, then attach read-only wallet
const providerClient = createClient({
network: "mainnet",
chain: mainnet,
provider: {
type: "blockfrost",
baseUrl: "https://cardano-mainnet.blockfrost.io/api/v0",
Expand Down Expand Up @@ -302,7 +302,7 @@ User keys never leave their device. Provider API keys never exposed to frontend.
```typescript
// WRONG - Frontend has no provider
const client = createClient({
network: "mainnet",
chain: mainnet,
wallet: { type: "api", api: walletApi }
// No provider!
});
Expand All @@ -315,7 +315,7 @@ const builder = client.newTx(); // Error: Cannot build without provider
```typescript
// CORRECT - Frontend signs, backend builds
const client = createClient({
network: "mainnet",
chain: mainnet,
wallet: { type: "api", api: walletApi }
});

Expand All @@ -328,7 +328,7 @@ const witnessSet = await client.signTx(txCborFromBackend);
```typescript
// WRONG - Backend has no private keys
const client = createClient({
network: "mainnet",
chain: mainnet,
provider: { /* ... */ },
wallet: {
type: "read-only",
Expand All @@ -344,8 +344,8 @@ await client.sign(); // Error: Cannot sign with read-only wallet
```typescript
// CORRECT - Backend builds, frontend signs
const client = createClient({
network: "mainnet",
provider: { /* ... */ },
chain: mainnet,
provider: { /* ... */ },
wallet: {
type: "read-only",
address: userAddress
Expand Down
Loading
Loading