diff --git a/.github/workflows/check-doc-links.yml b/.github/workflows/check-doc-links.yml new file mode 100644 index 00000000..1cd2c061 --- /dev/null +++ b/.github/workflows/check-doc-links.yml @@ -0,0 +1,31 @@ +name: Check Doc Links + +# Fails a PR when current docs (docs/) contain browser-relative internal links +# that should be source-tree-relative .md / Card docId links. Run +# `npm run normalize-doc-links` locally to fix. Scoped to docs/ only; +# versioned_docs snapshots are healed at deploy time, not validated here. +on: + pull_request: + paths: + - "docs/**" + - "scripts/normalize-doc-links.mjs" + - ".github/workflows/check-doc-links.yml" + +jobs: + check-doc-links: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: "npm" + + - name: Install deps + run: npm install --frozen-lockfile + + - name: Check doc links + run: npm run check:doc-links diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 21a58a83..46e40a25 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -317,6 +317,12 @@ jobs: - name: Install deps run: npm install --frozen-lockfile + # Heal browser-relative internal links across the whole tree (current docs + # + every versioned_docs snapshot) before building. Versioned snapshots are + # not normalized in-repo, so this is where historical versions get fixed. + - name: Normalize docs links + run: npm run normalize-doc-links:all + - name: Build site env: NODE_OPTIONS: "--max-old-space-size=12288" # 12GB diff --git a/docs/builder/get-started/accounts.md b/docs/builder/get-started/accounts.md index b25fad61..74ef9e26 100644 --- a/docs/builder/get-started/accounts.md +++ b/docs/builder/get-started/accounts.md @@ -113,7 +113,7 @@ To run the code examples in this guide, you'll need to set up a development envi ### Rust Environment -If you already created `my-test-project` during [installation](./setup/installation#rust-project), you can reuse it. Otherwise, create a new project: +If you already created `my-test-project` during [installation](./setup/installation.md#rust-project), you can reuse it. Otherwise, create a new project: ```bash title=">_ Terminal" miden new my-project @@ -134,7 +134,7 @@ cargo run --bin demo --release ### TypeScript Environment -If you already created `miden-app` during [installation](./setup/installation#typescript-project), you can reuse it. Otherwise, scaffold a new Vite vanilla-ts project: +If you already created `miden-app` during [installation](./setup/installation.md#typescript-project), you can reuse it. Otherwise, scaffold a new Vite vanilla-ts project: ```bash title=">_ Terminal" npm create vite@latest miden-app -- --template vanilla-ts @@ -165,7 +165,7 @@ npm run dev Open the dev-server URL in the browser and watch the devtools console for output. :::tip -For detailed frontend setup guidance (React, wallets, UI), see the [Tutorials section](../tutorials/). +For detailed frontend setup guidance (React, wallets, UI), see the [Tutorials section](../tutorials/index.md). ::: ## Creating Accounts Programmatically @@ -406,6 +406,6 @@ Faucet account ID: 0xde0ba31282f7522046d3d4af40722b - **BasicFungibleFaucet**: Enables token minting capabilities - **AuthSingleSig**: Handles cryptographic authentication (Falcon512 or ECDSA via the `AuthScheme` enum) -Now that you understand how to create accounts and faucets, you're ready to learn about Miden's unique transaction model. Continue to [Notes & Transactions](./notes) to explore how assets move between accounts using notes. +Now that you understand how to create accounts and faucets, you're ready to learn about Miden's unique transaction model. Continue to [Notes & Transactions](./notes.md) to explore how assets move between accounts using notes. --- diff --git a/docs/builder/get-started/index.md b/docs/builder/get-started/index.md index 120fb9a1..e22bb0fb 100644 --- a/docs/builder/get-started/index.md +++ b/docs/builder/get-started/index.md @@ -25,22 +25,22 @@ Key concepts you'll encounter: Follow these guides in order: - + Install the Miden toolchain with `midenup`. - + Essential Miden CLI commands — create a wallet and mint your first tokens. - + Create and manage Miden accounts programmatically in Rust and TypeScript. - + Miden's note-based transaction model for private asset transfers. - + Query account storage data and interact with deployed smart contracts. - + Build, test, and deploy a smart contract on Miden using Rust. diff --git a/docs/builder/get-started/notes.md b/docs/builder/get-started/notes.md index b77bc8a0..0c3110c2 100644 --- a/docs/builder/get-started/notes.md +++ b/docs/builder/get-started/notes.md @@ -57,7 +57,7 @@ This approach provides several advantages over direct transfers: ## Set Up Development Environment -To run the code examples in this guide, you'll need to set up a development environment. If you haven't already, follow the setup instructions in the [Accounts](./accounts#set-up-development-environment) guide. +To run the code examples in this guide, you'll need to set up a development environment. If you haven't already, follow the setup instructions in the [Accounts](./accounts.md#set-up-development-environment) guide. ## Minting Tokens diff --git a/docs/builder/get-started/read-storage.md b/docs/builder/get-started/read-storage.md index a0ee4e1e..4ae69074 100644 --- a/docs/builder/get-started/read-storage.md +++ b/docs/builder/get-started/read-storage.md @@ -26,7 +26,7 @@ Miden accounts contain several types of data you can read. ## Set Up Development Environment -To run the code examples in this guide, you'll need to set up a development environment. If you haven't already, follow the setup instructions in the [Accounts](./accounts#set-up-development-environment) guide. +To run the code examples in this guide, you'll need to set up a development environment. If you haven't already, follow the setup instructions in the [Accounts](./accounts.md#set-up-development-environment) guide. ## Reading from a Public Smart Contract diff --git a/docs/builder/get-started/your-first-smart-contract/create.md b/docs/builder/get-started/your-first-smart-contract/create.md index d2cbf59d..009c173d 100644 --- a/docs/builder/get-started/your-first-smart-contract/create.md +++ b/docs/builder/get-started/your-first-smart-contract/create.md @@ -260,6 +260,6 @@ The counter example demonstrates a complete interaction pattern: the account con ## Next Steps -Now that you understand the contract code structure, let's move on to [deploying your contract](./deploy) and learn how the integration folder enables interaction with your contracts on the Miden network. +Now that you understand the contract code structure, let's move on to [deploying your contract](./deploy.md) and learn how the integration folder enables interaction with your contracts on the Miden network. --- diff --git a/docs/builder/get-started/your-first-smart-contract/index.md b/docs/builder/get-started/your-first-smart-contract/index.md index 826cec03..e26c1115 100644 --- a/docs/builder/get-started/your-first-smart-contract/index.md +++ b/docs/builder/get-started/your-first-smart-contract/index.md @@ -31,13 +31,13 @@ The counter example is designed to teach core Miden concepts through a simple, u ## Prerequisites -Before starting this guide, ensure you have completed the [Installation](../setup/installation) tutorial and have: +Before starting this guide, ensure you have completed the [Installation](../setup/installation.md) tutorial and have: - **Rust toolchain** installed and configured - **midenup toolchain** installed with Miden CLI tools :::tip Prerequisites Required -You need those development tools installed for this guide. If you haven't set up your environment yet, please complete the [installation](../setup/installation) guide first. +You need those development tools installed for this guide. If you haven't set up your environment yet, please complete the [installation](../setup/installation.md) guide first. ::: ## No Prior Experience Required @@ -62,9 +62,9 @@ If you get stuck during this tutorial: This tutorial is divided into focused sections: -1. **[Create Your Project](./create)** - Set up your workspace and understand the counter contract code -2. **[Deploy Your Contract](./deploy)** - Learn the integration folder and deploy to testnet -3. **[Test Your Contract](./test)** - Learn how to effectively test your contracts +1. **[Create Your Project](./create.md)** - Set up your workspace and understand the counter contract code +2. **[Deploy Your Contract](./deploy.md)** - Learn the integration folder and deploy to testnet +3. **[Test Your Contract](./test.md)** - Learn how to effectively test your contracts Each section builds on the previous one, so we recommend following them in order. diff --git a/docs/builder/get-started/your-first-smart-contract/test.md b/docs/builder/get-started/your-first-smart-contract/test.md index 76b4917f..d9fcd88a 100644 --- a/docs/builder/get-started/your-first-smart-contract/test.md +++ b/docs/builder/get-started/your-first-smart-contract/test.md @@ -304,7 +304,7 @@ Congratulations! You've successfully completed the Miden smart contract quick st To deepen your knowledge, we recommend exploring the following resources: -- Visit the [Tutorials section](../../tutorials/) for detailed, hands-on guides on topics such as contract interactions, advanced storage, custom note scripting, and integrating with external applications. -- For in-depth technical explanations, consult the [Reference section](../../../reference/) of the documentation. Here you'll find comprehensive information on Miden's architecture, account model, transaction lifecycle, and the underlying zero-knowledge technology that powers the network. +- Visit the [Tutorials section](../../tutorials/index.md) for detailed, hands-on guides on topics such as contract interactions, advanced storage, custom note scripting, and integrating with external applications. +- For in-depth technical explanations, consult the [Reference section](../../../reference/index.md) of the documentation. Here you'll find comprehensive information on Miden's architecture, account model, transaction lifecycle, and the underlying zero-knowledge technology that powers the network. The foundational patterns and concepts you've practiced in this Quick Start will enable you to build complex, privacy-preserving applications on the Miden network. Continue with the resources above to take your development further! diff --git a/docs/builder/glossary.md b/docs/builder/glossary.md index dc20cb0b..6e5e7fea 100644 --- a/docs/builder/glossary.md +++ b/docs/builder/glossary.md @@ -55,7 +55,7 @@ A key-value store associated with an account. Made up of storage slots. ### MultiSig -A multi-signature account on Miden that requires a configurable threshold (N-of-M) of authorized signers to approve transactions before execution. MultiSig workflows are coordinated through [Miden Guardian](./miden-guardian/). +A multi-signature account on Miden that requires a configurable threshold (N-of-M) of authorized signers to approve transactions before execution. MultiSig workflows are coordinated through [Miden Guardian](./miden-guardian/index.md). ## Notes & assets @@ -125,11 +125,11 @@ A data structure that represents the basic unit of computation and storage in Mi ### Miden Guardian -Infrastructure built by OpenZeppelin for managing private account state on Miden. Guardian provides a server and client SDKs for backing up, syncing, and coordinating state across devices and parties without trust assumptions. See the [Miden Guardian documentation](./miden-guardian/). +Infrastructure built by OpenZeppelin for managing private account state on Miden. Guardian provides a server and client SDKs for backing up, syncing, and coordinating state across devices and parties without trust assumptions. See the [Miden Guardian documentation](./miden-guardian/index.md). ### Canonicalization -The background process by which [Miden Guardian](./miden-guardian/) promotes candidate deltas to canonical status by verifying them against the Miden network. +The background process by which [Miden Guardian](./miden-guardian/index.md) promotes candidate deltas to canonical status by verifying them against the Miden network. ### Delta @@ -137,7 +137,7 @@ A Delta represents the changes between two states `s` and `s'`. Applying a Delta ### Delta Proposal -A coordination mechanism in [Miden Guardian](./miden-guardian/) that allows multiple signers to propose, review, and co-sign state changes before they are promoted to a canonical delta. +A coordination mechanism in [Miden Guardian](./miden-guardian/index.md) that allows multiple signers to propose, review, and co-sign state changes before they are promoted to a canonical delta. ### Threshold Signature diff --git a/docs/builder/index.md b/docs/builder/index.md index cc08cb81..239e5200 100644 --- a/docs/builder/index.md +++ b/docs/builder/index.md @@ -11,10 +11,10 @@ Accounts, notes, and transactions — authored in Rust, compiled to MASM, proved ## Start here - + Install midenup, create a wallet, and send your first transaction — in under ten minutes. - + Walk through writing, proving, and deploying a counter contract in Rust. @@ -22,16 +22,16 @@ Accounts, notes, and transactions — authored in Rust, compiled to MASM, proved ## Build - + Accounts, notes, storage, components, transactions — the full Rust SDK surface. - + Real-world examples: the Miden Bank, private multisig, custom note scripts. - + Testing, debugging, and common pitfalls when writing Miden programs. - + Rust, Web, and React SDKs · playground · block explorer · CLI. @@ -39,13 +39,13 @@ Accounts, notes, and transactions — authored in Rust, compiled to MASM, proved ## Ship - + Breaking changes, renames, and new features across accounts, notes, transactions, MASM, and the client. - + Backup, sync, and coordinate private account state across devices. - + Multi-party threshold signature workflows built on Miden. @@ -53,10 +53,10 @@ Accounts, notes, and transactions — authored in Rust, compiled to MASM, proved ## Reference - + Frequently asked questions about Miden. - + Key terms and definitions used throughout the docs. diff --git a/docs/builder/miden-guardian/index.md b/docs/builder/miden-guardian/index.md index 2ed303ee..cb0b22b0 100644 --- a/docs/builder/miden-guardian/index.md +++ b/docs/builder/miden-guardian/index.md @@ -55,22 +55,22 @@ Guardian has an explicit trust boundary: ## Learn more - + Roles, trust boundaries, state flow, and failure behavior. - + State, deltas, commitments, and delta proposals. - + API, authentication, storage, and other server components. - + Trust model, integrity guarantees, and edge cases. - + How to run, deploy, and troubleshoot a Guardian server. - + Multi-party threshold signature workflows powered by Guardian. diff --git a/docs/builder/miden-guardian/operator-guide/running.md b/docs/builder/miden-guardian/operator-guide/running.md index 463c4f17..e57cdc15 100644 --- a/docs/builder/miden-guardian/operator-guide/running.md +++ b/docs/builder/miden-guardian/operator-guide/running.md @@ -103,4 +103,4 @@ cargo run -p guardian-server --features postgres --bin server | `PUT /delta/proposal` | Signed headers | | `/dashboard/accounts*` | Dashboard session | -Signed requests carry three headers: `x-pubkey`, `x-signature`, and `x-timestamp`. Timestamps must be within ±5 minutes of server time and strictly greater than the last value the server saw for that public key — see [Authentication failures](./troubleshooting#authentication-failures) if requests are being rejected. +Signed requests carry three headers: `x-pubkey`, `x-signature`, and `x-timestamp`. Timestamps must be within ±5 minutes of server time and strictly greater than the last value the server saw for that public key — see [Authentication failures](./troubleshooting.md#authentication-failures) if requests are being rejected. diff --git a/docs/builder/migration/05-asset-vault-faucet.md b/docs/builder/migration/05-asset-vault-faucet.md index 94bbfd18..11f5842b 100644 --- a/docs/builder/migration/05-asset-vault-faucet.md +++ b/docs/builder/migration/05-asset-vault-faucet.md @@ -43,7 +43,7 @@ let bal: AssetAmount = vault.get_balance(key)?; ### Summary -The separate `BasicFungibleFaucet` and `NetworkFungibleFaucet` components were merged into a single **`FungibleFaucet`** component, and its old `FungibleFaucetBuilder` was replaced with a `bon`‑generated builder (`FungibleFaucet::builder()`). The constructor accepts a structured `TokenName` plus optional token‑metadata fields and an `AssetAmount` `max_supply`. A companion `FungibleTokenMetadata` component exposes the metadata via MASM getters. For the end‑to‑end client construction recipe (with `TokenPolicyManager`), see [(Rust) `FungibleFaucet` builder + `TokenPolicyManager`](./client-changes#rust-fungiblefaucet-builder--tokenpolicymanager-construction). +The separate `BasicFungibleFaucet` and `NetworkFungibleFaucet` components were merged into a single **`FungibleFaucet`** component, and its old `FungibleFaucetBuilder` was replaced with a `bon`‑generated builder (`FungibleFaucet::builder()`). The constructor accepts a structured `TokenName` plus optional token‑metadata fields and an `AssetAmount` `max_supply`. A companion `FungibleTokenMetadata` component exposes the metadata via MASM getters. For the end‑to‑end client construction recipe (with `TokenPolicyManager`), see [(Rust) `FungibleFaucet` builder + `TokenPolicyManager`](./07-client-changes.md#rust-fungiblefaucet-builder--tokenpolicymanager-construction). ### Affected Code @@ -73,7 +73,7 @@ let faucet = FungibleFaucet::builder() A new **`AssetComposition`** enum (`None`, `Fungible`, `Custom`) discriminates assets, and the asset vault key's metadata byte now encodes the composition (plus the asset‑callback flag). `AssetVaultKey::new(asset_id, faucet_id, composition, callback_flag)` is the general constructor; `AssetVaultKey::new_fungible(faucet_id, callback_flag)` is the fungible shortcut. (`Custom` composition is reserved and currently rejected.) -**What composition means:** it describes how two instances of the same asset combine in a vault — `None` (non‑fungible: instances never merge), `Fungible` (instances merge by summing amounts), and `Custom` (reserved for faucet‑defined logic; rejected at construction today). Because composition is carried in the key's metadata byte rather than derived from the faucet ID, the vault key is self‑describing. Read it back with `AssetVaultKey::composition()` and the callback flag with `AssetVaultKey::callback_flag()`. See the [asset encoding reference](../../reference/protocol/asset#encoding) and [composition reference](../../reference/protocol/asset#composition) for the full layout, and [MASM Changes](./masm-changes#asset-vault-key-composition) for the procedure‑level effects. +**What composition means:** it describes how two instances of the same asset combine in a vault — `None` (non‑fungible: instances never merge), `Fungible` (instances merge by summing amounts), and `Custom` (reserved for faucet‑defined logic; rejected at construction today). Because composition is carried in the key's metadata byte rather than derived from the faucet ID, the vault key is self‑describing. Read it back with `AssetVaultKey::composition()` and the callback flag with `AssetVaultKey::callback_flag()`. See the [asset encoding reference](../../reference/protocol/asset#encoding) and [composition reference](../../reference/protocol/asset#composition) for the full layout, and [MASM Changes](./08-masm-changes.md#asset-vault-key-composition) for the procedure‑level effects. ### Migration Steps diff --git a/docs/builder/migration/07-client-changes.md b/docs/builder/migration/07-client-changes.md index 2db81422..0f0350a3 100644 --- a/docs/builder/migration/07-client-changes.md +++ b/docs/builder/migration/07-client-changes.md @@ -424,7 +424,7 @@ const proven2 = await wasmWebClient.proveTransaction(txResult); ## (Web) `InputNoteRecord.nullifier()` returns `string | undefined` ### Summary -Because a 0.15 nullifier folds in the note's metadata (see [Nullifier now includes metadata and attachments commitment](./note-changes#nullifier-now-includes-metadata-and-attachments-commitment)), a **partial (metadata-less) input note record has no computable nullifier** — `InputNoteRecord.nullifier()` now returns `string | undefined`, pairing with `id()`'s `NoteId | undefined`. A record missing either is a partial note that sync has not yet completed. +Because a 0.15 nullifier folds in the note's metadata (see [Nullifier now includes metadata and attachments commitment](./04-note-changes.md#nullifier-now-includes-metadata-and-attachments-commitment)), a **partial (metadata-less) input note record has no computable nullifier** — `InputNoteRecord.nullifier()` now returns `string | undefined`, pairing with `id()`'s `NoteId | undefined`. A record missing either is a partial note that sync has not yet completed. ### Migration Steps 1. Guard `record.nullifier()` against `undefined` alongside the existing `record.id()` guard; treat records missing either as not-yet-consumable and skip them from listings. diff --git a/docs/builder/migration/08-masm-changes.md b/docs/builder/migration/08-masm-changes.md index 5318e791..d858ee0a 100644 --- a/docs/builder/migration/08-masm-changes.md +++ b/docs/builder/migration/08-masm-changes.md @@ -85,7 +85,7 @@ eq.COMPOSITION_FUNGIBLE 2. To branch on the asset type, call `asset::key_to_composition` and compare against the `COMPOSITION_*` constants instead of inspecting raw bits. 3. No change is needed for `asset::key_to_faucet_id`, `asset::key_into_faucet_id`, `asset::key_to_asset_id`, or `asset::key_into_asset_id` — their names and stack effects are unchanged. Only code that **hand-decodes** the metadata byte is affected by the bit-layout shift; callers using these helper procs are not. -See [Assets, Vault & Faucet](./asset-vault-faucet) for the matching Rust-side `AssetComposition` / `AssetVaultKey` changes. +See [Assets, Vault & Faucet](./05-asset-vault-faucet.md) for the matching Rust-side `AssetComposition` / `AssetVaultKey` changes. --- diff --git a/docs/builder/migration/index.md b/docs/builder/migration/index.md index 95e1e0d5..97a56272 100644 --- a/docs/builder/migration/index.md +++ b/docs/builder/migration/index.md @@ -78,7 +78,7 @@ This guide is for: - **Smart contract authors** writing MASM or using protocol APIs - **App developers** using the protocol, standards, or client crates -If you're starting fresh on v0.15, you can skip this guide and go directly to the [Get Started guide](../get-started). +If you're starting fresh on v0.15, you can skip this guide and go directly to the [Get Started guide](../get-started/index.md). ::: --- @@ -129,16 +129,16 @@ Work through these sections in order for a complete migration: | Section | Topics | |---------|--------| -| [1. Imports & Dependencies](./imports-dependencies) | Crate bumps, package.json, MSRV 1.93, no round-trip of 0.14 artifacts | -| [2. Hashing, SMT & Crypto Changes](./hashing-stack) | Poseidon2-domain-separated SMT leaves, `miden-crypto` 0.25 renames, `PartialSmt` / `LargeSmt` / 0.24 API breaks | -| [3. Account Changes](./account-changes) | `AccountType` removed/renamed, network-account allowlist, `procedure_root!`, typed roots | -| [4. Note Changes](./note-changes) | `NoteDetailsCommitment`, `PartialNoteMetadata`, multiple attachments, 1-bit `NoteType`, nullifier change, PSWAP | -| [5. Assets, Vault & Faucet](./asset-vault-faucet) | `AssetAmount`, unified `FungibleFaucet`, `AssetVaultKey`, `AssetComposition` | -| [6. Transaction Changes](./transaction-changes) | `fee_faucet_id`, `TransactionScriptRoot`, `ProvenBatch::new_unchecked` | -| [7. Client Changes](./client-changes) | `GetAccount` surface, `sync_nullifiers`, `TokenPolicyManager`, Web/React/CLI changes | -| [8. MASM Changes](./masm-changes) | `metadata_into_*` renames, trimmed kernel outputs, `adv_push.N` removed | -| [9. VM & Assembler Changes](./vm-assembler) | Sync-first execution, `prove_sync`, stricter assembly, MAST wire format `0.0.3` | -| [10. Rust SDK & Compiler Changes](./rust-sdk-compiler) | `#[component]` trait + storage struct, required `miden-project.toml`, explicit `#[account(...)]`, v0.15 tx-kernel bindings | +| [1. Imports & Dependencies](./01-imports-dependencies.md) | Crate bumps, package.json, MSRV 1.93, no round-trip of 0.14 artifacts | +| [2. Hashing, SMT & Crypto Changes](./02-hashing-stack.md) | Poseidon2-domain-separated SMT leaves, `miden-crypto` 0.25 renames, `PartialSmt` / `LargeSmt` / 0.24 API breaks | +| [3. Account Changes](./03-account-changes.md) | `AccountType` removed/renamed, network-account allowlist, `procedure_root!`, typed roots | +| [4. Note Changes](./04-note-changes.md) | `NoteDetailsCommitment`, `PartialNoteMetadata`, multiple attachments, 1-bit `NoteType`, nullifier change, PSWAP | +| [5. Assets, Vault & Faucet](./05-asset-vault-faucet.md) | `AssetAmount`, unified `FungibleFaucet`, `AssetVaultKey`, `AssetComposition` | +| [6. Transaction Changes](./06-transaction-changes.md) | `fee_faucet_id`, `TransactionScriptRoot`, `ProvenBatch::new_unchecked` | +| [7. Client Changes](./07-client-changes.md) | `GetAccount` surface, `sync_nullifiers`, `TokenPolicyManager`, Web/React/CLI changes | +| [8. MASM Changes](./08-masm-changes.md) | `metadata_into_*` renames, trimmed kernel outputs, `adv_push.N` removed | +| [9. VM & Assembler Changes](./09-vm-assembler.md) | Sync-first execution, `prove_sync`, stricter assembly, MAST wire format `0.0.3` | +| [10. Rust SDK & Compiler Changes](./10-rust-sdk-compiler.md) | `#[component]` trait + storage struct, required `miden-project.toml`, explicit `#[account(...)]`, v0.15 tx-kernel bindings | --- diff --git a/docs/builder/private-multisig/index.md b/docs/builder/private-multisig/index.md index f3666fc7..e1eda865 100644 --- a/docs/builder/private-multisig/index.md +++ b/docs/builder/private-multisig/index.md @@ -17,7 +17,7 @@ In Miden's private account model, account state lives client-side. The chain sto - Proposals and signatures need an offchain coordination surface. - Without a shared state view, participants risk divergent state or stale approvals. -The [Miden Guardian](../miden-guardian/) solves this by acting as the coordination server for multisig accounts — keeping signers synchronized, managing proposal workflows, and ensuring all parties work from the same canonical state. +The [Miden Guardian](../miden-guardian/index.md) solves this by acting as the coordination server for multisig accounts — keeping signers synchronized, managing proposal workflows, and ensuring all parties work from the same canonical state. ## How it works @@ -57,13 +57,13 @@ sequenceDiagram ## Learn more - + Transaction lifecycle, key architecture, and offline fallback. - + Rust SDK for building multisig workflows. - + TypeScript SDK for building multisig workflows. diff --git a/docs/builder/smart-contracts/accounts/account-operations.md b/docs/builder/smart-contracts/accounts/account-operations.md index dcefd68f..a085bb21 100644 --- a/docs/builder/smart-contracts/accounts/account-operations.md +++ b/docs/builder/smart-contracts/accounts/account-operations.md @@ -92,7 +92,7 @@ When proof generation fails: 3. No state changes occur 4. The client receives an error describing the failure -The last row is enforced at end-of-execution by the VM kernel rather than mid-execution: a transaction that mutates no account state (storage, vault, or nonce) **and** consumes no notes is rejected. The Rust client also catches this case before submission as `TransactionRequestError::NoInputNotesNorAccountChange`. See [Empty Transaction](../../tutorials/helpers/pitfalls#empty-transaction-no-state-change-no-notes) for the recommended pattern. +The last row is enforced at end-of-execution by the VM kernel rather than mid-execution: a transaction that mutates no account state (storage, vault, or nonce) **and** consumes no notes is rejected. The Rust client also catches this case before submission as `TransactionRequestError::NoInputNotesNorAccountChange`. See [Empty Transaction](../../tutorials/helpers/pitfalls.md#empty-transaction-no-state-change-no-notes) for the recommended pattern. ## Example: ManagedWallet @@ -125,7 +125,7 @@ impl ManagedWallet { } ``` -To move assets out of an account, create [output notes](../notes/output-notes) with `output_note::add_asset`. For signature verification and nonce management, see [Authentication](./authentication). +To move assets out of an account, create [output notes](../notes/output-notes.md) with `output_note::add_asset`. For signature verification and nonce management, see [Authentication](./authentication.md). :::info API Reference Full API docs on docs.rs: [`miden`](https://docs.rs/miden/latest/miden/) diff --git a/docs/builder/smart-contracts/accounts/authentication.md b/docs/builder/smart-contracts/accounts/authentication.md index 9853b4f9..33f57e49 100644 --- a/docs/builder/smart-contracts/accounts/authentication.md +++ b/docs/builder/smart-contracts/accounts/authentication.md @@ -6,7 +6,7 @@ description: "Authentication component pattern and nonce management for Miden ac # Authentication -Miden uses digital signatures for transaction authentication. Because transactions execute on the client rather than onchain validators, the system needs a way to prove that a transaction was authorized by the account owner. Without authentication, anyone could construct a valid proof that transfers assets out of an account. The nonce prevents replay attacks — without it, a valid proof could be resubmitted to execute the same state change twice. For details on the cryptographic primitives, see [Cryptography](./cryptography). +Miden uses digital signatures for transaction authentication. Because transactions execute on the client rather than onchain validators, the system needs a way to prove that a transaction was authorized by the account owner. Without authentication, anyone could construct a valid proof that transfers assets out of an account. The nonce prevents replay attacks — without it, a valid proof could be resubmitted to execute the same state change twice. For details on the cryptographic primitives, see [Cryptography](./cryptography.md). v0.14 unifies the previous per-scheme components (`AuthFalcon512Rpo`, `AuthEcdsaK256Keccak`, …) into a single scheme-agnostic [`AuthSingleSig`](https://docs.rs/miden-standards/latest/miden_standards/account/auth/struct.AuthSingleSig.html) component that takes an `AuthScheme` enum (`Falcon512Poseidon2` or `EcdsaK256Keccak`). The native hash function is Poseidon2, and the Falcon-512 verifier MASM module is `miden::core::crypto::dsa::falcon512_poseidon2`. @@ -25,7 +25,7 @@ During transaction execution the kernel invokes the `@auth_script`-annotated pro 2. Computes the transaction summary message: `hash([ACCOUNT_DELTA_COMMITMENT, INPUT_NOTES_COMMITMENT, OUTPUT_NOTES_COMMITMENT, [0, 0, ref_block_num, final_nonce]])`. 3. Requests the signature from the advice provider and verifies it with the scheme indicated by the stored scheme ID. -If verification fails, proof generation fails and the transaction is rejected before reaching the network. The signature itself isn't passed as a function argument — it's provided through the **advice provider**, a mechanism that supplies auxiliary data to the VM during proof generation. See [Advice Provider](../transactions/advice-provider) for the full API. +If verification fails, proof generation fails and the transaction is rejected before reaching the network. The signature itself isn't passed as a function argument — it's provided through the **advice provider**, a mechanism that supplies auxiliary data to the VM during proof generation. See [Advice Provider](../transactions/advice-provider.md) for the full API. ## Attaching `AuthSingleSig` to an account @@ -87,7 +87,7 @@ The nonce prevents replay attacks — each transaction must use a unique nonce. The nonce is committed into the transaction proof. If someone tries to replay a transaction, the nonce won't match the account's current nonce and verification will fail. -Auth components are invoked automatically by the kernel — you do not call them directly from note scripts or [transaction scripts](../transactions/transaction-scripts). For access control and security patterns, see [Patterns](../patterns). +Auth components are invoked automatically by the kernel — you do not call them directly from note scripts or [transaction scripts](../transactions/transaction-scripts.md). For access control and security patterns, see [Patterns](../patterns.md). :::info API Reference Full API docs on docs.rs: [`miden`](https://docs.rs/miden/latest/miden/), [`AuthSingleSig`](https://docs.rs/miden-standards/latest/miden_standards/account/auth/struct.AuthSingleSig.html), [`AuthScheme`](https://docs.rs/miden-protocol/latest/miden_protocol/account/auth/enum.AuthScheme.html) @@ -95,6 +95,6 @@ Full API docs on docs.rs: [`miden`](https://docs.rs/miden/latest/miden/), [`Auth ## Related -- [Cryptography](./cryptography) — Falcon-512 / Poseidon2 verification and hashing primitives -- [Advice Provider](../transactions/advice-provider) — supplying auxiliary data during proof generation -- [Patterns](../patterns) — access control, rate limiting, and anti-patterns +- [Cryptography](./cryptography.md) — Falcon-512 / Poseidon2 verification and hashing primitives +- [Advice Provider](../transactions/advice-provider.md) — supplying auxiliary data during proof generation +- [Patterns](../patterns.md) — access control, rate limiting, and anti-patterns diff --git a/docs/builder/smart-contracts/accounts/components.md b/docs/builder/smart-contracts/accounts/components.md index 7e012989..d799fdae 100644 --- a/docs/builder/smart-contracts/accounts/components.md +++ b/docs/builder/smart-contracts/accounts/components.md @@ -6,7 +6,7 @@ description: "Define Miden account components using the #[component] macro — s # Components -Components are the building blocks of Miden accounts. Each component defines a [storage](./storage) layout, exposes public methods, and can be composed with other components on the same account — for example, a wallet component + an auth component + custom logic. This modularity lets you reuse a wallet component across many accounts and test or upgrade components independently. +Components are the building blocks of Miden accounts. Each component defines a [storage](./storage.md) layout, exposes public methods, and can be composed with other components on the same account — for example, a wallet component + an auth component + custom logic. This modularity lets you reuse a wallet component across many accounts and test or upgrade components independently. ## The `#[component]` macro @@ -118,7 +118,7 @@ pub fn do_something(&mut self) { ### Supported parameter and return types -Public methods can use SDK types (`Felt`, `Word`, `Asset`, `AccountId`, `NoteIdx`) and custom types annotated with [`#[export_type]`](./custom-types). +Public methods can use SDK types (`Felt`, `Word`, `Asset`, `AccountId`, `NoteIdx`) and custom types annotated with [`#[export_type]`](./custom-types.md). ## Auto-generated methods @@ -165,7 +165,7 @@ self.compute_storage_commitment() -> Word // ... and more (see API Reference) ``` -For the full list of auto-generated methods, see [Account Operations](./account-operations). To export your own types for use in public method signatures, see [Custom Types](./custom-types). +For the full list of auto-generated methods, see [Account Operations](./account-operations.md). To export your own types for use in public method signatures, see [Custom Types](./custom-types.md). :::info API Reference Full API docs on docs.rs: [`miden`](https://docs.rs/miden/latest/miden/) (top-level — `#[component]` macro) diff --git a/docs/builder/smart-contracts/accounts/cryptography.md b/docs/builder/smart-contracts/accounts/cryptography.md index 803c2e52..6126bffa 100644 --- a/docs/builder/smart-contracts/accounts/cryptography.md +++ b/docs/builder/smart-contracts/accounts/cryptography.md @@ -58,5 +58,5 @@ let hash: [u8; 32] = sha256_hash(input_bytes); ## Related -- [Authentication](./authentication) — auth component pattern and nonce management -- [Advice Provider](../transactions/advice-provider) — supplying auxiliary data during proof generation +- [Authentication](./authentication.md) — auth component pattern and nonce management +- [Advice Provider](../transactions/advice-provider.md) — supplying auxiliary data during proof generation diff --git a/docs/builder/smart-contracts/accounts/custom-types.md b/docs/builder/smart-contracts/accounts/custom-types.md index 1fc5ead0..7600ef85 100644 --- a/docs/builder/smart-contracts/accounts/custom-types.md +++ b/docs/builder/smart-contracts/accounts/custom-types.md @@ -6,7 +6,7 @@ description: "Export custom structs and enums for use in public component method # Custom Types -When public [component](./components) methods use custom structs or enums, those types must be annotated with `#[export_type]` so the compiler can include them in the component's public API. Types used only internally (in private methods or local variables) don't need this annotation. +When public [component](./components.md) methods use custom structs or enums, those types must be annotated with `#[export_type]` so the compiler can include them in the component's public API. Types used only internally (in private methods or local variables) don't need this annotation. :::tip If you forget `#[export_type]` on a public API type, the compiler will emit an error telling you to add it. diff --git a/docs/builder/smart-contracts/accounts/storage.md b/docs/builder/smart-contracts/accounts/storage.md index 9d284883..c0fcdb46 100644 --- a/docs/builder/smart-contracts/accounts/storage.md +++ b/docs/builder/smart-contracts/accounts/storage.md @@ -6,7 +6,7 @@ description: "Persistent state management with Value slots and StorageMaps in Mi # Storage -Miden accounts have persistent storage organized into up to 255 name-addressable slots. Each slot holds either a single [`Word`](../types) (via `Value`) or a key-value map (via `StorageMap`). Slots are identified by `StorageSlotId` values derived from slot names, which in turn are derived from the component package name and the field name. Renaming a field changes the slot ID and is a breaking change for stored data. +Miden accounts have persistent storage organized into up to 255 name-addressable slots. Each slot holds either a single [`Word`](../types.md) (via `Value`) or a key-value map (via `StorageMap`). Slots are identified by `StorageSlotId` values derived from slot names, which in turn are derived from the component package name and the field name. Renaming a field changes the slot ID and is a breaking change for stored data. ## Storage slots @@ -174,7 +174,7 @@ let initial: Word = storage::get_initial_map_item(slot_id, &key); These functions return values from before any modifications in the current transaction. -For Felt and Word conversion details, see [Types](../types). To export your own types for public APIs, see [Custom Types](./custom-types). For common storage patterns like access control and rate limiting, see [Patterns](../patterns). +For Felt and Word conversion details, see [Types](../types.md). To export your own types for public APIs, see [Custom Types](./custom-types.md). For common storage patterns like access control and rate limiting, see [Patterns](../patterns.md). :::info API Reference Full API docs on docs.rs: [`miden::storage`](https://docs.rs/miden/latest/miden/storage/) diff --git a/docs/builder/smart-contracts/cross-component-calls.md b/docs/builder/smart-contracts/cross-component-calls.md index ff3479d5..dfe9b545 100644 --- a/docs/builder/smart-contracts/cross-component-calls.md +++ b/docs/builder/smart-contracts/cross-component-calls.md @@ -6,7 +6,7 @@ description: "Call methods across account components and from note scripts." # Cross-Component Calls -Miden [components](./accounts/components) can call each other's methods. Since accounts can have multiple components (e.g., wallet + auth + custom logic), those components need to communicate. [Note scripts](./notes/note-scripts) also need to call methods on the account's components to transfer assets. +Miden [components](./accounts/components.md) can call each other's methods. Since accounts can have multiple components (e.g., wallet + auth + custom logic), those components need to communicate. [Note scripts](./notes/note-scripts.md) also need to call methods on the account's components to transfer assets. ## How it works diff --git a/docs/builder/smart-contracts/index.md b/docs/builder/smart-contracts/index.md index 3ae40897..425c4f7a 100644 --- a/docs/builder/smart-contracts/index.md +++ b/docs/builder/smart-contracts/index.md @@ -6,27 +6,27 @@ pagination_prev: null # Miden Smart Contracts -This section covers the developer-facing paths for building smart contracts on Miden: an authoring guide for **Miden Assembly (MASM)** (the supported path for mainnet production today) and **Rust** (in active development as the long-term direction), plus the [Miden Standards](./standards/) library of reusable components callable from either. +This section covers the developer-facing paths for building smart contracts on Miden: an authoring guide for **Miden Assembly (MASM)** (the supported path for mainnet production today) and **Rust** (in active development as the long-term direction), plus the [Miden Standards](./standards/index.md) library of reusable components callable from either. :::tip Building for mainnet? -Miden mainnet supports smart contracts authored in **Miden Assembly (MASM)** today. The Rust SDK is in active development and will become the default authoring path once it ships v1. For production deployments now, see [MASM Smart Contracts](./masm/). +Miden mainnet supports smart contracts authored in **Miden Assembly (MASM)** today. The Rust SDK is in active development and will become the default authoring path once it ships v1. For production deployments now, see [MASM Smart Contracts](./masm/index.md). ::: -If you're new to Miden, the hands-on [Miden Bank Tutorial](../tutorials/miden-bank/) walks through the full lifecycle using the Rust SDK; the concepts (accounts, notes, transactions, components) translate directly to MASM. +If you're new to Miden, the hands-on [Miden Bank Tutorial](../tutorials/miden-bank/index.md) walks through the full lifecycle using the Rust SDK; the concepts (accounts, notes, transactions, components) translate directly to MASM. ## Sections - + How accounts, notes, transactions, and components fit together. Concepts apply regardless of authoring language. - + Author production-ready smart contracts directly in Miden Assembly. The path Miden mainnet supports today. - + Build accounts, notes, transactions, and reusable logic with the Rust-first workflow. Currently in active development and not yet production-ready for mainnet. - + Standard components, note scripts, faucet policies, and MASM modules. Callable from MASM or Rust. @@ -43,13 +43,13 @@ If you're new to Miden, the hands-on [Miden Bank Tutorial](../tutorials/miden-ba Transaction context, scripts, and the advice provider. - + Calling methods across account components and from note scripts. - + Core types: Felt, Word, AccountId, NoteId, and more. - + Access control, rate limiting, spending limits, and anti-patterns. diff --git a/docs/builder/smart-contracts/masm/index.md b/docs/builder/smart-contracts/masm/index.md index f2409bd3..74dc555e 100644 --- a/docs/builder/smart-contracts/masm/index.md +++ b/docs/builder/smart-contracts/masm/index.md @@ -19,10 +19,10 @@ You're here because you want to deploy a contract to Miden mainnet. MASM is a sm | **Mainnet production** | Supported today | In active development | | **Performance / cycle control** | Direct control over emitted instructions | Compiles via Wasm → MASM; less predictable | | **Learning curve** | Small instruction set, explicit stack semantics | Familiar Rust ergonomics | -| **Miden Standards** | [Standards modules](../standards/) callable directly | Same standards via Rust bindings | +| **Miden Standards** | [Standards modules](../standards/index.md) callable directly | Same standards via Rust bindings | | **Long-term direction** | Long-lived for system-level / performance-critical code | Will become the default authoring path once mature | -For mainnet shipping today, the choice is straightforward: write MASM. Most production patterns — account components, note scripts, transaction scripts, P2ID and P2IDE flows, faucet policies — are already covered by [Miden Standards](../standards/), so most contracts compose existing standards rather than rolling everything from scratch. +For mainnet shipping today, the choice is straightforward: write MASM. Most production patterns — account components, note scripts, transaction scripts, P2ID and P2IDE flows, faucet policies — are already covered by [Miden Standards](../standards/index.md), so most contracts compose existing standards rather than rolling everything from scratch. ## Where the language reference lives @@ -41,11 +41,11 @@ Practical, end-to-end tutorials are in progress in the [Miden tutorials reposito | Testing with MockChain | In progress | | Debugging MASM contracts | In progress | -In the meantime, the existing [Rust-based Miden Bank tutorial](../../tutorials/miden-bank/) is useful for understanding the overall transaction lifecycle and the patterns that translate to MASM. The [Reference assembly section](/reference/miden-vm/user_docs/assembly/) covers the language itself. +In the meantime, the existing [Rust-based Miden Bank tutorial](../../tutorials/miden-bank/index.md) is useful for understanding the overall transaction lifecycle and the patterns that translate to MASM. The [Reference assembly section](/reference/miden-vm/user_docs/assembly/) covers the language itself. ## See also -- [Miden Standards](../standards/) — reusable account components, standard notes, faucet policies, callable from MASM. +- [Miden Standards](../standards/index.md) — reusable account components, standard notes, faucet policies, callable from MASM. - [Reference → Miden VM → Assembly](/reference/miden-vm/user_docs/assembly/) — full language reference (instructions, stack semantics, control flow). -- [Smart Contracts → Overview](../overview) — execution model and lifecycle (the concepts apply regardless of authoring language). -- [Tools → Playground](../../tools/playground) — interactive browser-based MASM environment for quick experiments. +- [Smart Contracts → Overview](../overview.md) — execution model and lifecycle (the concepts apply regardless of authoring language). +- [Tools → Playground](../../tools/playground.md) — interactive browser-based MASM environment for quick experiments. diff --git a/docs/builder/smart-contracts/notes/introduction.md b/docs/builder/smart-contracts/notes/introduction.md index ecbaedba..ed198131 100644 --- a/docs/builder/smart-contracts/notes/introduction.md +++ b/docs/builder/smart-contracts/notes/introduction.md @@ -23,13 +23,13 @@ Every note has four parts: | **Storage** | Custom data stored with the note that the script can read at consumption time (e.g., a target account ID, an expiration block) | | **Metadata** | Sender ID, note tag (for discovery routing), and auxiliary data | -The **recipient** is a cryptographic hash that encodes who can consume the note. When creating notes programmatically (via [`output_note::create`](./output-notes#create-a-note)), you compute a `Recipient` from the note's serial number, script root, and storage commitment: +The **recipient** is a cryptographic hash that encodes who can consume the note. When creating notes programmatically (via [`output_note::create`](./output-notes.md#create-a-note)), you compute a `Recipient` from the note's serial number, script root, and storage commitment: ``` recipient = hash(hash(hash(serial_num, [0;4]), script_root), storage_commitment) ``` -Only someone who knows these values can construct a valid consumption proof. See [Computing a Recipient](./output-notes#computing-a-recipient) for the SDK API. +Only someone who knows these values can construct a valid consumption proof. See [Computing a Recipient](./output-notes.md#computing-a-recipient) for the SDK API. ## The two-transaction model @@ -63,7 +63,7 @@ Notes come in two visibility modes: Private notes provide stronger privacy guarantees — the network can't even see what assets a note carries — but they require the sender and recipient to have a communication channel outside the protocol. -Miden provides built-in note patterns (P2ID, P2IDE, SWAP) for common transfer scenarios — see [Standard Note Types](./note-types). You can also write fully custom note scripts for arbitrary consumption logic. +Miden provides built-in note patterns (P2ID, P2IDE, SWAP) for common transfer scenarios — see [Standard Note Types](./note-types.md). You can also write fully custom note scripts for arbitrary consumption logic. ## How notes differ from EVM transfers diff --git a/docs/builder/smart-contracts/notes/note-scripts.md b/docs/builder/smart-contracts/notes/note-scripts.md index 17160e9f..8a45f91e 100644 --- a/docs/builder/smart-contracts/notes/note-scripts.md +++ b/docs/builder/smart-contracts/notes/note-scripts.md @@ -88,7 +88,7 @@ pub fn run(self, _arg: Word, account: &mut Account) { } ``` -The `Account` type is auto-generated from the bindings of the dependent component — see [Cross-Component Calls](../cross-component-calls). +The `Account` type is auto-generated from the bindings of the dependent component — see [Cross-Component Calls](../cross-component-calls.md). ### Without account access @@ -132,7 +132,7 @@ impl CounterNote { } ``` -This note doesn't take `&mut Account` — instead it calls the counter contract's methods directly through generated bindings. See [Cross-Component Calls](../cross-component-calls). +This note doesn't take `&mut Account` — instead it calls the counter contract's methods directly through generated bindings. See [Cross-Component Calls](../cross-component-calls.md). ## Cargo.toml for note scripts @@ -149,5 +149,5 @@ project-kind = "note-script" ## Related -- [Cross-Component Calls](../cross-component-calls) — how `bindings::Account` and `counter_contract::` calls work -- [Transaction Context](../transactions/transaction-context) — transaction scripts with `#[tx_script]` +- [Cross-Component Calls](../cross-component-calls.md) — how `bindings::Account` and `counter_contract::` calls work +- [Transaction Context](../transactions/transaction-context.md) — transaction scripts with `#[tx_script]` diff --git a/docs/builder/smart-contracts/notes/note-types.md b/docs/builder/smart-contracts/notes/note-types.md index 0d9d7d25..9792c427 100644 --- a/docs/builder/smart-contracts/notes/note-types.md +++ b/docs/builder/smart-contracts/notes/note-types.md @@ -159,8 +159,8 @@ SwapNote::create( Returns a tuple of `(Note, NoteDetails)` — the SWAP note to submit and the expected payback note details (for tracking). -`NoteAttachment` is defined in the `miden-standards` crate (not the core `miden` SDK). It wraps the attachment data that gets set on output notes — see [note attachments](./output-notes#note-attachments) for the underlying SDK API. +`NoteAttachment` is defined in the `miden-standards` crate (not the core `miden` SDK). It wraps the attachment data that gets set on output notes — see [note attachments](./output-notes.md#note-attachments) for the underlying SDK API. ## More note types -For writing custom note scripts, see [Note Scripts](./note-scripts). For the transaction context and `#[tx_script]`, see [Transaction Context](../transactions/transaction-context). +For writing custom note scripts, see [Note Scripts](./note-scripts.md). For the transaction context and `#[tx_script]`, see [Transaction Context](../transactions/transaction-context.md). diff --git a/docs/builder/smart-contracts/notes/output-notes.md b/docs/builder/smart-contracts/notes/output-notes.md index e3a1bc77..a032e3ef 100644 --- a/docs/builder/smart-contracts/notes/output-notes.md +++ b/docs/builder/smart-contracts/notes/output-notes.md @@ -54,7 +54,7 @@ Returns a `NoteMetadata` struct (not a raw `Word`): let metadata: NoteMetadata = output_note::get_metadata(note_idx); ``` -See [Reading Notes — Note metadata](./reading-notes#note-metadata) for the `NoteMetadata` struct definition. +See [Reading Notes — Note metadata](./reading-notes.md#note-metadata) for the `NoteMetadata` struct definition. ## Note attachments diff --git a/docs/builder/smart-contracts/notes/reading-notes.md b/docs/builder/smart-contracts/notes/reading-notes.md index 42c9f3ab..86219d27 100644 --- a/docs/builder/smart-contracts/notes/reading-notes.md +++ b/docs/builder/smart-contracts/notes/reading-notes.md @@ -30,7 +30,7 @@ struct MyNote { } ``` -See [Note Scripts](./note-scripts) for the full `#[note]` pattern. The low-level `active_note::get_storage()` function is also available for advanced use cases: +See [Note Scripts](./note-scripts.md) for the full `#[note]` pattern. The low-level `active_note::get_storage()` function is also available for advanced use cases: ```rust let storage: Vec = active_note::get_storage(); diff --git a/docs/builder/smart-contracts/overview.md b/docs/builder/smart-contracts/overview.md index f330fd92..0c547b33 100644 --- a/docs/builder/smart-contracts/overview.md +++ b/docs/builder/smart-contracts/overview.md @@ -7,10 +7,10 @@ description: "Miden's execution model, account structure, note system, and trans # What is a Miden Smart Contract :::info Concepts apply to both authoring paths -This page describes Miden's execution model — accounts, notes, transactions, and lifecycle. The concepts apply regardless of whether you author contracts in MASM (the mainnet path) or the Rust SDK (in active development). Code examples on this page use Rust; for the MASM path, see [MASM Smart Contracts](./masm/). +This page describes Miden's execution model — accounts, notes, transactions, and lifecycle. The concepts apply regardless of whether you author contracts in MASM (the mainnet path) or the Rust SDK (in active development). Code examples on this page use Rust; for the MASM path, see [MASM Smart Contracts](./masm/index.md). ::: -Miden is a zero-knowledge layer 2 where transactions execute on the client and only a cryptographic proof is submitted to the network. Every entity — wallets, contracts, faucets — is an account with code, storage, a vault, and a nonce. Assets move between accounts through notes, which act as programmable UTXOs. This page describes the execution model, account structure, note system, and transaction lifecycle. For a hands-on walkthrough, see the [Miden Bank Tutorial](../tutorials/miden-bank/). +Miden is a zero-knowledge layer 2 where transactions execute on the client and only a cryptographic proof is submitted to the network. Every entity — wallets, contracts, faucets — is an account with code, storage, a vault, and a nonce. Assets move between accounts through notes, which act as programmable UTXOs. This page describes the execution model, account structure, note system, and transaction lifecycle. For a hands-on walkthrough, see the [Miden Bank Tutorial](../tutorials/miden-bank/index.md). ## What makes Miden different @@ -33,7 +33,7 @@ Miden runs **MASM** (Miden Assembly) — the VM's native instruction set. There MASM → ZK Circuit → Proof ``` -You write MASM directly and build it into a `.masp` package (Miden Assembly Package). This is what mainnet supports for production today. See [MASM Smart Contracts](./masm/). +You write MASM directly and build it into a `.masp` package (Miden Assembly Package). This is what mainnet supports for production today. See [MASM Smart Contracts](./masm/index.md). **Rust** (in active development): @@ -41,7 +41,7 @@ You write MASM directly and build it into a `.masp` package (Miden Assembly Pack Rust → Wasm → MASM → ZK Circuit → Proof ``` -The Miden compiler (`cargo-miden`) compiles your `#![no_std]` Rust to WebAssembly, then translates it to MASM. The output is the same `.masp` package, so both paths share the same execution model and the same [Miden Standards](./standards/) library. +The Miden compiler (`cargo-miden`) compiles your `#![no_std]` Rust to WebAssembly, then translates it to MASM. The output is the same `.masp` package, so both paths share the same execution model and the same [Miden Standards](./standards/index.md) library. When a transaction executes, the Miden VM runs the MASM and produces a zero-knowledge proof of correct execution. The output of `cargo miden build` (Rust) or the MASM build tooling is a `.masp` file containing the compiled MASM and metadata. @@ -76,7 +76,7 @@ impl MyWallet { Each component defines its own storage layout and public methods. The `#[component]` macro generates the necessary WIT (WebAssembly Interface Type) definitions for cross-component interoperability. -See [Components](./accounts/components) for full details. +See [Components](./accounts/components.md) for full details. ## Notes as UTXOs @@ -135,7 +135,7 @@ If the assertion fails, the ZK circuit **cannot produce a valid proof**. This me This is fundamentally different from Ethereum's `revert` — there's no onchain transaction that fails. The proof simply doesn't exist if the execution is invalid. -A separate failure mode is the [empty transaction](../tutorials/helpers/pitfalls#empty-transaction-no-state-change-no-notes) — a transaction that completes without mutating account state or consuming a note is also rejected, since Miden refuses to admit transactions with no observable effect. +A separate failure mode is the [empty transaction](../tutorials/helpers/pitfalls.md#empty-transaction-no-state-change-no-notes) — a transaction that completes without mutating account state or consuming a note is also rejected, since Miden refuses to admit transactions with no observable effect. ## Account types @@ -154,23 +154,23 @@ Miden supports four account types, set at deployment time. The same types are us | Section | When to use | |---|---| -| [MASM Smart Contracts](./masm/) | Production contracts for mainnet today | -| [Rust SDK](./rust/) | Prototyping today; long-term default once it ships v1 | -| [Miden Standards](./standards/) | Reusable building blocks callable from either path | +| [MASM Smart Contracts](./masm/index.md) | Production contracts for mainnet today | +| [Rust SDK](./rust/index.md) | Prototyping today; long-term default once it ships v1 | +| [Miden Standards](./standards/index.md) | Reusable building blocks callable from either path | **Topic guides** (concepts apply regardless of authoring language): | Topic | Description | |---|---| -| [Components](./accounts/components) | Reusable code modules with storage and exported interfaces | -| [Storage](./accounts/storage) | Up to 255 slots of `Value` or `StorageMap` | -| [Custom Types](./accounts/custom-types) | Exported structs/enums for public APIs | -| [Account Operations](./accounts/account-operations) | Read/write account state and vault | +| [Components](./accounts/components.md) | Reusable code modules with storage and exported interfaces | +| [Storage](./accounts/storage.md) | Up to 255 slots of `Value` or `StorageMap` | +| [Custom Types](./accounts/custom-types.md) | Exported structs/enums for public APIs | +| [Account Operations](./accounts/account-operations.md) | Read/write account state and vault | | [Notes](./notes/) | Programmable UTXOs for asset transfers | | [Transactions](./transactions/) | Transaction context, scripts, and the advice provider | -| [Authentication](./accounts/authentication) | RPO-Falcon512 signatures and replay protection | -| [Cross-Component Calls](./cross-component-calls) | Inter-component communication | -| [Types](./types) | Felt, Word, Asset — the VM's native types | -| [Patterns](./patterns) | Access control, rate limiting, spending limits, anti-patterns | +| [Authentication](./accounts/authentication.md) | RPO-Falcon512 signatures and replay protection | +| [Cross-Component Calls](./cross-component-calls.md) | Inter-component communication | +| [Types](./types.md) | Felt, Word, Asset — the VM's native types | +| [Patterns](./patterns.md) | Access control, rate limiting, spending limits, anti-patterns | -Ready to start building? The [Miden Bank Tutorial](../tutorials/miden-bank/) is a hands-on walkthrough (currently written against the Rust SDK; the concepts translate to MASM). +Ready to start building? The [Miden Bank Tutorial](../tutorials/miden-bank/index.md) is a hands-on walkthrough (currently written against the Rust SDK; the concepts translate to MASM). diff --git a/docs/builder/smart-contracts/patterns.md b/docs/builder/smart-contracts/patterns.md index c68240d1..fa7d5c2b 100644 --- a/docs/builder/smart-contracts/patterns.md +++ b/docs/builder/smart-contracts/patterns.md @@ -6,7 +6,7 @@ description: "Common patterns and security considerations for Miden smart contra # Patterns -Security considerations and common patterns for Miden smart contracts. For runnable examples, see the [compiler examples directory](https://github.com/0xMiden/compiler/tree/next/examples) and the [Miden Bank Tutorial](../tutorials/miden-bank/). +Security considerations and common patterns for Miden smart contracts. For runnable examples, see the [compiler examples directory](https://github.com/0xMiden/compiler/tree/next/examples) and the [Miden Bank Tutorial](../tutorials/miden-bank/index.md). ## Access control @@ -16,7 +16,7 @@ Unlike Solidity, account component procedures cannot check "who is calling me." - **Account components** rely on authentication components (Falcon512, ECDSA) which the transaction kernel invokes automatically in the epilogue ::: -For account-level access control, Miden uses **authentication components** rather than manual sender checks. The transaction kernel calls the account's `auth` procedure automatically during the transaction epilogue — if the signature is invalid, the entire transaction fails. See [Authentication](./accounts/authentication) for the full pattern. +For account-level access control, Miden uses **authentication components** rather than manual sender checks. The transaction kernel calls the account's `auth` procedure automatically during the transaction epilogue — if the signature is invalid, the entire transaction fails. See [Authentication](./accounts/authentication.md) for the full pattern. For note-level access control, note scripts can check who created the note using `active_note::get_sender()`. The protocol-level `ownable` standard (`miden-standards/asm/standards/access/ownable.masm`) provides `verify_owner`, `get_owner`, `transfer_ownership`, and `renounce_ownership` procedures. @@ -24,7 +24,7 @@ For note-level access control, note scripts can check who created the note using Use `tx::get_block_number()` to enforce cooldown periods between actions. Store the last action block number in a `Value` storage slot, then compare against the current block number before allowing the next action. -See [Transaction Context](./transactions/transaction-context) for the available block and transaction info functions. +See [Transaction Context](./transactions/transaction-context.md) for the available block and transaction info functions. ## Security @@ -41,7 +41,7 @@ When an assertion fails, proof generation fails and the transaction is rejected ### Replay protection -Every state-changing transaction must increment the nonce. The auth component handles this automatically — see [Authentication](./accounts/authentication). +Every state-changing transaction must increment the nonce. The auth component handles this automatically — see [Authentication](./accounts/authentication.md). ### Safe arithmetic @@ -55,7 +55,7 @@ let elapsed = current_block.saturating_sub(last_block); let elapsed = current_block - last_block; ``` -For Felt arithmetic, values wrap modulo the prime field (no overflow panic), but the result may not be what you expect if you're treating Felts as integers. See [Types — Felt](./types#felt--field-elements) for details. +For Felt arithmetic, values wrap modulo the prime field (no overflow panic), but the result may not be what you expect if you're treating Felts as integers. See [Types — Felt](./types.md#felt--field-elements) for details. ### Anti-patterns diff --git a/docs/builder/smart-contracts/rust/index.md b/docs/builder/smart-contracts/rust/index.md index 42c5da51..d604e701 100644 --- a/docs/builder/smart-contracts/rust/index.md +++ b/docs/builder/smart-contracts/rust/index.md @@ -8,7 +8,7 @@ description: "Author Miden smart contracts in Rust — the long-term direction f The Rust SDK is the long-term direction for Miden smart-contract development: define account components, note scripts, and transaction scripts in idiomatic `#![no_std]` Rust with typed storage, attribute macros, and client-side proving. The SDK compiles to Miden Assembly (MASM) under the hood, so the same execution model and standards library apply. :::caution Currently in active development -The Rust SDK is being actively developed and is **not yet production-ready for mainnet**. For production deployments today, write contracts in [Miden Assembly (MASM)](../masm/) — the supported path Miden mainnet verifies. Use the Rust SDK for prototyping, experimentation, and exploration of the long-term direction. +The Rust SDK is being actively developed and is **not yet production-ready for mainnet**. For production deployments today, write contracts in [Miden Assembly (MASM)](../masm/index.md) — the supported path Miden mainnet verifies. Use the Rust SDK for prototyping, experimentation, and exploration of the long-term direction. ::: The pages below describe the Rust SDK's current shape: how accounts and components compose, how notes are scripted, how transactions execute, and the patterns you can already build with. @@ -25,13 +25,13 @@ The pages below describe the Rust SDK's current shape: how accounts and componen Transaction context, scripts, and the advice provider. - + Calling methods across account components and from note scripts. - + Core types: Felt, Word, AccountId, NoteId, and more. - + Access control, rate limiting, spending limits, and anti-patterns. @@ -40,16 +40,16 @@ The pages below describe the Rust SDK's current shape: how accounts and componen | Concern | Rust SDK | MASM | |---|---|---| -| **Mainnet production** | In active development | [Supported today](../masm/) | +| **Mainnet production** | In active development | [Supported today](../masm/index.md) | | **Ergonomics** | Familiar Rust idioms, type-checked storage, attribute macros | Stack-based assembly, explicit control | | **Compilation target** | Compiles via Wasm → MASM | Directly authored | | **Use case** | Long-term default once mature; prototyping and exploration today | Production contracts for mainnet | -Both authoring paths share the same [Miden Standards](../standards/) library — standard components, notes, and faucet policies are callable from either. +Both authoring paths share the same [Miden Standards](../standards/index.md) library — standard components, notes, and faucet policies are callable from either. ## Related pages -- [MASM Smart Contracts](../masm/) — the path mainnet supports today. -- [Miden Standards](../standards/) — reusable building blocks callable from Rust or MASM. -- [Smart Contracts → Overview](../overview) — execution model and lifecycle (concepts apply to both authoring paths). +- [MASM Smart Contracts](../masm/index.md) — the path mainnet supports today. +- [Miden Standards](../standards/index.md) — reusable building blocks callable from Rust or MASM. +- [Smart Contracts → Overview](../overview.md) — execution model and lifecycle (concepts apply to both authoring paths). - [API reference on docs.rs](https://docs.rs/miden/latest/miden/) — full Rust SDK API documentation. diff --git a/docs/builder/smart-contracts/standards/account-components.md b/docs/builder/smart-contracts/standards/account-components.md index 917328fd..0bf36d56 100644 --- a/docs/builder/smart-contracts/standards/account-components.md +++ b/docs/builder/smart-contracts/standards/account-components.md @@ -64,7 +64,7 @@ fn build_wallet_account() -> Result<(), Box> { } ``` -For authentication details, see [Authentication](../accounts/authentication). For how component methods are authored in Rust, see [Components](../accounts/components). +For authentication details, see [Authentication](../accounts/authentication.md). For how component methods are authored in Rust, see [Components](../accounts/components.md). ## Check note compatibility @@ -95,6 +95,6 @@ Reach for MASM directly when you are implementing low-level behavior, integratin ## Related pages -- [Standard notes](./standard-notes) - which account interfaces each standard note expects -- [Faucets and policies](./faucets-and-policies) - using faucet and mint policy components +- [Standard notes](./standard-notes.md) - which account interfaces each standard note expects +- [Faucets and policies](./faucets-and-policies.md) - using faucet and mint policy components - [`miden-standards` account source](https://github.com/0xMiden/protocol/tree/next/crates/miden-standards/src/account) - current implementation diff --git a/docs/builder/smart-contracts/standards/faucets-and-policies.md b/docs/builder/smart-contracts/standards/faucets-and-policies.md index 2cdb3b7c..70fdcaa2 100644 --- a/docs/builder/smart-contracts/standards/faucets-and-policies.md +++ b/docs/builder/smart-contracts/standards/faucets-and-policies.md @@ -118,7 +118,7 @@ For standard flows: - The recipient discovers and consumes the note. - The recipient's account must be able to receive the asset, usually by including `BasicWallet`. -This is the same two-transaction note model described in [What are Notes?](../notes/introduction). +This is the same two-transaction note model described in [What are Notes?](../notes/introduction.md). ## Burn returned assets @@ -140,7 +140,7 @@ If you only need additional public methods, compose the faucet account with an e ## Related pages -- [Account components](./account-components) - composing faucets with standard auth and ownership components -- [Standard notes](./standard-notes) - mint and burn notes -- [Assets, Vault, and Faucet migration notes](../../migration/asset-vault-faucet) - v0.14 asset and faucet changes +- [Account components](./account-components.md) - composing faucets with standard auth and ownership components +- [Standard notes](./standard-notes.md) - mint and burn notes +- [Assets, Vault, and Faucet migration notes](../../migration/05-asset-vault-faucet.md) - v0.14 asset and faucet changes - [`miden-standards` faucet source](https://github.com/0xMiden/protocol/tree/next/crates/miden-standards/src/account/faucets) - current implementation diff --git a/docs/builder/smart-contracts/standards/index.md b/docs/builder/smart-contracts/standards/index.md index a2c81327..d573f3db 100644 --- a/docs/builder/smart-contracts/standards/index.md +++ b/docs/builder/smart-contracts/standards/index.md @@ -28,13 +28,13 @@ Smart Contracts is the domain. Rust and Miden Assembly are authoring paths insid ## What this section covers - + Use standard wallet, authentication, access-control, faucet, and metadata components. - + Choose P2ID, P2IDE, SWAP, PSWAP, mint, and burn note scripts. - + Build token faucets and choose mint, burn, send, and receive policy modules. @@ -59,5 +59,5 @@ You can mix both approaches. A typical application account starts with standard - [Accounts](../accounts/) - components, storage, authentication, and account operations - [Notes](../notes/) - note model, note scripts, standard note types, and output notes -- [Cross-component calls](../cross-component-calls) - calling component interfaces from scripts and components +- [Cross-component calls](../cross-component-calls.md) - calling component interfaces from scripts and components - [`miden-standards` source](https://github.com/0xMiden/protocol/tree/next/crates/miden-standards) - current standards implementation diff --git a/docs/builder/smart-contracts/standards/standard-notes.md b/docs/builder/smart-contracts/standards/standard-notes.md index 788f3add..c86961cd 100644 --- a/docs/builder/smart-contracts/standards/standard-notes.md +++ b/docs/builder/smart-contracts/standards/standard-notes.md @@ -20,7 +20,7 @@ Use the Rust APIs to construct standard notes in client or transaction-building | MINT | A faucet is minting fungible tokens into a note. | `MintNote` | `miden::standards::notes::mint` | | BURN | A faucet is burning fungible tokens returned through a note. | `BurnNote` | `miden::standards::notes::burn` | -For the note model itself, start with [What are Notes?](../notes/introduction). This page focuses on how the standards fit into builder workflows. +For the note model itself, start with [What are Notes?](../notes/introduction.md). This page focuses on how the standards fit into builder workflows. ```rust title="Create a public P2ID note" use miden_protocol::Word; @@ -101,7 +101,7 @@ The Rust types live under `miden_standards::note`. The MASM scripts live under ` ## Related pages -- [Standard Note Types](../notes/note-types) - more detail on P2ID, P2IDE, and SWAP -- [Output Notes](../notes/output-notes) - creating output notes from transactions -- [Note Scripts](../notes/note-scripts) - writing custom note scripts +- [Standard Note Types](../notes/note-types.md) - more detail on P2ID, P2IDE, and SWAP +- [Output Notes](../notes/output-notes.md) - creating output notes from transactions +- [Note Scripts](../notes/note-scripts.md) - writing custom note scripts - [`miden-standards` note source](https://github.com/0xMiden/protocol/tree/next/crates/miden-standards/src/note) - current implementation diff --git a/docs/builder/smart-contracts/transactions/advice-provider.md b/docs/builder/smart-contracts/transactions/advice-provider.md index 2d0725a5..0d22c4c3 100644 --- a/docs/builder/smart-contracts/transactions/advice-provider.md +++ b/docs/builder/smart-contracts/transactions/advice-provider.md @@ -88,7 +88,7 @@ let note_type = data[1]; // ... ``` -See [Transaction Scripts](./transaction-scripts) for the full `basic-wallet-tx-script` example. +See [Transaction Scripts](./transaction-scripts.md) for the full `basic-wallet-tx-script` example. ## Writing to the advice map @@ -119,7 +119,7 @@ adv_insert_mem(key, start_addr, end_addr); ## Requesting a Falcon signature -`emit_falcon_sig_to_stack` emits an `AUTH_REQUEST_EVENT` that instructs the host to push a Falcon512 signature onto the advice stack. This is typically used in [authentication components](../accounts/authentication) before calling `rpo_falcon512_verify`. +`emit_falcon_sig_to_stack` emits an `AUTH_REQUEST_EVENT` that instructs the host to push a Falcon512 signature onto the advice stack. This is typically used in [authentication components](../accounts/authentication.md) before calling `rpo_falcon512_verify`. ```rust use miden::intrinsics::advice::emit_falcon_sig_to_stack; @@ -135,6 +135,6 @@ Full API docs on docs.rs: [`miden::intrinsics::advice`](https://docs.rs/miden/la ## Related -- [Authentication](../accounts/authentication) — Falcon512 signature verification (over Poseidon2) and nonce management -- [Transaction Scripts](./transaction-scripts) — executing logic in the transaction context -- [Transaction Context](./transaction-context) — overview of transaction execution +- [Authentication](../accounts/authentication.md) — Falcon512 signature verification (over Poseidon2) and nonce management +- [Transaction Scripts](./transaction-scripts.md) — executing logic in the transaction context +- [Transaction Context](./transaction-context.md) — overview of transaction execution diff --git a/docs/builder/smart-contracts/transactions/introduction.md b/docs/builder/smart-contracts/transactions/introduction.md index 77c7539b..f29576c0 100644 --- a/docs/builder/smart-contracts/transactions/introduction.md +++ b/docs/builder/smart-contracts/transactions/introduction.md @@ -70,7 +70,7 @@ The ZK circuit **cannot produce a valid proof**. This means: This is fundamentally different from Ethereum's `revert`, where the failed transaction still lands onchain, consumes gas, and is visible to everyone. -A separate failure mode is the **empty transaction**: a transaction that runs to completion but mutates no account state (storage, vault, or nonce) and consumes no input notes. Both the Rust client (which raises `TransactionRequestError::NoInputNotesNorAccountChange` before submission) and the VM kernel reject it. This typically catches transaction scripts whose conditional logic takes a no-op branch — see [Empty Transaction](../../tutorials/helpers/pitfalls#empty-transaction-no-state-change-no-notes) in the pitfalls guide for the recommended pattern. +A separate failure mode is the **empty transaction**: a transaction that runs to completion but mutates no account state (storage, vault, or nonce) and consumes no input notes. Both the Rust client (which raises `TransactionRequestError::NoInputNotesNorAccountChange` before submission) and the VM kernel reject it. This typically catches transaction scripts whose conditional logic takes a no-op branch — see [Empty Transaction](../../tutorials/helpers/pitfalls.md#empty-transaction-no-state-change-no-notes) in the pitfalls guide for the recommended pattern. ## How transactions differ from EVM transactions diff --git a/docs/builder/smart-contracts/transactions/transaction-context.md b/docs/builder/smart-contracts/transactions/transaction-context.md index 9414f6b2..8eea96a3 100644 --- a/docs/builder/smart-contracts/transactions/transaction-context.md +++ b/docs/builder/smart-contracts/transactions/transaction-context.md @@ -57,9 +57,9 @@ The expiration delta determines how many blocks after creation the transaction r ## Transaction scripts -Transaction scripts use the `#[tx_script]` macro to define a top-level entry point for the transaction. See [Transaction Scripts](./transaction-scripts) for the full `#[tx_script]` API and examples. +Transaction scripts use the `#[tx_script]` macro to define a top-level entry point for the transaction. See [Transaction Scripts](./transaction-scripts.md) for the full `#[tx_script]` API and examples. -For signature verification using the transaction context, see [Authentication](../accounts/authentication). For time-based patterns using `tx::get_block_number()`, see [Patterns — Rate limiting](../patterns#rate-limiting). +For signature verification using the transaction context, see [Authentication](../accounts/authentication.md). For time-based patterns using `tx::get_block_number()`, see [Patterns — Rate limiting](../patterns.md#rate-limiting). :::info API Reference Full API docs on docs.rs: [`miden::tx`](https://docs.rs/miden/latest/miden/tx/) diff --git a/docs/builder/smart-contracts/transactions/transaction-scripts.md b/docs/builder/smart-contracts/transactions/transaction-scripts.md index f8bda2e1..fd16e880 100644 --- a/docs/builder/smart-contracts/transactions/transaction-scripts.md +++ b/docs/builder/smart-contracts/transactions/transaction-scripts.md @@ -6,7 +6,7 @@ description: "Write transaction scripts with #[tx_script] to orchestrate multi-n # Transaction Scripts -A transaction script is a top-level function that runs once per transaction, after all note scripts have executed. Use it to orchestrate logic that spans multiple consumed notes — moving assets from the account vault into output notes, calling account methods via [cross-component calls](../cross-component-calls), or running anything that must happen after all note scripts finish. +A transaction script is a top-level function that runs once per transaction, after all note scripts have executed. Use it to orchestrate logic that spans multiple consumed notes — moving assets from the account vault into output notes, calling account methods via [cross-component calls](../cross-component-calls.md), or running anything that must happen after all note scripts finish. ## `#[tx_script]` signature @@ -94,11 +94,11 @@ This script uses the advice map to pass structured input data. The caller encode ::: :::tip -`adv_push_mapvaln` and `adv_load_preimage` are part of the advice provider — the mechanism for supplying auxiliary data to a transaction. See [Advice Provider](./advice-provider) for the full function reference. +`adv_push_mapvaln` and `adv_load_preimage` are part of the advice provider — the mechanism for supplying auxiliary data to a transaction. See [Advice Provider](./advice-provider.md) for the full function reference. ::: ## Related -- [Transaction Context](./transaction-context) — `tx` module (block info, note commitments, expiration) -- [Cross-Component Calls](../cross-component-calls) — how `&mut Account` works in tx scripts -- [Reading Notes](../notes/reading-notes) — reading input notes by index inside tx scripts +- [Transaction Context](./transaction-context.md) — `tx` module (block info, note commitments, expiration) +- [Cross-Component Calls](../cross-component-calls.md) — how `&mut Account` works in tx scripts +- [Reading Notes](../notes/reading-notes.md) — reading input notes by index inside tx scripts diff --git a/docs/builder/smart-contracts/types.md b/docs/builder/smart-contracts/types.md index 78ece75b..893a608f 100644 --- a/docs/builder/smart-contracts/types.md +++ b/docs/builder/smart-contracts/types.md @@ -6,7 +6,7 @@ description: "Felt field arithmetic, Word layout, Asset encoding, and type conve # Types -Miden's type system is built around field elements rather than standard integers. All computation inside the Miden VM is modular arithmetic over the Goldilocks prime field ($p = 2^{64} - 2^{32} + 1$), so overflow and division behave differently from standard integers. `Felt` is the native numeric type, `Word` is a tuple of four Felts used for [storage](./accounts/storage) and hashing, and `Asset` encodes fungible and non-fungible assets as Words. +Miden's type system is built around field elements rather than standard integers. All computation inside the Miden VM is modular arithmetic over the Goldilocks prime field ($p = 2^{64} - 2^{32} + 1$), so overflow and division behave differently from standard integers. `Felt` is the native numeric type, `Word` is a tuple of four Felts used for [storage](./accounts/storage.md) and hashing, and `Asset` encodes fungible and non-fungible assets as Words. ## Felt — Field elements @@ -283,7 +283,7 @@ The SDK also provides `NoteIdx`, `Tag`, `NoteType`, `Recipient`, `Digest`, and ` | `[u32; 4]` / `[u16; 4]` / `[u8; 4]` / `[bool; 4]` | `Word` | `Word::from(arr)` | | `Word` | `[Felt; 4]` | `w.into_elements()` or `let arr: [Felt; 4] = w.into()` | -Use these types in [component definitions](./accounts/components), store and retrieve Words from [persistent storage](./accounts/storage), or define your own types for public APIs with [`#[export_type]`](./accounts/custom-types). +Use these types in [component definitions](./accounts/components.md), store and retrieve Words from [persistent storage](./accounts/storage.md), or define your own types for public APIs with [`#[export_type]`](./accounts/custom-types.md). :::info API Reference Full API docs on docs.rs: [`Felt`](https://docs.rs/miden/latest/miden/struct.Felt.html), [`Word`](https://docs.rs/miden/latest/miden/struct.Word.html), [`Asset`](https://docs.rs/miden/latest/miden/struct.Asset.html) diff --git a/docs/builder/tools/bridging/index.md b/docs/builder/tools/bridging/index.md index 2414eb1a..a54dfb54 100644 --- a/docs/builder/tools/bridging/index.md +++ b/docs/builder/tools/bridging/index.md @@ -24,15 +24,15 @@ mainnet funds. ## Start here - + Run the mock 1Click Bridge API locally and reproduce the Sepolia-to-Miden and Miden-to-Sepolia testing flow. - + Understand the actors, solver role, public Miden notes, and inbound/outbound lifecycle. - + Integration shape for `/v0/tokens`, `/v0/quote`, `/v0/deposit/submit`, and `/v0/status`. @@ -58,4 +58,4 @@ Use these docs when you need to: For core account, note, and transaction concepts, start with the Smart Contracts section instead. For testnet RPC, explorer, faucet, and remote prover endpoints, -see [Network](../network). +see [Network](../network.md). diff --git a/docs/builder/tools/bridging/testnet-sandbox.md b/docs/builder/tools/bridging/testnet-sandbox.md index f3efe302..f517823f 100644 --- a/docs/builder/tools/bridging/testnet-sandbox.md +++ b/docs/builder/tools/bridging/testnet-sandbox.md @@ -95,7 +95,7 @@ make sepolia-reset The `/demo/*` and `/lab` endpoints in the sandbox are local helpers. App integrations should use only the `/v0/*` endpoints described in the -[API reference](./api-reference). +[API reference](./api-reference.md). ## Run live testnet evidence diff --git a/docs/builder/tools/clients/index.md b/docs/builder/tools/clients/index.md index 31350c95..545c6409 100644 --- a/docs/builder/tools/clients/index.md +++ b/docs/builder/tools/clients/index.md @@ -15,10 +15,10 @@ The Miden client manages accounts, builds and executes transactions, produces ze Native Rust library and CLI. Best for services, proving infrastructure, tests, scripting, and local exploration. - + `@miden-sdk/miden-sdk` — Rust compiled to WebAssembly with a typed TypeScript API. Browser, Node, Electron, service workers. - + `@miden-sdk/react` — `MidenProvider` + hooks (`useMiden`, `useAccount`, `useSend`, …) wrapping the Web SDK. @@ -43,13 +43,13 @@ The Miden client manages accounts, builds and executes transactions, produces ze ## Shared topics - + Run a local node, point Rust and web clients at localhost, import genesis accounts, and debug local transaction state. Errors, diagnostic output, and recovery patterns shared across all surfaces. - + End-to-end walkthroughs using each client surface — Miden Bank, recipes, helpers. diff --git a/docs/builder/tools/index.md b/docs/builder/tools/index.md index 913c3535..8433ef88 100644 --- a/docs/builder/tools/index.md +++ b/docs/builder/tools/index.md @@ -14,10 +14,10 @@ Developer tools for building on and interacting with the Miden network. Use the Full-featured Rust library for Miden layer 2 integration — accounts, transactions, notes, proving. - + Browser-based client for managing accounts and transactions from a web app. - + Hooks and components for Miden dApps. @@ -25,19 +25,19 @@ Developer tools for building on and interacting with the Miden network. Use the ## Toolchain + environments - + Install and switch between Miden toolchain channels — VM, compiler, client, stdlib, kernel — from a unified `miden` command. - + Interactive environment for writing and testing Miden Assembly programs. - + Live Miden testnet endpoints — status, block explorer (MidenScan), RPC, faucet, remote prover. - + Offchain relay service for delivering private note payloads between senders and recipients. - + Testnet bridge tooling and interoperability guides, starting with the mock 1Click bridge sandbox. diff --git a/docs/builder/tools/midenup.md b/docs/builder/tools/midenup.md index fa5f0239..f2cbc5b3 100644 --- a/docs/builder/tools/midenup.md +++ b/docs/builder/tools/midenup.md @@ -105,13 +105,13 @@ Everything outside the alias table is forwarded to the underlying binary — e.g ## Related - + Full environment setup — prerequisites, node install, first account. - + Walk through `miden account`, `miden send`, `miden faucet`, and the rest. - + Endpoints the `miden` CLI points at — RPC, faucet, remote prover, block explorer. diff --git a/docs/builder/tools/network.md b/docs/builder/tools/network.md index 53864023..d7c60962 100644 --- a/docs/builder/tools/network.md +++ b/docs/builder/tools/network.md @@ -46,7 +46,7 @@ Hard-coding testnet URLs in client configs is fine for demos, but the Miden ops -**Install the toolchain** — `midenup` pulls the client, CLI, and compiler in one step. See [Installation](../get-started/setup/installation). +**Install the toolchain** — `midenup` pulls the client, CLI, and compiler in one step. See [Installation](../get-started/setup/installation.md). **Point the client at testnet** — default config targets the testnet RPC, so `miden new` projects work out of the box. @@ -61,7 +61,7 @@ Hard-coding testnet URLs in client configs is fine for demos, but the Miden ops ## Related - + End-to-end walkthrough — client → RPC → MidenScan verification. diff --git a/docs/builder/tools/note-transport/index.md b/docs/builder/tools/note-transport/index.md index 85bf4ead..ceac2551 100644 --- a/docs/builder/tools/note-transport/index.md +++ b/docs/builder/tools/note-transport/index.md @@ -14,13 +14,13 @@ Private note contents are not published onchain. The chain stores note commitmen ## Start here - + How the node stores notes, assigns cursors, routes by tag, and handles current protocol boundaries. - + CLI flags, Docker Compose, telemetry, storage, ports, retention, and production cautions. - + Request and response shapes for send, fetch, stream, stats, plus the recommended client sync pattern. diff --git a/docs/builder/tools/playground.md b/docs/builder/tools/playground.md index 31b3449a..610fb1d9 100644 --- a/docs/builder/tools/playground.md +++ b/docs/builder/tools/playground.md @@ -32,19 +32,19 @@ An interactive browser environment for writing, compiling, and executing Miden A -The Playground shines for learning MASM and for quick prototyping. For anything bigger than a snippet — components, storage, note dispatch, transaction flows — move to a `miden new` Rust project locally. See [your first smart contract](../get-started/your-first-smart-contract) for the handoff. +The Playground shines for learning MASM and for quick prototyping. For anything bigger than a snippet — components, storage, note dispatch, transaction flows — move to a `miden new` Rust project locally. See [your first smart contract](../get-started/your-first-smart-contract/index.md) for the handoff. ## Related - + Install the toolchain and build + deploy a counter contract in Rust. - + New `word(...)` / `event(...)` constants, `std::math::u128`, and other MASM-level deltas. - + Accounts, notes, transactions, and the Rust SDK surface. diff --git a/docs/builder/tutorials/helpers/pitfalls.md b/docs/builder/tutorials/helpers/pitfalls.md index 505f0fc6..f3425f50 100644 --- a/docs/builder/tutorials/helpers/pitfalls.md +++ b/docs/builder/tutorials/helpers/pitfalls.md @@ -541,7 +541,7 @@ let request = TransactionRequestBuilder::new() ``` :::tip Standard auth handles this for you -Most account templates run an authentication procedure that calls `incr_nonce()` on every transaction. If your account uses `BasicWallet`, `IncrNonceAuthComponent`, or any auth component that increments the nonce, you only hit this pitfall in transaction-script-only flows that skip the auth path. See [Authentication](../../smart-contracts/accounts/authentication) for details. +Most account templates run an authentication procedure that calls `incr_nonce()` on every transaction. If your account uses `BasicWallet`, `IncrNonceAuthComponent`, or any auth component that increments the nonce, you only hit this pitfall in transaction-script-only flows that skip the auth path. See [Authentication](../../smart-contracts/accounts/authentication.md) for details. ::: ### Why this exists @@ -550,7 +550,7 @@ A Miden transaction commits to a state delta plus a set of consumed notes. A tra :::info See also - Client-side error catalog: [`TransactionRequestError::NoInputNotesNorAccountChange`](../../tools/clients/common-errors) -- Failure modes table: [Account Operations](../../smart-contracts/accounts/account-operations#when-proof-generation-fails) +- Failure modes table: [Account Operations](../../smart-contracts/accounts/account-operations.md#when-proof-generation-fails) ::: --- @@ -575,6 +575,6 @@ See these patterns in context in the [miden-bank repository](https://github.com/ ## Next Steps -- **[Debugging Guide](./debugging)** - Troubleshoot errors -- **[Testing Guide](./testing)** - MockChain patterns -- **[Miden Bank Tutorial](../miden-bank/)** - See these patterns in context +- **[Debugging Guide](./debugging.md)** - Troubleshoot errors +- **[Testing Guide](./testing.md)** - MockChain patterns +- **[Miden Bank Tutorial](../miden-bank/index.md)** - See these patterns in context diff --git a/docs/builder/tutorials/helpers/testing.md b/docs/builder/tutorials/helpers/testing.md index ff2bdc58..1acf54e1 100644 --- a/docs/builder/tutorials/helpers/testing.md +++ b/docs/builder/tutorials/helpers/testing.md @@ -605,6 +605,6 @@ See the complete test implementations in the [miden-bank repository](https://git ## Next Steps -- **[Debugging Guide](./debugging)** - Troubleshoot common issues -- **[Common Pitfalls](./pitfalls)** - Avoid known gotchas -- **[Miden Bank Tutorial](../miden-bank/)** - See testing in action +- **[Debugging Guide](./debugging.md)** - Troubleshoot common issues +- **[Common Pitfalls](./pitfalls.md)** - Avoid known gotchas +- **[Miden Bank Tutorial](../miden-bank/index.md)** - See testing in action diff --git a/docs/builder/tutorials/index.md b/docs/builder/tutorials/index.md index 9d19467d..330ee4e6 100644 --- a/docs/builder/tutorials/index.md +++ b/docs/builder/tutorials/index.md @@ -11,7 +11,7 @@ Hands-on walkthroughs for building on Miden. Every tutorial pairs with runnable ## Pick a path - + A 9-part curriculum — build a complete banking application covering components, storage, note scripts, cross-component calls, and output notes. @@ -28,19 +28,19 @@ Hands-on walkthroughs for building on Miden. Every tutorial pairs with runnable ## Development helpers - + Test your contracts against MockChain for local simulation. - + Interpret errors and debug common issues. - + Avoid known issues and limitations. ## Prerequisites -- [Install the Miden toolchain](../get-started/setup/installation) with `midenup`. +- [Install the Miden toolchain](../get-started/setup/installation.md) with `midenup`. - Basic familiarity with Rust (or TypeScript for the client examples). -- Understanding of the [core concepts](../smart-contracts/) — accounts, notes, transactions. +- Understanding of the [core concepts](../smart-contracts/index.md) — accounts, notes, transactions. diff --git a/package.json b/package.json index 27297f71..03c5d20f 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,9 @@ "generate:og": "node scripts/generate-og-images.mjs", "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", + "check:doc-links": "node scripts/normalize-doc-links.mjs", + "normalize-doc-links": "node scripts/normalize-doc-links.mjs --fix", + "normalize-doc-links:all": "node scripts/normalize-doc-links.mjs --fix --all", "typecheck": "tsc" }, "dependencies": { diff --git a/scripts/normalize-doc-links.mjs b/scripts/normalize-doc-links.mjs new file mode 100644 index 00000000..63c68dd0 --- /dev/null +++ b/scripts/normalize-doc-links.mjs @@ -0,0 +1,304 @@ +#!/usr/bin/env node + +import fs from "node:fs"; +import path from "node:path"; + +const repoRoot = process.cwd(); +const fix = process.argv.includes("--fix"); +// By default only the current docs (docs/) are scanned, so `check` stays green +// against the committed tree. Pass --all to additionally scan every +// versioned_docs/ snapshot — used at deploy time to heal historical +// versions, which are intentionally not normalized in-repo. +const includeVersioned = process.argv.includes("--all"); +const markdownExtensions = new Set([".md", ".mdx"]); +const versionedRoot = path.join(repoRoot, "versioned_docs"); +const docsRoots = [ + path.join(repoRoot, "docs"), + ...(includeVersioned && fs.existsSync(versionedRoot) + ? fs + .readdirSync(versionedRoot, { withFileTypes: true }) + .filter((entry) => entry.isDirectory()) + .map((entry) => path.join(versionedRoot, entry.name)) + : []), +]; + +function walk(dir) { + const entries = fs.readdirSync(dir, { withFileTypes: true }); + const files = []; + + for (const entry of entries) { + const fullPath = path.join(dir, entry.name); + + if (entry.isDirectory()) { + files.push(...walk(fullPath)); + } else if (markdownExtensions.has(path.extname(entry.name))) { + files.push(fullPath); + } + } + + return files; +} + +function toPosix(filePath) { + return filePath.split(path.sep).join(path.posix.sep); +} + +function getRoot(filePath) { + return docsRoots.find((root) => filePath.startsWith(`${root}${path.sep}`)); +} + +function splitUrl(rawUrl) { + const suffixIndex = rawUrl.search(/[?#]/); + + if (suffixIndex === -1) { + return { pathname: rawUrl, suffix: "" }; + } + + return { + pathname: rawUrl.slice(0, suffixIndex), + suffix: rawUrl.slice(suffixIndex), + }; +} + +function isRelativeDocCandidate(rawUrl) { + if (!(rawUrl.startsWith("./") || rawUrl.startsWith("../"))) { + return false; + } + + const { pathname } = splitUrl(rawUrl); + return !path.posix.extname(pathname); +} + +function candidateFiles(root, sourceFile, rawUrl) { + const { pathname } = splitUrl(rawUrl); + const sourceDir = path.posix.dirname( + toPosix(path.relative(root, sourceFile)), + ); + const target = path.posix.normalize(path.posix.join(sourceDir, pathname)); + const rootPosix = toPosix(root); + + const directCandidates = [ + `${target}.md`, + `${target}.mdx`, + path.posix.join(target, "index.md"), + path.posix.join(target, "index.mdx"), + ].map((candidate) => path.join(rootPosix, candidate)); + + return [ + ...directCandidates, + ...numberPrefixedCandidates(rootPosix, target), + ]; +} + +function numberPrefixedCandidates(root, target) { + const targetDir = path.posix.dirname(target); + const targetBase = path.posix.basename(target); + const absoluteDir = path.join(root, targetDir); + + if (!fs.existsSync(absoluteDir)) { + return []; + } + + const candidates = []; + const prefixPattern = new RegExp(`^\\d+[-_]${escapeRegExp(targetBase)}(?:\\.mdx?)?$`); + + for (const entry of fs.readdirSync(absoluteDir, { withFileTypes: true })) { + if (!prefixPattern.test(entry.name)) { + continue; + } + + const candidate = path.join(absoluteDir, entry.name); + + if (entry.isFile() && markdownExtensions.has(path.extname(entry.name))) { + candidates.push(candidate); + } + + if (entry.isDirectory()) { + candidates.push(path.join(candidate, "index.md")); + candidates.push(path.join(candidate, "index.mdx")); + } + } + + return candidates; +} + +function escapeRegExp(value) { + return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} + +function stripNumberPrefix(value) { + return value.replace(/^\d+[-_]/, ""); +} + +function resolveTarget(root, sourceFile, rawUrl) { + for (const candidate of candidateFiles(root, sourceFile, rawUrl)) { + if (fs.existsSync(candidate)) { + return candidate; + } + } + + return undefined; +} + +function relativeMarkdownPath(sourceFile, targetFile, suffix) { + const sourceDir = path.posix.dirname(toPosix(sourceFile)); + let relativePath = path.posix.relative(sourceDir, toPosix(targetFile)); + + if (!relativePath.startsWith(".")) { + relativePath = `./${relativePath}`; + } + + return `${relativePath}${suffix}`; +} + +function docId(root, targetFile) { + return toPosix(path.relative(root, targetFile)) + .replace(/\.mdx?$/, "") + .split("/") + .map(stripNumberPrefix) + .join("/"); +} + +function normalizeMarkdownLink(root, sourceFile, rawUrl) { + if (!isRelativeDocCandidate(rawUrl)) { + return rawUrl; + } + + const target = resolveTarget(root, sourceFile, rawUrl); + + if (!target) { + return rawUrl; + } + + const { suffix } = splitUrl(rawUrl); + return relativeMarkdownPath(sourceFile, target, suffix); +} + +// Link-text alternation: backtick-quoted code (which may contain `]`) or any +// non-`]`, non-backtick character. Lets the regex traverse text like +// `[\`#[export_type]\`]`. The two branches are mutually exclusive on the first +// character — keeps the engine off exponential backtracking paths. +const linkTextPattern = String.raw`(?:\`[^\`\n]*\`|[^\]\`])*?`; + +// Fenced code block (``` or ~~~) or HTML/MDX comment. Anything matched here is +// passed through untouched so example markdown in docs isn't rewritten. +// Indented fences (inside list items) are not supported — they trigger +// catastrophic regex backtracking on large docs. +const protectedRegionPattern = + /(?:^(`{3,}|~{3,})[^\n]*\n[\s\S]*?^\1[^\n]*$|)/gm; + +function replaceOutsideProtectedRegions(content, transform) { + let result = ""; + let lastIndex = 0; + + for (const match of content.matchAll(protectedRegionPattern)) { + result += transform(content.slice(lastIndex, match.index)); + result += match[0]; + lastIndex = match.index + match[0].length; + } + + result += transform(content.slice(lastIndex)); + return result; +} + +function normalizeMarkdownLinks(root, sourceFile, content) { + let normalized = replaceOutsideProtectedRegions(content, (chunk) => + chunk.replace( + new RegExp( + `(!?\\[${linkTextPattern}\\]\\()(<[^>\\s]+>|[^\\s)]+)([^)]*\\))`, + "g", + ), + (match, prefix, rawUrl, suffix) => { + const wrapped = rawUrl.startsWith("<") && rawUrl.endsWith(">"); + const url = wrapped ? rawUrl.slice(1, -1) : rawUrl; + const normalizedUrl = normalizeMarkdownLink(root, sourceFile, url); + + if (normalizedUrl === url) { + return match; + } + + return `${prefix}${wrapped ? `<${normalizedUrl}>` : normalizedUrl}${suffix}`; + }, + ), + ); + + normalized = replaceOutsideProtectedRegions(normalized, (chunk) => + chunk.replace( + /^(\s*\[[^\]]+\]:\s+)(\S+)(.*)$/gm, + (match, prefix, rawUrl, suffix) => { + const normalizedUrl = normalizeMarkdownLink(root, sourceFile, rawUrl); + + if (normalizedUrl === rawUrl) { + return match; + } + + return `${prefix}${normalizedUrl}${suffix}`; + }, + ), + ); + + return normalized; +} + +function normalizeCardLinks(root, sourceFile, content) { + return replaceOutsideProtectedRegions(content, (chunk) => + chunk.replace(/\n]*\bhref="([^"]+)"[^>\n]*>/g, (tag, rawUrl) => { + if (!isRelativeDocCandidate(rawUrl)) { + return tag; + } + + const target = resolveTarget(root, sourceFile, rawUrl); + + if (!target) { + return tag; + } + + const { suffix } = splitUrl(rawUrl); + + // Bail out on query strings — Card has no prop for them and silently + // dropping a query suffix would change the link target. + if (suffix && !suffix.startsWith("#")) { + return tag; + } + + const id = docId(root, target); + return tag.replace( + `href="${rawUrl}"`, + `docId="${id}"${suffix ? ` hash="${suffix}"` : ""}`, + ); + }), + ); +} + +const changedFiles = []; + +for (const root of docsRoots) { + for (const file of walk(root)) { + const content = fs.readFileSync(file, "utf8"); + const normalized = normalizeCardLinks( + root, + file, + normalizeMarkdownLinks(root, file, content), + ); + + if (normalized !== content) { + changedFiles.push(path.relative(repoRoot, file)); + + if (fix) { + fs.writeFileSync(file, normalized); + } + } + } +} + +if (changedFiles.length > 0) { + console.log( + `${fix ? "Updated" : "Would update"} ${changedFiles.length} docs files.`, + ); + for (const file of changedFiles) { + console.log(file); + } + process.exit(fix ? 0 : 1); +} + +console.log("Docs links are already normalized."); diff --git a/src/components/mdx/Card/index.tsx b/src/components/mdx/Card/index.tsx index 74e66e63..efd08fc4 100644 --- a/src/components/mdx/Card/index.tsx +++ b/src/components/mdx/Card/index.tsx @@ -1,16 +1,160 @@ import React, { type ReactNode } from "react"; import Link from "@docusaurus/Link"; +import { + useActiveDocContext, + useLayoutDoc, + type GlobalDoc, + type GlobalVersion, +} from "@docusaurus/plugin-content-docs/client"; import clsx from "clsx"; import styles from "./styles.module.css"; type CardProps = { title: string; href?: string; + docId?: string; + hash?: string; icon?: ReactNode; eyebrow?: string; children?: ReactNode; }; +type CardLinkProps = { + href?: string; + docId?: string; + hash?: string; + children: ReactNode; +}; + +function splitHref(href: string): { pathname: string; suffix: string } { + const suffixIndex = href.search(/[?#]/); + + if (suffixIndex === -1) { + return { pathname: href, suffix: "" }; + } + + return { + pathname: href.slice(0, suffixIndex), + suffix: href.slice(suffixIndex), + }; +} + +function isRelativePath(href: string): boolean { + return href.startsWith("./") || href.startsWith("../"); +} + +function normalizeDocId(pathname: string): string { + const parts: string[] = []; + + for (const part of pathname.split("/")) { + if (!part || part === ".") { + continue; + } + + if (part === "..") { + parts.pop(); + continue; + } + + parts.push(part); + } + + return parts.join("/"); +} + +function getDocSourceDir(docId: string): string { + const indexSuffix = "/index"; + + if (docId.endsWith(indexSuffix)) { + return docId.slice(0, -indexSuffix.length); + } + + return docId.split("/").slice(0, -1).join("/"); +} + +function findVersionDoc( + version: GlobalVersion, + targetId: string, +): GlobalDoc | undefined { + return version.docs.find( + (doc) => doc.id === targetId || doc.id === `${targetId}/index`, + ); +} + +function getVersionPath(version: GlobalVersion): string { + return version.path === "/" ? "" : version.path.replace(/\/$/, ""); +} + +function resolveDocRelativeHref( + href: string, + activeDoc: GlobalDoc | undefined, + activeVersion: GlobalVersion | undefined, +): string { + if (!activeDoc || !activeVersion) { + return href; + } + + const { pathname, suffix } = splitHref(href); + const sourceDir = getDocSourceDir(activeDoc.id); + const targetId = normalizeDocId(`${sourceDir}/${pathname}`); + const targetDoc = findVersionDoc(activeVersion, targetId); + + if (targetDoc) { + return `${targetDoc.path}${suffix}`; + } + + return `${getVersionPath(activeVersion)}/${targetId.replace(/\/$/, "")}/${suffix}`; +} + +function DocIdCardLink({ docId, hash, children }: CardLinkProps): JSX.Element { + const doc = useLayoutDoc(docId!); + + return ( + + {children} + + ); +} + +function RelativeCardLink({ href, children }: CardLinkProps): JSX.Element { + const { activeDoc, activeVersion } = useActiveDocContext(undefined); + const to = resolveDocRelativeHref(href!, activeDoc, activeVersion); + + return ( + + {children} + + ); +} + +function CardLink({ + href, + docId, + hash, + children, +}: CardLinkProps): JSX.Element { + if (docId) { + return ( + + {children} + + ); + } + + if (href && isRelativePath(href)) { + return {children}; + } + + return ( + + {children} + + ); +} + /** * `` — a standalone bordered card for MDX docs. Use inside a * `` for grouped layouts, or drop it inline for single-link cards. @@ -18,6 +162,8 @@ type CardProps = { export default function Card({ title, href, + docId, + hash, icon, eyebrow, children, @@ -32,7 +178,7 @@ export default function Card({ {eyebrow ? {eyebrow} : null}

{title}

{children ?
{children}
: null} - {href ? ( + {href || docId ? ( @@ -40,11 +186,11 @@ export default function Card({ ); - if (href) { + if (href || docId) { return ( - + {inner} - + ); }