-
Notifications
You must be signed in to change notification settings - Fork 37
Add Miden Standards builder docs #298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,96 @@ | ||||||
| --- | ||||||
| title: "Account Components" | ||||||
| description: "Use standard account components for wallets, authentication, access control, faucets, and metadata." | ||||||
| --- | ||||||
|
|
||||||
| # Account Components | ||||||
|
|
||||||
| Standard account components are prebuilt modules you can compose into accounts. They give an account a recognizable interface, such as "can receive assets", "can authenticate with this signature scheme", "can mint fungible tokens", or "uses this access-control model". | ||||||
|
|
||||||
| Use these components from Rust when you build accounts with the SDK, or import the underlying MASM modules when you are writing lower-level account code. The same standards surface is what note scripts and transaction scripts rely on when they call account procedures. | ||||||
|
|
||||||
| ## Common components | ||||||
|
|
||||||
| | Component | Use it for | Rust module | | ||||||
| |-----------|------------|-------------| | ||||||
| | `BasicWallet` | Holding assets, receiving assets from standard notes, and moving assets into output notes. | `miden_standards::account::wallets` | | ||||||
| | `FungibleFaucet` | Minting, sending, receiving, and burning fungible assets from faucet accounts. | `miden_standards::account::faucets` | | ||||||
| | `AuthSingleSig` | Authenticating transactions with one supported signature scheme. | `miden_standards::account::auth` | | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
This component supports various signature schemes. |
||||||
| | `AuthSingleSigAcl` | Single-signature authentication with an access-control list. | `miden_standards::account::auth` | | ||||||
| | `AuthMultisig` / `AuthMultisigSmart` | Threshold or policy-aware multisig authentication. | `miden_standards::account::auth` | | ||||||
| | `AuthGuardedMultisig` | Multisig guarded by a guardian configuration. | `miden_standards::account::auth` | | ||||||
| | `AuthNetworkAccount` | Authentication for network-account flows. | `miden_standards::account::auth` | | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| | `Ownable2Step` | Ownership transfer with an explicit accept step. | `miden_standards::account::access` | | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Not sure what framing is best, but I think the primary purpose of the component is more about defining what account owner means, and the transfer of ownership is secondary. |
||||||
| | `RoleBasedAccessControl` | Role-based authorization for standard policy management. | `miden_standards::account::access` | | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Fits better with |
||||||
| | `Authority` | Shared authority component used by policy-management standards. | `miden_standards::account::access` | | ||||||
|
|
||||||
| These are building blocks. They do not prevent you from adding custom components to the same account. | ||||||
|
|
||||||
| :::info v0.14 differences | ||||||
| The v0.14 snapshot uses separate `BasicFungibleFaucet` and `NetworkFungibleFaucet` components and does not include RBAC, authority, guarded multisig, smart multisig, or network-account auth in the same form. Use the v0.14 versioned docs when building against the v0.14 crates. | ||||||
| ::: | ||||||
|
|
||||||
| ## Start with wallet and auth | ||||||
|
|
||||||
| Most regular accounts need: | ||||||
|
|
||||||
| - an authentication component, such as `AuthSingleSig` or `AuthMultisig` | ||||||
| - a wallet component, usually `BasicWallet` | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
For now we don't have any other wallet components and I don't think we plan on having one. |
||||||
|
|
||||||
| `AuthSingleSig` controls transaction authorization. `BasicWallet` exposes the standard wallet procedures used by common notes, including the ability to receive assets and move assets into output notes. | ||||||
|
|
||||||
| ```rust title="Compose a regular account with standard auth and wallet components" | ||||||
| use miden_protocol::Word; | ||||||
| use miden_protocol::account::auth::{AuthScheme, PublicKeyCommitment}; | ||||||
| use miden_protocol::account::{AccountBuilder, AccountStorageMode, AccountType}; | ||||||
| use miden_standards::account::auth::AuthSingleSig; | ||||||
| use miden_standards::account::wallets::BasicWallet; | ||||||
|
|
||||||
| fn build_wallet_account() -> Result<(), Box<dyn std::error::Error>> { | ||||||
| let public_key = PublicKeyCommitment::from(Word::from([1, 2, 3, 4u32])); | ||||||
|
|
||||||
| let account = AccountBuilder::new([1; 32]) | ||||||
| .account_type(AccountType::RegularAccountImmutableCode) | ||||||
| .storage_mode(AccountStorageMode::Public) | ||||||
| .with_auth_component(AuthSingleSig::new(public_key, AuthScheme::Falcon512Poseidon2)) | ||||||
| .with_component(BasicWallet) | ||||||
| .build()?; | ||||||
|
|
||||||
| assert_eq!(account.account_type(), AccountType::RegularAccountImmutableCode); | ||||||
| Ok(()) | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| For authentication details, see [Authentication](../accounts/authentication). For how component methods are authored in Rust, see [Components](../accounts/components). | ||||||
|
|
||||||
| ## Check note compatibility | ||||||
|
|
||||||
| Standard notes assume the consuming account exposes the procedures they need. For example, P2ID and P2IDE notes need a wallet-compatible account that can receive assets. SWAP notes additionally need the wallet procedure that moves the requested asset into the payback note. | ||||||
|
|
||||||
| At the builder level, the practical rule is: | ||||||
|
|
||||||
| - Add `BasicWallet` to accounts that should receive standard asset-transfer notes. | ||||||
| - Add `FungibleFaucet` to faucet accounts that should mint or burn fungible assets. | ||||||
| - Add auth components to every account that must reject unauthorized transactions. | ||||||
|
Comment on lines
+70
to
+74
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would differentiate the last point into two:
|
||||||
|
|
||||||
| If you write a custom wallet component instead of using `BasicWallet`, match the expected interface deliberately and test consumption of the relevant standard notes. | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of suggesting that builders match the interface, I'd change the framing to: "build on top of |
||||||
|
|
||||||
| ## Rust and MASM entry points | ||||||
|
|
||||||
| Rust APIs are the usual entry point for account composition. MASM modules are available when you need exact low-level behavior. | ||||||
|
|
||||||
| | Area | Rust module | MASM module family | | ||||||
| |------|-------------|--------------------| | ||||||
| | Wallets | `miden_standards::account::wallets` | `miden::standards::wallets::*` | | ||||||
| | Authentication | `miden_standards::account::auth` | `miden::standards::auth::*` | | ||||||
| | Access control | `miden_standards::account::access` | `miden::standards::access::*` | | ||||||
| | Faucets | `miden_standards::account::faucets` | `miden::standards::faucets::*` | | ||||||
| | Metadata | `miden_standards::account::metadata` | `miden::standards::metadata::*` | | ||||||
|
|
||||||
| Reach for MASM directly when you are implementing low-level behavior, integrating a custom component with a standard procedure, or verifying exact stack effects. | ||||||
|
|
||||||
| ## 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 | ||||||
| - [`miden-standards` account source](https://github.com/0xMiden/protocol/tree/next/crates/miden-standards/src/account) - current implementation | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this link to the corresponding release, for which these docs are built? This would at least prevent confusion, and in the worst case prevent looking at the wrong source and building something that's broken because of it. I think this might be a more general doc problem, namely that we're linking to |
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| --- | ||
| title: "Faucets and Policies" | ||
| description: "Build fungible token faucets and choose standard mint, burn, send, and receive policies." | ||
| --- | ||
|
|
||
| # Faucets and Policies | ||
|
|
||
| In Miden, a token issuer is an account. A fungible faucet account can mint and burn the fungible asset identified by that faucet's account ID. The standard faucet components give builders a reusable way to create token issuers without hand-writing the entire faucet interface. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Heads-up: This is going to be outdated in 0.15 (see also 0xMiden/protocol#2956). The account type no longer decides what type of asset can be issued, instead this is decided at the asset level ( |
||
|
|
||
| Use this page when you need to create a faucet account, decide who can mint or burn, or understand how faucet behavior relates to standard notes. | ||
|
|
||
| :::info v0.14 differences | ||
| The current unstable standards surface uses a unified `FungibleFaucet` component and a richer `TokenPolicyManager`. The v0.14 snapshot uses separate `BasicFungibleFaucet` and `NetworkFungibleFaucet` components plus mint-policy components. Use the versioned docs if you are building against v0.14. | ||
| ::: | ||
|
|
||
| ## Faucet component | ||
|
|
||
| The current standard fungible faucet component is `FungibleFaucet`. | ||
|
|
||
| | Surface | Entry point | | ||
| |---------|-------------| | ||
| | Rust component | `miden_standards::account::faucets::FungibleFaucet` | | ||
| | Rust builder/helper | `FungibleFaucetBuilder`, `create_fungible_faucet` | | ||
| | MASM component | `miden::standards::faucets::fungible` | | ||
| | Account type | `FungibleFaucet` account | | ||
|
|
||
| Public storage is typical for shared token faucets because clients can discover faucet state and metadata. Private storage is possible, but it changes who can observe the faucet's state. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Replace "storage" with "state", since for a public account, everything is public, not just storage (in particular also the account's asset vault and code). |
||
|
|
||
| ```rust title="Create a fungible faucet with allow-all policies" | ||
| use miden_protocol::Word; | ||
| use miden_protocol::account::AccountStorageMode; | ||
| use miden_protocol::account::auth::{AuthScheme, PublicKeyCommitment}; | ||
| use miden_protocol::asset::{AssetAmount, TokenSymbol}; | ||
| use miden_standards::AuthMethod; | ||
| use miden_standards::account::access::AccessControl; | ||
| use miden_standards::account::faucets::{ | ||
| Description, | ||
| FungibleFaucet, | ||
| TokenName, | ||
| create_fungible_faucet, | ||
| }; | ||
| use miden_standards::account::policies::{ | ||
| BurnPolicyConfig, | ||
| MintPolicyConfig, | ||
| PolicyRegistration, | ||
| TokenPolicyManager, | ||
| TransferPolicy, | ||
| }; | ||
|
|
||
| fn create_faucet_account() -> Result<(), Box<dyn std::error::Error>> { | ||
| let public_key = PublicKeyCommitment::from(Word::from([1, 2, 3, 4u32])); | ||
|
|
||
| let faucet = FungibleFaucet::builder() | ||
| .name(TokenName::new("Example Token")?) | ||
| .symbol(TokenSymbol::new("EXT")?) | ||
| .decimals(6) | ||
| .max_supply(AssetAmount::from(1_000_000u32)) | ||
| .description(Description::new("Example token")?) | ||
| .build()?; | ||
|
|
||
| let policies = TokenPolicyManager::new() | ||
| .with_mint_policy(MintPolicyConfig::AllowAll, PolicyRegistration::Active)? | ||
| .with_burn_policy(BurnPolicyConfig::AllowAll, PolicyRegistration::Active)? | ||
| .with_send_policy(TransferPolicy::AllowAll, PolicyRegistration::Active)? | ||
| .with_receive_policy(TransferPolicy::AllowAll, PolicyRegistration::Active)?; | ||
|
|
||
| let account = create_fungible_faucet( | ||
| [9; 32], | ||
| faucet, | ||
| AccountStorageMode::Public, | ||
| AuthMethod::SingleSig { | ||
| approver: (public_key, AuthScheme::Falcon512Poseidon2), | ||
| }, | ||
| AccessControl::AuthControlled, | ||
| policies, | ||
| )?; | ||
|
|
||
| assert!(account.is_faucet()); | ||
| Ok(()) | ||
| } | ||
| ``` | ||
|
|
||
| ## Token identity | ||
|
|
||
| A fungible asset is tied to its faucet account ID. The faucet's metadata describes the token, while the account ID identifies the asset issuer. | ||
|
|
||
| | Field | Meaning | | ||
| |-------|---------| | ||
| | Symbol | Short token symbol. | | ||
| | Decimals | Display precision for client UX. | | ||
| | Max supply | Upper bound enforced by the faucet component. | | ||
| | Metadata | Optional display fields such as token name, description, logo URI, and external link. | | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: |
||
| | Faucet account ID | The issuer ID used when constructing fungible assets and checking balances. | | ||
|
|
||
| When an account checks its balance for a fungible token, it queries by the faucet account ID. | ||
|
|
||
| ## Choose policy modules | ||
|
|
||
| Policy modules decide which operations are allowed for a token faucet. | ||
|
|
||
| | Policy area | Current standard examples | Use it for | | ||
| |-------------|---------------------------|------------| | ||
| | Mint | `MintAllowAll`, `MintOwnerOnly` | Gate mint operations. | | ||
| | Burn | `BurnAllowAll`, `BurnOwnerOnly` | Gate burn operations. | | ||
| | Send | `TransferAllowAll`, `BasicBlocklist`, `OwnerControlledBlocklist` | Gate assets leaving accounts through notes. | | ||
| | Receive | `TransferAllowAll`, `BasicBlocklist`, `OwnerControlledBlocklist` | Gate assets entering account vaults. | | ||
|
|
||
| `TokenPolicyManager` owns the active policy roots and validates policy changes. Authority for changing policies comes from the account's access-control setup, such as owner-controlled or role-based authority. | ||
|
|
||
| ## Mint with notes | ||
|
|
||
| Minting does not directly credit a recipient's account vault. A faucet creates a note carrying the minted asset, and the recipient consumes that note to receive the asset. | ||
|
|
||
| For standard flows: | ||
|
|
||
| - The faucet creates a mint note or a P2ID note containing the minted asset. | ||
| - 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). | ||
|
|
||
| ## Burn returned assets | ||
|
|
||
| Burning is also note-based. A burn note returns assets to the faucet and executes the standard burn behavior. Use `BurnNote` from `miden-standards` rather than hand-writing a burn script unless your protocol needs custom conditions. | ||
|
|
||
| ## When to write a custom faucet | ||
|
|
||
| Use `FungibleFaucet` when supply, metadata, minting, burning, and transfer policies match the standard pattern. | ||
|
|
||
| Write a custom faucet component when: | ||
|
|
||
| - Minting depends on application state, proofs, allowlists, or rate limits. | ||
| - Supply policy is more complex than a fixed max supply and a standard authority check. | ||
| - You need custom public methods beyond the standard faucet interface. | ||
|
|
||
|
Comment on lines
+130
to
+135
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| Even then, consider reusing standard auth, ownership, and wallet components where they fit. Custom faucet logic does not require custom authentication or custom note formats by default. | ||
|
|
||
| ## 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 | ||
| - [`miden-standards` faucet source](https://github.com/0xMiden/protocol/tree/next/crates/miden-standards/src/account/faucets) - current implementation | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| --- | ||
| title: "Miden Standards" | ||
| description: "Use standard Miden account components, notes, faucets, and policies from Rust or Miden Assembly." | ||
| --- | ||
|
|
||
| # Miden Standards | ||
|
|
||
| Miden Standards are reusable building blocks for common smart-contract behavior: wallet interfaces, authentication components, token faucets, note scripts, and policy modules. | ||
|
|
||
| Use them when you want your account, note, or transaction flow to interoperate with the rest of the Miden ecosystem instead of defining every interface from scratch. | ||
|
|
||
| :::caution Current docs are unstable | ||
| The current docs track the unstable standards line. The v0.14 snapshot has a different standards surface in a few important places, especially faucet and policy APIs. Use the version selector if you are building against v0.14. | ||
| ::: | ||
|
|
||
| This section is a builder guide, not the canonical standards specification. It explains which standard to reach for, how it fits into the smart-contract model, and where to switch to reference docs when you need exact procedure names, storage schemas, or script roots. | ||
|
|
||
| ## How standards fit into smart contracts | ||
|
|
||
| Smart Contracts is the domain. Rust and Miden Assembly are authoring paths inside that domain. | ||
|
|
||
| | Layer | Role | | ||
| |------|------| | ||
| | Rust | Compose standard account components and construct standard notes through Rust APIs. | | ||
| | Miden Assembly | Import and call standard MASM modules directly when writing low-level account, note, transaction, or library code. | | ||
| | Miden Standards | Shared account components, note scripts, faucet policies, and helper modules used by both authoring paths. | | ||
|
|
||
| ## What this section covers | ||
|
|
||
| <CardGrid cols={3}> | ||
| <Card title="Account components" href="./account-components" eyebrow="Compose accounts"> | ||
| Use standard wallet, authentication, access-control, faucet, and metadata components. | ||
| </Card> | ||
| <Card title="Standard notes" href="./standard-notes" eyebrow="Move assets"> | ||
| Choose P2ID, P2IDE, SWAP, PSWAP, mint, and burn note scripts. | ||
| </Card> | ||
| <Card title="Faucets and policies" href="./faucets-and-policies" eyebrow="Issue tokens"> | ||
| Build token faucets and choose mint, burn, send, and receive policy modules. | ||
| </Card> | ||
| </CardGrid> | ||
|
|
||
| ## When to use standards | ||
|
|
||
| Use a standard component or note when: | ||
|
|
||
| - You want other accounts, note scripts, clients, or tooling to recognize your account interface. | ||
| - Your behavior matches an existing pattern, such as holding assets, receiving a P2ID transfer, minting a fungible token, or verifying a single signature. | ||
| - You need a stable building block before adding custom application logic. | ||
|
|
||
| Write custom components or note scripts when: | ||
|
|
||
| - The authorization rules are application-specific. | ||
| - The note consumption condition is not covered by P2ID, P2IDE, SWAP, mint, or burn notes. | ||
| - The account's state model needs custom storage and custom exported methods. | ||
|
|
||
| You can mix both approaches. A typical application account starts with standard authentication and wallet components, then adds one or more custom components for protocol-specific logic. | ||
|
|
||
| ## Related pages | ||
|
|
||
| - [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 | ||
| - [`miden-standards` source](https://github.com/0xMiden/protocol/tree/next/crates/miden-standards) - current standards implementation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to list everything here or just "common" ones?
In any case,
TokenPolicyManagerwould also be useful to mention, and probably theBasicBlocklistandBasicAllowlist. These are not in 0.14.x (as the PR description suggests), iirc, but neither isAuthoritywhich is already listed.