# Table of Contents - [Guides | Mesh SDK](#guides-mesh-sdk) - [Mesh API | Mesh SDK](#mesh-api-mesh-sdk) - [React Components | Mesh SDK](#react-components-mesh-sdk) - [Feature complete Web3 SDK | Mesh SDK](#feature-complete-web3-sdk-mesh-sdk) - [Branding | Mesh SDK](#branding-mesh-sdk) - [Support Us | Mesh SDK](#support-us-mesh-sdk) - [Project Catalyst | Mesh SDK](#project-catalyst-mesh-sdk) - [Providers | Mesh SDK](#providers-mesh-sdk) - [Write a Smart Contract | Mesh SDK](#write-a-smart-contract-mesh-sdk) - [Mesh AI Features | Mesh SDK](#mesh-ai-features-mesh-sdk) - [Getting Started | Mesh SDK](#getting-started-mesh-sdk) - [Aiken | Mesh SDK](#aiken-mesh-sdk) - [Learn | Mesh SDK](#learn-mesh-sdk) - [Build Transactions | Mesh SDK](#build-transactions-mesh-sdk) - [Layer 2 scaling solution | Mesh SDK](#layer-2-scaling-solution-mesh-sdk) - [Hydra Instance | Mesh SDK](#hydra-instance-mesh-sdk) - [Midnight | Mesh SDK](#midnight-mesh-sdk) - [End-to-end Hydra Tutorial | Mesh SDK](#end-to-end-hydra-tutorial-mesh-sdk) - [Solutions | Mesh SDK](#solutions-mesh-sdk) - [Mesh Data | Mesh SDK](#mesh-data-mesh-sdk) - [Ogmios Provider | Mesh SDK](#ogmios-provider-mesh-sdk) - [UI Components | Mesh SDK](#ui-components-mesh-sdk) - [Svelte Components | Mesh SDK](#svelte-components-mesh-sdk) - [Data Overview | Mesh SDK](#data-overview-mesh-sdk) - [Offline Evaluator | Mesh SDK](#offline-evaluator-mesh-sdk) - [Wallet Hooks | Mesh SDK](#wallet-hooks-mesh-sdk) - [Build Transactions | Mesh SDK](#build-transactions-mesh-sdk) - [JSON Data | Mesh SDK](#json-data-mesh-sdk) - [Getting Started with React | Mesh SDK](#getting-started-with-react-mesh-sdk) - [Yaci | Mesh SDK](#yaci-mesh-sdk) - [UI Components | Mesh SDK](#ui-components-mesh-sdk) - [Transaction Parser | Mesh SDK](#transaction-parser-mesh-sdk) - [Wallets | Mesh SDK](#wallets-mesh-sdk) - [Parser Basics | Mesh SDK](#parser-basics-mesh-sdk) - [Getting Started | Mesh SDK](#getting-started-mesh-sdk) - [Getting Started with Svelte | Mesh SDK](#getting-started-with-svelte-mesh-sdk) - [Unit Testing Transaction | Mesh SDK](#unit-testing-transaction-mesh-sdk) - [Koios Provider | Mesh SDK](#koios-provider-mesh-sdk) - [Blockfrost Provider | Mesh SDK](#blockfrost-provider-mesh-sdk) - [Frequently Asked Questions | Mesh SDK](#frequently-asked-questions-mesh-sdk) - [Aiken Hello World | Mesh SDK](#aiken-hello-world-mesh-sdk) - [Hydra Provider (beta) | Mesh SDK](#hydra-provider-beta-mesh-sdk) - [Maestro Provider | Mesh SDK](#maestro-provider-mesh-sdk) - [UTxORPC Provider | Mesh SDK](#utxorpc-provider-mesh-sdk) - [OfflineFetcher | Mesh SDK](#offlinefetcher-mesh-sdk) - [Utilities | Mesh SDK](#utilities-mesh-sdk) - [Transaction Builder | Mesh SDK](#transaction-builder-mesh-sdk) - [Use Cases & Showcases | Mesh SDK](#use-cases-showcases-mesh-sdk) - [Overview | Mesh SDK](#overview-mesh-sdk) - [Deserializers | Mesh SDK](#deserializers-mesh-sdk) - [Installation | Mesh SDK](#installation-mesh-sdk) - [Implement Custom Provider | Mesh SDK](#implement-custom-provider-mesh-sdk) - [Prove Wallet Ownership | Mesh SDK](#prove-wallet-ownership-mesh-sdk) - [Available Contracts | Mesh SDK](#available-contracts-mesh-sdk) - [Serializers | Mesh SDK](#serializers-mesh-sdk) - [Usage | Mesh SDK](#usage-mesh-sdk) - [GiftCard | Mesh SDK](#giftcard-mesh-sdk) - [Data | Mesh SDK](#data-mesh-sdk) - [Core API Methods | Mesh SDK](#core-api-methods-mesh-sdk) - [Smart Contracts | Mesh SDK](#smart-contracts-mesh-sdk) - [Payment Splitter | Mesh SDK](#payment-splitter-mesh-sdk) - [Overview | Mesh SDK](#overview-mesh-sdk) - [Blueprints | Mesh SDK](#blueprints-mesh-sdk) - [Escrow | Mesh SDK](#escrow-mesh-sdk) - [Hello World | Mesh SDK](#hello-world-mesh-sdk) - [Mint an NFT Collection | Mesh SDK](#mint-an-nft-collection-mesh-sdk) - [Develop your first Web3 App | Mesh SDK](#develop-your-first-web3-app-mesh-sdk) - [Swap | Mesh SDK](#swap-mesh-sdk) - [Project Structure | Mesh SDK](#project-structure-mesh-sdk) - [Value | Mesh SDK](#value-mesh-sdk) - [Multi-Signatures Transaction | Mesh SDK](#multi-signatures-transaction-mesh-sdk) - [Executing a standalone script | Mesh SDK](#executing-a-standalone-script-mesh-sdk) - [Minting Application | Mesh SDK](#minting-application-mesh-sdk) - [Marketplace | Mesh SDK](#marketplace-mesh-sdk) - [Yaci Provider | Mesh SDK](#yaci-provider-mesh-sdk) - [Cardano Course | Mesh SDK](#cardano-course-mesh-sdk) - [Vesting Script End-to-End | Mesh SDK](#vesting-script-end-to-end-mesh-sdk) - [Resolve Node-Specific Imports Errors | Mesh SDK](#resolve-node-specific-imports-errors-mesh-sdk) - [Content Ownership | Mesh SDK](#content-ownership-mesh-sdk) - [Staking Transactions | Mesh SDK](#staking-transactions-mesh-sdk) - [NFT Minting Machine | Mesh SDK](#nft-minting-machine-mesh-sdk) - [Developer Resources | Mesh SDK](#developer-resources-mesh-sdk) - [Resolvers | Mesh SDK](#resolvers-mesh-sdk) - [Browser Wallet | Mesh SDK](#browser-wallet-mesh-sdk) - [Vesting | Mesh SDK](#vesting-mesh-sdk) - [Smart Contracts | Mesh SDK](#smart-contracts-mesh-sdk) - [Mesh Wallet | Mesh SDK](#mesh-wallet-mesh-sdk) - [Transaction Basics | Mesh SDK](#transaction-basics-mesh-sdk) - [Governance Transactions | Mesh SDK](#governance-transactions-mesh-sdk) - [Lace Wallet Integration | Mesh SDK](#lace-wallet-integration-mesh-sdk) - [Smart Contract Transactions | Mesh SDK](#smart-contract-transactions-mesh-sdk) - [Integration Examples | Mesh SDK](#integration-examples-mesh-sdk) - [Mint and Burn Assets | Mesh SDK](#mint-and-burn-assets-mesh-sdk) - [End-to-End Hydra Happy Flow | Mesh SDK](#end-to-end-hydra-happy-flow-mesh-sdk) - [Web3 Services | Mesh SDK](#web3-services-mesh-sdk) - [Course Lessons | Mesh SDK](#course-lessons-mesh-sdk) - [Avoid Redundant Validation | Mesh SDK](#avoid-redundant-validation-mesh-sdk) - [Aiken Contracts | Mesh SDK](#aiken-contracts-mesh-sdk) - [Interpreting Blueprint | Mesh SDK](#interpreting-blueprint-mesh-sdk) - [Getting Started | Mesh SDK](#getting-started-mesh-sdk) - [Vesting Contract | Mesh SDK](#vesting-contract-mesh-sdk) - [Multi-signature Transactions | Mesh SDK](#multi-signature-transactions-mesh-sdk) - [Hello World | Mesh SDK](#hello-world-mesh-sdk) - [Contract Testing | Mesh SDK](#contract-testing-mesh-sdk) - [Plutus NFT Contract | Mesh SDK](#plutus-nft-contract-mesh-sdk) - [Tutorials | Mesh SDK](#tutorials-mesh-sdk) - [Unknown](#unknown) --- # Guides | Mesh SDK [Learn](https://meshjs.dev/resources) Guides ====== Guides for web developers and blockchain full-stack developers. Copy MarkdownOpen [Develop your first Web3 App\ \ A step-by-step guide to setup a Next.js web application, add a wallet connection and browse assets.](https://meshjs.dev/guides/nextjs) [Minting Application\ \ Load CLI generated keys and mint assets on Node.js.](https://meshjs.dev/guides/minting-on-nodejs) [Multi-Signatures Transaction\ \ Learn about multi-sig transaction, build a minting transaction involving MeshWallet and BrowserWallet.](https://meshjs.dev/guides/multisig-minting) [Prove Wallet Ownership\ \ Cryptographically prove the ownership of a wallet by signing a piece of data using data sign.](https://meshjs.dev/guides/prove-wallet-ownership) [Implement Custom Provider\ \ Build custom Providers that provides an API to access and process information provided by services.](https://meshjs.dev/guides/custom-provider) [Smart Contract Transactions\ \ Build a marketplace with Plutus (Haskell), where users can list their assets for sale and purchase the listed assets.](https://meshjs.dev/guides/smart-contract-transactions) [Aiken Hello World\ \ Create smart contracts with Aiken and execute transactions with Mesh.](https://meshjs.dev/guides/aiken) [Executing a standalone script\ \ Learn how to execute a standalone script to manage wallets and creating transactions.](https://meshjs.dev/guides/standalone) [Vesting Script End-to-End\ \ Learn how to vesting contract that locks up funds for a period of time and allows the beneficiary to withdraw the funds after the lockup period.](https://meshjs.dev/guides/vesting) [Resolve Node-Specific Imports Errors\ \ How to Resolve Node-Specific Imports Errors (e.g., Buffer, TextEncoder) in Browser-Based Projects](https://meshjs.dev/guides/node-specific-imports) [Mint an NFT Collection\ \ Learn to mint an NFT Collection with JavaScript & the MeshSDK.](https://meshjs.dev/guides/nft-collection) [Web3 Services\ \ Onboard seamlessly with non-custodial wallet-as-a-service and transaction sponsorship.](https://meshjs.dev/resources/cardano-course/lessons/10-web3-services) [Develop your first Web3 App\ \ Next Page](https://meshjs.dev/guides/nextjs) Ask AI --- # Mesh API | Mesh SDK Mesh API ======== From wallet integrations to transaction builders, Mesh makes Web3 development easy with reliable, scalable, and well-engineered APIs & developer tools. Copy MarkdownOpen [Wallets\ \ Wallets APIs for interacting with the blockchain.](https://meshjs.dev/apis/wallets) [Transaction Builder\ \ Build transactions with cardano-cli like APIs](https://meshjs.dev/apis/txbuilder) [Transaction Parser\ \ Parse transactions for testing and rebuilding](https://meshjs.dev/apis/txparser) [Providers\ \ Data providers for connecting to the blockchain](https://meshjs.dev/providers) [Utilities\ \ Serializers, resolvers and data types for converting between different formats.](https://meshjs.dev/apis/utilities) [React Components\ \ Frontend React UI components and React hooks](https://meshjs.dev/react) [Svelte Components\ \ Svelte UI components for wallet connections](https://meshjs.dev/svelte) [Smart Contracts Lib\ \ Open-source smart contracts, complete with documentation, and live demos](https://meshjs.dev/smart-contracts) [Aiken\ \ Functional programming language created for Cardano smart contract development](https://meshjs.dev/aiken) [Hydra\ \ Layer 2 scaling solution for Cardano](https://meshjs.dev/hydra) [Yaci\ \ Custom devnet to tailor your devnet needs with a builtin indexer](https://meshjs.dev/yaci) [Midnight\ \ Zero-knowledge privacy network for Cardano](https://meshjs.dev/midnight) [Wallet as a Service\ \ Access self-custodial wallet using social logins](https://utxos.dev/wallet-as-a-service) [Transaction Sponsorship\ \ Sponsor blockchain transaction fees for your users to eliminate friction.](https://utxos.dev/transaction-sponsorship) Ask AI --- # React Components | Mesh SDK React Components ================ Frontend React UI components and React hooks Copy MarkdownOpen [Getting Started with React\ \ Frontend components for wallet connections, and useful React hooks to getting wallet states](https://meshjs.dev/react/getting-started) [UI Components\ \ UI components to speed up your app development.](https://meshjs.dev/react/ui-components) [Wallet Hooks\ \ React hooks for interacting with connected wallets.](https://meshjs.dev/react/wallet-hooks) [Blueprints\ \ Blueprints for script with either apply parameters or no parameters](https://meshjs.dev/apis/utilities/blueprints) [Getting Started with React\ \ Frontend components for wallet connections, and useful React hooks to getting wallet states](https://meshjs.dev/react/getting-started) Ask AI --- # Feature complete Web3 SDK | Mesh SDK Feature complete Web3 SDK ========================= Our enterprise-ready SDK is professionally designed, robust, and developer-friendly. With simple transaction builders, seamless wallet integrations, and reliable data services, building Web3 applications has never been this effortless. Copy MarkdownOpen Our Team ======== ![Jingles](https://meshjs.dev/team/jingles.png) Jingles ======= [X](https://x.com/jinglescode) [GitHub](https://github.com/jinglescode) ![Felix](https://meshjs.dev/team/felix.png) Felix ===== [X](https://x.com/CatalystSwarm) [GitHub](https://github.com/Felix-at-Swarm) ![Erick](https://meshjs.dev/team/erick.jpg) Erick ===== [X](https://x.com/ErickRomeroEdda) [GitHub](https://github.com/ErickRomeroDev) ![Hinson](https://meshjs.dev/team/hinson.png) Hinson ====== [X](https://x.com/HinsonSIDAN) [GitHub](https://github.com/HinsonSIDAN) ![Tszwai](https://meshjs.dev/team/tszwai.png) Tszwai ====== [GitHub](https://github.com/twwu123) ![QS](https://meshjs.dev/team/qs.jpg) QS == [GitHub](https://github.com/QSchlegel) ![Leif](https://meshjs.dev/team/leif.jpg) Leif ==== [](https://www.linkedin.com/in/leifelliott/) [GitHub](https://github.com/JustLeif) ![Luis Lucena](https://meshjs.dev/team/luis-lucena.png) Luis Lucena =========== [X](https://x.com/_luisald) [GitHub](https://github.com/luislucena16) ![Santosh](https://meshjs.dev/team/santosh.jpg) Santosh ======= [](https://www.linkedin.com/in/smutyala2000/) [GitHub](https://github.com/smutyala1at) What are we working on? ======================= Check out our [GitHub milestones](https://github.com/MeshJS/mesh/milestones) to see what we are currently working on. Incorporation ============= MeshJS Pte. Ltd. is a company registered in Singapore since 2023, with the registration number (UEN): 202344120W. Status ====== Stay up to date with our latest releases, tests and build status. ### Published on NPM [![](https://img.shields.io/npm/v/%40meshsdk%2Fcore?style=for-the-badge)](https://www.npmjs.com/package/@meshsdk/core) ### Build status [![](https://github.com/meshjs/mesh/actions/workflows/build.yml/badge.svg)](https://github.com/meshjs/mesh/actions/workflows/build.yml) ### Publish status [![](https://github.com/meshjs/mesh/actions/workflows/publish.yml/badge.svg)](https://github.com/meshjs/mesh/actions/workflows/publish.yml) Ask AI --- # Branding | Mesh SDK [Feature complete Web3 SDK](https://meshjs.dev/about) Branding ======== These resources exist to help you use Mesh's assets. Copy MarkdownOpen [Logo](https://meshjs.dev/about/branding#logo-toc) --------------------------------------------------- The Mesh logo is available in two color schemes: black and white. You can use the logo in either color scheme depending on your design needs. The logo is available in various sizes to suit different use cases. ![mesh-black-512](https://meshjs.dev/_next/image?url=%2Flogo-mesh%2Fblack%2Flogo-mesh-black-512x512.png&w=1080&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) Download black logo: [SVG](https://meshjs.dev/logo-mesh/black/logo-mesh-vector.svg) [16x16](https://meshjs.dev/logo-mesh/black/logo-mesh-black-16x16.png) [32x32](https://meshjs.dev/logo-mesh/black/logo-mesh-black-32x32.png) [64x64](https://meshjs.dev/logo-mesh/black/logo-mesh-black-64x64.png) [128x128](https://meshjs.dev/logo-mesh/black/logo-mesh-black-128x128.png) [256x256](https://meshjs.dev/logo-mesh/black/logo-mesh-black-256x256.png) [512x512](https://meshjs.dev/logo-mesh/black/logo-mesh-black-512x512.png) ![mesh-white-512](https://meshjs.dev/_next/image?url=%2Flogo-mesh%2Fwhite%2Flogo-mesh-white-512x512.png&w=1080&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) Download white logo: [SVG](https://meshjs.dev/logo-mesh/white/logo-mesh-vector.svg) [16x16](https://meshjs.dev/logo-mesh/white/logo-mesh-white-16x16.png) [32x32](https://meshjs.dev/logo-mesh/white/logo-mesh-white-32x32.png) [64x64](https://meshjs.dev/logo-mesh/white/logo-mesh-white-64x64.png) [128x128](https://meshjs.dev/logo-mesh/white/logo-mesh-white-128x128.png) [256x256](https://meshjs.dev/logo-mesh/white/logo-mesh-white-256x256.png) [512x512](https://meshjs.dev/logo-mesh/white/logo-mesh-white-512x512.png) ![mesh-black-title-512](https://meshjs.dev/logo-mesh/meshlogo-with-title-black.svg?dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) Download black logo with title: [SVG](https://meshjs.dev/logo-mesh/meshlogo-with-title-black.svg) ![mesh-white-title-512](https://meshjs.dev/logo-mesh/meshlogo-with-title-white.svg?dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) Download white logo with title:[SVG](https://meshjs.dev/logo-mesh/meshlogo-with-title-white.svg) ![mesh-background](https://meshjs.dev/_next/image?url=%2Flogo-mesh%2Fmesh.png&w=1080&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) Download logo with background:[PNG](https://meshjs.dev/logo-mesh/mesh.png) Ask AI --- # Support Us | Mesh SDK [Feature complete Web3 SDK](https://meshjs.dev/about) Support Us ========== Thank you for your interest in Mesh, we appreciate any kind of support! Here are some ways you can support us. Copy MarkdownOpen [Follow us on Twitter](https://meshjs.dev/about/support-us#follow-us-on-twitter-toc) ===================================================================================== Follow us on Twitter so you get updated with the latest development! [Follow us on Twitter](https://x.com/meshsdk) ![support-x](https://meshjs.dev/support/x-logo.svg?dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) [Donate to Mesh](https://meshjs.dev/about/support-us#donate-to-mesh-toc) ========================================================================= Your support for this open-source SDK will go a long way. So thank you! [Coming soon](https://meshjs.dev/about/support-us) [Star Mesh GitHub Repo](https://meshjs.dev/about/support-us#star-mesh-github-repo-toc) ======================================================================================= Visit our GitHub and star it! [Star GitHub repo](https://github.com/MeshJS/mesh) ![support-github](https://meshjs.dev/support/github-mark-white.svg?dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) [Add Mesh Badge in your Application](https://meshjs.dev/about/support-us#add-mesh-badge-in-your-application-toc) ================================================================================================================= Add our beautiful Mesh Badge to give your users confidence knowing that your application is running on top of a solid SDK. import { MeshBadge } from '@meshsdk/react'; export default function Page() { return ( <> ); } ![support-mesh](https://meshjs.dev/_next/image?url=%2Fsupport%2Fmeshbadge.png&w=640&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) [Join our Discord Server](https://meshjs.dev/about/support-us#join-our-discord-server-toc) =========================================================================================== Come and talk to us in our Discord server. [Join Mesh's Discord server](https://discord.com/invite/WvnCNqmAxy) ![support-discord](https://meshjs.dev/_next/image?url=%2Fsupport%2Fdiscord.png&w=640&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) Ask AI --- # Project Catalyst | Mesh SDK [Feature complete Web3 SDK](https://meshjs.dev/about) Project Catalyst ================ Proposals that we have submitted to Project Catalyst and its progress. Copy MarkdownOpen Fund13 ====== Hydra Tools for administrating & interacting with Hydra Heads ------------------------------------------------------------- In Progress Provide all the tools needed to integration Hydra on apps, to enable end-user operations like interacting with wallet, query UTXOs/balance and submit transactions. Hydra Provider Wallets integration Transaction building End-to-end working example [projectcatalyst.io](https://projectcatalyst.io/funds/13/f13-cardano-open-developers/mesh-hydra-tools-for-administrating-and-interacting-with-hydra-heads) Cardano Devkit - 'Ganache' of Cardano for better DevXP ------------------------------------------------------ In ProgressNot Funded An app to launch local blockchain to test and deploy transactions and smart contracts, to run tests and experiments to develop Cardano applications. Improve devnet deployment Desktop app to launch local blockchain Get blockchain data e.g. UTXOs and balances [projectcatalyst.io](https://projectcatalyst.io/funds/13/f13-cardano-use-cases-concept/mesh-cardano-devkit-ganache-better-devxp-with-local-cardano-network) Cquisitor - Transaction Investigation Tool ------------------------------------------ In Progress Enhancing Devtools with hosted Rust-based validation modules, and improving error handling to provide clearer feedback, helping developers debug and validate efficiently. Update Cquisitor Phase-1 validation Phase-2 validation Integration with Whisky and Mesh [projectcatalyst.io](https://projectcatalyst.io/funds/13/f13-cardano-open-developers/mesh-cquisitor-transaction-investigation-tool) Multisig Platform ----------------- In Progress Open source multisig platform for teams and organizations to manage their treasury and participate in governance. Full governance features Native tokens support Discord integrations Fluidtokens and Minswap integrations Plutus script multisig wallet [projectcatalyst.io](https://projectcatalyst.io/funds/13/f13-cardano-use-cases-product/cardano-multisig-platform-by-mesh-clarity-dao-and-fluid-tokens) Builder Fest #2 in Asia ----------------------- In Progress Hosting Buidler Fest #2, a 2-day event for tech-savvy Cardano builders to connect, showcase and share. Gathering of developers in Vietnam Increase collaboration between projects for Cardano ecosystem open-source [projectcatalyst.io](https://projectcatalyst.io/funds/13/f13-cardano-open-ecosystem/cardano-builder-fest-asia-by-mesh-socious-sidan-vietnam-cardano) Maintain Mesh and Build Developer Community ------------------------------------------- In Progress Maintenance and operations of the Mesh open source libraries and tool suits. Growing Cardano developer community. Provide community support Resolve GitHub issues Create tutorials and documentation Create workshops and live coding sessions [projectcatalyst.io](https://projectcatalyst.io/funds/13/f13-cardano-open-developers/maintain-mesh-and-build-developer-community) Fund12 ====== Cardano Service Layer Framework for DApps ----------------------------------------- In Progress R&D a framework to quickly spin up a service layer for specific Cardano DApps, allowing DApps to re-use all infrastructure such as contracts and MeshJS, while possible for custom protocol parameters. Parallel Cardano Blockchain MeshJS Integration Customized Protocol Parameters Persistent Record & Immutability Framework DevOps Documentation and training materials [projectcatalyst.io](https://projectcatalyst.io/funds/12/cardano-open-developers/sidan-or-meshjs-cardano-service-layer-framework-for-dapps) New Features to Improve Developer experience and Adoption --------------------------------------------------------- Closing We will upgrade Mesh by implementing CIP 45, WebRTC wallet connect, handle multiple serialization libs, revamp to support backend transactions building, and improve error messages to improve DevXP. Mesh application wallet Modular CSL library Wallet support for private blockchain networks (e.g. Yaci) CIP 45 Improve error messages [projectcatalyst.io](https://projectcatalyst.io/funds/12/cardano-open-developers/mesh-new-features-to-improve-developer-experience-and-cardano-adoption) Mesh Software as a Service -------------------------- In Progress We provide hosted server instances for wallet and transactions builder by restful APIs, this allow integration and interaction to Cardano blockchain from any technology stacks and systems. Cloud infrastructure User-defined transaction building JSON schema for transaction Utitlities for transaction building Hosted wallet / private key for signing [projectcatalyst.io](https://projectcatalyst.io/funds/12/cardano-use-cases-concept/mesh-software-as-a-service) Maintaining Mesh SDK, community support and content creation to onboard developers ---------------------------------------------------------------------------------- Closing Maintenance and operations of Mesh SDK, community support and content creation, in order to onboard developers and users to the Cardano blockchain ecosystem. Provide community support Resolve GitHub issues Create tutorials and documentation Create workshops and live coding sessions [projectcatalyst.io](https://projectcatalyst.io/funds/12/cardano-open-developers/sustain-and-maintain-mesh-sdk) Fund11 ====== Aiken Open-Source Smart Contract Library ---------------------------------------- In Progress We create a collection of open-source smart contracts with Aiken (including Workspace, Mesh TX builder components) and integrate them into the Mesh SDK library on Github - open and accessible to all. Marketplace Escrow Vesting Gift card Swap Payment splitter Content ownership NFT minting machine Bad examples [projectcatalyst.io](https://projectcatalyst.io/funds/11/cardano-open-developers/aiken-open-source-smart-contract-library-by-meshjs-and-trustlevel) Sustain & Maintain MeshJS ------------------------- Closing This proposal enables implementations not limited to Voltaire features, Hydra & Aiken integration, and data providers integrations. Including bounties for issues, features, and learning materials. Lower-level APIs completed Technical documentation released Resolved numerous reported GitHub issues Active Discord engagement to help developers Transaction building support for Hydra apps Plutus version 3 integration Revamped/refactored transaction and utilities class Conway features [projectcatalyst.io](https://projectcatalyst.io/funds/11/cardano-open-developers/sustain-and-maintain-meshjs) Fund10 ====== Supporting Open-Source Library Development, Developer Resources & Builder Community ----------------------------------------------------------------------------------- Closing To guarantee and ensure sustainability of a team dedicated to maintaining and developing one of the best open-source libraries on Cardano, providing devs with something easy-to-use, fun and productive. Lower-level APIs core functionality Mesh PBL course content Workshops and live coding Community Q&A support Demos and tutorials repository Mesh PBL Season #1 [projectcatalyst.io](https://projectcatalyst.io/funds/10/f10-osde-open-source-dev-ecosystem/meshjs-sdk-operations-supporting-open-source-library-development-developer-resources-and-builder-community) Support Teams Building Cardano dApps ------------------------------------ CompletedNot Funded Pro-actively facilitate integration of our open source code into other Cardano Projects by directly providing financial and human resources to support and facilitate these integrations. Provide community technical support Provide funding for integrating Cardano [projectcatalyst.io](https://projectcatalyst.io/funds/10/f10-developer-ecosystem-the-evolution/mesh-support-teams-building-cardano-dapps-with-mesh-js-sdk-a-comprehensive-open-source-sdk-for-building-dapps-on-cardano) Ask AI --- # Providers | Mesh SDK Providers ========= Data providers for connecting to the blockchain Copy MarkdownOpen [Blockfrost Provider\ \ Featuring over 100 APIs tailored for easy access to Cardano blockchain](https://meshjs.dev/providers/blockfrost) [Hydra Provider (beta)\ \ Layer 2 scaling solution for Cardano that increases transaction throughput and ensures cost efficiency while maintaining security.](https://meshjs.dev/providers/hydra) [Koios Provider\ \ Distributed & open-source public API query layer for Cardano](https://meshjs.dev/providers/koios) [Maestro Provider\ \ Advanced UTxO-indexing data layer to supercharge Defi on Bitcoin, Cardano & Dogecoin](https://meshjs.dev/providers/maestro) [Ogmios Provider\ \ Lightweight bridge interface for cardano-node that offers WebSockets API that enables local clients to speak Ouroboros' mini-protocols](https://meshjs.dev/providers/ogmios) [UTxORPC Provider\ \ Highly efficient through gRPC, using a compact and high-performance binary format](https://meshjs.dev/providers/utxorpc) [Yaci Provider\ \ Custom Cardano devnet to tailor your devnet needs with a builtin indexer and custom viewer for devnet](https://meshjs.dev/providers/yaci) [Offline Fetcher\ \ Provider for testing, development and offline scenarios](https://meshjs.dev/providers/offline-fetcher) [Offline Evaluator\ \ An offline Plutus script evaluator for testing and validation.](https://meshjs.dev/providers/offline-evaluator) [Unit Testing Transaction\ \ Parse and test transactions with various options](https://meshjs.dev/apis/txparser/txtester) [Blockfrost Provider\ \ Featuring over 100 APIs tailored for easy access to Cardano blockchain](https://meshjs.dev/providers/blockfrost) Ask AI --- # Write a Smart Contract | Mesh SDK [Aiken](https://meshjs.dev/aiken) Write a Smart Contract ====================== Learn how to write your first Aiken script, with a simple redeemer Copy MarkdownOpen [Write your first smart contract in Aiken](https://meshjs.dev/aiken/first-script#write-your-first-smart-contract-in-aiken) --------------------------------------------------------------------------------------------------------------------------- In this section, we will walk you through the process of writing a simple smart contract in Aiken. We will use the Visual Studio Code editor for this tutorial. You can use any other editor of your choice, but we recommend using Visual Studio Code for its rich feature set and support for Aiken. First, we create a new Aiken project within this project folder: $ aiken new meshjs/hello_world $ cd hello_world $ aiken check Remember to check your Aiken project by running `aiken check` after creating a new project and as you develop the contract. ### [Write the smart contract](https://meshjs.dev/aiken/first-script#write-the-smart-contract-toc) Let's create file for our validator, `validators/hello_world.ak`: use aiken/hash.{Blake2b_224, Hash} use aiken/list use aiken/transaction.{ScriptContext} use aiken/transaction/credential.{VerificationKey} type Datum { owner: Hash, } type Redeemer { msg: ByteArray, } validator { fn hello_world(datum: Datum, redeemer: Redeemer, context: ScriptContext) -> Bool { let must_say_hello = redeemer.msg == "Hello, World!" let must_be_signed = list.has(context.transaction.extra_signatories, datum.owner) must_say_hello && must_be_signed } } The validator checks for two conditions: * The redeemer message is `Hello, World!` * The transaction is signed by the owner If both conditions are met, the validator returns `true`. Otherwise, it returns `false`. [Compile and build](https://meshjs.dev/aiken/first-script#compile-and-build) ----------------------------------------------------------------------------- Let's compile the smart contract with the Aiken CLI: $ aiken build This command will compile the smart contract and generate the `plutus.json` file in the root folder. This file is a [CIP-0057 Plutus blueprint](https://cips.cardano.org/cip/CIP-0057) , blueprint describes your on-chain contract and its binary interface. [Getting Started\ \ Setting up your system to compile Aiken smart contracts](https://meshjs.dev/aiken/getting-started) [Build Transactions\ \ Build transactions to interact with smart contracts](https://meshjs.dev/aiken/transactions) ### On this page [Write your first smart contract in Aiken](https://meshjs.dev/aiken/first-script#write-your-first-smart-contract-in-aiken) [Compile and build](https://meshjs.dev/aiken/first-script#compile-and-build) Ask AI --- # Mesh AI Features | Mesh SDK Mesh AI Features ================ We've built AI tools to help you work with Mesh faster Copy MarkdownOpen [Ask MeshAI](https://meshjs.dev/ai#ask-meshai) ----------------------------------------------- Ask MeshAI is the chatbot on the website which answers your queries instantly and accurately by utilizing the contextual retrieval built on top of traditional RAG. ### [How it works:](https://meshjs.dev/ai#how-it-works) MeshAI searches through all the vector embeddings of Mesh documentation, code examples and starter templates to find the right answer for your question. It uses contextual retrieval technique to pull closet vectors to your query and make an LLM call to produce accurate answer without making things up. ### [Example Response:](https://meshjs.dev/ai#example-response) In this demo, we create a transaction that transfers ADA back to the sender’s own address using MeshAI. [LLMs.txt](https://meshjs.dev/ai#llmstxt) ------------------------------------------ Mesh provides llms.txt file that is easily understood by AI tools. This file contains everything from Mesh documentation and code examples. This file can be plugged into any AI code editors and will be instantly indexed to help you code with AI using up-to-date documentation from Mesh. Because the file follows a standardized AI-friendly format, code generation stays consistent across different tools. Since it's written in markdown text, it's just as easy for humans to browse as it is for machines to process. You can find llms.txt file [here](https://meshjs.dev/llms.txt) . AI code editors like Cursor let you add and index documentation, so you can reference it directly in your chats. For example, you can bring Mesh docs into Cursor by typing @Docs → Add new doc. A modal will open where you can paste the link to the [/llms.txt](https://meshjs.dev/llms.txt) file. Once added, the doc becomes available as context, making it easier and faster to build apps with AI. [Mesh MCP Setup](https://meshjs.dev/ai#mesh-mcp-setup) ------------------------------------------------------- Use Mesh MCP to access Mesh docs and get coding/debugging help directly in VS Code, Cursor, or Claude Desktop. ### [Quick Install (Cursor)](https://meshjs.dev/ai#quick-install-cursor) If you're using Cursor, you can install Mesh MCP with one click: [![Add mesh-mcp MCP server to Cursor](https://cursor.com/deeplink/mcp-install-light.svg)](https://cursor.com/en-US/install-mcp?name=mesh-mcp&config=eyJuYW1lIjoibWVzaC1tY3Atc2VydmVyIiwiZW52Ijp7IkFQSV9LRVkiOiJ5b3VyLWFwaS1rZXkiLCJNT0RFTCI6InlvdXItcHJlZmVycmVkLW1vZGVsIn0sImNvbW1hbmQiOiJucHggLXkgbWVzaGpzLW1jcCJ9) [![Add mesh-mcp MCP server to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=mesh-mcp&config=eyJuYW1lIjoibWVzaC1tY3Atc2VydmVyIiwiZW52Ijp7IkFQSV9LRVkiOiJ5b3VyLWFwaS1rZXkiLCJNT0RFTCI6InlvdXItcHJlZmVycmVkLW1vZGVsIn0sImNvbW1hbmQiOiJucHggLXkgbWVzaGpzLW1jcCJ9) **Note:** After clicking the button, you'll need to configure your `API_KEY` and `MODEL` environment variables in Cursor's MCP settings. ### [CLI Setup (Claude Desktop)](https://meshjs.dev/ai#cli-setup-claude-desktop) If you have the `claude` CLI installed, you can add Mesh MCP with: claude mcp add-json mesh-mcp '{ "command": "npx", "args": ["-y", "meshjs-mcp"], "env": { "API_KEY": "your-api-key", "MODEL": "your-preferred-model" } }' ### [Manual Setup](https://meshjs.dev/ai#manual-setup) Add this to your MCP server settings: { "servers": { "mesh-mcp": { "name": "mesh-mcp-server", "command": "npx", "args": ["-y", "meshjs-mcp"], "env": { "API_KEY": "your-api-key", "MODEL": "your-preferred-model" } } } } ### [Setup notes](https://meshjs.dev/ai#setup-notes) 1. Replace your-api-key with your API key from the supported providers (OpenAI, Gemini, or Anthropic Claude). 2. Set MODEL to the model you want to use from respective provider. 3. Restart your editor after saving the config. 4. Start the server manually (restarting alone doesn't run it): * VS Code: Open Command Palette (Cmd+Shift+P), search "MCP: List Servers", select "mesh-mcp", and choose "Run Server". * Cursor: Similar to VS Code, use the MCP extension's list servers command to run it. * Claude Desktop: The server should start automatically on launch if configured correctly in settings; check the MCP logs if issues arise. 5. Get help to code faster with Mesh MCP and AI editor ### [Example](https://meshjs.dev/ai#example) ![mcp-example](https://meshjs.dev/ai/mcp-example.png) ### On this page [Ask MeshAI](https://meshjs.dev/ai#ask-meshai) [How it works:](https://meshjs.dev/ai#how-it-works) [Example Response:](https://meshjs.dev/ai#example-response) [LLMs.txt](https://meshjs.dev/ai#llmstxt) [Mesh MCP Setup](https://meshjs.dev/ai#mesh-mcp-setup) [Quick Install (Cursor)](https://meshjs.dev/ai#quick-install-cursor) [CLI Setup (Claude Desktop)](https://meshjs.dev/ai#cli-setup-claude-desktop) [Manual Setup](https://meshjs.dev/ai#manual-setup) [Setup notes](https://meshjs.dev/ai#setup-notes) [Example](https://meshjs.dev/ai#example) Ask AI --- # Getting Started | Mesh SDK [Aiken](https://meshjs.dev/aiken) Getting Started =============== Setting up your system to compile Aiken smart contracts Copy MarkdownOpen [Installation Instructions](https://meshjs.dev/aiken/getting-started#installation-instructions) ------------------------------------------------------------------------------------------------ This section will guide you through the process of setting up your system compile Aiken smart contracts. You can skip this section if you have already set up your system or do not wish to compile the contract. ### [Using aikup (on Linux & MacOS only)](https://meshjs.dev/aiken/getting-started#using-aikup-on-linux--macos-only-toc) If you are using Linux or MacOS, you can use the utility tool to download and manage Aiken's pre-compiled executables. You can install the Aiken CLI by running the following command in your terminal: $ curl -sSfL https://install.aiken-lang.org | bash After installing the Aiken CLI, you can use the following command to installs the latest version available. `aikup` is a cross-platform utility tool to download and manage Aiken's across multiple versions and for seamless upgrades. $ aikup ### [From sources (all platforms)](https://meshjs.dev/aiken/getting-started#from-sources-all-platforms-toc) You will know you have successfully installed Rust and Cargo when you can run the following commands in your terminal: $ rustc --version $ cargo --version Next, you will need to install the Aiken CLI. You can install the Aiken CLI by running the following command in your terminal: $ cargo install aiken ### [Check your installation](https://meshjs.dev/aiken/getting-started#check-your-installation-toc) You will know you have successfully installed the Aiken CLI when you can run the following command in your terminal: $ aiken -V If you face any issues, please check the installation instructions on the [Aiken website](https://aiken-lang.org/installation-instructions) for more information. [Editor integrations](https://meshjs.dev/aiken/getting-started#editor-integrations) ------------------------------------------------------------------------------------ Aiken language support for Visual Studio Code is provided by the Aiken extension. This extension provides syntax highlighting, code snippets, and error checking for Aiken smart contracts. Download the extension from the [Visual Studio Code Marketplace](https://marketplace.visualstudio.com/items?itemName=TxPipe.aiken) or search `aiken` in the extensions tab of Visual Studio Code. [Useful commands](https://meshjs.dev/aiken/getting-started#useful-commands) ---------------------------------------------------------------------------- Here are some useful commands you can use to compile and test your scripts. * `aiken build` - compiles the Aiken smart contract and generates a `plutus.json` file which contains type information, params, redeemer, datum, and the compiled code for each validator of your project and their corresponding hash digests to be used in addresses * `aiken check` - type-check a project and run tests * `aiken docs` - if you're writing a library, this generate documentation from you project * `aiken blueprint` - provides utility functions to generate addresses, apply parameters and convert the build output to various formats [Aiken\ \ A programming language and toolkit for developing smart contracts](https://meshjs.dev/aiken) [Write a Smart Contract\ \ Learn how to write your first Aiken script, with a simple redeemer](https://meshjs.dev/aiken/first-script) ### On this page [Installation Instructions](https://meshjs.dev/aiken/getting-started#installation-instructions) [Editor integrations](https://meshjs.dev/aiken/getting-started#editor-integrations) [Useful commands](https://meshjs.dev/aiken/getting-started#useful-commands) Ask AI --- # Aiken | Mesh SDK Aiken ===== A programming language and toolkit for developing smart contracts Copy MarkdownOpen Aiken is a functional programming language created for Cardano smart contract development. It prioritizes on-chain execution and offers a user-friendly approach for building secure and efficient smart contracts, making it a valuable choice for developers aiming to create robust on-chain applications. [Getting Started\ \ Setting up your system to compile Aiken smart contracts](https://meshjs.dev/aiken/getting-started) [Write a Smart Contract\ \ Learn how to write your first Aiken script, with a simple redeemer](https://meshjs.dev/aiken/first-script) [Build Transactions\ \ Build transactions to interact with smart contracts](https://meshjs.dev/aiken/transactions) [Smart Contracts Library\ \ A library of smart contracts to help you start building and learning](https://meshjs.dev/smart-contracts) [Vesting\ \ Locks up funds and allows the beneficiary to withdraw the funds after the lockup period](https://meshjs.dev/smart-contracts/vesting) [Getting Started\ \ Setting up your system to compile Aiken smart contracts](https://meshjs.dev/aiken/getting-started) Ask AI --- # Learn | Mesh SDK Learn ===== Comprehensive courses, tutorials, and resources for Cardano developers. Copy MarkdownOpen [Cardano Course\ \ A comprehensive 10-lesson course covering wallet integration, Aiken smart contracts, and advanced Cardano development patterns.](https://meshjs.dev/resources/cardano-course) [Tutorials\ \ Step-by-step guides for specific use cases and common patterns in Cardano development.](https://meshjs.dev/resources/tutorials) [Use Cases\ \ Real-world examples and implementations showcasing what you can build with Mesh SDK.](https://meshjs.dev/resources/use-cases) [Developer Resources\ \ Essential tools, communities, and resources for Cardano developers using Mesh SDK.](https://meshjs.dev/resources/developer-resources) [FAQ\ \ Frequently asked questions about Mesh SDK and Cardano development.](https://meshjs.dev/resources/faq) [Guides\ \ Whether you are new to web development or a seasoned blockchain full-stack developer, these guides will help you get started.](https://meshjs.dev/guides) [Build Transactions\ \ Building and submitting transactions on Yaci](https://meshjs.dev/yaci/transactions) [Cardano Course\ \ A comprehensive course for building Cardano applications with Mesh SDK and Aiken smart contracts.](https://meshjs.dev/resources/cardano-course) Ask AI --- # Build Transactions | Mesh SDK [Aiken](https://meshjs.dev/aiken) Build Transactions ================== Build transactions to interact with smart contracts Copy MarkdownOpen [Create transaction to lock tokens](https://meshjs.dev/aiken/transactions#create-transaction-to-lock-tokens) ------------------------------------------------------------------------------------------------------------- In this section, we will create a simple UI that allows users to lock assets on the Cardano blockchain. First, we get initialze the `PlutusScript` and resolve the script address: function getScript() { const scriptCbor = applyParamsToScript(compiledCode, []); const script: PlutusScript = { code: scriptCbor, version: "V2", }; const scriptAddress = resolvePlutusScriptAddress(script, 0); return { script, scriptAddress }; } const { scriptAddress } = await getScript(); We are using the `resolvePlutusScriptAddress` function to resolve the script address. You notice here we use the `applyParamsToScript`, which apply parameters to a script allows you to create a custom [CIP-57 compliant script](https://cips.cardano.org/cip/cip-57) based on some inputs. For this script, we don't have any parameters to apply, but simply applied with double CBOR encoding to `scriptCbor`. Next, we get the wallet address hash: async function getWalletAddress(wallet: BrowserWallet) { const addresses = await wallet.getUsedAddresses(); const address = addresses[0]; if (!address) { throw new Error("No address found"); } const hash = resolvePaymentKeyHash(address); return { address, hash }; } const { hash } = await getWalletAddress(wallet); Here, we use the `resolvePaymentKeyHash` function to resolve the payment key hash of the wallet. Then, we create the `Data` (datum) object containing the address hash: const datum: Data = { alternative: 0, fields: [hash], }; Finally, we prepare the transaction to lock the assets on the Cardano blockchain. const tx = new Transaction({ initiator: wallet }); tx.sendLovelace( { address: scriptAddress, datum: { value: datum }, }, "5000000", ); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Create transaction to redeem tokens](https://meshjs.dev/aiken/transactions#create-transaction-to-redeem-tokens) ----------------------------------------------------------------------------------------------------------------- In this section, we will walk you through the process of creating a transaction to redeem tokens. First, we need to get the script and script address. We can do this by calling the function we created in the previous section. const { script, scriptAddress } = await getScript(); Next, we need to get the wallet address and its hash. We can do this by calling the function we created in the previous section. const { address, hash } = await getWalletAddress(wallet); As the contracts requires the owner's address in the datum field, we are creating a new datum with the owner's address. We create the `Data` (datum) object containing the address hash: const datum: Data = { alternative: 0, fields: [hash], }; After that, we get the UTXO in the script based on the datum: async function getAssetUtxo({ scriptAddress, asset, datum, }: { scriptAddress: string; asset: string; datum: any; }) { const provider = getProvider(); const utxos = await provider.fetchAddressUTxOs( scriptAddress, asset, ); const dataHash = resolveDataHash(datum); let utxo = utxos.find((utxo: any) => { return utxo.output.dataHash == dataHash; }); return utxo; } const assetUtxo = await getAssetUtxo({ scriptAddress: scriptAddress, asset: "lovelace", datum: datum, }); Finally, we prepare the transaction to redeem the tokens: const redeemer = { data: { alternative: 0, fields: ["Hello, World!"] } }; const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datum, redeemer: redeemer, }) .sendValue(address, assetUtxo) .setRequiredSigners([address]); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); Here you notice that in the `redeemer`. As the validator requires, here we specify `Hello, World!`, which is the message we need to provide to unlock the tokens. For the transaction, we use the `redeemValue` function to redeem the locked assets, the `sendValue` function to send the assets to the owner's address, and the `setRequiredSigners` function to set the required signers. [Write a Smart Contract\ \ Learn how to write your first Aiken script, with a simple redeemer](https://meshjs.dev/aiken/first-script) [Layer 2 scaling solution\ \ Scaling solution for Cardano that increases transaction throughput and ensures cost efficiency while maintaining rigorous security.](https://meshjs.dev/hydra) ### On this page [Create transaction to lock tokens](https://meshjs.dev/aiken/transactions#create-transaction-to-lock-tokens) [Create transaction to redeem tokens](https://meshjs.dev/aiken/transactions#create-transaction-to-redeem-tokens) Ask AI --- # Layer 2 scaling solution | Mesh SDK Layer 2 scaling solution ======================== Scaling solution for Cardano that increases transaction throughput and ensures cost efficiency while maintaining rigorous security. Copy MarkdownOpen [Hydra Instance\ \ The HydraInstance is a class interface for interacting with a Hydra head after initialization.](https://meshjs.dev/hydra/instance) [Hydra Provider (beta)\ \ Layer 2 scaling solution for Cardano that increases transaction throughput and ensures cost efficiency while maintaining security.](https://meshjs.dev/providers/hydra) [End-to-end Hydra Tutorial\ \ Open a layer 2 state channel between two participants, build transactions, and close the Hydra head](https://meshjs.dev/hydra/tutorial) [Build Transactions\ \ Build transactions to interact with smart contracts](https://meshjs.dev/aiken/transactions) [End-to-end Hydra Tutorial\ \ Open a layer 2 state channel between two participants, build transactions, and close the Hydra head](https://meshjs.dev/hydra/tutorial) Ask AI --- # Hydra Instance | Mesh SDK [Hydra](https://meshjs.dev/hydra) Hydra Instance ============== The HydraInstance is a class interface for interacting with a Hydra head after initialization. Copy MarkdownOpen [Overview](https://meshjs.dev/hydra/instance#overview) ------------------------------------------------------- The `HydraInstance` is intialized together with `HydraProvider`, for accessing other methods to interact with Hydra head after `HeadIsInitializing` phase. [Get started:](https://meshjs.dev/hydra/instance#get-started) -------------------------------------------------------------- import { HydraInstance, HydraProvider } from "@meshsdk/hydra"; const provider = new HydraProvider({ httpUrl: "", }); const instance = new HydraInstance({ provider: hydraProvider, fetcher: "", submitter: "", }); ### [Commit Empty](https://meshjs.dev/hydra/instance#commit-empty) If you don't want to commit any funds and only want to receive on layer 2, you can request an empty commit transaction to open the head const commit = await instance.commitEmpty(); const submitTx = await wallet.submitTx(commit); console.log("submitTx", submitTx); ### [Commit Funds](https://meshjs.dev/hydra/instance#commit-funds) Commits funds to the Hydra head by selecting specific UTxOs to make available on layer 2. **Parameters:** * `txHash` * `outputIndex` **Returns:** The transaction CBOR hex ready to be partially signed await instance.commitFunds(txHash: string, outputIndex: number) const txHash = "00000000000000000000000000000000000000000000000000000000000000000"; const outputIndex = 0; const commitTx = await instance.commitFunds(txHash, outputIndex); const signedTx = await wallet.signTx(commitTx, true); const commitTxHash = await wallet.submitTx(signedTx); ### [Commit Blueprint](https://meshjs.dev/hydra/instance#commit-blueprint) Commits a Cardano transaction blueprint to the Hydra head. This is useful for advanced use cases such as commiting `scriptUTxOs`. **Parameters:** * `txHash` * `outputIndex` * `hydraTransaction` await instance.commitBlueprint("txHash", outputIndex, { cborHex: "", description: "commit tx", type: "Tx ConwayEra", }); const commitTx = await instance.commitBlueprint(txHash, outputIndex, { cborHex: "", description: "commit tx", type: "Tx ConwayEra", }); const signedTx = await wallet.signTx(commitTx, true); const commitTxHash = await wallet.submitTx(signedTx); ### [Incremental Commit](https://meshjs.dev/hydra/instance#incremental-commit) Incremental commit methods allow you commit additional UTxOs to an open hydra head after the initial commit: The time it takes for it top be added after commit depends on the `hydra-node` configuration parameter `--deposit-period` To read more on incremental commit, see [the Hydra documentation](https://hydra.family/head-protocol/docs/how-to/incremental-commit) . ### [incrementalCommitFunds](https://meshjs.dev/hydra/instance#incrementalcommitfunds) await instance.incrementalCommitFunds(txHash: string, outputIndex: number) ### [incrementalBlueprintCommit](https://meshjs.dev/hydra/instance#incrementalblueprintcommit) await instance.incrementalBlueprintCommit(txHash, outputIndex, { cborHex: "unsignedTx", description: "commit tx", type: "Tx ConwayEra", }); [Basic Workflow](https://meshjs.dev/hydra/instance#basic-workflow) ------------------------------------------------------------------- ### [commit Funds](https://meshjs.dev/hydra/instance#commit-funds-1) import { HydraInstance, HydraProvider } from "@meshsdk/hydra"; import { BlockfrostProvider } from "@meshsdk/core"; const provider = new HydraProvider({ httpUrl: "http://localhost:4001", }); const instance = new HydraInstance({ provider: provider, fetcher: "blockchainProvider", submitter: "blockchainProvider", }); await provider.connect(); await provider.init(); provider.onMessage((message) => { const status = message.tag === "Greetings" ? { headStatus: message.headStatus } : { tag: message.tag }; if ( status.tag === "HeadIsInitializing" || status.headStatus === "Initializing" ) { } const commitTx = await instance.commitFunds(txHash, outputIndex); const signedTx = await wallet.signTx(commitTx, true); await wallet.submitTx(signedTx); }); ### [Blueprint Commit](https://meshjs.dev/hydra/instance#blueprint-commit) provider.onMessage((message) => { const status = message.tag === "Greetings" ? { headStatus: message.headStatus } : { tag: message.tag }; if ( status.tag === "HeadIsInitializing" || status.headStatus === "Initializing" ) { const txBuilder = new MeshTxBuilder({ submitter: "", fetcher: "", verbose: true, }); const unsignedTx = await txBuilder .txIn(txHash, outputIndex) .setFee("0") .changeAddress(address) .selectUtxosFrom(UTxOs) .complete(); const commitTx = await instance.commitBlueprint(txHash, outputIndex, { type: "Tx ConwayEra", cborHex: unsignedTx, description: "Commit Blueprint", }); const signedTx = await wallet.signTx(commitTx); const commitTxHash = await wallet.submitTx(signedTx); console.log(commitTxHash); } }); [End-to-end Hydra Tutorial\ \ Open a layer 2 state channel between two participants, build transactions, and close the Hydra head](https://meshjs.dev/hydra/tutorial) [Midnight\ \ Zero-knowledge privacy network for Cardano](https://meshjs.dev/midnight) ### On this page [Overview](https://meshjs.dev/hydra/instance#overview) [Get started:](https://meshjs.dev/hydra/instance#get-started) [Commit Empty](https://meshjs.dev/hydra/instance#commit-empty) [Commit Funds](https://meshjs.dev/hydra/instance#commit-funds) [Commit Blueprint](https://meshjs.dev/hydra/instance#commit-blueprint) [Incremental Commit](https://meshjs.dev/hydra/instance#incremental-commit) [incrementalCommitFunds](https://meshjs.dev/hydra/instance#incrementalcommitfunds) [incrementalBlueprintCommit](https://meshjs.dev/hydra/instance#incrementalblueprintcommit) [Basic Workflow](https://meshjs.dev/hydra/instance#basic-workflow) [commit Funds](https://meshjs.dev/hydra/instance#commit-funds-1) [Blueprint Commit](https://meshjs.dev/hydra/instance#blueprint-commit) Ask AI --- # Midnight | Mesh SDK Midnight ======== Zero-knowledge privacy network for Cardano Copy MarkdownOpen [Midnight Setup\ \ Complete development setup for building Midnight Network dApps](https://meshjs.dev/midnight/midnight-setup) [Midnight Contracts Wizard\ \ CLI tool to scaffold Midnight smart contract projects with pre-built templates](https://meshjs.dev/midnight/midnight-contracts-wizard) [Hydra Instance\ \ The HydraInstance is a class interface for interacting with a Hydra head after initialization.](https://meshjs.dev/hydra/instance) [Overview\ \ Complete development setup for building Midnight Network dApps](https://meshjs.dev/midnight/midnight-setup) Ask AI --- # End-to-end Hydra Tutorial | Mesh SDK [Hydra](https://meshjs.dev/hydra) End-to-end Hydra Tutorial ========================= Open a layer 2 state channel between two participants, build transactions, and close the Hydra head Copy MarkdownOpen This tutorial demonstrates how to use Hydra Head protocol on Cardano's preprod testing environment to open a layer 2 state channel between two participants using Mesh. Hydra Head is a layer 2 scaling solution for Cardano that enables fast, low-cost transactions between participants. This tutorial is adapted from [the Hydra documentation](https://hydra.family/head-protocol/docs/tutorial) . ### [Initialize Hydra with Mesh](https://meshjs.dev/hydra/tutorial#initialize-hydra-with-mesh-toc) To initialize Hydra with Mesh, you need to set the `HydraProvider` with the Hydra API URL and then use it to initialize the `HydraInstance`. You can use one of the cardano [providers](https://meshjs.dev/providers) , example: `blockfrostProvider`, or `maestroProvider`, to initialize the `HydraInstance`. import { HydraInstance, HydraProvider } from "@meshsdk/hydra"; const provider = new HydraProvider({ httpUrl: "", }); const hydraInstance = new HydraInstance({ provider: provider, fetcher: "", submitter: "", }); [Prerequisites](https://meshjs.dev/hydra/tutorial#prerequisites) ----------------------------------------------------------------- * A running cardano node is required to access `cardano-cli` * A `Hydra-node` * Another participant following this tutorial (recommended), or * Access to two such machines * 100 test ada per participant in a wallet on the `preprod` network Hydra-node and cardano-node running, check [Installation](https://hydra.family/head-protocol/docs/tutorial#step-0-installation) . You could also set-up a Docker container for a `cardano-node` and `Hydra-node` to quickly follow this tutorial. Check the setup example/demo for a devnet [here](https://github.com/cardano-scaling/hydra/tree/master/demo) [Step 1. Prepare keys and funding](https://meshjs.dev/hydra/tutorial#step-1-prepare-keys-and-funding) ------------------------------------------------------------------------------------------------------ In a Hydra head, each participant is authenticated using two sets of keys. The first set identifies a participant on the Cardano layer 1 and is used to hold ada for paying fees. Each hydra-node requires a `cardano-signing-key`, and you must provide the `cardano-verification-key` for each participant. First, generate Cardano key pairs and addresses for both participants with `cardano-cli` to identify the hydra-node and manage funds on layer 1. Alice's keys: mkdir -p credentials cardano-cli address key-gen \ --verification-key-file credentials/alice-node.vk \ --signing-key-file credentials/alice-node.sk cardano-cli address build \ --payment-verification-key-file credentials/alice-node.vk \ --out-file credentials/alice-node.addr \ --testnet-magic 1 cardano-cli address key-gen \ --verification-key-file credentials/alice-funds.vk \ --signing-key-file credentials/alice-funds.sk cardano-cli address build \ --payment-verification-key-file credentials/alice-funds.vk \ --out-file credentials/alice-funds.addr \ --testnet-magic 1 Bob's keys: mkdir -p credentials cardano-cli address key-gen \ --verification-key-file credentials/bob-node.vk \ --signing-key-file credentials/bob-node.sk cardano-cli address build \ --payment-verification-key-file credentials/bob-node.vk \ --out-file credentials/bob-node.addr \ --testnet-magic 1 cardano-cli address key-gen \ --verification-key-file credentials/bob-funds.vk \ --signing-key-file credentials/bob-funds.sk cardano-cli address build \ --payment-verification-key-file credentials/bob-funds.vk \ --out-file credentials/bob-funds.addr \ --testnet-magic 1 After generating the addresses, make sure to fund both Alice's and Bob's addresses with test ADA. if you don't have testAda, you can use [cardano-faucet](https://docs.cardano.org/cardano-testnets/tools/faucet) to fund the generated addresses * Send at least `30 tADA` to `alice-node.addr` and `bob-node.addr` addresses. * Send any amount of `tADA` to `alice-funds.addr` and `bob-funds.addr` addresses. Next, generate Hydra key pairs for use on layer 2. Use this Hydra-node command to generate the keys for alice and/or bob respectively: hydra-node gen-hydra-key --output-file credentials/alice-hydra hydra-node gen-hydra-key --output-file credentials/bob-hydra The next step involves configuring the protocol parameters for the ledger within our Hydra head. For the purposes of this tutorial, we'll modify the default Cardano layer 1 parameters to eliminate transaction fees, cardano-cli query protocol-parameters --testnet-magic 1 --socket-path /"${socketPath}" --out-file protocol-parameters.json Simplifying Hydra fees and environments, change the following parameters: * `txFeeFixed` to 0 * `txFeePerByte` to 0 * `executionUnitPrices.priceMemory` to 0 * `executionUnitPrices.priceSteps` to 0 [Step 2. Configure Hydra nodes](https://meshjs.dev/hydra/tutorial#step-2-configure-hydra-nodes) ------------------------------------------------------------------------------------------------ Configure your Hydra nodes with the generated keys and network settings. Each participant needs to set up their hydra-node with the correct configuration. Alice: hydra-node \ --node-id alice-node \ --api-host 0.0.0.0 \ --api-port 4001 \ --listen 172.16.239.10:5001 \ --monitoring-port 6001 \ --peer 172.16.239.20:5001 \ --hydra-scripts-tx-id c9c4d820d5575173cfa81ba2d2d1096fc40f84d16d8c17284da410a4fb5e64eb,ae4443b46f550289337fc5c2c52b24f1288dab36d1a229167a6e04f056a966fe,48bd29e43dd01d12ab464f75fe40eed80e4051c8d3409e1cb20b8c01120b425e \ --cardano-signing-key /credentials/alice-node.sk \ --cardano-verification-key /credentials/bob-node.vk \ --hydra-signing-key /keys/alice-hydra.sk \ --hydra-verification-key /keys/bob-hydra.vk \ --ledger-protocol-parameters ./testnet/protocol-parameters.json \ --testnet-magic 1 \ --node-socket /cardano-node/db/node.socket \ --contestation-period 300s Bob: hydra-node \ --node-id bob-node \ --api-host 0.0.0.0 \ --api-port 4002 \ --listen 172.16.239.20:5001 \ --monitoring-port 6001 \ --peer 172.16.239.10:5001 \ --hydra-scripts-tx-id c9c4d820d5575173cfa81ba2d2d1096fc40f84d16d8c17284da410a4fb5e64eb,ae4443b46f550289337fc5c2c52b24f1288dab36d1a229167a6e04f056a966fe,48bd29e43dd01d12ab464f75fe40eed80e4051c8d3409e1cb20b8c01120b425e \ --cardano-signing-key /credentials/bob-node.sk \ --cardano-verification-key /credentials/alice-node.vk \ --hydra-signing-key /keys/bob-hydra.sk \ --hydra-verification-key /keys/alice-hydra.vk \ --ledger-protocol-parameters ./testnet/protocol-parameters.json \ --testnet-magic 1 \ --node-socket /cardano-node/db/node.socket \ --contestation-period 300s Fields in the Hydra node configuration: * `node-id`: Unique identifier for each Hydra node. This distinguishes Alice's node from Bob's node. * `api-host`: as the API is not authenticated by default, the node is only binding to `0.0.0.0`. * `api-port`: The port on which the API will listen. * `listen`: The IP address and port on which the Hydra node will listen for incoming connections. * `peer`: The IP address of another Hydra node to connect to. This is how nodes discover and communicate with each other. * `monitoring-port`: The port on which the monitoring API will listen. This is used to monitor the Hydra node's performance. * `cardano-signing-key`: These keys authenticate on-chain transactions and ensure that only authorized participants can control the head's lifecycle used to hold ada for paying fees * `hydra-signing-key`: Used for multi-signing snapshots within a head. Although these keys may eventually support an aggregated multi-signature scheme, they currently use the Ed25519 format. * `hydra-scripts-tx-id`: The hydra-node uses reference scripts to reduce transaction sizes driving the head's lifecycle. For public (test) networks, you can use the [pre-published Hydra scripts](https://github.com/cardano-scaling/hydra/blob/master/hydra-node/networks.json) with each new release, listing transaction IDs in the release notes and networks.json. Note: The value of above `--hydra-scripts-tx-id` comes from the hydra-node release 0.22.2. * `ledger-protocol-parameters`: This defines the updatable protocol parameters to be used on L2 such as fees or transaction sizes. These parameters follow the same format as the `cardano-cli query protocol-parameters` output. * `contestation-period`:This is an important protocol parameter, defined in seconds The contestation period is used to set the contestation deadline. That is, after `Close`, all participants have at minimum `CP` to submit a `Contest` transaction More on hydra [configuration](https://hydra.family/head-protocol/docs/configuration) . Ensure both nodes can communicate with each other and change to your correct file paths in the above configuration. This configuration sets up Alice's node to listen to API connection on port 4001 Bob's node on port 4002. [Step 3. Open a Hydra head](https://meshjs.dev/hydra/tutorial#step-3-open-a-hydra-head) ---------------------------------------------------------------------------------------- ### [Connect to the Hydra head](https://meshjs.dev/hydra/tutorial#connect-to-the-hydra-head-toc) Now that both Hydra nodes are running and connected, we can start using the head API url and port together with Mesh `HydraProvider` in connecting to the Hydra head. await provider.connect(); ### [Initialize the Head](https://meshjs.dev/hydra/tutorial#initialize-the-head-toc) Send the initialization command to start the Hydra head: await provider.init(); ### [Commit Funds](https://meshjs.dev/hydra/tutorial#commit-funds-toc) After initialization, both participants need to commit funds to the head. In this tutorial we use the `commitFunds` function on `HydraInstance` by selecting specific UTxOs and make them available for layer 2 transactions: import { HydraInstance , HydraProvider} from "@meshsdk/hydra"; const provider = new HydraProvider({ httpUrl: "", }); const hInstance = new HydraInstance({ provider: provider, fetcher: "", submitter: "", }); const wallet = new MeshWallet({ networkId: 0, // 0: testnet fetcher: "", submitter: "", key: { type: 'cli', payment: 'alice-funds.sk', }, }); const outputIndex = 0; const txHash = "00000000000000000000000000000000000000000000000000000000000000000"; const commitTx = await hInstance.commitFunds(txHash, outputIndex); const signedTx = await wallet.signTx(commitTx, true); const commitTxHash = await wallet.submitTx(signedTx); console.log(commitTxHash); The hydra-node will create a draft commit transaction for you to sign. Once signed and submitted to the Cardano network, you'll see a `Committed` message in your WebSocket connection. When both parties have committed their funds, the Hydra head will open automatically. You'll see a `HeadIsOpen` message confirming the head is operational and ready for transactions. ### [Hydra Head Status Flow](https://meshjs.dev/hydra/tutorial#hydra-head-status-flow-toc) The head goes through these status changes: * `HeadIsInitializing` - Head is being initialized * `Committed` - Funds are committed to the head * `HeadIsOpen` - Head is open and ready for transactions [Step 4. Use the Hydra head](https://meshjs.dev/hydra/tutorial#step-4-use-the-hydra-head) ------------------------------------------------------------------------------------------ Now that the Hydra head is open, you can perform transactions within the layer 2 state channel. Hydra Head operates as an isomorphic protocol, meaning that functionalities available on Cardano layer 1 are also available on layer 2. This allows us to use Mesh SDK for transaction creation within the head. ### [Fetch UTxOs](https://meshjs.dev/hydra/tutorial#fetch-utxos-toc) First, let's see what UTxOs are available in the Hydra head: const utxos = await provider.fetchUTxOs(); ### [Fetch Address UTxOs](https://meshjs.dev/hydra/tutorial#fetch-address-utxos-toc) Alternatively, you can fetch Head UTxOs for a specific address: const utxos = await provider.fetchAddressUTxOs("alice-funds.addr") ### [Build and Submit Transaction](https://meshjs.dev/hydra/tutorial#build-and-submit-transaction-toc) You can build transactions just like on layer 1 assuming you are sending from alice to bob: const pp = await provider.fetchProtocolParameters(); const utxos = await provider.fetchAddressUTxOs("address"); const txBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, isHydra: true, params: pp, }); const unsignedTx = await txBuilder .txOut( "bob-funds.addr", [{ unit: "lovelace", quantity: "3000000" }] ) .changeAddress("alice-funds.addr") .selectUtxosFrom(utxos) .setNetwork("preprod") .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await provider.submitTx(signedTx); console.log(txHash); The transaction will be validated by both hydra-nodes and either result in a `TxValid` message or a `TxInvalid` message If valid, you'll see a `SnapshotConfirmedmessage` shortly after with the new UTxO set. ### [Transaction Flow](https://meshjs.dev/hydra/tutorial#transaction-flow-toc) The transaction goes through these steps: * `NewTx` - Transaction submitted to head * `TxValid` - Transaction validated by all nodes * `SnapshotConfirmed` - New state confirmed [Step 5. Close the Hydra head](https://meshjs.dev/hydra/tutorial#step-5-close-the-hydra-head) ---------------------------------------------------------------------------------------------- You can close the head to return head utxos to layer 1. This process involves closing the head, waiting for the contestation period, and then fan out the final state. ### [Close the Head](https://meshjs.dev/hydra/tutorial#close-the-head-toc) Any participant can initiate closing the Hydra head. Once closed, no more transactions can be submitted to the head. The head enters a contestation period where participants can challenge the closing snapshot. await provider.close() ### [Contestation Period](https://meshjs.dev/hydra/tutorial#contestation-period-toc) After closing, there's a contestation period (configurable with `--contestation-period`). During this time: * Participants can contest the closing snapshot * If contested, a more recent snapshot can be used * After the deadline, fanout becomes possible ### [Fanout the Head](https://meshjs.dev/hydra/tutorial#fanout-the-head-toc) After the contestation period, the head participants can use the `fanout` to fully close the `hydra-head` and return the head utxos to layer one. await provider.fanout() ### [Check Final Balances](https://meshjs.dev/hydra/tutorial#check-final-balances-toc) After fanout, check the final balances on layer one: const aliceFundsBalance = await blockchainProvider.fetchAddressUTxOs("alice-funds.addr"); const bobFundsBalance = await blockchainProvider.fetchAddressUTxOs("bob-funds.addr"); ### [Head Lifecycle](https://meshjs.dev/hydra/tutorial#head-lifecycle-toc) The complete head lifecycle: * `INITIALIZE` - Initial state * `COMMIT` - Committing to Hydra head * `OPEN` - Head open for transactions * `NEW TX` - New transaction submitted in Hydra head * `CLOSE` - Ready to fanout * `CONTEST` - Head closed, contestation period * `FANOUT` - Head finalized on layer one Congratulations! You've completed the full lifecycle of a Hydra head from initialization to finalization. [Layer 2 scaling solution\ \ Scaling solution for Cardano that increases transaction throughput and ensures cost efficiency while maintaining rigorous security.](https://meshjs.dev/hydra) [Hydra Instance\ \ The HydraInstance is a class interface for interacting with a Hydra head after initialization.](https://meshjs.dev/hydra/instance) ### On this page [Prerequisites](https://meshjs.dev/hydra/tutorial#prerequisites) [Step 1. Prepare keys and funding](https://meshjs.dev/hydra/tutorial#step-1-prepare-keys-and-funding) [Step 2. Configure Hydra nodes](https://meshjs.dev/hydra/tutorial#step-2-configure-hydra-nodes) [Step 3. Open a Hydra head](https://meshjs.dev/hydra/tutorial#step-3-open-a-hydra-head) [Step 4. Use the Hydra head](https://meshjs.dev/hydra/tutorial#step-4-use-the-hydra-head) [Step 5. Close the Hydra head](https://meshjs.dev/hydra/tutorial#step-5-close-the-hydra-head) Ask AI --- # Solutions | Mesh SDK Solutions ========= Mesh provides a set of solutions to help you build blockchain applications Copy MarkdownOpen [Web3 Services\ \ Streamline user onboarding and Web3 integration, accelerating your app's time to market](https://utxos.dev/) [Smart Contracts Lib\ \ Open-source smart contracts, complete with documentation, and live demos](https://meshjs.dev/smart-contracts) [Multisig platform\ \ Secure your treasury and participant in Cardano governance as a team with multi-signature](https://multisig.meshjs.dev/) [Cquisitor\ \ Debug, validate and inspect any CBOR and Cardano objects](https://cloud.meshjs.dev/cquisitor) Ask AI --- # Mesh Data | Mesh SDK [Mesh API](https://meshjs.dev/apis) Data Mesh Data ========= Parse and manipulate data with Mesh Data type Copy MarkdownOpen Mesh provides a full set of utility functions to help constructing the Mesh `Data` type you need for your Web3 app. **Types Support** All utility functions start with the prefix of m and all types All the utility functions start with the prefix of m, and are designed to return a type with the same naming as the utilities function, with capitalizing first letter, you can build your data with type supports in complex types, some examples: * `mConstr` returns `MConstr` type * `mBool` returns `MBool` type [Utilities in Building Constructor Mesh Data](https://meshjs.dev/apis/data/mesh#utilities-in-building-constructor-mesh-data) ----------------------------------------------------------------------------------------------------------------------------- `mConStr` build the constructor object in Mesh `Data` type, with parameters: * alternative (number) - the constructor index * fields (any\[\]) - the constructor fields in array There are also some quick utilities only taking in **fields** as parameters for 0 - 2 indices: * `mConStr0` - building index 0 constructor * `mConStr1` - building index 1 constructor * `mConStr2` - building index 2 constructor ### [Constructor](https://meshjs.dev/apis/data/mesh#constructor-toc) Building Mesh constructor object import { mConStr } from "@meshsdk/core"; mConStr(0, []); [Utilities in Building Primitives Mesh Data](https://meshjs.dev/apis/data/mesh#utilities-in-building-primitives-mesh-data) --------------------------------------------------------------------------------------------------------------------------- `mBool` build the boolean object in , with parameters: * b (boolean | boolean) - the boolean to be built For the rest of data primitives, they are represented by JS primitives: * Integer - `number` and `bigint` * Byte string - `string` * List - JS `Array` * Map - JS `Map` ### [Constructor](https://meshjs.dev/apis/data/mesh#constructor-toc-1) Building Mesh bool object import { mBool } from "@meshsdk/core"; mBool(true); [Other Utilities](https://meshjs.dev/apis/data/mesh#other-utilities) --------------------------------------------------------------------- The code example showing above does not cover all utilities, please checkout the hosted documentation for more details. The not covered utilities are as below: * `mAssetClass` * `mOutputReference` * `mTxOutRef` * `mTuple` * `mMaybeStakingHash` * `mPubKeyAddress` * `mScriptAddress` ### On this page [Utilities in Building Constructor Mesh Data](https://meshjs.dev/apis/data/mesh#utilities-in-building-constructor-mesh-data) [Utilities in Building Primitives Mesh Data](https://meshjs.dev/apis/data/mesh#utilities-in-building-primitives-mesh-data) [Other Utilities](https://meshjs.dev/apis/data/mesh#other-utilities) Ask AI --- # Ogmios Provider | Mesh SDK [Providers](https://meshjs.dev/providers) Ogmios Provider =============== Lightweight bridge interface for cardano-node that offers WebSockets API that enables local clients to speak Ouroboros' mini-protocols Copy MarkdownOpen [Ogmios](https://ogmios.dev/) is a lightweight bridge interface for cardano-node. It offers a WebSockets API that enables local clients to speak Ouroboros' mini-protocols via JSON/RPC. Ogmios is a fast and lightweight solution that can be deployed alongside relays to create entry points on the Cardano network for various types of applications. Get started: import { OgmiosProvider } from "@meshsdk/core"; const provider = new OgmiosProvider(''); [Evaluate Transaction](https://meshjs.dev/providers/ogmios#evaluate-transaction) --------------------------------------------------------------------------------- `evaluateTx()` accepts an unsigned transaction (`unsignedTx`) and it evaluates the resources required to execute the transaction. Note that, this is only valid for transaction interacting with redeemer (smart contract). By knowing the budget required, you can use this to adjust the redeemer's budget so you don't spend more than you need to execute transactions for this smart contract. const unsignedTx = await tx.build(); const evaluateTx = await provider.evaluateTx(unsignedTx); Example responses from unlocking assets from the always succeed smart contract. [\ {\ "index": 0,\ "tag": "SPEND",\ "budget": {\ "mem": 1700,\ "steps": 368100\ }\ }\ ] With the `mem` and `steps`, you can refine the budget for the redeemer. For example: const redeemer = { data: { alternative: 0, fields: [...] }, budget: { mem: 1700, steps: 368100, }, }; [Submit Transaction](https://meshjs.dev/providers/ogmios#submit-transaction) ----------------------------------------------------------------------------- Submit a serialized transaction to the network. await provider.submitTx(signedTx); [Maestro Provider\ \ Advanced UTxO-indexing data layer to supercharge Defi on Bitcoin, Cardano & Dogecoin](https://meshjs.dev/providers/maestro) [UTxORPC Provider\ \ Highly efficient through gRPC, using a compact and high-performance binary format](https://meshjs.dev/providers/utxorpc) ### On this page [Evaluate Transaction](https://meshjs.dev/providers/ogmios#evaluate-transaction) [Submit Transaction](https://meshjs.dev/providers/ogmios#submit-transaction) Ask AI --- # UI Components | Mesh SDK [React Components](https://meshjs.dev/react) UI Components ============= UI components to speed up your app development. Copy MarkdownOpen Mesh provide a collection of useful UI components, so you can easily include web3 functionality and convenient utilities for your application. [Connect Wallet](https://meshjs.dev/react/ui-components#connect-wallet) ------------------------------------------------------------------------ In order for pps to communicate with the user's wallet, we need a way to connect to their wallet. Add this CardanoWallet to allow the user to select a wallet to connect to your app. After the wallet is connected, see [Browser Wallet](https://meshjs.dev/apis/wallets/browserwallet) for a list of CIP-30 APIs. The signature for the CardanoWallet component is as follows: { label?: string; onConnected?: Function; isDark?: boolean; } ### [Customization](https://meshjs.dev/react/ui-components#customization-toc) For dark mode style, add isDark. For a custom label, add the label prop. The customization is limited. For more customization, you can easily build your own wallet connection component. If you are using React, the [React hooks](https://meshjs.dev/react/wallet-hooks) will be useful. You may also take reference from [this component](https://github.com/MeshJS/mesh/blob/main/packages/mesh-react/src/cardano-wallet/index.tsx) . ### [Persist user session](https://meshjs.dev/react/ui-components#persist-user-session-toc) If you would like to save the user last connected wallet and automatically connect to it on the next visit, you can use the persist prop. ### [onConnected](https://meshjs.dev/react/ui-components#onconnected-toc) If you want to run a function after the wallet is connected, you can add the onConnected prop. export default function Page() { function afterConnectedWallet() { // do something } return ( <> ); } The above code will log "Hello, World!" to the console when the wallet is connected. ### [Mesh Web3 Services](https://meshjs.dev/react/ui-components#mesh-web3-services-toc) [Mesh Web3 Services](https://utxos.dev/) streamline user onboarding and on-chain feature integration, accelerating your app's time to market. To integrate Mesh Web3 Services, use the `web3Services` prop. The `networkId` is the network ID of the wallet you are connecting to. You may use any [providers](https://meshjs.dev/providers) for `fetcher` and `submitter`. const provider = new BlockfrostProvider(''); ### [Decentralized WebRTC Wallet Communication (CIP 45)](https://meshjs.dev/react/ui-components#decentralized-webrtc-wallet-communication-cip-45-toc) [CIP-45](https://cips.cardano.org/cip/CIP-45) is a communication method between pps and wallets based on WebTorrent trackers and WebRTC. Using WebTorrent trackers for the peer discovery to remove the need of this central component. ### [Burner wallet](https://meshjs.dev/react/ui-components#burner-wallet-toc) Burner wallets are wallets that are created on the fly on the user's device. They are temporary wallets useful for testing purposes. The private keys are generated and stored on the user's device. ### [MetaMask Snaps](https://meshjs.dev/react/ui-components#metamask-snaps-toc) MetaMask Snaps are a new way to extend MetaMask with custom functionality and integrations. You can check the implementation to integrate NuFi from the [GitHub repository](https://github.com/MeshJS/mesh/tree/main/apps/playground/src/components/cardano/connect-browser-wallet) . Use the `injectFn` prop to add custom functionality. await checkIfMetamaskInstalled("preprod")} /> ### [Connect Wallet Component](https://meshjs.dev/react/ui-components#connect-wallet-component-toc) Connect to user's wallet to interact with app import { CardanoWallet } from '@meshsdk/react'; export default function Page() { return ( <> {console.log('on connected')}} cardanoPeerConnect={{ dAppInfo: { name: "Mesh SDK", url: "https://meshjs.dev/", }, announce: [\ "wss://dev.btt.cf-identity-wallet.metadata.dev.cf-deployments.org",\ ], }} burnerWallet={{ networkId: 0, provider: provider, }} /> ); } [Powered by Mesh Badge](https://meshjs.dev/react/ui-components#powered-by-mesh-badge) -------------------------------------------------------------------------------------- If you love Mesh, here's a beautifully designed badge for you to embed in your application. ### [Mesh Badge Component](https://meshjs.dev/react/ui-components#mesh-badge-component-toc) Show your support for Mesh import { CardanoWallet } from '@meshsdk/react'; export default function Page() { return ( <> ); } [Getting Started with React\ \ Frontend components for wallet connections, and useful React hooks to getting wallet states](https://meshjs.dev/react/getting-started) [Wallet Hooks\ \ React hooks for interacting with connected wallets.](https://meshjs.dev/react/wallet-hooks) ### On this page [Connect Wallet](https://meshjs.dev/react/ui-components#connect-wallet) [Powered by Mesh Badge](https://meshjs.dev/react/ui-components#powered-by-mesh-badge) Ask AI --- # Svelte Components | Mesh SDK Svelte Components ================= Svelte UI components for wallet connections Copy MarkdownOpen [Getting Started with Svelte\ \ Svelte frontend components for wallet connections.](https://meshjs.dev/svelte/getting-started) [UI Components\ \ UI components to speed up your app development.](https://meshjs.dev/svelte/ui-components) [Wallet Hooks\ \ React hooks for interacting with connected wallets.](https://meshjs.dev/react/wallet-hooks) [Getting Started with Svelte\ \ Svelte frontend components for wallet connections.](https://meshjs.dev/svelte/getting-started) Ask AI --- # Data Overview | Mesh SDK [Mesh API](https://meshjs.dev/apis) Data Data Overview ============= Learn about the basics, and how Mesh handles Cardano data Copy MarkdownOpen Parsing and converting data in Plutus is a common task when working with transactions. This page will show you how to do that. [Use of Data in Cardano](https://meshjs.dev/apis/data/overview#use-of-data-in-cardano) --------------------------------------------------------------------------------------- Cardano data and information is usually communicated in `CBOR` encoding format, which can be decoded into `JSON` representation. On top of the 2, Mesh also provides the `Data` type which get rids of unnecessary wrappers. Mesh supports building data for your app in all 3 different formats. * `Mesh` - the `Data` type * `JSON` * `CBOR` [Mesh Data Type](https://meshjs.dev/apis/data/overview#mesh-data-type) ----------------------------------------------------------------------- Mesh `Data` type is best used when you want to quickly and easily compose your data types. [Learn more](https://meshjs.dev/apis/data/mesh) [JSON Data Type](https://meshjs.dev/apis/data/overview#json-data-type) ----------------------------------------------------------------------- All Cardano data has the JSON representation, which is suitable for building Web3 app which needs frequent back and forth conversion between on-chain and off-chain code. Mesh also supports building data in JSON format with strong input validation support. [Learn more](https://meshjs.dev/apis/data/json) [CBOR](https://meshjs.dev/apis/data/overview#cbor) --------------------------------------------------- CBOR is the lowest level representation of data in Cardano. Mesh provides endpoints to allow users to provide CBOR in providing data, which is the case for developers utilizing other serialization package other than mesh in part the application. ### On this page [Use of Data in Cardano](https://meshjs.dev/apis/data/overview#use-of-data-in-cardano) [Mesh Data Type](https://meshjs.dev/apis/data/overview#mesh-data-type) [JSON Data Type](https://meshjs.dev/apis/data/overview#json-data-type) [CBOR](https://meshjs.dev/apis/data/overview#cbor) Ask AI --- # Offline Evaluator | Mesh SDK [Providers](https://meshjs.dev/providers) Offline Evaluator ================= An offline Plutus script evaluator for testing and validation. Copy MarkdownOpen The OfflineEvaluator calculates execution costs (memory and CPU steps) for Plutus scripts in transactions without requiring network connectivity. It works with an [OfflineFetcher](https://meshjs.dev/providers/offline-fetcher) to resolve the UTXOs needed for script validation. This is also compatible with any other fetchers to provide online data fetching. Get started: import { OfflineEvaluator } from "@meshsdk/core-csl"; import { OfflineFetcher } from "@meshsdk/core"; // Create fetcher for resolving UTXOs const fetcher = new OfflineFetcher(); // Add UTXOs required for script evaluation fetcher.addUTxOs([\ {\ input: {\ txHash: "5de23a2...",\ outputIndex: 0\ },\ output: {\ address: "addr1...",\ amount: [{ unit: "lovelace", quantity: "1000000" }],\ scriptHash: "32b7e3d..." // For script UTXOs\ }\ }\ ]); // Create evaluator for the desired network const evaluator = new OfflineEvaluator(fetcher, "preprod"); Once initialized, you can evaluate Plutus scripts in transactions: // Evaluate Plutus scripts in a transaction try { const actions = await evaluator.evaluateTx(transactionCbor); // Example result: // [{\ // index: 0,\ // tag: "MINT",\ // budget: {\ // mem: 508703, // Memory units used\ // steps: 164980381 // CPU steps used\ // }\ // }] } catch (error) { console.error('Script evaluation failed:', error); } The evaluator is particularly useful for testing Plutus scripts, ensuring they execute within memory and CPU limits: // In your test file describe("Plutus Script Tests", () => { let evaluator: OfflineEvaluator; let fetcher: OfflineFetcher; beforeEach(() => { fetcher = new OfflineFetcher(); evaluator = new OfflineEvaluator(fetcher, "preprod"); // Add test UTXOs fetcher.addUTxOs([...]); }); it("should evaluate minting policy", async () => { const result = await evaluator.evaluateTx(txCbor); expect(result[0].tag).toBe("MINT"); expect(result[0].budget.mem).toBeLessThan(600000); }); }); The evaluation results include memory units and CPU steps required for each script execution, helping you optimize your scripts and ensure they meet protocol constraints. [Evaluate Transaction](https://meshjs.dev/providers/offline-evaluator#evaluate-transaction) -------------------------------------------------------------------------------------------- `evaluateTx()` accepts an unsigned transaction (`unsignedTx`) and it evaluates the resources required to execute the transaction. Note that, this is only valid for transaction interacting with redeemer (smart contract). By knowing the budget required, you can use this to adjust the redeemer's budget so you don't spend more than you need to execute transactions for this smart contract. const unsignedTx = await tx.build(); const evaluateTx = await provider.evaluateTx(unsignedTx); Example responses from unlocking assets from the always succeed smart contract. [\ {\ "index": 0,\ "tag": "SPEND",\ "budget": {\ "mem": 1700,\ "steps": 368100\ }\ }\ ] With the `mem` and `steps`, you can refine the budget for the redeemer. For example: const redeemer = { data: { alternative: 0, fields: [...] }, budget: { mem: 1700, steps: 368100, }, }; [OfflineFetcher\ \ An offline blockchain data provider for testing, development and offline scenarios.](https://meshjs.dev/providers/offline-fetcher) [Utilities\ \ Serializers, resolvers and data types for converting between different formats.](https://meshjs.dev/apis/utilities) ### On this page [Evaluate Transaction](https://meshjs.dev/providers/offline-evaluator#evaluate-transaction) Ask AI --- # Wallet Hooks | Mesh SDK [React Components](https://meshjs.dev/react) Wallet Hooks ============ React hooks for interacting with connected wallets. Copy MarkdownOpen React Hooks allow function components to have access to state and other React features. With Mesh Hooks, you can easily interact and access wallet data. [useWallet Hook](https://meshjs.dev/react/wallet-hooks#usewallet-hook) ----------------------------------------------------------------------- Provide information on the current wallet's state, and functions for connecting and disconnecting user wallet. const { wallet, state, connected, name, connecting, connect, disconnect, error } = useWallet(); `wallet` is a [Browser Wallet](https://meshjs.dev/apis/wallets/browserwallet) instance, which expose all CIP wallets functions from getting assets to signing tranasction. `state`, a enum string, the state of the wallet, can be `NOT_CONNECTED`, `CONNECTING` or `CONNECTED`. `connected`, a boolean, `true` if user's wallet is connected. `name`, a string, the name of the connect wallet. `connecting`, a boolean, `true` if the wallet is connecting and initializing. `connect(walletName: string)`, a function, provide the wallet name to connect wallet. Retrive a list of available wallets with `useWalletList()`. `disconnect()`, a function, to disconnect the connected wallet. `error`, returns the error object if any error occurs during wallet connection, such as "account not set". ### [useWallet Hook](https://meshjs.dev/react/wallet-hooks#usewallet-hook-toc) Interact with user's wallet import { useWallet } from '@meshsdk/react'; export default function Page() { const { wallet, state, connected, name, connecting, connect, disconnect, error } = useWallet(); return (

State: {state}

Connected?: {connected ? 'Is connected' : 'Not connected'}

Connecting wallet?: {connecting ? 'Connecting...' : 'No'}

Name of connected wallet: {name}

); } [useWalletList Hook](https://meshjs.dev/react/wallet-hooks#usewalletlist-hook) ------------------------------------------------------------------------------- Returns a list of wallets installed on user's device. const wallets = useWalletList(); You can define a function to be injected into the wallet provider by passing it as the `injectFn` prop. const wallets = useWalletList({injectFn={async () => await checkIfMetamaskInstalled("preprod")})} ### [useWalletList Hook](https://meshjs.dev/react/wallet-hooks#usewalletlist-hook-toc) List of wallets installed on user's device const wallets = useWalletList(); [] import { useWalletList } from '@meshsdk/react'; export default function Page() { const wallets = useWalletList(); return ( <> {wallets.map((wallet, i) => { return (

{wallet.name}

); })} ); } [useAddress Hook](https://meshjs.dev/react/wallet-hooks#useaddress-hook) ------------------------------------------------------------------------- Return address of connected wallet. `accountId` is an optional parameter, that allows you to choose which address to return. const address = useAddress(accountId = 0); ### [useAddress Hook](https://meshjs.dev/react/wallet-hooks#useaddress-hook-toc) List of wallets installed on user's device import { useAddress } from '@meshsdk/react'; const address = useAddress();

Your wallet address is: {address}

[useAssets Hook](https://meshjs.dev/react/wallet-hooks#useassets-hook) ----------------------------------------------------------------------- Return a list of assets in connected wallet from all UTXOs. const assets = useAssets(); ### [useAssets Hook](https://meshjs.dev/react/wallet-hooks#useassets-hook-toc) List assets of connected wallet import { useAssets } from '@meshsdk/react'; const assets = useAssets(); {JSON.stringify(assets, null, 2)} [useLovelace Hook](https://meshjs.dev/react/wallet-hooks#uselovelace-hook) --------------------------------------------------------------------------- Return amount of lovelace in wallet. const lovelace = useLovelace(); ### [useLovelace Hook](https://meshjs.dev/react/wallet-hooks#uselovelace-hook-toc) Fetch the lovelace balance of the connected wallet import { useLovelace } from '@meshsdk/react'; const lovelace = useLovelace();

Your lovelace balance is: {lovelace}

[useNetwork Hook](https://meshjs.dev/react/wallet-hooks#usenetwork-hook) ------------------------------------------------------------------------- Return the network of connected wallet. const network = useNetwork(); ### [useNetwork Hook](https://meshjs.dev/react/wallet-hooks#usenetwork-hook-toc) Fetch the network of the connected wallet import { useNetwork } from '@meshsdk/react'; const network = useNetwork();

Connected network: {network}.

[UI Components\ \ UI components to speed up your app development.](https://meshjs.dev/react/ui-components) [Svelte Components\ \ Svelte UI components for wallet connections](https://meshjs.dev/svelte) ### On this page [useWallet Hook](https://meshjs.dev/react/wallet-hooks#usewallet-hook) [useWalletList Hook](https://meshjs.dev/react/wallet-hooks#usewalletlist-hook) [useAddress Hook](https://meshjs.dev/react/wallet-hooks#useaddress-hook) [useAssets Hook](https://meshjs.dev/react/wallet-hooks#useassets-hook) [useLovelace Hook](https://meshjs.dev/react/wallet-hooks#uselovelace-hook) [useNetwork Hook](https://meshjs.dev/react/wallet-hooks#usenetwork-hook) Ask AI --- # Build Transactions | Mesh SDK [Yaci](https://meshjs.dev/yaci) Build Transactions ================== Building and submitting transactions on Yaci Copy MarkdownOpen [Import Yaci Provider](https://meshjs.dev/yaci/transactions#import-yaci-provider) ---------------------------------------------------------------------------------- First, We import `YaciProvider` import { YaciProvider } from "@meshsdk/core"; const provider = new YaciProvider('', ''); By default, the `YaciProvider` will use the default URL, `https://yaci-node.meshjs.dev/api/v1/`. If you want to use a custom URL, you can pass it as a parameter. In this example, we initialize the `YaciProvider` and fetch the UTxOs of an address. You can topup ADA in your wallet by running the following command from devne in order to fetch the UTxOs of an address. devnet:default>topup addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9 1000 ### [Get UTxOs](https://meshjs.dev/yaci/transactions#get-utxos-toc) Fetch UTxOs of an address. Note: your Yaci devnet must be running. **Address** `addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337...pmtv7cc3yel9uu0nq93swx9` **Yaci URL** `https://yaci-node.meshjs.dev/api/v1/` import { YaciProvider } from "@meshsdk/core"; const provider = new YaciProvider('https://yaci-node.meshjs.dev/api/v1/'); const utxos = await provider.fetchAddressUTxOs('addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9'); [Basic Transaction](https://meshjs.dev/yaci/transactions#basic-transaction) ---------------------------------------------------------------------------- We import a wallet, for example `MeshWallet` with `YaciProvider` as the `fetcher` and `submitter`: const provider = new YaciProvider(); const wallet = new MeshWallet({ networkId: 0, fetcher: provider, submitter: provider, key: { type: "mnemonic", words: demoMnemonic, }, }); Next, we create a transaction and send 1 ADA to the recipient address. const tx = new Transaction({ initiator: wallet }); tx.sendLovelace('', "1000000"); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); Note: for this transaction to work, you must have a Yaci devnet running and the wallet is funded. You can topup ADA in your wallet by running the following command from devnet: devnet:default>topup addr_test1qryvgass5dsrf2kxl3vgfz76uhp83kv5lagzcp29tcana68ca5aqa6swlq6llfamln09tal7n5kvt4275ckwedpt4v7q48uhex 1000 ### [Get UTxOs](https://meshjs.dev/yaci/transactions#get-utxos-toc-1) Fetch UTxOs of an address. Note: your Yaci devnet must be running. **Recipient Address** `addr_test1qryvgass5dsrf2kxl3vgfz76uhp83kv5lag...tal7n5kvt4275ckwedpt4v7q48uhex` **Yaci URL** `https://yaci-node.meshjs.dev/api/v1/` import { YaciProvider } from "@meshsdk/core"; const provider = new YaciProvider('https://yaci-node.meshjs.dev/api/v1/'); const utxos = await provider.fetchAddressUTxOs('addr_test1qryvgass5dsrf2kxl3vgfz76uhp83kv5lagzcp29tcana68ca5aqa6swlq6llfamln09tal7n5kvt4275ckwedpt4v7q48uhex'); [Getting Started\ \ Set up Yaci Dev Kit and start the devnet](https://meshjs.dev/yaci/getting-started) [Learn\ \ Comprehensive courses, tutorials, and resources for Cardano developers.](https://meshjs.dev/resources) ### On this page [Import Yaci Provider](https://meshjs.dev/yaci/transactions#import-yaci-provider) [Basic Transaction](https://meshjs.dev/yaci/transactions#basic-transaction) Ask AI --- # JSON Data | Mesh SDK [Mesh API](https://meshjs.dev/apis) Data JSON Data ========= Parse and manipulate data with JSON Copy MarkdownOpen Mesh offers a full set of utility functions to help constructing the JSON data you need for your Web3 app, with the naming philosophy similar to Mesh `Data` type, with extra utilities mimicing the data type names in PlutusTx and Aiken. **Types Support** All the utilities are designed to return a type with the same naming as the utilities function, with capitalizing first letter, you can build your data in JSON with robust type supports, some examples: * `constr` returns `Constr` type * `integer` returns `Integer` type * `byteString` returns `ByteString` type [Utilities in Building Constructor Data in JSON](https://meshjs.dev/apis/data/json#utilities-in-building-constructor-data-in-json) ----------------------------------------------------------------------------------------------------------------------------------- `conStr` build the constructor object, with parameters: * constructor (number) - the constructor index * fields (any\[\]) - the constructor fields in array There are also some quick utilities only taking in **fields** as parameters for 0 - 2 indices: * `conStr0` - building index 0 constructor * `conStr1` - building index 1 constructor * `conStr2` - building index 2 constructor ### [Constructor](https://meshjs.dev/apis/data/json#constructor-toc) Building JSON constructor object import { conStr } from "@meshsdk/core"; conStr(0, []); [Utilities in Building Integer Data in JSON](https://meshjs.dev/apis/data/json#utilities-in-building-integer-data-in-json) --------------------------------------------------------------------------------------------------------------------------- `integer` build the integer object, with parameters: * int (number | bigint) - the integer to be built This utility is compatible for both number and bigint type, which allow big integer exceeding the JS precision limit. **Aliases** * `posixTime` - for the same functionality. ### [Constructor](https://meshjs.dev/apis/data/json#constructor-toc-1) Building JSON integer object **int** `1000000` import { integer } from "@meshsdk/core"; integer(1000000); [Utilities in Building ByteString Data in JSON](https://meshjs.dev/apis/data/json#utilities-in-building-bytestring-data-in-json) --------------------------------------------------------------------------------------------------------------------------------- `byteString` build the byte string object, with parameters: * bytes (string) - the byte string in hex to be built, validation would be performed on whether the bytes is a valid hex string **Aliases** * `builtinByteString` - for the same functionality, for developers more familiar to the PlutusTx naming convention. * `scriptHash` / `pubKeyHash` / `policyId` / `currencySymbol` / `assetName` / token\`Name - same building the byte string JSON but with further input validation. ### [Constructor](https://meshjs.dev/apis/data/json#constructor-toc-2) Building JSON byteString object **byteString** `a0bd47e8938e7c41d4c1d7c22033892319d28f86fdace791d45c51946553791b` import { byteString } from "@meshsdk/core"; byteString("a0bd47e8938e7c41d4c1d7c22033892319d28f86fdace791d45c51946553791b"); [Utilities in Building Boolean Data in JSON](https://meshjs.dev/apis/data/json#utilities-in-building-boolean-data-in-json) --------------------------------------------------------------------------------------------------------------------------- `bool` build the boolean object, with parameters: * b (boolean | boolean) - the boolean to be built ### [Constructor](https://meshjs.dev/apis/data/json#constructor-toc-3) Building JSON bool object import { bool } from "@meshsdk/core"; bool(true); [Utilities in Building List Data in JSON](https://meshjs.dev/apis/data/json#utilities-in-building-list-data-in-json) --------------------------------------------------------------------------------------------------------------------- `list` build the list object, with parameters: * pList (T\[\]) - the list with items to be built. The items in the * optional - validation (boolean) - indicate if the current data construction should perform basic validation of whether it is of typeobject (where all JSON data is in type of object) ### [Constructor](https://meshjs.dev/apis/data/json#constructor-toc-4) Building JSON list object import { bool, byteString, integer, list } from "@meshsdk/core"; list([\ byteString(\ "a0bd47e8938e7c41d4c1d7c22033892319d28f86fdace791d45c51946553791b"\ ),\ integer(1000000),\ bool(false),\ ]); [Utilities in Building Map Data in JSON](https://meshjs.dev/apis/data/json#utilities-in-building-map-data-in-json) ------------------------------------------------------------------------------------------------------------------- `assocMap` build the (associative) map object, with parameters: * mapItems - (\[KeyType, ValueType\]\[\]) - the array of map item in JS tuple format (array of array). * optional - validation (boolean) - indicate if the current data construction should perform basic validation of whether it is of typeobject (where all JSON data is in type of object) ### [Constructor](https://meshjs.dev/apis/data/json#constructor-toc-5) Building JSON list object import { assocMap, byteString, integer } from "@meshsdk/core"; assocMap([\ [byteString("aa"), integer(1000000)],\ [byteString("bb"), integer(2000000)],\ ]); [Other Utilities](https://meshjs.dev/apis/data/json#other-utilities) --------------------------------------------------------------------- The code example showing above does not cover all utilities, please checkout the hosted documentation for more details. The not covered utilities are as below: * `assetClass` * `outputReference` * `txOutRef` * `dict` * `tuple` * `maybeStakingHash` * `pubKeyAddress` * `scriptAddress` ### On this page [Utilities in Building Constructor Data in JSON](https://meshjs.dev/apis/data/json#utilities-in-building-constructor-data-in-json) [Utilities in Building Integer Data in JSON](https://meshjs.dev/apis/data/json#utilities-in-building-integer-data-in-json) [Utilities in Building ByteString Data in JSON](https://meshjs.dev/apis/data/json#utilities-in-building-bytestring-data-in-json) [Utilities in Building Boolean Data in JSON](https://meshjs.dev/apis/data/json#utilities-in-building-boolean-data-in-json) [Utilities in Building List Data in JSON](https://meshjs.dev/apis/data/json#utilities-in-building-list-data-in-json) [Utilities in Building Map Data in JSON](https://meshjs.dev/apis/data/json#utilities-in-building-map-data-in-json) [Other Utilities](https://meshjs.dev/apis/data/json#other-utilities) Ask AI --- # Getting Started with React | Mesh SDK [React Components](https://meshjs.dev/react) Getting Started with React ========================== Frontend components for wallet connections, and useful React hooks to getting wallet states Copy MarkdownOpen Mesh provide a collection of useful UI components, so you can easily include web3 functionality and convenient utilities for your application. [Setup](https://meshjs.dev/react/getting-started#setup) -------------------------------------------------------- The fastest way to get started a new project with React is to use the Mesh-CLI, which will scaffold a new project for you. To do this, run the following: npx meshjs your-app-name During the installation process, you will be asked to choose a template. Choose the React template. This will scaffold a new React project with Mesh pre-installed. To manually, install the Mesh React package, run the following: npm install @meshsdk/react Next, add the Mesh CSS to your application, doing so will apply the default styles to the components. You can add this in `/pages/_app.tsx`. import "@meshsdk/react/styles.css"; [Mesh Provider](https://meshjs.dev/react/getting-started#mesh-provider) ------------------------------------------------------------------------ React Context allows apps to share data across the app, and `MeshProvider` allows your app to subscribe to context changes. If you use the CLI to initialize your project, `MeshProvider` has been added in the root component. Otherwise, you can wrap `MeshProvider` at the root of your application, for example in Next.js: import "@meshsdk/react/styles.css"; import { MeshProvider } from "@meshsdk/react"; function MyApp({ Component, pageProps }: AppProps) { return ( ); }; Now your application is ready, explore the available UI components and wallet hooks and start using them in your application. [Connect Wallet](https://meshjs.dev/react/getting-started#connect-wallet) -------------------------------------------------------------------------- In order for pps to communicate with the user's wallet, we need a way to connect to their wallet. Add this CardanoWallet to allow the user to select a wallet to connect to your app. After the wallet is connected, see [Browser Wallet](https://meshjs.dev/apis/wallets/browserwallet) for a list of CIP-30 APIs. The signature for the CardanoWallet component is as follows: { label?: string; onConnected?: Function; isDark?: boolean; } ### [Customization](https://meshjs.dev/react/getting-started#customization-toc) For dark mode style, add isDark. For a custom label, add the label prop. The customization is limited. For more customization, you can easily build your own wallet connection component. If you are using React, the [React hooks](https://meshjs.dev/react/wallet-hooks) will be useful. You may also take reference from [this component](https://github.com/MeshJS/mesh/blob/main/packages/mesh-react/src/cardano-wallet/index.tsx) . ### [Persist user session](https://meshjs.dev/react/getting-started#persist-user-session-toc) If you would like to save the user last connected wallet and automatically connect to it on the next visit, you can use the persist prop. ### [onConnected](https://meshjs.dev/react/getting-started#onconnected-toc) If you want to run a function after the wallet is connected, you can add the onConnected prop. export default function Page() { function afterConnectedWallet() { // do something } return ( <> ); } The above code will log "Hello, World!" to the console when the wallet is connected. ### [Mesh Web3 Services](https://meshjs.dev/react/getting-started#mesh-web3-services-toc) [Mesh Web3 Services](https://utxos.dev/) streamline user onboarding and on-chain feature integration, accelerating your app's time to market. To integrate Mesh Web3 Services, use the `web3Services` prop. The `networkId` is the network ID of the wallet you are connecting to. You may use any [providers](https://meshjs.dev/providers) for `fetcher` and `submitter`. const provider = new BlockfrostProvider(''); ### [Decentralized WebRTC Wallet Communication (CIP 45)](https://meshjs.dev/react/getting-started#decentralized-webrtc-wallet-communication-cip-45-toc) [CIP-45](https://cips.cardano.org/cip/CIP-45) is a communication method between pps and wallets based on WebTorrent trackers and WebRTC. Using WebTorrent trackers for the peer discovery to remove the need of this central component. ### [Burner wallet](https://meshjs.dev/react/getting-started#burner-wallet-toc) Burner wallets are wallets that are created on the fly on the user's device. They are temporary wallets useful for testing purposes. The private keys are generated and stored on the user's device. ### [MetaMask Snaps](https://meshjs.dev/react/getting-started#metamask-snaps-toc) MetaMask Snaps are a new way to extend MetaMask with custom functionality and integrations. You can check the implementation to integrate NuFi from the [GitHub repository](https://github.com/MeshJS/mesh/tree/main/apps/playground/src/components/cardano/connect-browser-wallet) . Use the `injectFn` prop to add custom functionality. await checkIfMetamaskInstalled("preprod")} /> ### [Connect Wallet Component](https://meshjs.dev/react/getting-started#connect-wallet-component-toc) Connect to user's wallet to interact with app import { CardanoWallet } from '@meshsdk/react'; export default function Page() { return ( <> {console.log('on connected')}} cardanoPeerConnect={{ dAppInfo: { name: "Mesh SDK", url: "https://meshjs.dev/", }, announce: [\ "wss://dev.btt.cf-identity-wallet.metadata.dev.cf-deployments.org",\ ], }} burnerWallet={{ networkId: 0, provider: provider, }} /> ); } [useWallet Hook](https://meshjs.dev/react/getting-started#usewallet-hook) -------------------------------------------------------------------------- Provide information on the current wallet's state, and functions for connecting and disconnecting user wallet. const { wallet, state, connected, name, connecting, connect, disconnect, error } = useWallet(); `wallet` is a [Browser Wallet](https://meshjs.dev/apis/wallets/browserwallet) instance, which expose all CIP wallets functions from getting assets to signing tranasction. `state`, a enum string, the state of the wallet, can be `NOT_CONNECTED`, `CONNECTING` or `CONNECTED`. `connected`, a boolean, `true` if user's wallet is connected. `name`, a string, the name of the connect wallet. `connecting`, a boolean, `true` if the wallet is connecting and initializing. `connect(walletName: string)`, a function, provide the wallet name to connect wallet. Retrive a list of available wallets with `useWalletList()`. `disconnect()`, a function, to disconnect the connected wallet. `error`, returns the error object if any error occurs during wallet connection, such as "account not set". ### [useWallet Hook](https://meshjs.dev/react/getting-started#usewallet-hook-toc) Interact with user's wallet import { useWallet } from '@meshsdk/react'; export default function Page() { const { wallet, state, connected, name, connecting, connect, disconnect, error } = useWallet(); return (

State: {state}

Connected?: {connected ? 'Is connected' : 'Not connected'}

Connecting wallet?: {connecting ? 'Connecting...' : 'No'}

Name of connected wallet: {name}

); } [React Components\ \ Frontend React UI components and React hooks](https://meshjs.dev/react) [UI Components\ \ UI components to speed up your app development.](https://meshjs.dev/react/ui-components) ### On this page [Setup](https://meshjs.dev/react/getting-started#setup) [Mesh Provider](https://meshjs.dev/react/getting-started#mesh-provider) [Connect Wallet](https://meshjs.dev/react/getting-started#connect-wallet) [useWallet Hook](https://meshjs.dev/react/getting-started#usewallet-hook) Ask AI --- # Yaci | Mesh SDK Yaci ==== Customizable Cardano devnet for enabling faster iterations Copy MarkdownOpen Custom Cardano devnet that can be created and reset in seconds using the user-friendly Yaci CLI. This allows for rapid iteration and experimentation, tailored to specific needs through flexible configuration options. The default devnet is optimized for speed, with customizable parameters for various testing scenarios. Integrated tools like the lightweight chain indexer Yaci Store and the browser-based Yaci Viewer enhance transaction building and submission. Yaci DevKit's compatibility with Blockfrost API endpoints ensures seamless integration with client SDKs. [Getting Started\ \ Set up Yaci Dev Kit and start the devnet](https://meshjs.dev/yaci/getting-started) [Hosted Yaci Devnet\ \ Connect to the hosted Yaci Devnet](https://cloud.meshjs.dev/yaci) [Build Transactions\ \ Building and submitting transactions on Yaci](https://meshjs.dev/yaci/transactions) [Yaci Provider\ \ For fetching data and submitting transactions on Yaci](https://meshjs.dev/providers/yaci) [Project Structure\ \ Understanding the generated project structure](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure) [Getting Started\ \ Set up Yaci Dev Kit and start the devnet](https://meshjs.dev/yaci/getting-started) Ask AI --- # UI Components | Mesh SDK [Svelte Components](https://meshjs.dev/svelte) UI Components ============= UI components to speed up your app development. Copy MarkdownOpen Mesh provide a collection of useful UI components, so you can easily include web3 functionality and convenient utilities for your application. [Connect Wallet](https://meshjs.dev/svelte/ui-components#connect-wallet) ------------------------------------------------------------------------- In order for apps to communicate with the user's wallet, we need a way to connect to their wallet. Add `CardanoWallet` to allow the user to select a wallet to connect to your app. After the wallet is connected, see [Browser Wallet](https://meshjs.dev/apis/wallets/browserwallet) for a list of CIP-30 APIs. The signature for the `CardanoWallet` component is as follows: { label?: string; onConnected?: Function; isDark?: boolean; } ### [Customization](https://meshjs.dev/svelte/ui-components#customization-toc) For dark mode style, add isDark. For a custom label, add the label prop. The customization is limited. For more customization, you can easily build your own wallet connection component. You may also take reference from [this component](https://github.com/MeshJS/mesh/blob/main/packages/mesh-react/src/cardano-wallet/index.tsx) . ### [onConnected](https://meshjs.dev/svelte/ui-components#onconnected-toc) If you want to run a function after the wallet is connected, you can add the onConnected prop. export default function Page() { function afterConnectedWallet() { // do something } return ( <> ); } The above code will log "Hello, World!" to the console when the wallet is connected. ### [Connect Wallet Component](https://meshjs.dev/svelte/ui-components#connect-wallet-component-toc) Connect to user's wallet to interact with app
[Getting Started with Svelte\ \ Svelte frontend components for wallet connections.](https://meshjs.dev/svelte/getting-started) [Smart Contracts\ \ Open-source smart contracts, complete with documentation, and live demos](https://meshjs.dev/smart-contracts) ### On this page [Connect Wallet](https://meshjs.dev/svelte/ui-components#connect-wallet) Ask AI --- # Transaction Parser | Mesh SDK Transaction Parser ================== Parse transactions for testing and rebuilding Copy MarkdownOpen [Parser Basics\ \ Parse transactions and rebuild](https://meshjs.dev/apis/txparser/basics) [Unit Testing Transaction\ \ Parse and test transactions with various options](https://meshjs.dev/apis/txparser/txtester) [Governance Transactions\ \ Transactions for participating in Cardano's on-chain governance](https://meshjs.dev/apis/txbuilder/governance) [Parser Basics\ \ Parse transactions and rebuild](https://meshjs.dev/apis/txparser/basics) Ask AI --- # Wallets | Mesh SDK Wallets ======= Wallets APIs for interacting with the blockchain. Copy MarkdownOpen [Browser Wallet\ \ For connecting, queries and performs wallet functions in accordance to CIP-30.](https://meshjs.dev/apis/wallets/browserwallet) [Mesh Wallet\ \ Mesh Wallet provides a set of APIs to interact with the blockchain. This wallet is compatible with Mesh transaction builders.](https://meshjs.dev/apis/wallets/meshwallet) [Browser Wallet\ \ For connecting, querying and performing wallet functions in accordance to CIP-30.](https://meshjs.dev/apis/wallets/browserwallet) Ask AI --- # Parser Basics | Mesh SDK [Transaction Parser](https://meshjs.dev/apis/txparser) Parser Basics ============= Parse transactions and rebuild Copy MarkdownOpen The `TxParser` is a tool where you can parse the typical transaction CBOR hex back into the `MeshTxBuilderBody`. With such capability, you can proceed with rebuilding a transaction or examing the with unit testing frameworks. In this page, we will cover how to initialize the `TxParser`. [Initialize Tx Parser](https://meshjs.dev/apis/txparser/basics#initialize-tx-parser) ------------------------------------------------------------------------------------- To start parsing transaction, you need to first initialize `TxParser`: import { BlockfrostProvider, TxParser } from "@meshsdk/core"; import { CSLSerializer } from "@meshsdk/core-csl"; const fetcher = new BlockfrostProvider(''); const serializer = new CSLSerializer(); const txParser = new TxParser(serializer, fetcher); There are 2 fields to pass in to initialized `TxParser`: 1. `serializer`: The serializer instance that will be used for parsing transaction 2. `fetcher` (optional): `TxParser` requires all input `UTxO` information provided since the transaction CBOR hex only preserves transaction hash and output index. When you are not providing all input `UTxO` information, the `fetcher` instance is used to fetch the missing `UTxO` [Rebuild Transaction](https://meshjs.dev/apis/txparser/basics#rebuild-transaction) ----------------------------------------------------------------------------------- To parse a transaction, you only need: const txBuilderBody = await txParser.parse(txHex, utxos); With the parsed `txBuilderBody` in type `MeshTxBuilderBody`, you can proceed with adding / removing elements and rebuilding the transaction. There are 2 necessary fields to pass in: 1. `txHex`: The transaction CBOR to be parsed 2. `providedUtxos`: The input information, for all inputs, reference inputs, and collateral. You can either construct it manually or obtain it from `fetcher`. [Unit Testing Transaction](https://meshjs.dev/apis/txparser/basics#unit-testing-transaction) --------------------------------------------------------------------------------------------- To unit test a transaction, you can parse the transaction and then convert the instance to `TxTester`: await txParser.parse(txHex, utxos); const txTester = txParser.toTester(); The detailed testing APIs can be found in the [documentation](https://meshjs.dev/apis/txparser/txtester) . [Transaction Parser\ \ Parse transactions for testing and rebuilding](https://meshjs.dev/apis/txparser) [Unit Testing Transaction\ \ Parse and test transactions with various options](https://meshjs.dev/apis/txparser/txtester) ### On this page [Initialize Tx Parser](https://meshjs.dev/apis/txparser/basics#initialize-tx-parser) [Rebuild Transaction](https://meshjs.dev/apis/txparser/basics#rebuild-transaction) [Unit Testing Transaction](https://meshjs.dev/apis/txparser/basics#unit-testing-transaction) Ask AI --- # Getting Started | Mesh SDK [Yaci](https://meshjs.dev/yaci) Getting Started =============== Set up Yaci Dev Kit and start the devnet Copy MarkdownOpen [Mesh Hosted Yaci Devnet](https://meshjs.dev/yaci/getting-started#mesh-hosted-yaci-devnet) ------------------------------------------------------------------------------------------- ### [Connect right away with Yaci Provider](https://meshjs.dev/yaci/getting-started#connect-right-away-with-yaci-provider-toc) Mesh has a hosted Yaci Devnet that you can connect to right away. You can use the following URL to connect to the hosted Yaci Devnet: https://yaci-node.meshjs.dev/api/v1/ ### [Import Yaci Provider](https://meshjs.dev/yaci/getting-started#import-yaci-provider-toc) Import `YaciProvider` and start using it to interact with the Yaci Devnet. import { YaciProvider } from "@meshsdk/core"; const provider = new YaciProvider(); const params = await provider.fetchProtocolParameters(); console.log(params); [Learn more about Yaci Provider](https://meshjs.dev/yaci/transactions#import-yaci-provider) and learn more about [hosted Yaci Devnet](https://cloud.meshjs.dev/yaci) [Set up your system to run Yaci Devkit](https://meshjs.dev/yaci/getting-started#set-up-your-system-to-run-yaci-devkit) ----------------------------------------------------------------------------------------------------------------------- ### [Download and install Docker](https://meshjs.dev/yaci/getting-started#download-and-install-docker-toc) You can download Docker from the official website. Docker is a platform for developers and sysadmins to develop, deploy, and run applications with containers. Go to the [Docker website](https://docs.docker.com/get-started/get-docker/) and download the latest version, then follow the instructions to install it. After installing, open the Docker Desktop app and make sure it's running in the background. ### [Download the latest Yaci DevKit release](https://meshjs.dev/yaci/getting-started#download-the-latest-yaci-devkit-release-toc) Go to Yaci releases on Github and download the latest release. Under `Assets`, you will find the `yaci-devkit-version.zip` file. Extract the zip file to a folder on your system. This folder will be your Yaci DevKit root directory. [Start a Yaci Devnet](https://meshjs.dev/yaci/getting-started#start-a-yaci-devnet) ----------------------------------------------------------------------------------- Open a terminal and navigate to the Yaci DevKit root directory. Run the following command to start the DevKit containers and yaci-cli: $ ./bin/devkit.sh start ### [Start node](https://meshjs.dev/yaci/getting-started#start-node-toc) To create a new devnet, run the following command from yaci-cli: yaci-cli:>create-node -o --start To create a new devnet with Babbage era, run the following command from yaci-cli: yaci-cli:>create-node -o --era babbage --start To start a devnet with zero fees, run the following command from yaci-cli: yaci-cli:>create-node -o --genesis-profile zero_fee --start To start a devnet with 30 slots per epoch, run the following command from yaci-cli: yaci-cli:>create-node -o -e 30 --start After you have started your devnet, you can open Yaci Viewer from [http://localhost:5173](http://localhost:5173/) . Here you can view the blocks, transactions, and other details of the devnet. If you want to configure the devnet, go to `config/node.properties`. And if you want to change settings and change default topup addreses, go to `config/env`. You can use `YaciProvider` with the Yaci Store Api URL ([http://localhost:8080/api/v1](http://localhost:8080/api/v1) ), to interact with the Yaci Devnet. import { YaciProvider } from "@meshsdk/core"; const provider = new YaciProvider('http://localhost:8080/api/v1/'); const params = await provider.fetchProtocolParameters(); console.log(params); ### [Support external PostgreSQL database for indexer](https://meshjs.dev/yaci/getting-started#support-external-postgresql-database-for-indexer-toc) By default, Yaci DevKit's indexer uses an embedded H2 database. With this update, you can also configure an external PostgreSQL database. For Non-Docker distribution, edit config/application.properties and uncomment the following properties to set PostgreSQL database details: yaci.store.db.url=jdbc:postgresql://:/?currentSchema= yaci.store.db.username=user yaci.store.db.password=password For Docker distribution, edit config/env and uncomment the following properties: yaci_store_db_url=jdbc:postgresql://:/?currentSchema= yaci_store_db_username=user yaci_store_db_password=password [Useful commands](https://meshjs.dev/yaci/getting-started#useful-commands) --------------------------------------------------------------------------- Here are some useful commands to interact with the Yaci DevKit. ### [Topup ADA](https://meshjs.dev/yaci/getting-started#topup-ada-toc) After you have started your devnet, you can topup ADA in your wallet. To topup ADA in your wallet, run the following command from devnet: devnet:default>topup
For example: devnet:default>topup addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9 1000 ### [Check UTXO](https://meshjs.dev/yaci/getting-started#check-utxo-toc) To check the UTXO of an address, run the following command from devnet: devnet:default>utxos
For example: devnet:default>utxos addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9 ### [Default address info](https://meshjs.dev/yaci/getting-started#default-address-info-toc) You can get the default addresses of the devnet by running: devnet:default> default-addresses By default, wallet mnemonic is test test test test test test test test test test test test test test test test test test test test test test test sauce And it's address is addr_test1qryvgass5dsrf2kxl3vgfz76uhp83kv5lagzcp29tcana68ca5aqa6swlq6llfamln09tal7n5kvt4275ckwedpt4v7q48uhex ### [Stop Devnet and yaci-cli](https://meshjs.dev/yaci/getting-started#stop-devnet-and-yaci-cli-toc) To stop the devnet, run the following command from devnet: devnet:default>exit To stop yaci-cli, run the following command: yaci-cli:>exit To stop the DevKit containers, run the following command from the Yaci DevKit root directory: ./bin/devkit.sh stop Sometimes you just want to reset the devnet and start from scratch. To do that, run: devnet:default>reset [Yaci\ \ Customizable Cardano devnet for enabling faster iterations](https://meshjs.dev/yaci) [Build Transactions\ \ Building and submitting transactions on Yaci](https://meshjs.dev/yaci/transactions) ### On this page [Mesh Hosted Yaci Devnet](https://meshjs.dev/yaci/getting-started#mesh-hosted-yaci-devnet) [Set up your system to run Yaci Devkit](https://meshjs.dev/yaci/getting-started#set-up-your-system-to-run-yaci-devkit) [Start a Yaci Devnet](https://meshjs.dev/yaci/getting-started#start-a-yaci-devnet) [Useful commands](https://meshjs.dev/yaci/getting-started#useful-commands) Ask AI --- # Getting Started with Svelte | Mesh SDK [Svelte Components](https://meshjs.dev/svelte) Getting Started with Svelte =========================== Svelte frontend components for wallet connections. Copy MarkdownOpen [Setup](https://meshjs.dev/svelte/getting-started#setup) --------------------------------------------------------- The fastest way to get started a new project with Svelte is to use the Mesh-CLI, which will scaffold a new project for you. To do this, run the following: npx meshjs your-app-name During the installation process, you will be asked to choose a template. Choose the Svelte template. This will scaffold a new Svelte project with Mesh pre-installed. To manually, install the Mesh Svelte package, run the following: npm install @meshsdk/svelte Next, add the Mesh CSS to your application, doing so will apply the default styles to the components. You can add this in `+layout.svelte`. {@render children()} [Connect Wallet](https://meshjs.dev/svelte/getting-started#connect-wallet) --------------------------------------------------------------------------- In order for apps to communicate with the user's wallet, we need a way to connect to their wallet. Add `CardanoWallet` to allow the user to select a wallet to connect to your app. After the wallet is connected, see [Browser Wallet](https://meshjs.dev/apis/wallets/browserwallet) for a list of CIP-30 APIs. The signature for the `CardanoWallet` component is as follows: { label?: string; onConnected?: Function; isDark?: boolean; } ### [Customization](https://meshjs.dev/svelte/getting-started#customization-toc) For dark mode style, add isDark. For a custom label, add the label prop. The customization is limited. For more customization, you can easily build your own wallet connection component. You may also take reference from [this component](https://github.com/MeshJS/mesh/blob/main/packages/mesh-react/src/cardano-wallet/index.tsx) . ### [onConnected](https://meshjs.dev/svelte/getting-started#onconnected-toc) If you want to run a function after the wallet is connected, you can add the onConnected prop. export default function Page() { function afterConnectedWallet() { // do something } return ( <> ); } The above code will log "Hello, World!" to the console when the wallet is connected. ### [Connect Wallet Component](https://meshjs.dev/svelte/getting-started#connect-wallet-component-toc) Connect to user's wallet to interact with app
[Get Wallet State](https://meshjs.dev/svelte/getting-started#get-wallet-state) ------------------------------------------------------------------------------- Obtain information on the current wallet's state, all fields on the `BrowserWalletState` JavaScript object are Svelte 5 runes, meaning when using the accessor, these values are reactive. `wallet` is a [Browser Wallet](https://meshjs.dev/apis/wallets/browserwallet) instance, which expose all CIP wallets functions from getting assets to signing tranasction. `connected`, a boolean, `true` if user's wallet is connected. `name`, a string, the name of the connect wallet. `connecting`, a boolean, `true` if the wallet is connecting and initializing. ### [Wallet State](https://meshjs.dev/svelte/getting-started#wallet-state-toc) Get the current wallet's state
[Svelte Components\ \ Svelte UI components for wallet connections](https://meshjs.dev/svelte) [UI Components\ \ UI components to speed up your app development.](https://meshjs.dev/svelte/ui-components) ### On this page [Setup](https://meshjs.dev/svelte/getting-started#setup) [Connect Wallet](https://meshjs.dev/svelte/getting-started#connect-wallet) [Get Wallet State](https://meshjs.dev/svelte/getting-started#get-wallet-state) Ask AI --- # Unit Testing Transaction | Mesh SDK [Transaction Parser](https://meshjs.dev/apis/txparser) Unit Testing Transaction ======================== Parse and test transactions with various options Copy MarkdownOpen The `TxParser` is a tool where you can parse the typical transaction CBOR hex back into the `MeshTxBuilderBody`. With such capability, you can proceed with rebuilding a transaction or examing the with unit testing frameworks. In this page, we will cover how to initialize the `TxParser`. [Initialize Tx Parser](https://meshjs.dev/apis/txparser/txtester#initialize-tx-parser) --------------------------------------------------------------------------------------- To start parsing transaction, you need to first initialize `TxParser`: import { BlockfrostProvider, TxParser } from "@meshsdk/core"; import { CSLSerializer } from "@meshsdk/core-csl"; const fetcher = new BlockfrostProvider(''); const serializer = new CSLSerializer(); const txParser = new TxParser(serializer, fetcher); There are 2 fields to pass in to initialized `TxParser`: 1. `serializer`: The serializer instance that will be used for parsing transaction 2. `fetcher` (optional): `TxParser` requires all input `UTxO` information provided since the transaction CBOR hex only preserves transaction hash and output index. When you are not providing all input `UTxO` information, the `fetcher` instance is used to fetch the missing `UTxO` [Interpret Result](https://meshjs.dev/apis/txparser/txtester#interpret-result) ------------------------------------------------------------------------------- After performing the tests, you can interpret the results of the tests using the `success` and `errors` methods. const result = txTester.success(); console.log("Errors:", txTester.errors()); 1. `success`: Return a boolean indicating if all tests are passed 2. `errors`: Show all the errors that occurred during the tests . If there are no errors, it will return an empty string. [Testing Inputs](https://meshjs.dev/apis/txparser/txtester#testing-inputs) --------------------------------------------------------------------------- Testing inputs starts with locating the inputs you want to test. The filtering will not reset until the filtering methods are called again. txTester .inputsAt( "addr_test1qrs3jlcsapdufgagzt35ug3nncwl26mlkcux49gs673sflmrjfm6y2eu7del3pprckzt4jaal9s7w9gq5kguqs5pf6fq542mmq", ) .inputsValue( MeshValue.fromAssets([{ unit: "lovelace", quantity: "10000000000" }]), ) There are multiple methods available to filter the inputs: 1. `allInputs`: not apply filters 2. `inputsAt`: filtering inputs with address 3. `inputsWith`: filtering inputs with token 4. `inputsWithPolicy`: filtering inputs with policy id 5. `inputsAtWith`: filtering inputs with address and token 6. `inputsAtWithPolicy`: filtering inputs with address and policy id After applying filters, you can proceed with checking value: 1. `inputsValue`: Check the total value of the filtered inputs [Testing Outputs](https://meshjs.dev/apis/txparser/txtester#testing-outputs) ----------------------------------------------------------------------------- Testing outputs starts with locating the outputs you want to test. The filtering will not reset until the filtering methods are called again. txTester .outputsAt( "addr_test1qrs3jlcsapdufgagzt35ug3nncwl26mlkcux49gs673sflmrjfm6y2eu7del3pprckzt4jaal9s7w9gq5kguqs5pf6fq542mmq", ) .outputsValue( MeshValue.fromAssets([{ unit: "lovelace", quantity: "10000000000" }]), ) .outputsInlineDatumExist(datumCbor); There are multiple methods available to filter the outputs: 1. `allOutputs`: not apply filters 2. `outputsAt`: filtering outputs with address 3. `outputsWith`: filtering outputs with token 4. `outputsWithPolicy`: filtering outputs with policy id 5. `outputsAtWith`: filtering outputs with address and token 6. `outputsAtWithPolicy`: filtering outputs with address and policy id After applying filters, you can proceed with checking value: 1. `outputsValue`: Check the total value of the filtered outputs 2. `outputsInlineDatumExist`: Check whether any one of the outputs contains inline datum (provided as CBOR) [Testing Mints](https://meshjs.dev/apis/txparser/txtester#testing-mints) ------------------------------------------------------------------------- Testing mints with below APIs: txTester .tokenMinted( "eab3a1d125a3bf4cd941a6a0b5d7752af96fae7f5bcc641e8a0b6762", "", 1, ); 1. `tokenMinted`: Checks if a specific token is minted in the transaction. 2. `onlyTokenMinted`: Checks if a specific token is minted in the transaction and that it is the only mint. 3. `policyOnlyMintedToken`: Checks if a specific token is minted in the transaction, ensuring that it is the only mint for the given policy ID. 4. `checkPolicyOnlyBurn`: Checks if a specific policy ID is burned in the transaction, ensuring that it is the only minting (i.e. burning item). [Testing Time](https://meshjs.dev/apis/txparser/txtester#testing-time) ----------------------------------------------------------------------- Testing time with below APIs: txTester .validBefore(beforeTimestamp) .validAfter(afterTimestamp); 1. `validAfter`: Checks if the transaction is valid after a specified timestamp. 2. `validBefore`: Checks if the transaction is valid before a specified timestamp. [Testing Signature](https://meshjs.dev/apis/txparser/txtester#testing-signature) --------------------------------------------------------------------------------- Testing time with below APIs: txTester .keySigned("fa5136e9e9ecbc9071da73eeb6c9a4ff73cbf436105cf8380d1c525c"); 1. `keySigned`: Checks if a specific key is signed in the transaction. 2. `oneOfKeysSigned`: Checks if any one of the specified keys is signed in the transaction. 3. `allKeysSigned`: Checks if all specified keys are signed in the transaction. [Parser Basics\ \ Parse transactions and rebuild](https://meshjs.dev/apis/txparser/basics) [Providers\ \ Data providers for connecting to the blockchain](https://meshjs.dev/providers) ### On this page [Initialize Tx Parser](https://meshjs.dev/apis/txparser/txtester#initialize-tx-parser) [Interpret Result](https://meshjs.dev/apis/txparser/txtester#interpret-result) [Testing Inputs](https://meshjs.dev/apis/txparser/txtester#testing-inputs) [Testing Outputs](https://meshjs.dev/apis/txparser/txtester#testing-outputs) [Testing Mints](https://meshjs.dev/apis/txparser/txtester#testing-mints) [Testing Time](https://meshjs.dev/apis/txparser/txtester#testing-time) [Testing Signature](https://meshjs.dev/apis/txparser/txtester#testing-signature) Ask AI --- # Koios Provider | Mesh SDK [Providers](https://meshjs.dev/providers) Koios Provider ============== Distributed & open-source public API query layer for Cardano Copy MarkdownOpen [Koios](https://www.koios.rest/) provides a query layer which allows your app to access information stored on the blockchain. Get started: import { KoiosProvider } from "@meshsdk/core"; const provider = new KoiosProvider( 'preprod', // "api" | "preview" | "preprod" | "guild" '', ); Get your API key from [Koios User Profile page](https://koios.rest/Profile.html) . [Get data from URL](https://meshjs.dev/providers/koios#get-data-from-url) -------------------------------------------------------------------------- You can fetch any data from the blockchain by providing the URL path. await provider.get('/addresses/addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9/transactions') [Fetch Account Info](https://meshjs.dev/providers/koios#fetch-account-info) ---------------------------------------------------------------------------- Obtain information about a specific stake account. await provider.fetchAccountInfo('stake_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n') [Fetch Address Assets](https://meshjs.dev/providers/koios#fetch-address-assets) -------------------------------------------------------------------------------- Fetch assets from an address. await provider.fetchAddressAssets( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); ### [Fetch Address UTxOs](https://meshjs.dev/providers/koios#fetch-address-utxos-toc) Fetch UTxOs from address await provider.fetchAddressAssets( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); ### [Fetch assets from address](https://meshjs.dev/providers/koios#fetch-assets-from-address-toc) Fetch assets given an address await provider.fetchAddressAssets( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', ); [Fetch Address UTxOs](https://meshjs.dev/providers/koios#fetch-address-utxos) ------------------------------------------------------------------------------ Fetch UTxOs controlled by an address. await provider.fetchAddressUTxOs('addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') Optionally, you can filter UTXOs containing a particular `asset` by providing asset, where it is the concatenation of policy ID and asset. await fetchAddressUTxOs(address: string, asset?: string) [Fetch Asset Addresses](https://meshjs.dev/providers/koios#fetch-asset-addresses) ---------------------------------------------------------------------------------- Fetch a list of a addresses containing a specific `asset` where it is the concatenation of policy ID and asset. await provider.fetchAssetAddresses('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') [Fetch Asset Metadata](https://meshjs.dev/providers/koios#fetch-asset-metadata) -------------------------------------------------------------------------------- Fetch the asset metadata by providing asset's `unit`, which is the concatenation of policy ID and asset name in hex. await provider.fetchAssetMetadata('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') [Fetch Block Info](https://meshjs.dev/providers/koios#fetch-block-info) ------------------------------------------------------------------------ Fetch block infomation. You can get the hash from `fetchTxInfo()`. await provider.fetchBlockInfo('79f60880b097ec7dabb81f75f0b52fedf5e922d4f779a11c0c432dcf22c56089') [Fetch Collection Assets](https://meshjs.dev/providers/koios#fetch-collection-assets) -------------------------------------------------------------------------------------- Fetch a list of assets belonging to a collection by providing its Policy ID. await provider.fetchCollectionAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527') The API will return a list of `assets` and a cursor `next`. If the cursor is not null, you can use it to fetch the next page of results. Here is an example of the response. { "assets": [\ {\ "unit": "d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527",\ "quantity": "1"\ },\ ], "next": 2 } The `fetchCollectionAssets` function also accepts an optional `cursor` parameter to fetch the next page of results. The default value is `1`. await fetchCollectionAssets( policyId: string, cursor = 1 ) [Fetch Handle Address](https://meshjs.dev/providers/koios#fetch-handle-address) -------------------------------------------------------------------------------- [ADA Handle](https://handle.me/) allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. We can resolve the handle's address with `fetchHandleAddress`. // Handle: `meshsdk` await provider.fetchHandleAddress('meshsdk') [Fetch Handle](https://meshjs.dev/providers/koios#fetch-handle) ---------------------------------------------------------------- [ADA Handle](https://handle.me/) allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. ADA Handle also released a CIP68 handle and this function will fetch the metadata of the handle. // Handle: `meshsdk` await provider.fetchHandle('meshsdk') [Fetch Protocol Parameters](https://meshjs.dev/providers/koios#fetch-protocol-parameters) ------------------------------------------------------------------------------------------ Fetch the latest protocol parameters. await provider.fetchProtocolParameters() Optionally, you can provide an epoch number to fetch the protocol parameters of that epoch. [Fetch Transaction Info](https://meshjs.dev/providers/koios#fetch-transaction-info) ------------------------------------------------------------------------------------ Fetch transaction infomation. Only confirmed transaction can be retrieved. await provider.fetchTxInfo('f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159') [Fetch UTxOs](https://meshjs.dev/providers/koios#fetch-utxos) -------------------------------------------------------------- Get UTxOs for a given hash. await provider.fetchUTxOs('dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70') Optionally, you can specify the index of the index output. await provider.fetchUTxOs('hash_here', 0) [Fetch Proposal Info](https://meshjs.dev/providers/koios#fetch-proposal-info) ------------------------------------------------------------------------------ Get information for a given governance proposal, identified by the txHash and proposal index await provider.fetchGovernanceProposal('372d688faa77e146798b581b322c0f2981a9023764736ade5d12e0e4e796af8c', 0) [Submit Transaction](https://meshjs.dev/providers/koios#submit-transaction) ---------------------------------------------------------------------------- Submit a serialized transaction to the network. await provider.submitTx(signedTx); [On Transaction Confirmed](https://meshjs.dev/providers/koios#on-transaction-confirmed) ---------------------------------------------------------------------------------------- Allow you to listen to a transaction confirmation. Upon confirmation, the callback will be called. const tx = new Transaction({ initiator: wallet }); tx.sendLovelace('addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', '5000000'); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); provider.onTxConfirmed(txHash, () => { // Transaction confirmed }); [Hydra Provider (beta)\ \ Layer 2 scaling solution for Cardano that increases transaction throughput and ensures cost efficiency while maintaining security.](https://meshjs.dev/providers/hydra) [Maestro Provider\ \ Advanced UTxO-indexing data layer to supercharge Defi on Bitcoin, Cardano & Dogecoin](https://meshjs.dev/providers/maestro) ### On this page [Get data from URL](https://meshjs.dev/providers/koios#get-data-from-url) [Fetch Account Info](https://meshjs.dev/providers/koios#fetch-account-info) [Fetch Address Assets](https://meshjs.dev/providers/koios#fetch-address-assets) [Fetch Address UTxOs](https://meshjs.dev/providers/koios#fetch-address-utxos) [Fetch Asset Addresses](https://meshjs.dev/providers/koios#fetch-asset-addresses) [Fetch Asset Metadata](https://meshjs.dev/providers/koios#fetch-asset-metadata) [Fetch Block Info](https://meshjs.dev/providers/koios#fetch-block-info) [Fetch Collection Assets](https://meshjs.dev/providers/koios#fetch-collection-assets) [Fetch Handle Address](https://meshjs.dev/providers/koios#fetch-handle-address) [Fetch Handle](https://meshjs.dev/providers/koios#fetch-handle) [Fetch Protocol Parameters](https://meshjs.dev/providers/koios#fetch-protocol-parameters) [Fetch Transaction Info](https://meshjs.dev/providers/koios#fetch-transaction-info) [Fetch UTxOs](https://meshjs.dev/providers/koios#fetch-utxos) [Fetch Proposal Info](https://meshjs.dev/providers/koios#fetch-proposal-info) [Submit Transaction](https://meshjs.dev/providers/koios#submit-transaction) [On Transaction Confirmed](https://meshjs.dev/providers/koios#on-transaction-confirmed) Ask AI --- # Blockfrost Provider | Mesh SDK [Providers](https://meshjs.dev/providers) Blockfrost Provider =================== Featuring over 100 APIs tailored for easy access to Cardano blockchain Copy MarkdownOpen [Blockfrost](https://blockfrost.io/) provides restful APIs which allows your app to access information stored on the blockchain. Get started: import { BlockfrostProvider } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); If you are using a privately hosted Blockfrost instance, you can set the URL in the parameter: const provider = new BlockfrostProvider(''); ### [Get data from URL](https://meshjs.dev/providers/blockfrost#get-data-from-url) You can fetch any data from the blockchain by providing the URL path. await provider.get('/addresses/addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9/transactions') [Fetch Account Info](https://meshjs.dev/providers/blockfrost#fetch-account-info) --------------------------------------------------------------------------------- Obtain information about a specific stake account. await provider.fetchAccountInfo('stake_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n') [Fetch Address Assets](https://meshjs.dev/providers/blockfrost#fetch-address-assets) ------------------------------------------------------------------------------------- Fetch assets from an address. await provider.fetchAddressAssets('addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') ### [Fetch Address UTxOs](https://meshjs.dev/providers/blockfrost#fetch-address-utxos-toc) Fetch UTxOs from address **Address** addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9 await provider.fetchAddressAssets( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); ### [Fetch assets from address](https://meshjs.dev/providers/blockfrost#fetch-assets-from-address-toc) Fetch assets given an address **Address** addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9 await provider.fetchAddressAssets( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); [Fetch Address UTxOs](https://meshjs.dev/providers/blockfrost#fetch-address-utxos) ----------------------------------------------------------------------------------- Fetch UTxOs controlled by an address. await provider.fetchAddressUTxOs('addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') Optionally, you can filter UTXOs containing a particular `asset` by providing asset, where it is the concatenation of policy ID and asset. await fetchAddressUTxOs(address: string, asset?: string) ### [Fetch Address UTxOs](https://meshjs.dev/providers/blockfrost#fetch-address-utxos-toc-1) Fetch UTxOs from address **Address** addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9 await provider.fetchAddressUTxOs( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); ### [Fetch UTxOs with Asset](https://meshjs.dev/providers/blockfrost#fetch-utxos-with-asset-toc) Fetch UTxOs from address with asset **Address** addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9 **Asset**: `d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e` await provider.fetchAddressUTxOs( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); [Fetch Asset Addresses](https://meshjs.dev/providers/blockfrost#fetch-asset-addresses) --------------------------------------------------------------------------------------- Fetch a list of a addresses containing a specific `asset` where it is the concatenation of policy ID and asset. await provider.fetchAssetAddresses('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') ### [Fetch Asset Addresses](https://meshjs.dev/providers/blockfrost#fetch-asset-addresses-toc) Fetch list of addresses containing a specific asset **Asset Unit**: `d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e` await provider.fetchAssetAddresses( 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e' ); [Fetch Asset Metadata](https://meshjs.dev/providers/blockfrost#fetch-asset-metadata) ------------------------------------------------------------------------------------- Fetch the asset metadata by providing asset's `unit`, which is the concatenation of policy ID and asset name in hex. // Asset Unit: `d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e` await provider.fetchAssetMetadata('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') [Fetch Block Info](https://meshjs.dev/providers/blockfrost#fetch-block-info) ----------------------------------------------------------------------------- Fetch block infomation. You can get the hash from `fetchTxInfo()`. // Block hash: `79f60880b097ec7dabb81f75f0b52fedf5e922d4f779a11c0c432dcf22c56089` await provider.fetchBlockInfo('79f60880b097ec7dabb81f75f0b52fedf5e922d4f779a11c0c432dcf22c56089') [Fetch Collection Assets](https://meshjs.dev/providers/blockfrost#fetch-collection-assets) ------------------------------------------------------------------------------------------- Fetch a list of assets belonging to a collection by providing its Policy ID. await provider.fetchCollectionAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527') The API will return a list of `assets` and a cursor `next`. If the cursor is not null, you can use it to fetch the next page of results. Here is an example of the response. { "assets": [\ {\ "unit": "d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527",\ "quantity": "1"\ },\ ], "next": 2 } The `fetchCollectionAssets` function also accepts an optional `cursor` parameter to fetch the next page of results. The default value is `1`. await fetchCollectionAssets( policyId: string, cursor = 1 ) [Fetch Handle Address](https://meshjs.dev/providers/blockfrost#fetch-handle-address) ------------------------------------------------------------------------------------- ADA Handle allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. We can resolve the handle's address with `fetchHandleAddress`. // Handle: `meshsdk` await provider.fetchHandleAddress('meshsdk') [Fetch Handle](https://meshjs.dev/providers/blockfrost#fetch-handle) --------------------------------------------------------------------- ADA Handle allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. ADA Handle also released a CIP68 handle and this function will fetch the metadata of the handle. // Handle: `meshsdk` await provider.fetchHandle('meshsdk') [Fetch Protocol Parameters](https://meshjs.dev/providers/blockfrost#fetch-protocol-parameters) ----------------------------------------------------------------------------------------------- Fetch the latest protocol parameters. await provider.fetchProtocolParameters() Optionally, you can provide an epoch number to fetch the protocol parameters of that epoch. [Fetch Transaction Info](https://meshjs.dev/providers/blockfrost#fetch-transaction-info) ----------------------------------------------------------------------------------------- Fetch transaction infomation. Only confirmed transaction can be retrieved. // Transaction hash: `f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159` await provider.fetchTxInfo('f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159') [Fetch UTxOs](https://meshjs.dev/providers/blockfrost#fetch-utxos) ------------------------------------------------------------------- Get UTxOs for a given hash. await provider.fetchUTxOs('dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70') Optionally, you can specify the index of the index output. await provider.fetchUTxOs('hash_here', 0) [Fetch Proposal Info](https://meshjs.dev/providers/blockfrost#fetch-proposal-info) ----------------------------------------------------------------------------------- Get information for a given governance proposal, identified by the txHash and proposal index await provider.fetchGovernanceProposal('372d688faa77e146798b581b322c0f2981a9023764736ade5d12e0e4e796af8c', 0) [Evaluate Transaction](https://meshjs.dev/providers/blockfrost#evaluate-transaction) ------------------------------------------------------------------------------------- `evaluateTx()` accepts an unsigned transaction (`unsignedTx`) and it evaluates the resources required to execute the transaction. Note that, this is only valid for transaction interacting with redeemer (smart contract). By knowing the budget required, you can use this to adjust the redeemer's budget so you don't spend more than you need to execute transactions for this smart contract. const unsignedTx = await tx.build(); const evaluateTx = await provider.evaluateTx(unsignedTx); Example responses from unlocking assets from the always succeed smart contract. [\ {\ "index": 0,\ "tag": "SPEND",\ "budget": {\ "mem": 1700,\ "steps": 368100\ }\ }\ ] With the `mem` and `steps`, you can refine the budget for the redeemer. For example: const redeemer = { data: { alternative: 0, fields: [...] }, budget: { mem: 1700, steps: 368100, }, }; [Submit Transaction](https://meshjs.dev/providers/blockfrost#submit-transaction) --------------------------------------------------------------------------------- Submit a serialized transaction to the network. await provider.submitTx(signedTx); [On Transaction Confirmed](https://meshjs.dev/providers/blockfrost#on-transaction-confirmed) --------------------------------------------------------------------------------------------- Allow you to listen to a transaction confirmation. Upon confirmation, the callback will be called. const tx = new Transaction({ initiator: wallet }); tx.sendLovelace('addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', '5000000'); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); provider.onTxConfirmed(txHash, () => { // Transaction confirmed }); [Providers\ \ Data providers for connecting to the blockchain](https://meshjs.dev/providers) [Hydra Provider (beta)\ \ Layer 2 scaling solution for Cardano that increases transaction throughput and ensures cost efficiency while maintaining security.](https://meshjs.dev/providers/hydra) ### On this page [Get data from URL](https://meshjs.dev/providers/blockfrost#get-data-from-url) [Fetch Account Info](https://meshjs.dev/providers/blockfrost#fetch-account-info) [Fetch Address Assets](https://meshjs.dev/providers/blockfrost#fetch-address-assets) [Fetch Address UTxOs](https://meshjs.dev/providers/blockfrost#fetch-address-utxos) [Fetch Asset Addresses](https://meshjs.dev/providers/blockfrost#fetch-asset-addresses) [Fetch Asset Metadata](https://meshjs.dev/providers/blockfrost#fetch-asset-metadata) [Fetch Block Info](https://meshjs.dev/providers/blockfrost#fetch-block-info) [Fetch Collection Assets](https://meshjs.dev/providers/blockfrost#fetch-collection-assets) [Fetch Handle Address](https://meshjs.dev/providers/blockfrost#fetch-handle-address) [Fetch Handle](https://meshjs.dev/providers/blockfrost#fetch-handle) [Fetch Protocol Parameters](https://meshjs.dev/providers/blockfrost#fetch-protocol-parameters) [Fetch Transaction Info](https://meshjs.dev/providers/blockfrost#fetch-transaction-info) [Fetch UTxOs](https://meshjs.dev/providers/blockfrost#fetch-utxos) [Fetch Proposal Info](https://meshjs.dev/providers/blockfrost#fetch-proposal-info) [Evaluate Transaction](https://meshjs.dev/providers/blockfrost#evaluate-transaction) [Submit Transaction](https://meshjs.dev/providers/blockfrost#submit-transaction) [On Transaction Confirmed](https://meshjs.dev/providers/blockfrost#on-transaction-confirmed) Ask AI --- # Frequently Asked Questions | Mesh SDK [Learn](https://meshjs.dev/resources) Frequently Asked Questions ========================== Common questions and answers about Mesh - the TypeScript SDK for Cardano blockchain development. Copy MarkdownOpen Find answers to common questions about Mesh, the open-source TypeScript SDK for Cardano. [Getting Started](https://meshjs.dev/resources/faq#getting-started) -------------------------------------------------------------------- ### What is MeshJS? ### Why should I use Mesh for Cardano development? ### Is Mesh free to use? ### What are the system requirements? [Installation & Setup](https://meshjs.dev/resources/faq#installation--setup) ----------------------------------------------------------------------------- ### How do I install Mesh? ### Can I use Mesh with Next.js? ### Does Mesh support other frameworks? [Wallets & Integration](https://meshjs.dev/resources/faq#wallets--integration) ------------------------------------------------------------------------------- ### Which Cardano wallets does Mesh support? ### Can I build a wallet application with Mesh? ### How do I connect a wallet in my dApp? [Smart Contracts & Transactions](https://meshjs.dev/resources/faq#smart-contracts--transactions) ------------------------------------------------------------------------------------------------- ### Does Mesh support smart contracts? ### How do I build transactions with Mesh? ### Can I mint NFTs with Mesh? [Development & Debugging](https://meshjs.dev/resources/faq#development--debugging) ----------------------------------------------------------------------------------- ### How do I test my Cardano dApp? ### Where can I find code examples? ### How do I get help if I'm stuck? [Performance & Optimization](https://meshjs.dev/resources/faq#performance--optimization) ----------------------------------------------------------------------------------------- ### Is Mesh suitable for production applications? ### How do I optimize bundle size? ### Does Mesh work offline? [Commercial Use & Contributions](https://meshjs.dev/resources/faq#commercial-use--contributions) ------------------------------------------------------------------------------------------------- ### Can I use Mesh for commercial projects? ### How can I contribute to Mesh? [Still Have Questions?](https://meshjs.dev/resources/faq#still-have-questions) ------------------------------------------------------------------------------- If you can't find the answer you're looking for, please: * Join our [Discord community](https://discord.gg/dH48jH3BKa) * Ask on [GitHub Discussions](https://github.com/MeshJS/mesh/discussions) * Check our comprehensive [documentation](https://meshjs.dev/docs) * Reach out on [Twitter](https://twitter.com/meshsdk) [Developer Resources\ \ Essential tools, communities, and resources for Cardano developers using Mesh SDK.](https://meshjs.dev/resources/developer-resources) ### On this page [Getting Started](https://meshjs.dev/resources/faq#getting-started) [Installation & Setup](https://meshjs.dev/resources/faq#installation--setup) [Wallets & Integration](https://meshjs.dev/resources/faq#wallets--integration) [Smart Contracts & Transactions](https://meshjs.dev/resources/faq#smart-contracts--transactions) [Development & Debugging](https://meshjs.dev/resources/faq#development--debugging) [Performance & Optimization](https://meshjs.dev/resources/faq#performance--optimization) [Commercial Use & Contributions](https://meshjs.dev/resources/faq#commercial-use--contributions) [Still Have Questions?](https://meshjs.dev/resources/faq#still-have-questions) Ask AI --- # Aiken Hello World | Mesh SDK [Learn](https://meshjs.dev/resources) [Guides](https://meshjs.dev/guides) Aiken Hello World ================= Copy MarkdownOpen Aiken is a functional programming language for Cardano smart contract development. It prioritizes on-chain execution and offers a user-friendly approach for building secure and efficient smart contracts. This tutorial walks you through writing a smart contract in Aiken and creating two transactions to lock and unlock assets on the Cardano blockchain. Try the [live demo](https://aiken-template.meshjs.dev/) . View the code on the [GitHub repository](https://github.com/MeshJS/aiken-next-ts-template/tree/main) . [System setup](https://meshjs.dev/guides/aiken#system-setup) ------------------------------------------------------------- Set up your system to compile Aiken smart contracts. Skip this section if you have already set up your system or do not wish to compile the contract. Check the installation instructions on the [Aiken website](https://aiken-lang.org/installation-instructions) for more information. ### [Using aikup (on Linux & MacOS only)](https://meshjs.dev/guides/aiken#using-aikup-on-linux--macos-only-toc) Linux and MacOS users can use the utility tool to download and manage Aiken's pre-compiled executables. Install the Aiken CLI: $ curl -sSfL https://install.aiken-lang.org | bash $ aikup ### [From sources (all platforms)](https://meshjs.dev/guides/aiken#from-sources-all-platforms-toc) Aiken is written in Rust. Install Rust and Cargo to compile the smart contract. Install Rust via the [Rust website](https://www.rust-lang.org/) . Install Cargo, the Rust package manager, via the [Cargo website](https://doc.rust-lang.org/stable/book/ch01-01-installation.html) . Verify installation: $ rustc --version $ cargo --version Install the Aiken CLI: $ cargo install aiken ### [Check your installation](https://meshjs.dev/guides/aiken#check-your-installation-toc) Verify the Aiken CLI installation: $ aiken -V If issues arise, check the [Aiken website](https://aiken-lang.org/installation-instructions) . [Writing a smart contract with Aiken](https://meshjs.dev/guides/aiken#writing-a-smart-contract-with-aiken) ----------------------------------------------------------------------------------------------------------- Write a smart contract in Aiken and create two transactions to lock and unlock assets. Read more about this example on the [Aiken website](https://aiken-lang.org/example--hello-world/basics) . ### [Create a new project](https://meshjs.dev/guides/aiken#create-a-new-project-toc) Create a new project. Refer to [this guide](https://meshjs.dev/guides/nextjs) for creating a new Next.js project. Create a new Aiken project within this project folder: $ aiken meshjs/hello_world $ cd hello_world $ aiken check Run `aiken check` to verify your project. ### [Write the smart contract](https://meshjs.dev/guides/aiken#write-the-smart-contract-toc) Create `validators/hello_world.ak`: use aiken/hash.{Blake2b_224, Hash} use aiken/list use aiken/transaction.{ScriptContext} use aiken/transaction/credential.{VerificationKey} type Datum { owner: Hash, } type Redeemer { msg: ByteArray, } validator { fn hello_world(datum: Datum, redeemer: Redeemer, context: ScriptContext) -> Bool { let must_say_hello = redeemer.msg == "Hello, World!" let must_be_signed = list.has(context.transaction.extra_signatories, datum.owner) must_say_hello && must_be_signed } } This validator checks that the redeemer message is "Hello, World!" and that the transaction is signed by the datum owner. Returns `true` if both conditions are met; otherwise `false`. Compile the smart contract: $ aiken build This generates `plutus.json` in the root folder. This file is a [CIP-0057 Plutus blueprint](https://cips.cardano.org/cip/CIP-57) , describing your on-chain contract and its binary interface. [Creating locking transaction](https://meshjs.dev/guides/aiken#creating-locking-transaction) --------------------------------------------------------------------------------------------- ### [Preparing the frontend](https://meshjs.dev/guides/aiken#preparing-the-frontend-toc) Prepare the frontend to allow users to lock and unlock assets. Install `cbor`: $ npm install cbor Create a `data` folder and copy `plutus.json` into it. Open `pages/index.tsx` and import the packages: import { resolvePlutusScriptAddress, Transaction, KoiosProvider, resolveDataHash, resolvePaymentKeyHash, } from "@meshsdk/core"; import type { PlutusScript, Data } from "@meshsdk/core"; import { CardanoWallet, useWallet } from "@meshsdk/react"; import plutusScript from "../data/plutus.json"; import cbor from "cbor"; ### [Importing the contract](https://meshjs.dev/guides/aiken#importing-the-contract-toc) Import the contract: const script: PlutusScript = { code: cbor .encode(Buffer.from(plutusScript.validators[0].compiledCode, "hex")) .toString("hex"), version: "V2", }; const scriptAddress = resolvePlutusScriptAddress(script, 0); Use `plutus.json` to create the script and `resolvePlutusScriptAddress` to resolve the address. We encode the compiled validator code with cbor because the validator uses a flat format, unlike the format expected by cardano-cli and the serialization library. ### [Locking assets](https://meshjs.dev/guides/aiken#locking-assets-toc) Create the transaction to lock assets: const hash = resolvePaymentKeyHash((await wallet.getUsedAddresses())[0]); const datum: Data = { alternative: 0, fields: [hash], }; const tx = new Transaction({ initiator: wallet }).sendLovelace( { address: scriptAddress, datum: { value: datum }, }, "5000000" ); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); This transaction locks assets. `resolvePaymentKeyHash` resolves the wallet's key hash. `sendLovelace` sends lovelace to the script address. The contract requires the owner's address in the datum. We build, sign, and submit the transaction. [Unlocking assets](https://meshjs.dev/guides/aiken#unlocking-assets) --------------------------------------------------------------------- Create the transaction to unlock assets. Retrieve the UTXO of the locked assets: async function _getAssetUtxo({ scriptAddress, asset, datum }) { const utxos = await koios.fetchAddressUTxOs(scriptAddress, asset); const dataHash = resolveDataHash(datum); let utxo = utxos.find((utxo: any) => { return utxo.output.dataHash == dataHash; }); return utxo; } Create the unlock transaction: const scriptAddress = resolvePlutusScriptAddress(script, 0); const address = (await wallet.getUsedAddresses())[0]; const hash = resolvePaymentKeyHash(address); const datum: Data = { alternative: 0, fields: [hash], }; const assetUtxo = await _getAssetUtxo({ scriptAddress: scriptAddress, asset: "lovelace", datum: datum, }); const redeemer = { data: { alternative: 0, fields: ['Hello, World!'] } }; // create the unlock asset transaction const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datum, redeemer: redeemer, }) .sendValue(address, assetUtxo) .setRequiredSigners([address]); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); This transaction unlocks assets. `resolvePlutusScriptAddress` resolves the script address. `resolvePaymentKeyHash` resolves the wallet's key hash. `_getAssetUtxo` retrieves the locked asset UTXO. `redeemValue` redeems the assets. `sendValue` sends assets to the owner. `setRequiredSigners` sets the required signers. The validator requires "Hello, World!" as the redeemer message. We build, sign, and submit the transaction. Check the full code on [GitHub](https://github.com/MeshJS/aiken-next-ts-template/blob/main/pages/index.tsx) . [Smart Contract Transactions\ \ Previous Page](https://meshjs.dev/guides/smart-contract-transactions) [Executing a standalone script\ \ Next Page](https://meshjs.dev/guides/standalone) ### On this page [System setup](https://meshjs.dev/guides/aiken#system-setup) [Writing a smart contract with Aiken](https://meshjs.dev/guides/aiken#writing-a-smart-contract-with-aiken) [Creating locking transaction](https://meshjs.dev/guides/aiken#creating-locking-transaction) [Unlocking assets](https://meshjs.dev/guides/aiken#unlocking-assets) Ask AI --- # Hydra Provider (beta) | Mesh SDK [Providers](https://meshjs.dev/providers) Hydra Provider (beta) ===================== Layer 2 scaling solution for Cardano that increases transaction throughput and ensures cost efficiency while maintaining security. Copy MarkdownOpen The [Hydra Head protocol](https://hydra.family/head-protocol/) is a layer 2 scaling solution for Cardano rooted in peer-reviewed research that increases transaction throughput and ensures cost efficiency while maintaining rigorous security. Get started: import { HydraProvider } from "@meshsdk/hydra"; // Hydra Head URL and PORT: e.g. http://123.45.67.890:4001 const provider = new HydraProvider({ httpUrl: }); [connect](https://meshjs.dev/providers/hydra#connect) ------------------------------------------------------ Establishes a connection to a Hydra Head. This is typically managed through the HydraProvider.. await provider.connect(); [hydra-head messages](https://meshjs.dev/providers/hydra#hydra-head-messages) ------------------------------------------------------------------------------ Listens to messages from hydra-head provider.onMessage((message) => console.log("messages received from hydra", message) ); can be used together with connect to Receive Messages after connect await provider.connect(); provider.onMessage((message) => console.log("messages received from hydra", message) ); [disconnect](https://meshjs.dev/providers/hydra#disconnect) ------------------------------------------------------------ Closes the active connection to a Hydra Head. This is typically managed through the HydraProvider. Parameter (Optional) * timeout: Specifies the timeout duration in milliseconds. The default timeout is 5 minutes (300,000 ms). // Disconnect with default timeout (5 minutes) await provider.disconnect(); // Disconnect with custom timeout (e.g., 10 minutes) await provider.disconnect(10 * 60 * 1000); [Hydra commands APIs](https://meshjs.dev/providers/hydra#hydra-commands-apis) ------------------------------------------------------------------------------ ### [Initialize](https://meshjs.dev/providers/hydra#initialize) Initializes a new Head. This command is a no-op when a Head is already open and the server will output an `CommandFailed` message should this happen. await provider.init(); ### [Abort](https://meshjs.dev/providers/hydra#abort) Aborts a head before it is opened. This can only be done before all participants have committed. Once opened, the head can't be aborted anymore but it can be closed using: `Close`. await provider.abort(); ### [Commit](https://meshjs.dev/providers/hydra#commit) Commit a particular UTxO to the head. This will make the UTxO available on the layer 2. This is used together with the [`HydraInstance`](https://meshjs.dev/hydra/instance) (see the Hydra Instance page for details). await instance.commitFunds(txHash, outputIndex); ### [New Transaction](https://meshjs.dev/providers/hydra#new-transaction) Submit a transaction through the head. Note that the transaction is only broadcast if well-formed and valid. The `newTx` method accepts the following arguments: **parameters** * cborHex: This is the transaction in hex format usually the unsigned transaction. * type: Any transaction is tried to decode as a 'ConwayEra' transaction, which mostly is backward compatible to previous eras. * description(optional): transaction description **returns** * txId(transaction Hash) async provider.newTx({ cborHex: "", description: "commit tx", type: "Tx ConwayEra", }) Here is an example of how to create a transaction using the Hydra provider, Mesh wallet and Mesh transaction builder: async function makeTx() { const walletA = { addr: "addr_test1vpsthwvxgfkkm2lm8ggy0c5345u6vrfctmug6tdyx4rf4mqn2xcyw", key: "58201aae63d93899640e91b51c5e8bd542262df3ecf3246c3854f39c40f4eb83557d", }; const wallet = new MeshWallet({ networkId: 0, key: { type: "cli", payment: walletA.key, }, fetcher: provider, submitter: provider, }); const pp = await provider.fetchProtocolParameters(); const utxos = await wallet.getUtxos("enterprise"); const changeAddress = walletA.addr; const txBuilder = new MeshTxBuilder({ fetcher: provider, params: pp, verbose: true, }); const unsignedTx = await txBuilder .txOut("addr_test1vpd5axpq4qsh8sxvzny49cp22gc5tqx0djf6wmjv5cx7q5qyrzuw8", [\ { unit: "lovelace", quantity: "3000000" },\ ]) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); console.log("txHash", txHash); } ### [Decommit](https://meshjs.dev/providers/hydra#decommit) Request to decommit a UTxO from a Head by providing a decommit tx. Upon reaching consensus, this will eventually result in corresponding transaction outputs becoming available on the layer 1. The decommit method accepts the following arguments: async decommit({ cborHex: "", description: "commit tx", type: "Tx ConwayEra" }) ### [Close](https://meshjs.dev/providers/hydra#close) Terminate a head with the latest known snapshot. This effectively moves the head from the Open state to the Close state where the contestation phase begin. As a result of closing a head, no more transactions can be submitted via NewTx. await provider.close(); ### [Contest](https://meshjs.dev/providers/hydra#contest) Challenge the latest snapshot announced as a result of a head closure from another participant. Note that this necessarily contest with the latest snapshot known of your local Hydra node. Participants can only contest once. await provider.contest(); ### [Fanout](https://meshjs.dev/providers/hydra#fanout) Finalize a head UTxOs to L1 after the contestation period passed. await provider.fanout(); [Hydra Query APIs](https://meshjs.dev/providers/hydra#hydra-query-apis) ------------------------------------------------------------------------ ### [Fetch UTxOs](https://meshjs.dev/providers/hydra#fetch-utxos) Get UTxOs for a given hash. Optionally, you can specify the index of the index output. await provider.fetchUTxOs("txHash"); ### [Fetch Address UTxOs](https://meshjs.dev/providers/hydra#fetch-address-utxos) Fetch UTxOs controlled by an address. Optionally, you can filter UTXOs containing a particular asset by providing `asset`, where it is the concatenation of policy ID and assetname. await provider.fetchAddressUTxOs(address: string, asset?: string) ### [Fetch Asset Addresses](https://meshjs.dev/providers/hydra#fetch-asset-addresses) Fetches the addresses and quantities for a given Cardano asset. await provider.fetchAssetAddresses(asset: string): ### [Fetch collection Assest](https://meshjs.dev/providers/hydra#fetch-collection-assest) Fetches the list of assets for a given policy ID. await provider.fetchCollectionAssets(policyId: string) ### [Fetch Protocol Parameters](https://meshjs.dev/providers/hydra#fetch-protocol-parameters) Fetch the latest protocol parameters. await provider.fetchProtocolParameters(); Optionally, you can provide an epoch number to fetch the protocol parameters of that epoch.\` ### [Listens for new messages from Hydra node](https://meshjs.dev/providers/hydra#listens-for-new-messages-from-hydra-node) Listens for new messages from Hydra node. The callback function will be called with the message as the only argument. Check [all events emitted](https://hydra.family/head-protocol/api-reference) by the Hydra node. provider.onMessage((message) => { if (message.tag === "Greetings") { console.log("message.snapshotUtxo", message.snapshotUtxo); } }); ### [Submit Transaction](https://meshjs.dev/providers/hydra#submit-transaction) Submit a serialized transaction to the network. const txHash = await provider.submitTx(signedTx); console.log("txHash", txHash); [Blockfrost Provider\ \ Featuring over 100 APIs tailored for easy access to Cardano blockchain](https://meshjs.dev/providers/blockfrost) [Koios Provider\ \ Distributed & open-source public API query layer for Cardano](https://meshjs.dev/providers/koios) ### On this page [connect](https://meshjs.dev/providers/hydra#connect) [hydra-head messages](https://meshjs.dev/providers/hydra#hydra-head-messages) [disconnect](https://meshjs.dev/providers/hydra#disconnect) [Hydra commands APIs](https://meshjs.dev/providers/hydra#hydra-commands-apis) [Initialize](https://meshjs.dev/providers/hydra#initialize) [Abort](https://meshjs.dev/providers/hydra#abort) [Commit](https://meshjs.dev/providers/hydra#commit) [New Transaction](https://meshjs.dev/providers/hydra#new-transaction) [Decommit](https://meshjs.dev/providers/hydra#decommit) [Close](https://meshjs.dev/providers/hydra#close) [Contest](https://meshjs.dev/providers/hydra#contest) [Fanout](https://meshjs.dev/providers/hydra#fanout) [Hydra Query APIs](https://meshjs.dev/providers/hydra#hydra-query-apis) [Fetch UTxOs](https://meshjs.dev/providers/hydra#fetch-utxos) [Fetch Address UTxOs](https://meshjs.dev/providers/hydra#fetch-address-utxos) [Fetch Asset Addresses](https://meshjs.dev/providers/hydra#fetch-asset-addresses) [Fetch collection Assest](https://meshjs.dev/providers/hydra#fetch-collection-assest) [Fetch Protocol Parameters](https://meshjs.dev/providers/hydra#fetch-protocol-parameters) [Listens for new messages from Hydra node](https://meshjs.dev/providers/hydra#listens-for-new-messages-from-hydra-node) [Submit Transaction](https://meshjs.dev/providers/hydra#submit-transaction) Ask AI --- # Maestro Provider | Mesh SDK [Providers](https://meshjs.dev/providers) Maestro Provider ================ Advanced UTxO-indexing data layer to supercharge Defi on Bitcoin, Cardano & Dogecoin Copy MarkdownOpen [Maestro](https://www.gomaestro.org/) is the complete Web3 stack for Cardano which provides among others:- * ⛓️ Enterprise-grade onchain data access. * ⚡️ Transaction monitoring system with submission retires, rollback notifications and accelerated tranaction finality. * 💰 High-fidelity smart contract data feeds from top Cardano DeFi protocols. * 📝 Fully managed smart contract APIs and ready-to-go UI plugins. Get started: import { MaestroProvider } from "@meshsdk/core"; const provider = new MaestroProvider({ network: 'Preprod', // Mainnet / Preprod / Preview apiKey: '', // Get key at https://docs.gomaestro.org/ turboSubmit: false // Read about paid turbo transaction submission feature at https://docs.gomaestro.org }); [Get data from URL](https://meshjs.dev/providers/maestro#get-data-from-url) ---------------------------------------------------------------------------- You can fetch any data from the blockchain by providing the URL path. await provider.get('/addresses/addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9/transactions') [Fetch Account Info](https://meshjs.dev/providers/maestro#fetch-account-info) ------------------------------------------------------------------------------ Obtain information about a specific stake account. await provider.fetchAccountInfo('stake_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n') [Fetch Address Assets](https://meshjs.dev/providers/maestro#fetch-address-assets) ---------------------------------------------------------------------------------- Fetch assets from an address. await provider.fetchAddressAssets( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); [Fetch Address UTxOs](https://meshjs.dev/providers/maestro#fetch-address-utxos) -------------------------------------------------------------------------------- Fetch UTxOs from address await provider.fetchAddressAssets( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); [Fetch assets from address](https://meshjs.dev/providers/maestro#fetch-assets-from-address) -------------------------------------------------------------------------------------------- Fetch assets given an address await provider.fetchAddressAssets( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', ); [Fetch Address UTxOs](https://meshjs.dev/providers/maestro#fetch-address-utxos-1) ---------------------------------------------------------------------------------- Fetch UTxOs controlled by an address. await provider.fetchAddressUTxOs('addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') Optionally, you can filter UTXOs containing a particular asset by providing `asset`, where it is the concatenation of policy ID and asset. await provider.fetchAddressUTxOs( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e' ); [Fetch Asset Addresses](https://meshjs.dev/providers/maestro#fetch-asset-addresses) ------------------------------------------------------------------------------------ Fetch a list of a addresses containing a specific `asset` where it is the concatenation of policy ID and asset. await provider.fetchAssetAddresses('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') [Fetch Asset Metadata](https://meshjs.dev/providers/maestro#fetch-asset-metadata) ---------------------------------------------------------------------------------- Fetch the asset metadata by providing asset's `unit`, which is the concatenation of policy ID and asset name in hex. await provider.fetchAssetMetadata('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') [Fetch Block Info](https://meshjs.dev/providers/maestro#fetch-block-info) -------------------------------------------------------------------------- Fetch block infomation. You can get the hash from `fetchTxInfo()`. await provider.fetchBlockInfo('79f60880b097ec7dabb81f75f0b52fedf5e922d4f779a11c0c432dcf22c56089') [Fetch Collection Assets](https://meshjs.dev/providers/maestro#fetch-collection-assets) ---------------------------------------------------------------------------------------- Fetch a list of assets belonging to a collection by providing its Policy ID. await provider.fetchCollectionAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527') The API will return a list of `assets` and a cursor `next`. If the cursor is not null, you can use it to fetch the next page of results. Here is an example of the response. { "assets": [\ {\ "unit": "d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527",\ "quantity": "1"\ },\ ], "next": 2 } The `fetchCollectionAssets` function also accepts an optional `cursor` parameter to fetch the next page of results. The default value is `1`. await fetchCollectionAssets( policyId: string, cursor = 1 ) [Fetch Handle Address](https://meshjs.dev/providers/maestro#fetch-handle-address) ---------------------------------------------------------------------------------- [ADA Handle](https://handle.me/) allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. We can resolve the handle's address with `fetchHandleAddress`. // Handle: `meshsdk` await provider.fetchHandleAddress('meshsdk') [Fetch Handle](https://meshjs.dev/providers/maestro#fetch-handle) ------------------------------------------------------------------ [ADA Handle](https://handle.me/) allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. ADA Handle also released a CIP68 handle and this function will fetch the metadata of the handle. // Handle: `meshsdk` await provider.fetchHandle('meshsdk') [Fetch Protocol Parameters](https://meshjs.dev/providers/maestro#fetch-protocol-parameters) -------------------------------------------------------------------------------------------- Fetch the latest protocol parameters. await provider.fetchProtocolParameters() Optionally, you can provide an epoch number to fetch the protocol parameters of that epoch. [Fetch Transaction Info](https://meshjs.dev/providers/maestro#fetch-transaction-info) -------------------------------------------------------------------------------------- Fetch transaction infomation. Only confirmed transaction can be retrieved. // Transaction hash f.e. f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159 await provider.fetchTxInfo('f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159') [Fetch UTxOs](https://meshjs.dev/providers/maestro#fetch-utxos) ---------------------------------------------------------------- Get UTxOs for a given hash. await provider.fetchUTxOs('dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70') Optionally, you can specify the index of the index output. await provider.fetchUTxOs('hash_here', 0) [Fetch Proposal Info](https://meshjs.dev/providers/maestro#fetch-proposal-info) -------------------------------------------------------------------------------- Get information for a given governance proposal, identified by the txHash and proposal index // Params: TxHash, CertIndex await provider.fetchGovernanceProposal('372d688faa77e146798b581b322c0f2981a9023764736ade5d12e0e4e796af8c', 0) [Evaluate Transaction](https://meshjs.dev/providers/maestro#evaluate-transaction) ---------------------------------------------------------------------------------- `evaluateTx()` accepts an unsigned transaction (`unsignedTx`) and it evaluates the resources required to execute the transaction. Note that, this is only valid for transaction interacting with redeemer (smart contract). By knowing the budget required, you can use this to adjust the redeemer's budget so you don't spend more than you need to execute transactions for this smart contract. const unsignedTx = await tx.build(); const evaluateTx = await provider.evaluateTx(unsignedTx); Example responses from unlocking assets from the always succeed smart contract. [\ {\ "index": 0,\ "tag": "SPEND",\ "budget": {\ "mem": 1700,\ "steps": 368100\ }\ }\ ] With the `mem` and `steps`, you can refine the budget for the redeemer. For example: const redeemer = { data: { alternative: 0, fields: [...] }, budget: { mem: 1700, steps: 368100, }, }; [Submit Transaction](https://meshjs.dev/providers/maestro#submit-transaction) ------------------------------------------------------------------------------ Submit a serialized transaction to the network. await provider.submitTx(signedTx); [On Transaction Confirmed](https://meshjs.dev/providers/maestro#on-transaction-confirmed) ------------------------------------------------------------------------------------------ Allow you to listen to a transaction confirmation. Upon confirmation, the callback will be called. const tx = new Transaction({ initiator: wallet }); tx.sendLovelace('addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', '5000000'); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); provider.onTxConfirmed(txHash, () => { // Transaction confirmed }); [Koios Provider\ \ Distributed & open-source public API query layer for Cardano](https://meshjs.dev/providers/koios) [Ogmios Provider\ \ Lightweight bridge interface for cardano-node that offers WebSockets API that enables local clients to speak Ouroboros' mini-protocols](https://meshjs.dev/providers/ogmios) ### On this page [Get data from URL](https://meshjs.dev/providers/maestro#get-data-from-url) [Fetch Account Info](https://meshjs.dev/providers/maestro#fetch-account-info) [Fetch Address Assets](https://meshjs.dev/providers/maestro#fetch-address-assets) [Fetch Address UTxOs](https://meshjs.dev/providers/maestro#fetch-address-utxos) [Fetch assets from address](https://meshjs.dev/providers/maestro#fetch-assets-from-address) [Fetch Address UTxOs](https://meshjs.dev/providers/maestro#fetch-address-utxos-1) [Fetch Asset Addresses](https://meshjs.dev/providers/maestro#fetch-asset-addresses) [Fetch Asset Metadata](https://meshjs.dev/providers/maestro#fetch-asset-metadata) [Fetch Block Info](https://meshjs.dev/providers/maestro#fetch-block-info) [Fetch Collection Assets](https://meshjs.dev/providers/maestro#fetch-collection-assets) [Fetch Handle Address](https://meshjs.dev/providers/maestro#fetch-handle-address) [Fetch Handle](https://meshjs.dev/providers/maestro#fetch-handle) [Fetch Protocol Parameters](https://meshjs.dev/providers/maestro#fetch-protocol-parameters) [Fetch Transaction Info](https://meshjs.dev/providers/maestro#fetch-transaction-info) [Fetch UTxOs](https://meshjs.dev/providers/maestro#fetch-utxos) [Fetch Proposal Info](https://meshjs.dev/providers/maestro#fetch-proposal-info) [Evaluate Transaction](https://meshjs.dev/providers/maestro#evaluate-transaction) [Submit Transaction](https://meshjs.dev/providers/maestro#submit-transaction) [On Transaction Confirmed](https://meshjs.dev/providers/maestro#on-transaction-confirmed) Ask AI --- # UTxORPC Provider | Mesh SDK [Providers](https://meshjs.dev/providers) UTxORPC Provider ================ Highly efficient through gRPC, using a compact and high-performance binary format Copy MarkdownOpen Highly efficient through gRPC, using a compact and high-performance binary format The UTxORPC (u5c) provider facilitates access to this state in a standardized and efficient manner through gRPC, using a compact and high-performance binary format. It enables seamless interaction with the Cardano blockchain, to facilitate the creation, signing, and submission of transactions. * Standardized Interface: Implements the UTxORPC specification to ensure compatibility and interoperability across UTxO-based blockchains. * Performance Optimized: Utilizes gRPC for efficient communication with blockchain nodes, minimizing network overhead and message size. * Flexible Provider Options: Suitable for use with hosted services, local nodes like Dolos, or any UTxORPC-compliant service. The following code samples assume that the UTxORPC node is running locally on localhost:50051. If your node is hosted remotely or on a different server, replace "[http://localhost:50051](http://localhost:50051/) " with the appropriate server URL and port for your environment. You can also use the UTxORPC provider with a hosted service like [Demeter.run](https://demeter.run/) . Demeter is a PaaS (Platform-as-a-Service) that provides managed Cardano infrastructure. One of their services consists of a cloud-hosted endpoint for Cardano integration using the UTxO RPC spec. Developers can sign-up and get access to the API on a per-request basis. For more details on configuring your node, refer to the [UTxORPC Ecosystem Servers Documentation](https://github.com/utxorpc/docs/blob/main/pages/servers.md) . import { U5CProvider } from "@meshsdk/core"; const provider = new U5CProvider({ url: "http://localhost:50051", headers: { "dmtr-api-key": "", }, }); [Get data from URL](https://meshjs.dev/providers/utxorpc#get-data-from-url) ---------------------------------------------------------------------------- You can fetch any data from the blockchain by providing the URL path. await provider.get('/addresses/addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9/transactions') [Fetch Account Info](https://meshjs.dev/providers/utxorpc#fetch-account-info) ------------------------------------------------------------------------------ Obtain information about a specific stake account. await provider.fetchAccountInfo('stake_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n') [Fetch Address Assets](https://meshjs.dev/providers/utxorpc#fetch-address-assets) ---------------------------------------------------------------------------------- Fetch assets from an address. await provider.fetchAddressAssets('addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') ### [Fetch Address UTxOs](https://meshjs.dev/providers/utxorpc#fetch-address-utxos-toc) Fetch UTxOs from address await provider.fetchAddressAssets( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); ### [Fetch assets from address](https://meshjs.dev/providers/utxorpc#fetch-assets-from-address-toc) Fetch assets given an address. await provider.fetchAddressAssets( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', ); [Fetch Address UTxOs](https://meshjs.dev/providers/utxorpc#fetch-address-utxos) -------------------------------------------------------------------------------- Fetch UTxOs controlled by an address. await provider.fetchAddressUTxOs('addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') Optionally, you can filter UTXOs containing a particular asset by providing `asset`, where it is the concatenation of policy ID and asset. await fetchAddressUTxOs(address: string, asset?: string) [Fetch Asset Addresses](https://meshjs.dev/providers/utxorpc#fetch-asset-addresses) ------------------------------------------------------------------------------------ Fetch a list of a addresses containing a specific asset where it is the concatenation of policy ID and asset. await provider.fetchAssetAddresses('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') [Fetch Asset Metadata](https://meshjs.dev/providers/utxorpc#fetch-asset-metadata) ---------------------------------------------------------------------------------- Fetch the asset metadata by providing asset's `unit`, which is the concatenation of policy ID and asset name in hex. await provider.fetchAssetMetadata('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') [Fetch Block Info](https://meshjs.dev/providers/utxorpc#fetch-block-info) -------------------------------------------------------------------------- Fetch block infomation. You can get the hash from `fetchTxInfo()`. await provider.fetchBlockInfo('79f60880b097ec7dabb81f75f0b52fedf5e922d4f779a11c0c432dcf22c56089') [Fetch Collection Assets](https://meshjs.dev/providers/utxorpc#fetch-collection-assets) ---------------------------------------------------------------------------------------- Fetch a list of assets belonging to a collection by providing its Policy ID. await provider.fetchCollectionAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527') The API will return a list of `assets` and a cursor `next`. If the cursor is not null, you can use it to fetch the next page of results. Here is an example of the response. { "assets": [\ {\ "unit": "d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527",\ "quantity": "1"\ },\ ], "next": 2 } The `fetchCollectionAssets` function also accepts an optional `cursor` parameter to fetch the next page of results. The default value is `1`. await fetchCollectionAssets( policyId: string, cursor = 1 ) [Fetch Handle Address](https://meshjs.dev/providers/utxorpc#fetch-handle-address) ---------------------------------------------------------------------------------- [ADA Handle](https://handle.me/) allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. We can resolve the handle's address with `fetchHandleAddress`. // Handle: `meshsdk` await provider.fetchHandleAddress('meshsdk') [Fetch Handle](https://meshjs.dev/providers/utxorpc#fetch-handle) ------------------------------------------------------------------ [ADA Handle](https://handle.me/) allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. ADA Handle also released a CIP68 handle and this function will fetch the metadata of the handle. // Handle: `meshsdk` await provider.fetchHandle('meshsdk') ### [Fetch Protocol Parameters](https://meshjs.dev/providers/utxorpc#fetch-protocol-parameters) Fetch the latest protocol parameters. await provider.fetchProtocolParameters() Optionally, you can provide an epoch number to fetch the protocol parameters of that epoch. [Fetch Transaction Info](https://meshjs.dev/providers/utxorpc#fetch-transaction-info) -------------------------------------------------------------------------------------- Fetch transaction infomation. Only confirmed transaction can be retrieved. await provider.fetchTxInfo('f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159') [Fetch UTxOs](https://meshjs.dev/providers/utxorpc#fetch-utxos) ---------------------------------------------------------------- Get UTxOs for a given hash. // Hash f.e. dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70 await provider.fetchUTxOs('dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70') Optionally, you can specify the index of the index output. await provider.fetchUTxOs('hash_here', 0) [Fetch Proposal Info](https://meshjs.dev/providers/utxorpc#fetch-proposal-info) -------------------------------------------------------------------------------- Get information for a given governance proposal, identified by the txHash and proposal index await provider.fetchGovernanceProposal('372d688faa77e146798b581b322c0f2981a9023764736ade5d12e0e4e796af8c', 0) [Evaluate Transaction](https://meshjs.dev/providers/utxorpc#evaluate-transaction) ---------------------------------------------------------------------------------- `evaluateTx()` accepts an unsigned transaction (`unsignedTx`) and it evaluates the resources required to execute the transaction. Note that, this is only valid for transaction interacting with redeemer (smart contract). By knowing the budget required, you can use this to adjust the redeemer's budget so you don't spend more than you need to execute transactions for this smart contract. const unsignedTx = await tx.build(); const evaluateTx = await provider.evaluateTx(unsignedTx); Example responses from unlocking assets from the always succeed smart contract. [\ {\ "index": 0,\ "tag": "SPEND",\ "budget": {\ "mem": 1700,\ "steps": 368100\ }\ }\ ] With the `mem` and `steps`, you can refine the budget for the redeemer. For example: const redeemer = { data: { alternative: 0, fields: [...] }, budget: { mem: 1700, steps: 368100, }, }; [Submit Transaction](https://meshjs.dev/providers/utxorpc#submit-transaction) ------------------------------------------------------------------------------ Submit a serialized transaction to the network. await provider.submitTx(signedTx); [On Transaction Confirmed](https://meshjs.dev/providers/utxorpc#on-transaction-confirmed) ------------------------------------------------------------------------------------------ Allow you to listen to a transaction confirmation. Upon confirmation, the callback will be called. const tx = new Transaction({ initiator: wallet }); tx.sendLovelace('addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', '5000000'); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); provider.onTxConfirmed(txHash, () => { // Transaction confirmed }); [Ogmios Provider\ \ Lightweight bridge interface for cardano-node that offers WebSockets API that enables local clients to speak Ouroboros' mini-protocols](https://meshjs.dev/providers/ogmios) [Yaci Provider\ \ Custom Cardano devnet to tailor your devnet needs with a builtin indexer and custom viewer for devnet](https://meshjs.dev/providers/yaci) ### On this page [Get data from URL](https://meshjs.dev/providers/utxorpc#get-data-from-url) [Fetch Account Info](https://meshjs.dev/providers/utxorpc#fetch-account-info) [Fetch Address Assets](https://meshjs.dev/providers/utxorpc#fetch-address-assets) [Fetch Address UTxOs](https://meshjs.dev/providers/utxorpc#fetch-address-utxos) [Fetch Asset Addresses](https://meshjs.dev/providers/utxorpc#fetch-asset-addresses) [Fetch Asset Metadata](https://meshjs.dev/providers/utxorpc#fetch-asset-metadata) [Fetch Block Info](https://meshjs.dev/providers/utxorpc#fetch-block-info) [Fetch Collection Assets](https://meshjs.dev/providers/utxorpc#fetch-collection-assets) [Fetch Handle Address](https://meshjs.dev/providers/utxorpc#fetch-handle-address) [Fetch Handle](https://meshjs.dev/providers/utxorpc#fetch-handle) [Fetch Protocol Parameters](https://meshjs.dev/providers/utxorpc#fetch-protocol-parameters) [Fetch Transaction Info](https://meshjs.dev/providers/utxorpc#fetch-transaction-info) [Fetch UTxOs](https://meshjs.dev/providers/utxorpc#fetch-utxos) [Fetch Proposal Info](https://meshjs.dev/providers/utxorpc#fetch-proposal-info) [Evaluate Transaction](https://meshjs.dev/providers/utxorpc#evaluate-transaction) [Submit Transaction](https://meshjs.dev/providers/utxorpc#submit-transaction) [On Transaction Confirmed](https://meshjs.dev/providers/utxorpc#on-transaction-confirmed) Ask AI --- # OfflineFetcher | Mesh SDK [Providers](https://meshjs.dev/providers) OfflineFetcher ============== An offline blockchain data provider for testing, development and offline scenarios. Copy MarkdownOpen The OfflineFetcher provides access to blockchain data without requiring network connectivity. It's ideal for testing, development, and scenarios where you need to work with pre-loaded blockchain data offline. Initialize the fetcher: import { OfflineFetcher } from "@meshsdk/core"; // Create a new instance const fetcher = new OfflineFetcher(); // Create with specified network const fetcherWithNetwork = new OfflineFetcher("mainnet"); Before you can fetch data, you need to add it to the fetcher. Here are examples of adding different types of blockchain data: // Add account information fetcher.addAccount("addr1...", { balance: "1000000", rewards: "500000", withdrawals: "100000", poolId: "pool1..." // optional }); // Add UTXOs fetcher.addUTxOs([\ {\ input: {\ txHash: "1234...",\ outputIndex: 0\ },\ output: {\ address: "addr1...",\ amount: [{ unit: "lovelace", quantity: "1000000" }],\ // Optional fields for script UTXOs:\ scriptHash: "abcd...",\ dataHash: "ef12...",\ plutusData: "...",\ scriptRef: "..."\ }\ }\ ]); // Add asset addresses fetcher.addAssetAddresses("policyID.assetName", [\ { address: "addr1...", quantity: "1" }\ ]); // Add asset metadata fetcher.addAssetMetadata("policyID.assetName", { name: "Asset Name", image: "ipfs://...", // Any other metadata attributes }); // Add protocol parameters fetcher.addProtocolParameters({ epoch: 290, minFeeA: 44, minFeeB: 155381, maxBlockSize: 73728, maxTxSize: 16384, maxBlockHeaderSize: 1100, keyDeposit: 2000000, poolDeposit: 500000000, minPoolCost: "340000000", // Other parameters... }); // Add serilized transaction fetcher.addSerializedTransaction("txHash"); The fetcher's state can be saved and loaded, making it easy to persist data between sessions: // Save state const state = fetcher.toJSON(); localStorage.setItem('fetcher-state', state); // Load state const savedState = localStorage.getItem('fetcher-state'); const fetcher = OfflineFetcher.fromJSON(savedState); Once data is added, you can use the fetch\* methods just like with other providers such as [BlockfrostProvider](https://meshjs.dev/providers/blockfrost) . This makes OfflineFetcher a drop-in replacement for testing and offline scenarios. [Get data from URL](https://meshjs.dev/providers/offline-fetcher#get-data-from-url) ------------------------------------------------------------------------------------ You can fetch any data from the blockchain by providing the URL path. // Params: URL await provider.get('/addresses/addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9/transactions') [Fetch Account Info](https://meshjs.dev/providers/offline-fetcher#fetch-account-info) -------------------------------------------------------------------------------------- Obtain information about a specific stake account. // Params: Stake Address await provider.fetchAccountInfo('stake_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n') [Fetch Address Assets](https://meshjs.dev/providers/offline-fetcher#fetch-address-assets) ------------------------------------------------------------------------------------------ Fetch assets from an address. // Params: Address await provider.fetchAddressAssets('addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') ### [Fetch Address UTxOs](https://meshjs.dev/providers/offline-fetcher#fetch-address-utxos-toc) Fetch UTxOs from address await provider.fetchAddressAssets( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); ### [Fetch assets from address](https://meshjs.dev/providers/offline-fetcher#fetch-assets-from-address-toc) Fetch assets given an address await provider.fetchAddressAssets( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', ); [Fetch Address UTxOs](https://meshjs.dev/providers/offline-fetcher#fetch-address-utxos) ---------------------------------------------------------------------------------------- Fetch UTxOs controlled by an address. // Params: Address await provider.fetchAddressUTxOs('addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') Optionally, you can filter UTXOs containing a particular asset by providing `asset`, where it is the concatenation of policy ID and asset. await fetchAddressUTxOs(address: string, asset?: string) ### [Fetch Address UTxOs](https://meshjs.dev/providers/offline-fetcher#fetch-address-utxos-toc-1) Fetch UTxOs from address await provider.fetchAddressUTxOs( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); ### [Fetch UTxOs with Asset](https://meshjs.dev/providers/offline-fetcher#fetch-utxos-with-asset-toc) Fetch UTxOs from address with asset await provider.fetchAddressUTxOs( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e' ); [Fetch Asset Addresses](https://meshjs.dev/providers/offline-fetcher#fetch-asset-addresses) -------------------------------------------------------------------------------------------- Fetch a list of a addresses containing a specific asset where it is the concatenation of policy ID and asset. // Params: Asset Unit await provider.fetchAssetAddresses('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') [Fetch Asset Metadata](https://meshjs.dev/providers/offline-fetcher#fetch-asset-metadata) ------------------------------------------------------------------------------------------ Fetch the asset metadata by providing asset's `unit`, which is the concatenation of policy ID and asset name in hex. // Params: Asset Unit await provider.fetchAssetMetadata('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') [Fetch Block Info](https://meshjs.dev/providers/offline-fetcher#fetch-block-info) ---------------------------------------------------------------------------------- Fetch block infomation. You can get the hash from `fetchTxInfo()`. // Params: Block hash await provider.fetchBlockInfo('79f60880b097ec7dabb81f75f0b52fedf5e922d4f779a11c0c432dcf22c56089') [Fetch Collection Assets](https://meshjs.dev/providers/offline-fetcher#fetch-collection-assets) ------------------------------------------------------------------------------------------------ Fetch a list of assets belonging to a collection by providing its Policy ID. await provider.fetchCollectionAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527') The API will return a list of `assets` and a cursor `next`. If the cursor is not null, you can use it to fetch the next page of results. Here is an example of the response. { "assets": [\ {\ "unit": "d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527",\ "quantity": "1"\ },\ ], "next": 2 } The `fetchCollectionAssets` function also accepts an optional `cursor` parameter to fetch the next page of results. The default value is `1`. await fetchCollectionAssets( policyId: string, cursor = 1 ) [Fetch Handle Address](https://meshjs.dev/providers/offline-fetcher#fetch-handle-address) ------------------------------------------------------------------------------------------ [ADA Handle](https://handle.me/) allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. We can resolve the handle's address with `fetchHandleAddress`. // Params: Handle await provider.fetchHandleAddress('meshsdk') [Fetch Handle](https://meshjs.dev/providers/offline-fetcher#fetch-handle) -------------------------------------------------------------------------- [ADA Handle](https://handle.me/) allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. ADA Handle also released a CIP68 handle and this function will fetch the metadata of the handle. // Params: Handle await provider.fetchHandle('meshsdk') [Fetch Protocol Parameters](https://meshjs.dev/providers/offline-fetcher#fetch-protocol-parameters) ---------------------------------------------------------------------------------------------------- Fetch the latest protocol parameters. await provider.fetchProtocolParameters() Optionally, you can provide an epoch number to fetch the protocol parameters of that epoch. [Fetch Transaction Info](https://meshjs.dev/providers/offline-fetcher#fetch-transaction-info) ---------------------------------------------------------------------------------------------- Fetch transaction infomation. Only confirmed transaction can be retrieved. await provider.fetchTxInfo('f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159') [Fetch UTxOs](https://meshjs.dev/providers/offline-fetcher#fetch-utxos) ------------------------------------------------------------------------ Get UTxOs for a given hash. // Params: Hash await provider.fetchUTxOs('dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70') Optionally, you can specify the index of the index output. await provider.fetchUTxOs('hash_here', 0) [Fetch Proposal Info](https://meshjs.dev/providers/offline-fetcher#fetch-proposal-info) ---------------------------------------------------------------------------------------- Get information for a given governance proposal, identified by the txHash and proposal index // Params: TxHash, CertIndex await provider.fetchGovernanceProposal('372d688faa77e146798b581b322c0f2981a9023764736ade5d12e0e4e796af8c', 0) [Yaci Provider\ \ Custom Cardano devnet to tailor your devnet needs with a builtin indexer and custom viewer for devnet](https://meshjs.dev/providers/yaci) [Offline Evaluator\ \ An offline Plutus script evaluator for testing and validation.](https://meshjs.dev/providers/offline-evaluator) ### On this page [Get data from URL](https://meshjs.dev/providers/offline-fetcher#get-data-from-url) [Fetch Account Info](https://meshjs.dev/providers/offline-fetcher#fetch-account-info) [Fetch Address Assets](https://meshjs.dev/providers/offline-fetcher#fetch-address-assets) [Fetch Address UTxOs](https://meshjs.dev/providers/offline-fetcher#fetch-address-utxos) [Fetch Asset Addresses](https://meshjs.dev/providers/offline-fetcher#fetch-asset-addresses) [Fetch Asset Metadata](https://meshjs.dev/providers/offline-fetcher#fetch-asset-metadata) [Fetch Block Info](https://meshjs.dev/providers/offline-fetcher#fetch-block-info) [Fetch Collection Assets](https://meshjs.dev/providers/offline-fetcher#fetch-collection-assets) [Fetch Handle Address](https://meshjs.dev/providers/offline-fetcher#fetch-handle-address) [Fetch Handle](https://meshjs.dev/providers/offline-fetcher#fetch-handle) [Fetch Protocol Parameters](https://meshjs.dev/providers/offline-fetcher#fetch-protocol-parameters) [Fetch Transaction Info](https://meshjs.dev/providers/offline-fetcher#fetch-transaction-info) [Fetch UTxOs](https://meshjs.dev/providers/offline-fetcher#fetch-utxos) [Fetch Proposal Info](https://meshjs.dev/providers/offline-fetcher#fetch-proposal-info) Ask AI --- # Utilities | Mesh SDK Utilities ========= Serializers, resolvers and data types for converting between different formats. Copy MarkdownOpen [Serializers\ \ Encode objects into CBOR or bech32 format.](https://meshjs.dev/apis/utilities/serializers) [Deserializers\ \ Parse CBOR or bech32 into objects.](https://meshjs.dev/apis/utilities/deserializers) [Resolvers\ \ Converts between different formats.](https://meshjs.dev/apis/utilities/resolvers) [Data\ \ Useful utilities to parse and manipulate data](https://meshjs.dev/apis/data) [Blueprints\ \ Blueprints for script with either apply parameters or no parameters](https://meshjs.dev/apis/utilities/blueprints) [Offline Evaluator\ \ An offline Plutus script evaluator for testing and validation.](https://meshjs.dev/providers/offline-evaluator) [Serializers\ \ Encode objects into CBOR or bech32 format.](https://meshjs.dev/apis/utilities/serializers) Ask AI --- # Transaction Builder | Mesh SDK Transaction Builder =================== Build transactions with Cardano-CLI like APIs Copy MarkdownOpen [Transaction Basics\ \ Working with transactions and its various options](https://meshjs.dev/apis/txbuilder/basics) [Mint and Burn Assets\ \ Minting and burning assets with Native Script and Plutus Script](https://meshjs.dev/apis/txbuilder/minting) [Smart Contracts\ \ Transactions to work with smart contracts](https://meshjs.dev/apis/txbuilder/smart-contract) [Staking Transactions\ \ Transactions for delegating ADA and managing stakepools](https://meshjs.dev/apis/txbuilder/staking) [Governance Transactions\ \ Transactions for participating in Cardano's on-chain governance](https://meshjs.dev/apis/txbuilder/governance) [Mesh Wallet\ \ Mesh Wallet provides a set of APIs to interact with the blockchain. This wallet is compatible with Mesh transaction builders.](https://meshjs.dev/apis/wallets/meshwallet) [Transaction Basics\ \ Working with transactions and its various options](https://meshjs.dev/apis/txbuilder/basics) Ask AI --- # Use Cases & Showcases | Mesh SDK [Learn](https://meshjs.dev/resources) Use Cases & Showcases ===================== Discover real-world applications and projects built with Mesh - from DeFi platforms to NFT marketplaces and enterprise solutions on Cardano. Copy MarkdownOpen Discover how developers and organizations are using Mesh to build innovative Cardano applications. From DeFi platforms to NFT marketplaces, Mesh powers a wide range of blockchain solutions. [DeFi Applications](https://meshjs.dev/resources/use-cases#defi-applications) ------------------------------------------------------------------------------ ### [Decentralized Exchanges (DEX)](https://meshjs.dev/resources/use-cases#decentralized-exchanges-dex) Mesh provides the perfect foundation for building decentralized exchanges on Cardano: * **Automated Market Makers (AMM)**: Build liquidity pools and swap mechanisms with Mesh's transaction builder * **Order Book DEXs**: Manage complex order matching with smart contract integration * **Multi-Asset Swaps**: Handle native token exchanges with ease **Key Features Used:** * Transaction building APIs * Multi-asset handling * Smart contract integration * Wallet connections ### [Lending Protocols](https://meshjs.dev/resources/use-cases#lending-protocols) Create secure lending and borrowing platforms: * **Collateral Management**: Lock and release assets with smart contracts * **Interest Calculations**: Automated interest accrual and distribution * **Liquidation Mechanisms**: Monitor and execute collateral liquidations **Real-World Example:** Lending protocols use Mesh to handle complex multi-party transactions, ensuring secure collateral locks and automated interest payments through Plutus smart contracts. ### [Staking Platforms](https://meshjs.dev/resources/use-cases#staking-platforms) Build custom staking solutions: * **Stake Pool Delegation**: Simplified delegation interfaces * **Rewards Distribution**: Automated reward calculations and distributions * **Multi-Pool Support**: Manage delegations across multiple pools [NFT Marketplaces](https://meshjs.dev/resources/use-cases#nft-marketplaces) ---------------------------------------------------------------------------- ### [NFT Minting Platforms](https://meshjs.dev/resources/use-cases#nft-minting-platforms) Mesh simplifies NFT creation and distribution: * **Single NFT Minting**: Easy one-off NFT creation * **Collection Launches**: Batch minting for entire collections * **Generative Art**: Create unique combinations programmatically * **Metadata Management**: CIP-25 and CIP-68 compliance **Implementation tip:** For minting NFTs in your own project, use the modern `MeshTxBuilder` APIs shown in the [Mint and Burn Assets guide](https://meshjs.dev/apis/txbuilder/minting) rather than the legacy `Transaction` class. ### [Secondary Marketplaces](https://meshjs.dev/resources/use-cases#secondary-marketplaces) Power NFT trading platforms with Mesh: * **Listing Management**: List and delist NFTs for sale * **Bidding Systems**: Implement auction mechanisms * **Instant Purchases**: Enable direct NFT purchases * **Royalty Enforcement**: Automated creator royalty distributions **Key Features:** * Smart contract escrow * Multi-signature support * Metadata resolution * Price oracles integration [Wallet Applications](https://meshjs.dev/resources/use-cases#wallet-applications) ---------------------------------------------------------------------------------- ### [Browser Extension Wallets](https://meshjs.dev/resources/use-cases#browser-extension-wallets) Build feature-rich Cardano wallets: * **Key Management**: Secure mnemonic and key storage * **Transaction Signing**: Sign and submit transactions * **dApp Connector**: CIP-30 compliance for dApp integration * **Multi-Account Support**: Manage multiple addresses ### [Hardware Wallet Integration](https://meshjs.dev/resources/use-cases#hardware-wallet-integration) Integrate with hardware wallets for enhanced security: * **Ledger Support**: Connect with Ledger devices * **Trezor Integration**: Support for Trezor hardware wallets * **Air-Gapped Signing**: Build offline transaction signing flows [Gaming & Metaverse](https://meshjs.dev/resources/use-cases#gaming--metaverse) ------------------------------------------------------------------------------- ### [Blockchain Games](https://meshjs.dev/resources/use-cases#blockchain-games) Create engaging gaming experiences on Cardano: * **In-Game Assets**: Represent items as NFTs * **Play-to-Earn**: Token rewards and economies * **Character NFTs**: Unique, tradeable characters * **Land Ownership**: Virtual real estate on-chain **Use Case Example:** A trading card game uses Mesh to handle card minting, trading between players, and tournament rewards distribution, all with seamless wallet integration. ### [Virtual Worlds](https://meshjs.dev/resources/use-cases#virtual-worlds) Build metaverse platforms: * **Land Parcels**: NFT-based land ownership * **Avatar Systems**: Customizable NFT avatars * **Virtual Economies**: In-world token systems * **Social Features**: Decentralized identity and messaging [Enterprise Solutions](https://meshjs.dev/resources/use-cases#enterprise-solutions) ------------------------------------------------------------------------------------ ### [Supply Chain Tracking](https://meshjs.dev/resources/use-cases#supply-chain-tracking) Implement transparent supply chain management: * **Asset Tracking**: Record product journey on-chain * **Authenticity Verification**: Prove product origin * **Smart Contracts**: Automated fulfillment conditions * **Multi-Party Workflows**: Coordinate between stakeholders **Real-World Application:** Track luxury goods from manufacturer to customer, with each transfer recorded on Cardano using Mesh, ensuring authenticity and preventing counterfeits. ### [Identity Verification](https://meshjs.dev/resources/use-cases#identity-verification) Build decentralized identity solutions: * **KYC/AML**: Store verified credentials on-chain * **Age Verification**: Prove age without revealing birthdate * **Professional Credentials**: Verifiable certifications * **Access Control**: Token-gated content and services ### [Voting & Governance](https://meshjs.dev/resources/use-cases#voting--governance) Create transparent governance systems: * **DAO Governance**: Token-weighted voting * **Proposal Systems**: Submit and vote on proposals * **Quadratic Voting**: Fair voting mechanisms * **Election Systems**: Verifiable public elections [Developer Tools](https://meshjs.dev/resources/use-cases#developer-tools) -------------------------------------------------------------------------- ### [Block Explorers](https://meshjs.dev/resources/use-cases#block-explorers) Build custom blockchain explorers: * **Transaction Search**: Query and display transaction history * **Address Monitoring**: Track address activity * **Smart Contract Viewers**: Inspect contract state * **Analytics Dashboards**: Blockchain statistics and metrics ### [API Services](https://meshjs.dev/resources/use-cases#api-services) Create Cardano API platforms: * **Data Providers**: Serve blockchain data to applications * **Webhook Services**: Real-time blockchain event notifications * **Query Interfaces**: GraphQL/REST APIs for Cardano data * **Historical Data**: Archive and serve historical blockchain data [Education & Research](https://meshjs.dev/resources/use-cases#education--research) ----------------------------------------------------------------------------------- ### [Learning Platforms](https://meshjs.dev/resources/use-cases#learning-platforms) Build educational tools for Cardano: * **Interactive Tutorials**: Hands-on Cardano development lessons * **Sandbox Environments**: Safe spaces to experiment * **Code Playgrounds**: Browser-based Cardano coding * **Certification Systems**: Issue blockchain certificates ### [Research Tools](https://meshjs.dev/resources/use-cases#research-tools) Enable blockchain research: * **Data Analysis**: Extract and analyze blockchain data * **Simulation Tools**: Model economic scenarios * **Testing Frameworks**: Automated smart contract testing * **Network Monitoring**: Track network health and performance [Social & Community](https://meshjs.dev/resources/use-cases#social--community) ------------------------------------------------------------------------------- ### [Social Platforms](https://meshjs.dev/resources/use-cases#social-platforms) Build Web3 social networks: * **Token-Gated Communities**: Access based on NFT/token ownership * **Creator Platforms**: Content monetization with NFTs * **Tipping Systems**: Microtransactions for content creators * **Decentralized Social Graphs**: On-chain social connections ### [Fundraising Platforms](https://meshjs.dev/resources/use-cases#fundraising-platforms) Create transparent fundraising solutions: * **Crowdfunding**: Decentralized campaign management * **Charity Platforms**: Transparent donation tracking * **Investment DAOs**: Collective investment vehicles * **Grant Programs**: Automated grant distribution [Real-World Success Metrics](https://meshjs.dev/resources/use-cases#real-world-success-metrics) ------------------------------------------------------------------------------------------------ Projects built with Mesh have achieved: * 📈 **Millions in Transaction Volume**: DeFi platforms processing substantial daily volumes * 🎨 **Thousands of NFTs Minted**: Successful collections with sell-outs * 👥 **Large User Bases**: Wallets and dApps with tens of thousands of users * ⚡ **Fast Performance**: Applications maintaining sub-second response times * 🔒 **Zero Security Incidents**: Secure smart contract implementations [Building Your Own?](https://meshjs.dev/resources/use-cases#building-your-own) ------------------------------------------------------------------------------- Ready to create your own Cardano application with Mesh? * **Start with [Guides](https://meshjs.dev/guides) **: Step-by-step tutorials for common use cases * **Explore [API Documentation](https://meshjs.dev/apis) **: Complete reference for all Mesh features * **Join [Community](https://discord.gg/dH48jH3BKa) **: Get help from other builders * **View [Examples](https://github.com/MeshJS/examples) **: Working code samples [Submit Your Project](https://meshjs.dev/resources/use-cases#submit-your-project) ---------------------------------------------------------------------------------- Built something awesome with Mesh? We'd love to feature it! Share your project: * Discord: Join our showcase channel * Twitter: Tag [@meshsdk](https://twitter.com/meshsdk) * GitHub: Add to our [ecosystem list](https://github.com/MeshJS/mesh) [Tutorials\ \ Step-by-step tutorials for building Cardano applications with Mesh SDK - from beginner to advanced.](https://meshjs.dev/resources/tutorials) [Developer Resources\ \ Essential tools, communities, and resources for Cardano developers using Mesh SDK.](https://meshjs.dev/resources/developer-resources) ### On this page [DeFi Applications](https://meshjs.dev/resources/use-cases#defi-applications) [Decentralized Exchanges (DEX)](https://meshjs.dev/resources/use-cases#decentralized-exchanges-dex) [Lending Protocols](https://meshjs.dev/resources/use-cases#lending-protocols) [Staking Platforms](https://meshjs.dev/resources/use-cases#staking-platforms) [NFT Marketplaces](https://meshjs.dev/resources/use-cases#nft-marketplaces) [NFT Minting Platforms](https://meshjs.dev/resources/use-cases#nft-minting-platforms) [Secondary Marketplaces](https://meshjs.dev/resources/use-cases#secondary-marketplaces) [Wallet Applications](https://meshjs.dev/resources/use-cases#wallet-applications) [Browser Extension Wallets](https://meshjs.dev/resources/use-cases#browser-extension-wallets) [Hardware Wallet Integration](https://meshjs.dev/resources/use-cases#hardware-wallet-integration) [Gaming & Metaverse](https://meshjs.dev/resources/use-cases#gaming--metaverse) [Blockchain Games](https://meshjs.dev/resources/use-cases#blockchain-games) [Virtual Worlds](https://meshjs.dev/resources/use-cases#virtual-worlds) [Enterprise Solutions](https://meshjs.dev/resources/use-cases#enterprise-solutions) [Supply Chain Tracking](https://meshjs.dev/resources/use-cases#supply-chain-tracking) [Identity Verification](https://meshjs.dev/resources/use-cases#identity-verification) [Voting & Governance](https://meshjs.dev/resources/use-cases#voting--governance) [Developer Tools](https://meshjs.dev/resources/use-cases#developer-tools) [Block Explorers](https://meshjs.dev/resources/use-cases#block-explorers) [API Services](https://meshjs.dev/resources/use-cases#api-services) [Education & Research](https://meshjs.dev/resources/use-cases#education--research) [Learning Platforms](https://meshjs.dev/resources/use-cases#learning-platforms) [Research Tools](https://meshjs.dev/resources/use-cases#research-tools) [Social & Community](https://meshjs.dev/resources/use-cases#social--community) [Social Platforms](https://meshjs.dev/resources/use-cases#social-platforms) [Fundraising Platforms](https://meshjs.dev/resources/use-cases#fundraising-platforms) [Real-World Success Metrics](https://meshjs.dev/resources/use-cases#real-world-success-metrics) [Building Your Own?](https://meshjs.dev/resources/use-cases#building-your-own) [Submit Your Project](https://meshjs.dev/resources/use-cases#submit-your-project) Ask AI --- # Overview | Mesh SDK [Midnight](https://meshjs.dev/midnight) Midnight Setup Overview ======== Complete development setup for building Midnight Network dApps Copy MarkdownOpen [Getting Started\ \ Install and set up @meshsdk/midnight-setup for building zero-knowledge privacy dApps](https://meshjs.dev/midnight/midnight-setup/getting-started) [Core API Methods\ \ Complete reference for MidnightSetupAPI methods and provider setup](https://meshjs.dev/midnight/midnight-setup/api) [Lace Wallet Integration\ \ Complete guide for integrating Lace Beta Wallet with Midnight Network dApps](https://meshjs.dev/midnight/midnight-setup/wallet) [Integration Examples\ \ React hooks, contract management, and complete dApp examples for Midnight Network](https://meshjs.dev/midnight/midnight-setup/examples) [Midnight\ \ Zero-knowledge privacy network for Cardano](https://meshjs.dev/midnight) [Getting Started\ \ Install and set up @meshsdk/midnight-setup for building zero-knowledge privacy dApps on Midnight Network](https://meshjs.dev/midnight/midnight-setup/getting-started) Ask AI --- # Deserializers | Mesh SDK [Utilities](https://meshjs.dev/apis/utilities) Deserializers ============= Parse CBOR or bech32 into objects Copy MarkdownOpen [Deserialize Address](https://meshjs.dev/apis/utilities/deserializers#deserialize-address) ------------------------------------------------------------------------------------------- Deserialize bech32 address into payment and staking parts, with visibility of whether they are script or key hash. ### [Deserialize Address](https://meshjs.dev/apis/utilities/deserializers#deserialize-address-toc) Convert bech32 address to The deserialized address object **Address:** `addr_test1qpvx0...93swx9` deserializeAddress('addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9'); [Deserialize Datum](https://meshjs.dev/apis/utilities/deserializers#deserialize-datum) --------------------------------------------------------------------------------------- Deserialize a datum from a CBOR string to JSON object. ### [Deserialize Datum](https://meshjs.dev/apis/utilities/deserializers#deserialize-datum-toc) Deserialize a datum from a CBOR string to JSON object **Datum** `167a4a048d87fcee0425ed200615ff2356f472c6413472c6106b8c5da52e3fd0` deserializeDatum('167a4a048d87fcee0425ed200615ff2356f472c6413472c6106b8c5da52e3fd0'); [Deserialize Pool Id](https://meshjs.dev/apis/utilities/deserializers#deserialize-pool-id) ------------------------------------------------------------------------------------------- Deserialize a script from a pool id to Ed25519 key hash. ### [Deserialize Pool Id](https://meshjs.dev/apis/utilities/deserializers#deserialize-pool-id-toc) Deserialize a script from a pool id to Ed25519 key hash **Pool Id** `pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx` deserializePoolId('pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx'); [Serializers\ \ Encode objects into CBOR or bech32 format.](https://meshjs.dev/apis/utilities/serializers) [Resolvers\ \ Converts between different formats.](https://meshjs.dev/apis/utilities/resolvers) ### On this page [Deserialize Address](https://meshjs.dev/apis/utilities/deserializers#deserialize-address) [Deserialize Datum](https://meshjs.dev/apis/utilities/deserializers#deserialize-datum) [Deserialize Pool Id](https://meshjs.dev/apis/utilities/deserializers#deserialize-pool-id) Ask AI --- # Installation | Mesh SDK [Midnight](https://meshjs.dev/midnight) Midnight Contracts Wizard Installation ============ How to use the Midnight Contracts Wizard CLI tool Copy MarkdownOpen The Midnight Contracts Wizard is a CLI tool that you can run directly using `npx`. No installation required! [Using npx (Recommended)](https://meshjs.dev/midnight/midnight-contracts-wizard/installation#using-npx-recommended) -------------------------------------------------------------------------------------------------------------------- Run the wizard directly without installing: npx @meshsdk/midnight-contracts-wizard This command will: * Download the latest version automatically * Run the interactive wizard * Create your project with selected contracts [Check Version](https://meshjs.dev/midnight/midnight-contracts-wizard/installation#check-version) -------------------------------------------------------------------------------------------------- You can check the latest version available: npx @meshsdk/midnight-contracts-wizard --version [Requirements](https://meshjs.dev/midnight/midnight-contracts-wizard/installation#requirements) ------------------------------------------------------------------------------------------------ * **Node.js**: Version 18 or higher * **npm**: Version 8 or higher (includes npx) [Next Steps](https://meshjs.dev/midnight/midnight-contracts-wizard/installation#next-steps) -------------------------------------------------------------------------------------------- Once you're ready, proceed to the [Usage](https://meshjs.dev/midnight/midnight-contracts-wizard/usage) section to learn how to create your first project. [Overview\ \ A CLI tool to create new Midnight contracts projects with selected smart contracts](https://meshjs.dev/midnight/midnight-contracts-wizard) [Usage\ \ Learn how to use the Midnight Contracts Wizard CLI tool](https://meshjs.dev/midnight/midnight-contracts-wizard/usage) ### On this page [Using npx (Recommended)](https://meshjs.dev/midnight/midnight-contracts-wizard/installation#using-npx-recommended) [Check Version](https://meshjs.dev/midnight/midnight-contracts-wizard/installation#check-version) [Requirements](https://meshjs.dev/midnight/midnight-contracts-wizard/installation#requirements) [Next Steps](https://meshjs.dev/midnight/midnight-contracts-wizard/installation#next-steps) Ask AI --- # Implement Custom Provider | Mesh SDK [Learn](https://meshjs.dev/resources) [Guides](https://meshjs.dev/guides) Implement Custom Provider ========================= Copy MarkdownOpen Mesh offers options like [Blockfrost](https://blockfrost.io/) or [Koios](https://www.koios.rest/) (see [Providers](https://meshjs.dev/providers) ). These providers access the Cardano blockchain to retrieve data, such as smart contract UTXOs, or submit signed transactions. Customize a provider to utilize GraphQL, cardano-cli, or websocket with Mesh SDK. Any query method works if the output conforms to the interface. This guide demonstrates how to create a custom provider and integrate it with Mesh to work with the transaction builder. [How it works](https://meshjs.dev/guides/custom-provider#how-it-works) ----------------------------------------------------------------------- JavaScript interfaces define the application structure and syntax for classes. Classes based on an interface must abide by its structure. Providers implement one or more interfaces. For example, the **KoiosProvider** Class implements **IFetcher** and **ISubmitter**. It must strictly conform to their structures. **KoiosProvider** implements **IFetcher** and **ISubmitter** using the **implement** keyword: export class KoiosProvider implements IFetcher, ISubmitter {} Visit the GitHub repo at [packages/module/src/common/contracts](https://github.com/MeshJS/mesh/tree/main/packages/module/src/common/contracts) for the latest interfaces. Create a custom provider class by creating functions with the same name, input parameters, and return type as the defined methods for each interface. This ensures compatibility with Mesh functions. IFetcher has 6 functions (see packages/module/src/common/contracts/fetcher.ts): import type { AccountInfo, AssetMetadata, Protocol, UTxO } from '@mesh/common/types'; export interface IFetcher { fetchAccountInfo(address: string): Promise; fetchAddressUTxOs(address: string, asset?: string): Promise; fetchAssetAddresses(asset: string): Promise<{ address: string; quantity: string }[]>; fetchAssetMetadata(asset: string): Promise; fetchHandleAddress(handle: string): Promise; fetchProtocolParameters(epoch: number): Promise; } **KoiosProvider** must implement these functions as defined in **IFetcher**. [Implement your own provider](https://meshjs.dev/guides/custom-provider#implement-your-own-provider) ----------------------------------------------------------------------------------------------------- Review existing providers to get started. Visit [packages/module/src/providers](https://github.com/MeshJS/mesh/tree/main/packages/module/src/providers) . Use this codebase as a starting point: import { IFetcher, ISubmitter } from "@mesh/common/contracts"; import { parseHttpError } from "@mesh/common/utils"; import type { AccountInfo, AssetMetadata, Protocol, UTxO, } from "@mesh/common/types"; export class NAMEProvider implements IFetcher, ISubmitter { constructor(network: "") { // init variables and other Javascript libraries needed } async fetchAccountInfo(address: string): Promise { try { // return { // ... // }; } catch (error) { throw parseHttpError(error); } } async fetchAddressUTxOs(address: string, asset?: string): Promise { try { // return [\ // ...\ // ]; } catch (error) { throw parseHttpError(error); } } async fetchAssetAddresses( asset: string ): Promise<{ address: string; quantity: string }[]> { try { // return AssetAddresses; } catch (error) { throw parseHttpError(error); } } async fetchAssetMetadata(asset: string): Promise { try { // return [\ // ...\ // ]; } catch (error) { throw parseHttpError(error); } } async fetchHandleAddress(handle: string): Promise { try { // return handleAddress; } catch (error) { throw parseHttpError(error); } } async fetchProtocolParameters(epoch = Number.NaN): Promise { try { // return { // ... // }; } catch (error) { throw parseHttpError(error); } } async submitTx(tx: string): Promise { try { // if (status === 200) // return txHash; } catch (error) { throw parseHttpError(error); } } } This code may change if the interface updates. Your provider may require different interfaces depending on its purpose. [Implement constructor and functions](https://meshjs.dev/guides/custom-provider#implement-constructor-and-functions) --------------------------------------------------------------------------------------------------------------------- Define the constructor. A constructor creates and initializes a class. It runs when creating an object using the **new** keyword. Providers usually require basic information, such as the network or API key. **KoiosProvider** requires **network** and **version** (optional): private readonly _axiosInstance: AxiosInstance; constructor(network: 'api' | 'preview' | 'preprod' | 'guild', version = 0) { this._axiosInstance = axios.create({ baseURL: `https://${network}.koios.rest/api/v${version}`, }); } This constructor initializes the Axios instance with user-provided parameters. Define each function required by the interface. Understand the following: * Query method for the blockchain provider. * Interface input parameters. * Blockchain provider input parameters. * Expected interface outputs. * Blockchain provider return values. Map data correctly from the blockchain provider to the interface's required data type. For example, **KoiosProvider** implements **fetchProtocolParameters()** to map Koios responses to the Protocol data type: async fetchProtocolParameters(epoch: number): Promise { try { const { data, status } = await this._axiosInstance.get( `epoch_params?_epoch_no=${epoch}`, ); if (status === 200) return { coinsPerUTxOSize: data[0].coins_per_utxo_size, collateralPercent: data[0].collateral_percent, decentralisation: data[0].decentralisation, epoch: data[0].epoch_no, keyDeposit: data[0].key_deposit, maxBlockExMem: data[0].max_block_ex_mem.toString(), maxBlockExSteps: data[0].max_block_ex_steps.toString(), maxBlockHeaderSize: data[0].max_bh_size, maxBlockSize: data[0].max_block_size, maxCollateralInputs: data[0].max_collateral_inputs, maxTxExMem: data[0].max_tx_ex_mem.toString(), maxTxExSteps: data[0].max_tx_ex_steps.toString(), maxTxSize: data[0].max_tx_size, maxValSize: data[0].max_val_size.toString(), minFeeA: data[0].min_fee_a, minFeeB: data[0].min_fee_b, minPoolCost: data[0].min_pool_cost, poolDeposit: data[0].pool_deposit, priceMem: data[0].price_mem, priceStep: data[0].price_step, }; throw parseHttpError(data); } catch (error) { throw parseHttpError(error); } } Implement every function specified by the interface and test them. [Create a pull request](https://github.com/MeshJS/mesh/pulls) if your provider benefits the Cardano developer community. [Prove Wallet Ownership\ \ Previous Page](https://meshjs.dev/guides/prove-wallet-ownership) [Smart Contract Transactions\ \ Next Page](https://meshjs.dev/guides/smart-contract-transactions) ### On this page [How it works](https://meshjs.dev/guides/custom-provider#how-it-works) [Implement your own provider](https://meshjs.dev/guides/custom-provider#implement-your-own-provider) [Implement constructor and functions](https://meshjs.dev/guides/custom-provider#implement-constructor-and-functions) Ask AI --- # Prove Wallet Ownership | Mesh SDK [Learn](https://meshjs.dev/resources) [Guides](https://meshjs.dev/guides) Prove Wallet Ownership ====================== Copy MarkdownOpen Cryptographically prove account ownership by signing data with a private key. Use the public address as an identifier and build authentication based on message signing. Use JSON Web Tokens (JWT) to pass authenticated user identity. Example uses: * **Authenticate sign-in**: Prove account ownership. * **Authenticate actions**: Authorize off-chain actions. * **Off-chain data**: Display user-specific off-chain data. [How it works](https://meshjs.dev/guides/prove-wallet-ownership#how-it-works) ------------------------------------------------------------------------------ ![cryptographically-prove-wallet-ownership-process](https://meshjs.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fcryptographically-prove-wallet-ownership-process.8480e544.png&w=3840&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) Signing a message affirms control of the wallet address. Four ingredients are required: * User wallet address * Private key * Public key * Message to sign To verify ownership, provide a message for the user to sign. Validate the signature using the public key. [Client: Connect Wallet and Get Staking Address](https://meshjs.dev/guides/prove-wallet-ownership#client-connect-wallet-and-get-staking-address) ------------------------------------------------------------------------------------------------------------------------------------------------- The backend User model requires `public address` and `nonce` fields. The address must be unique. On Cardano, use the wallet's staking address as the identifier. Retrieve it using `wallet.getUsedAddresses()`. Get the user's staking address and send it to the backend: const { wallet, connected } = useWallet(); async function frontendStartLoginProcess() { if (connected) { const userAddress = (await wallet.getUsedAddresses())[0]; // do: send request with 'userAddress' to the backend } } [Server: Generate Nonce and Store in Database](https://meshjs.dev/guides/prove-wallet-ownership#server-generate-nonce-and-store-in-database) --------------------------------------------------------------------------------------------------------------------------------------------- Generate a random nonce in the backend to create a unique authentication message. Use `generateNonce()` from Mesh. Check the database for the `userAddress`. Create a new entry for new users. Store the new nonce for existing users. import { generateNonce } from '@meshsdk/core'; async function backendGetNonce(userAddress) { // do: if new user, create new user model in the database const nonce = generateNonce('I agree to the term and conditions of the Mesh: '); // do: store 'nonce' in user model in the database // do: return 'nonce' } Return the `nonce` for signing. [Client: Verify ownership by signing the nonce](https://meshjs.dev/guides/prove-wallet-ownership#client-verify-ownership-by-signing-the-nonce) ----------------------------------------------------------------------------------------------------------------------------------------------- Sign the nonce using the wallet's private key with `wallet.signData(nonce, userAddress)` ([CIP-8](https://cips.cardano.org/cip/CIP-8) ). Request authorization. The app processes the generated signature. async function frontendSignMessage(nonce) { try { const userAddress = (await wallet.getUsedAddresses())[0]; const signature = await wallet.signData(nonce, userAddress); // do: send request with 'signature' and 'userAddress' to the backend } catch (error) { // catch error if user refuse to sign } } [Server: Verify Signature](https://meshjs.dev/guides/prove-wallet-ownership#server-verify-signature) ----------------------------------------------------------------------------------------------------- The backend retrieves the user and nonce from the database. Verify the signature using `checkSignature`. If verified, issue a JWT or session identifier. Prevent replay attacks by regenerating the nonce after verification. import { checkSignature } from '@meshsdk/core'; async function backendVerifySignature(userAddress, signature) { // do: get 'nonce' from user (database) using 'userAddress' const result = checkSignature(nonce, signature, userAddress); // do: update 'nonce' in the database with another random string // do: do whatever you need to do, once the user has proven ownership // it could be creating a valid JSON Web Token (JWT) or session // it could be doing something offchain // it could just be updating something in the database } [Putting It All Together](https://meshjs.dev/guides/prove-wallet-ownership#putting-it-all-together) ---------------------------------------------------------------------------------------------------- Frontend implementation: import { CardanoWallet, useWallet } from '@meshsdk/react'; export default function Page() { const { wallet, connected } = useWallet(); async function frontendStartLoginProcess() { if (connected) { const userAddress = (await wallet.getUsedAddresses())[0]; const nonce = await backendGetNonce(userAddress); await frontendSignMessage(nonce); } } async function frontendSignMessage(nonce) { try { const userAddress = (await wallet.getUsedAddresses())[0]; const signature = await wallet.signData(nonce, userAddress); await backendVerifySignature(userAddress, signature); } catch (error) { setState(0); } } return ( <> frontendStartLoginProcess()} /> ); } Server-side implementation: import { checkSignature, generateNonce } from '@meshsdk/core'; async function backendGetNonce(userAddress) { const nonce = generateNonce('I agree to the term and conditions of the Mesh: '); return nonce; } async function backendVerifySignature(userAddress, signature) { // do: get 'nonce' from database const result = checkSignature(nonce, signature, userAddress); if(result){ // create JWT or approve certain process } else{ // prompt user that signature is not correct } } This technique authenticates sign-ins or any user action. [Multi-Signatures Transaction\ \ Previous Page](https://meshjs.dev/guides/multisig-minting) [Implement Custom Provider\ \ Next Page](https://meshjs.dev/guides/custom-provider) ### On this page [How it works](https://meshjs.dev/guides/prove-wallet-ownership#how-it-works) [Client: Connect Wallet and Get Staking Address](https://meshjs.dev/guides/prove-wallet-ownership#client-connect-wallet-and-get-staking-address) [Server: Generate Nonce and Store in Database](https://meshjs.dev/guides/prove-wallet-ownership#server-generate-nonce-and-store-in-database) [Client: Verify ownership by signing the nonce](https://meshjs.dev/guides/prove-wallet-ownership#client-verify-ownership-by-signing-the-nonce) [Server: Verify Signature](https://meshjs.dev/guides/prove-wallet-ownership#server-verify-signature) [Putting It All Together](https://meshjs.dev/guides/prove-wallet-ownership#putting-it-all-together) Ask AI --- # Available Contracts | Mesh SDK [Midnight](https://meshjs.dev/midnight) Midnight Contracts Wizard Available Contracts =================== Explore the smart contract templates available in the Midnight Contracts Wizard Copy MarkdownOpen The Midnight Contracts Wizard includes several production-ready smart contract templates. Each contract is designed with privacy and zero-knowledge proofs in mind. [Tokenization Contract](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#tokenization-contract) --------------------------------------------------------------------------------------------------------------- **7 ZK Circuits** A complete project tokenization system with zero-knowledge privacy for investments. ### [Features](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#features) * Private token minting and burning * Confidential balance management * Investment tracking with ZK proofs * Transfer with privacy guarantees ### [Use Cases](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#use-cases) * Real estate tokenization * Asset-backed securities * Private equity tracking * Confidential fundraising * * * [Staking Contract](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#staking-contract) ----------------------------------------------------------------------------------------------------- **8 ZK Circuits** A privacy-focused staking system with rewards and configurable lock periods. ### [Features](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#features-1) * Private stake amounts * Confidential reward distribution * Flexible lock periods * Slashing mechanisms ### [Use Cases](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#use-cases-1) * Network validation * Governance participation * Yield generation * Long-term holding incentives * * * [Identity Contracts](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#identity-contracts) --------------------------------------------------------------------------------------------------------- **1 ZK Circuit** Complete identity management system with cryptographic libraries for privacy-preserving verification. ### [Features](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#features-2) * Zero-knowledge identity proofs * Selective disclosure * Credential verification * Privacy-preserving authentication ### [Use Cases](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#use-cases-2) * KYC compliance * Age verification * Credential validation * Access control * * * [Oracle Contract](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#oracle-contract) --------------------------------------------------------------------------------------------------- **7 ZK Circuits** Decentralized oracle system with privacy-preserving data feeds. ### [Features](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#features-3) * Confidential data ingestion * Multi-source aggregation * Tamper-proof feeds * Privacy-preserving validation ### [Use Cases](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#use-cases-3) * Price feeds * Weather data * Sports results * IoT data streams * * * [Lending & Borrowing Contract](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#lending--borrowing-contract) ---------------------------------------------------------------------------------------------------------------------------- **7 ZK Circuits** Privacy-preserving decentralized lending protocol. ### [Features](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#features-4) * Confidential collateral management * Private loan amounts * Interest rate privacy * Liquidation with ZK proofs ### [Use Cases](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#use-cases-4) * DeFi lending platforms * Peer-to-peer lending * Collateralized loans * Credit lines * * * [Contract Selection Tips](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#contract-selection-tips) ------------------------------------------------------------------------------------------------------------------- ### [Single Contract Projects](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#single-contract-projects) Perfect for focused applications or proof-of-concepts. Select one contract type and build a specialized solution. ### [Multi-Contract Projects](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#multi-contract-projects) Combine multiple contracts for complex dApps. For example: * **Tokenization + Oracle** - Real-world asset pricing * **Staking + Identity** - Governance with verified participants * **Lending + Oracle** - Price-aware DeFi protocols ### [All Contracts](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#all-contracts) Select all contracts to explore the full ecosystem or build a comprehensive platform. [Technical Details](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#technical-details) ------------------------------------------------------------------------------------------------------- Each contract includes: * Complete `.compact` source files * Compiled TypeScript interfaces * ZK circuit configurations * Build and deployment scripts * Example usage documentation [Next Steps](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#next-steps) ----------------------------------------------------------------------------------------- Learn about the [Project Structure](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure) that gets generated for your selected contracts. [Usage\ \ Learn how to use the Midnight Contracts Wizard CLI tool](https://meshjs.dev/midnight/midnight-contracts-wizard/usage) [Project Structure\ \ Understanding the generated project structure](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure) ### On this page [Tokenization Contract](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#tokenization-contract) [Features](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#features) [Use Cases](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#use-cases) [Staking Contract](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#staking-contract) [Features](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#features-1) [Use Cases](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#use-cases-1) [Identity Contracts](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#identity-contracts) [Features](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#features-2) [Use Cases](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#use-cases-2) [Oracle Contract](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#oracle-contract) [Features](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#features-3) [Use Cases](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#use-cases-3) [Lending & Borrowing Contract](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#lending--borrowing-contract) [Features](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#features-4) [Use Cases](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#use-cases-4) [Contract Selection Tips](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#contract-selection-tips) [Single Contract Projects](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#single-contract-projects) [Multi-Contract Projects](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#multi-contract-projects) [All Contracts](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#all-contracts) [Technical Details](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#technical-details) [Next Steps](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts#next-steps) Ask AI --- # Serializers | Mesh SDK [Utilities](https://meshjs.dev/apis/utilities) Serializers =========== Encode objects into CBOR or bech32 format. Copy MarkdownOpen In smart contract manipulations, serialization is a crucial process that encode data structures or objects into a format that can be easily stored or transmitted and later reconstructed. Below are utilities to help serialize various Cardano smart contracts components. [Serialize Native Script](https://meshjs.dev/apis/utilities/serializers#serialize-native-script) ------------------------------------------------------------------------------------------------- The function `serializeNativeScript` allows you to provide the `nativeScript` with an option of `networkId` and `stakeCredentialHash`, returns: * Bech32 address * Script Cbor This example demonstrates how to derive the native script from the `pubKeyHash` with the `deserializeAddress` then serialize the native script to a bech32 address and script Cbor. To read more on [deserializeAddress](https://meshjs.dev/apis/utilities/deserializers) . ### [Serialize Native Script](https://meshjs.dev/apis/utilities/serializers#serialize-native-script-toc) Serialize Native script into bech32 address import { serializeNativeScript, NativeScript, deserializeAddress } from "@meshsdk/core"; const { pubKeyHash: keyHash } = deserializeAddress( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', ); const nativeScript: NativeScript = { type: "all", scripts: [\ {\ type: "before",\ slot: "99999999",\ },\ {\ type: "sig",\ keyHash: keyHash,\ },\ ], }; serializeNativeScript(nativeScript); [Serialize Plutus Script](https://meshjs.dev/apis/utilities/serializers#serialize-plutus-script) ------------------------------------------------------------------------------------------------- The function `serializePlutusScript` allows you to provide the `plutusScript` with an option of `networkId` and `stakeCredentialHash`, returns: * Bech32 address This example demonstrates how to derive and serialize a plutus script into a bech32 address. ### [Serialize Plutus Script](https://meshjs.dev/apis/utilities/serializers#serialize-plutus-script-toc) Serialize Plutus script into bech32 address import { PlutusScript, serializePlutusScript } from "@meshsdk/core"; const plutusScript: PlutusScript = { code: demoPlutusAlwaysSucceedScript, version: "V2", }; serializePlutusScript(plutusScript); [Serialize Address Object](https://meshjs.dev/apis/utilities/serializers#serialize-address-object) --------------------------------------------------------------------------------------------------- Serialize address in Cardano data JSON format into bech32 address with `serializeAddressObj()`. First you need to create an address object with `pubKeyAddress()` or `scriptAddress()`. `pubKeyAddress()` accepts the following parameters: pubKeyAddress( bytes: string, stakeCredential?: string, isStakeScriptCredential?: boolean ): PubKeyAddress `scriptAddress()` accepts the following parameters: scriptAddress( bytes: string, stakeCredential?: string, isStakeScriptCredential?: boolean ): ScriptAddress `serializeAddressObj()` accepts the following parameters: serializeAddressObj( address: PubKeyAddress | ScriptAddress, networkId?: number ): string ### [Serialize Address Object](https://meshjs.dev/apis/utilities/serializers#serialize-address-object-toc) Serialize address in Cardano data JSON format into bech32 address import { pubKeyAddress, serializeAddressObj } from "@meshsdk/core"; const address = pubKeyAddress( 'aa048e4cc8a1e67e1d97ffbd4be614388014cbc2b2451527202943b6', '9d4dcd7e454d2434164f4efb8edeb358d86a1dad9ec6224cfcbce3e6' ); serializeAddressObj(address, 1); [Utilities\ \ Serializers, resolvers and data types for converting between different formats.](https://meshjs.dev/apis/utilities) [Deserializers\ \ Parse CBOR or bech32 into objects](https://meshjs.dev/apis/utilities/deserializers) ### On this page [Serialize Native Script](https://meshjs.dev/apis/utilities/serializers#serialize-native-script) [Serialize Plutus Script](https://meshjs.dev/apis/utilities/serializers#serialize-plutus-script) [Serialize Address Object](https://meshjs.dev/apis/utilities/serializers#serialize-address-object) Ask AI --- # Usage | Mesh SDK [Midnight](https://meshjs.dev/midnight) Midnight Contracts Wizard Usage ===== Learn how to use the Midnight Contracts Wizard CLI tool Copy MarkdownOpen [Basic Usage](https://meshjs.dev/midnight/midnight-contracts-wizard/usage#basic-usage) --------------------------------------------------------------------------------------- Run the wizard using npx (no installation required): npx @meshsdk/midnight-contracts-wizard [Interactive Mode](https://meshjs.dev/midnight/midnight-contracts-wizard/usage#interactive-mode) ------------------------------------------------------------------------------------------------- When you run the wizard, it will guide you through an interactive setup: 1. **Project Name** - Enter a name for your new project 2. **Select Contracts** - Choose which contract templates to include: * Tokenization Contract * Staking Contract * Identity Contracts * Oracle Contract * Lending & Borrowing Contract 3. **Confirmation** - Review your selections and confirm [Example Session](https://meshjs.dev/midnight/midnight-contracts-wizard/usage#example-session) ----------------------------------------------------------------------------------------------- $ npx @meshsdk/midnight-contracts-wizard Welcome to Midnight Contracts Wizard! ? Enter your project name: my-midnight-contracts ? Select contracts to include: (Use arrow keys and space to select) ◉ Tokenization Contract (7 ZK circuits) ◯ Staking Contract (8 ZK circuits) ◉ Identity Contracts (1 ZK circuit) ◯ Oracle Contract (7 ZK circuits) ◯ Lending & Borrowing Contract (7 ZK circuits) ✓ Project created successfully! ✓ Tokenization contract added ✓ Identity contracts added 📋 Next steps: 1) Navigate to the project folder: cd ./my-midnight-contracts 2) Compile your smart contracts: compact compile contracts/tokenization/tokenization.compact ./src/managed/tokenization compact compile contracts/identity/identity.compact ./src/managed/identity 💡 Your contracts will be compiled to `src/managed/` 💡 Check the `README.md` for detailed instructions [Command Options](https://meshjs.dev/midnight/midnight-contracts-wizard/usage#command-options) ----------------------------------------------------------------------------------------------- ### [Help](https://meshjs.dev/midnight/midnight-contracts-wizard/usage#help) Display help information: npx @meshsdk/midnight-contracts-wizard --help ### [Version](https://meshjs.dev/midnight/midnight-contracts-wizard/usage#version) Check the installed version: npx @meshsdk/midnight-contracts-wizard --version [Next Steps](https://meshjs.dev/midnight/midnight-contracts-wizard/usage#next-steps) ------------------------------------------------------------------------------------- * Explore [Available Contracts](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts) to understand each contract type * Review [Project Structure](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure) to learn about generated files [Installation\ \ How to use the Midnight Contracts Wizard CLI tool](https://meshjs.dev/midnight/midnight-contracts-wizard/installation) [Available Contracts\ \ Explore the smart contract templates available in the Midnight Contracts Wizard](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts) ### On this page [Basic Usage](https://meshjs.dev/midnight/midnight-contracts-wizard/usage#basic-usage) [Interactive Mode](https://meshjs.dev/midnight/midnight-contracts-wizard/usage#interactive-mode) [Example Session](https://meshjs.dev/midnight/midnight-contracts-wizard/usage#example-session) [Command Options](https://meshjs.dev/midnight/midnight-contracts-wizard/usage#command-options) [Help](https://meshjs.dev/midnight/midnight-contracts-wizard/usage#help) [Version](https://meshjs.dev/midnight/midnight-contracts-wizard/usage#version) [Next Steps](https://meshjs.dev/midnight/midnight-contracts-wizard/usage#next-steps) Ask AI --- # GiftCard | Mesh SDK [Smart Contracts](https://meshjs.dev/smart-contracts) GiftCard ======== Create a giftcard with native tokens Copy MarkdownOpen Giftcard contract allows users to create a transactions to lock assets into the smart contract, which can be redeemed by any user. Creating a giftcard will mint a token and send the assets to the contract. While redeeming will burn the token and send the assets to the redeemer. There are 2 actions (or endpoints) available to interact with this smart contract: * create giftcard * redeem giftcard ### [Install package](https://meshjs.dev/smart-contracts/giftcard#install-package-toc) First you can to install the `@meshsdk/contracts` package: npm install @meshsdk/contract ### [Initialize the contract](https://meshjs.dev/smart-contracts/giftcard#initialize-the-contract-toc) To initialize the contract, we need to initialize a provider, `MeshTxBuilder` and `MeshGiftCardContract`. import { MeshGiftCardContract } from "@meshsdk/contract"; import { MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshGiftCardContract({ mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }); Both on-chain and off-chain codes are open-source and available on [Mesh Github Repository](https://github.com/MeshJS/mesh/tree/main/packages/mesh-contract/src/giftcard) . [Create Giftcard](https://meshjs.dev/smart-contracts/giftcard#create-giftcard) ------------------------------------------------------------------------------- `createGiftCard()` create a gift card. The function accepts the following parameters: * tokenName (string) - name of the token * giftValue (Asset\[\]) - a list of assets The function returns a transaction hash if the gift card is successfully created. The function returns a transaction hex if giftcard has been created successfully. ### [Create Giftcard](https://meshjs.dev/smart-contracts/giftcard#create-giftcard-toc) Create a gift card with a given amount of lovelace **Gitfcard amount** `10000000` **Giftcard name** `Mesh_Gift_Card` const giftValue: Asset[] = [\ {\ unit: "lovelace",\ quantity: '10000000',\ },\ ]; const tx = await contract.createGiftCard('Mesh_Gift_Card', giftValue); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Redeem Giftcard](https://meshjs.dev/smart-contracts/giftcard#redeem-giftcard) ------------------------------------------------------------------------------- `redeemGiftCard()` redeem a gift card. The function accepts the following parameters: * giftCardUtxo (UTxO) - unspent transaction output in the script The function returns a transaction hash if the gift card is successfully redeemed. It will burn the gift card and transfer the value to the wallet signing this transaction. The function returns a transaction hex if the gift card has been redeemed successfully. We have provided a very handle function, `getUtxoByTxHash`, which will return the UTxO object for a given transaction hash. You can always create another function that searches by token name. A [successful redemption](https://preprod.cardanoscan.io/transaction/2bc1c39337de3ebcb2650aa41c73b1a873288282b8c7e1ed130d31f5c34090b7) will send the value to the wallet that signed the transaction to redeem the gift card. ### [Redeem Giftcard](https://meshjs.dev/smart-contracts/giftcard#redeem-giftcard-toc) Redeem a gift card given the gift card UTxO **Tx hash** `Tx hash` const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.redeemGiftCard(utxo); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Escrow\ \ Secure exchange of assets between two parties](https://meshjs.dev/smart-contracts/escrow) [Hello World\ \ Simple lock and unlock assets contract](https://meshjs.dev/smart-contracts/hello-world) ### On this page [Create Giftcard](https://meshjs.dev/smart-contracts/giftcard#create-giftcard) [Redeem Giftcard](https://meshjs.dev/smart-contracts/giftcard#redeem-giftcard) Ask AI --- # Data | Mesh SDK [Utilities](https://meshjs.dev/apis/utilities) Data ==== Useful utilities to parse and manipulate data Copy MarkdownOpen [Data Overview\ \ Learn about the basics, and how Mesh handles Cardano data](https://meshjs.dev/apis/data/overview) [Mesh Data\ \ Parse and manipulate data with Mesh Data type](https://meshjs.dev/apis/data/mesh) [JSON Data\ \ Parse and manipulate data with JSON](https://meshjs.dev/apis/data/json) [Value\ \ Manipulate Value Easily](https://meshjs.dev/apis/data/value) [Resolvers\ \ Converts between different formats.](https://meshjs.dev/apis/utilities/resolvers) [Blueprints\ \ Blueprints for script with either apply parameters or no parameters](https://meshjs.dev/apis/utilities/blueprints) Ask AI --- # Core API Methods | Mesh SDK [Midnight](https://meshjs.dev/midnight) Midnight Setup Core API Methods ================ Complete reference for MidnightSetupAPI methods and provider setup Copy MarkdownOpen [MidnightSetupAPI](https://meshjs.dev/midnight/midnight-setup/api#midnightsetupapi) ------------------------------------------------------------------------------------ The `MidnightSetupAPI` is the main class for interacting with Midnight Network contracts. It provides methods for deploying, joining, and managing smart contracts. ### [Core Methods](https://meshjs.dev/midnight/midnight-setup/api#core-methods) | Method | Description | Usage | | --- | --- | --- | | `deployContract(providers, contractInstance)` | Deploy a new contract | Creates new contract instance | | `joinContract(providers, contractInstance, address)` | Join existing contract | Connect to deployed contract | | `getContractState()` | Read contract state | Get current contract data | | `getLedgerState()` | Read ledger state | Get blockchain data | ### [Deploy Contract](https://meshjs.dev/midnight/midnight-setup/api#deploy-contract) Deploy a new smart contract to the Midnight Network: import { MidnightSetupAPI } from '@meshsdk/midnight-setup'; const api = await MidnightSetupAPI.deployContract(providers, contractInstance); console.log('Contract deployed:', api.deployedContractAddress); ### [Join Contract](https://meshjs.dev/midnight/midnight-setup/api#join-contract) Connect to an existing deployed contract: import { MidnightSetupAPI } from '@meshsdk/midnight-setup'; const contractAddress = "contract_address_here"; const api = await MidnightSetupAPI.joinContract(providers, contractInstance, contractAddress); console.log('Connected to contract:', contractAddress); ### [Get Contract State](https://meshjs.dev/midnight/midnight-setup/api#get-contract-state) Retrieve the current state of a contract: const state = await api.getContractState(); console.log('Contract state:', state); ### [Get Ledger State](https://meshjs.dev/midnight/midnight-setup/api#get-ledger-state) Access the current ledger state: const ledgerState = await api.getLedgerState(); console.log('Ledger state:', ledgerState); [Provider Setup](https://meshjs.dev/midnight/midnight-setup/api#provider-setup) -------------------------------------------------------------------------------- Set up providers for Midnight Network: import { setupProviders } from './lib/providers'; const providers = await setupProviders(); // Returns: MidnightSetupContractProviders ### [Provider Configuration](https://meshjs.dev/midnight/midnight-setup/api#provider-configuration) const providers = { fetcher: blockfrostProvider, submitter: blockfrostProvider, wallet: laceWallet, // Additional provider configurations }; [Error Handling](https://meshjs.dev/midnight/midnight-setup/api#error-handling) -------------------------------------------------------------------------------- Always wrap API calls in try-catch blocks for proper error handling: try { const api = await MidnightSetupAPI.deployContract(providers, contractInstance); const state = await api.getContractState(); console.log('Success:', state); } catch (error) { console.error('Error:', error.message); } [TypeScript Support](https://meshjs.dev/midnight/midnight-setup/api#typescript-support) ---------------------------------------------------------------------------------------- The package includes full TypeScript definitions: import { MidnightSetupAPI, MidnightSetupContractProviders, ContractInstance } from '@meshsdk/midnight-setup'; // Type-safe provider setup const providers: MidnightSetupContractProviders = await setupProviders(); // Type-safe contract instance const contractInstance: ContractInstance = { // Contract configuration }; [Best Practices](https://meshjs.dev/midnight/midnight-setup/api#best-practices) -------------------------------------------------------------------------------- 1. **Always handle errors** - Wrap API calls in try-catch blocks 2. **Use TypeScript** - Leverage type safety for better development experience 3. **Validate inputs** - Ensure contract instances and addresses are valid 4. **Monitor state changes** - Listen for contract state updates 5. **Test thoroughly** - Use testnet before deploying to mainnet [Getting Started\ \ Install and set up @meshsdk/midnight-setup for building zero-knowledge privacy dApps on Midnight Network](https://meshjs.dev/midnight/midnight-setup/getting-started) [Lace Wallet Integration\ \ Complete Lace Beta Wallet integration for Midnight Network dApps](https://meshjs.dev/midnight/midnight-setup/wallet) ### On this page [MidnightSetupAPI](https://meshjs.dev/midnight/midnight-setup/api#midnightsetupapi) [Core Methods](https://meshjs.dev/midnight/midnight-setup/api#core-methods) [Deploy Contract](https://meshjs.dev/midnight/midnight-setup/api#deploy-contract) [Join Contract](https://meshjs.dev/midnight/midnight-setup/api#join-contract) [Get Contract State](https://meshjs.dev/midnight/midnight-setup/api#get-contract-state) [Get Ledger State](https://meshjs.dev/midnight/midnight-setup/api#get-ledger-state) [Provider Setup](https://meshjs.dev/midnight/midnight-setup/api#provider-setup) [Provider Configuration](https://meshjs.dev/midnight/midnight-setup/api#provider-configuration) [Error Handling](https://meshjs.dev/midnight/midnight-setup/api#error-handling) [TypeScript Support](https://meshjs.dev/midnight/midnight-setup/api#typescript-support) [Best Practices](https://meshjs.dev/midnight/midnight-setup/api#best-practices) Ask AI --- # Smart Contracts | Mesh SDK Smart Contracts =============== Open-source smart contracts, complete with documentation, and live demos Copy MarkdownOpen [Content Ownership\ \ Manage ownership of digital content and assets](https://meshjs.dev/smart-contracts/content-ownership) [Escrow\ \ Secure exchange of assets between two parties](https://meshjs.dev/smart-contracts/escrow) [Giftcard\ \ Create a giftcard with native tokens](https://meshjs.dev/smart-contracts/giftcard) [Hello World\ \ Simple lock and unlock assets contract](https://meshjs.dev/smart-contracts/hello-world) [Marketplace\ \ Build a NFT marketplace to buy and sell NFTs](https://meshjs.dev/smart-contracts/marketplace) [NFT Minting Machine\ \ Mint NFT that ensure the token name is incremented by a counter](https://meshjs.dev/smart-contracts/plutus-nft) [Payment Splitter\ \ Split payouts equally among a list of specified payees](https://meshjs.dev/smart-contracts/payment-splitter) [Swap\ \ Swap contract facilitates the exchange of assets between two parties](https://meshjs.dev/smart-contracts/swap) [Vesting\ \ Locks up funds and allows the beneficiary to withdraw the funds after the lockup period](https://meshjs.dev/smart-contracts/vesting) [UI Components\ \ UI components to speed up your app development.](https://meshjs.dev/svelte/ui-components) [Content Ownership\ \ Manage ownership of digital content and assets](https://meshjs.dev/smart-contracts/content-ownership) Ask AI --- # Payment Splitter | Mesh SDK [Smart Contracts](https://meshjs.dev/smart-contracts) Payment Splitter ================ Split payouts equally among a list of specified payees Copy MarkdownOpen A payment splitter can be used for example to create a shared project donation address, ensuring that all payees receive the same amount Sending lovelace to the contract works similarly to sending lovelace to any other address. The payout transaction can only be submitted by one of the payees, and the output addresses are restricted to the payees. The output sum must be equally divided to ensure the transaction is successful. There are 2 actions (or endpoints) available to interact with this smart contract: * Send Lovelace to Payment Splitter * Trigger Payout ### [Install package](https://meshjs.dev/smart-contracts/payment-splitter#install-package-toc) First you can to install the `@meshsdk/contracts` package: npm install @meshsdk/contract ### [Initialize the contract](https://meshjs.dev/smart-contracts/payment-splitter#initialize-the-contract-toc) To initialize the payment splitter, we need to initialize a [provider](https://meshjs.dev/providers) , a `MeshTxBuilder`, and a `MeshPaymentSplitterContract`. Additionally, a list of payees is required to define the allowed payout addresses for the contract. import { MeshPaymentSplitterContract } from "@meshsdk/contract"; import { MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshPaymentSplitterContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, [\ 'addr_test1vpg334d6skwu6xxq0r4lqrnsjd5293n8s3d80em60kf6guc7afx8k',\ 'addr_test1vp4l2kk0encl7t7972ngepgm0044fu8695prkgh5vjj5l6sxu0l3p',\ 'addr_test1vqqnfs2vt42nq4htq460wd6gjxaj05jg9vzg76ur6ws4sngs55pwr',\ 'addr_test1vqv2qhqddxmf87pzky2nkd9wm4y5599mhp62mu4atuss5dgdja5pw',\ ] ); Both on-chain and off-chain codes are open-source and available on [Mesh Github Repository](https://github.com/MeshJS/mesh/tree/main/packages/mesh-contract/src/payment-splitter) . [Send Lovelace to Payment Splitter](https://meshjs.dev/smart-contracts/payment-splitter#send-lovelace-to-payment-splitter) --------------------------------------------------------------------------------------------------------------------------- `sendLovelaceToSplitter()` will lock Lovelace in the contract. The function accepts the following parameters: * lovelaceAmount (number) - the amount of Lovelace you want to send to the contract The function returns a transaction hash. ### [Send Lovelace to Payment Splitter](https://meshjs.dev/smart-contracts/payment-splitter#send-lovelace-to-payment-splitter-toc) Send Lovelace to the Payment Splitter contract to be distributed to the beneficiaries. **Listing price in Lovelace** `15000000` const tx = await contract.sendLovelaceToSplitter(15000000); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Trigger Payout](https://meshjs.dev/smart-contracts/payment-splitter#trigger-payout) ------------------------------------------------------------------------------------- `triggerPayout()` will split the locked amount equally among the list of payees. The function doesn't need any parameters. The function returns a transaction hash if the payout has been done successfully. ### [Trigger Payout](https://meshjs.dev/smart-contracts/payment-splitter#trigger-payout-toc) After the amount has been locked in the contract, you can trigger the payout to the payees. const tx = await contract.triggerPayout(); const signedTx = await wallet.signTx(tx, true); const txHash = await wallet.submitTx(signedTx); [NFT Minting Machine\ \ Mint NFT that ensure the token name is incremented by a counter](https://meshjs.dev/smart-contracts/plutus-nft) [Swap\ \ Swap contract facilitates the exchange of assets between two parties](https://meshjs.dev/smart-contracts/swap) ### On this page [Send Lovelace to Payment Splitter](https://meshjs.dev/smart-contracts/payment-splitter#send-lovelace-to-payment-splitter) [Trigger Payout](https://meshjs.dev/smart-contracts/payment-splitter#trigger-payout) Ask AI --- # Overview | Mesh SDK [Midnight](https://meshjs.dev/midnight) Midnight Contracts Wizard Overview ======== A CLI tool to create new Midnight contracts projects with selected smart contracts Copy MarkdownOpen [Installation\ \ Install the CLI tool and get started with Midnight Contracts Wizard](https://meshjs.dev/midnight/midnight-contracts-wizard/installation) [Usage\ \ Learn how to use the interactive wizard to scaffold your project](https://meshjs.dev/midnight/midnight-contracts-wizard/usage) [Available Contracts\ \ Explore pre-built contract templates for tokenization, staking, identity, oracle, and lending](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts) [Project Structure\ \ Understanding the generated project structure and configuration files](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure) [Integration Examples\ \ The fastest way to build on Midnight Network with pre-built smart contracts, complete API, and ready-to-use code snippets](https://meshjs.dev/midnight/midnight-setup/examples) [Installation\ \ How to use the Midnight Contracts Wizard CLI tool](https://meshjs.dev/midnight/midnight-contracts-wizard/installation) Ask AI --- # Blueprints | Mesh SDK [Utilities](https://meshjs.dev/apis/utilities) Blueprints ========== Blueprints for script with either apply parameters or no parameters Copy MarkdownOpen In Mesh, we have in built `Blueprint` utility classes to help manipulating serialization and deserialization logic around Cardano smart contracts / validators. Now it is supporting the basic use case around 3 purposes - `Spending`,`Minting` and `Withdrawal`. You can either directly use the `Blueprint` utility classes imported from Mesh, or use the [Cardano Bar](https://marketplace.visualstudio.com/items?itemName=sidan-lab.cardano-bar-vscode) from [SIDAN Lab](https://x.com/sidan_lab) , which perform a comprehensive parsing of the CIP57 blueprint object into Mesh's type. [Spending Script Blueprint](https://meshjs.dev/apis/utilities/blueprints#spending-script-blueprint) ---------------------------------------------------------------------------------------------------- `SpendingBlueprint` is a class for handling spending blueprint particularly. You can provide `plutusVersion`, `networkId` and the potential `stakeKeyHash` for the spending validator address to initialized the class. After that, providing the `compiledCode` and parameters to finish the setup. The class then provide easy access to common script information: * Script Hash * Script Cbor * Script Address A Spending validator with no parameter, allows to provides only the `compiledCode` instead. ### [Spending Script Blueprint - Apply parameter to script](https://meshjs.dev/apis/utilities/blueprints#spending-script-blueprint---apply-parameter-to-script-toc) Creates a spending script blueprint with apply parameter to script. import { SpendingBlueprint } from "@meshsdk/core"; const demoCompiledCode = "5906f401010032323232323232223225333005323232323253323300b3001300c37540042646464646464a66602260060022a66602860266ea8024540085854ccc044c01c00454ccc050c04cdd50048a8010b0b18089baa0081533300f30013010375400426464a64666024600860266ea80284c94ccc04cc014c050dd50008991919191919191919299980e1929998100008a5015333020302300114a22940cc88c8cc00400400c894ccc08c00452f5c026464a66604466ebcc048c090dd5180718121baa002005133026002330040040011330040040013027002302500137586018603c6ea8058c030c078dd51804180f1baa0091533301c001100214a02940cc00ccc008dd61802180e9baa01501a30063370666e08dd69803980e9baa00c018482827004cc008cc004dd61801980e1baa014300a301c3754016600a66e00dd69803180e1baa00b3330043756600c60386ea8c018c070dd5003a450048810022323300100100322533302000114bd6f7b63009991299980f99baf300f3021375400400a2646660020020046eacc030c088dd50019112999812801080089919980200218148019991191980080080291299981500089981599bb037520086e9800d2f5bded8c0264646464a66605666e400200084cc0bccdd81ba9008374c00e00a2a66605666e3c0200084c94ccc0b0c078c0b4dd500089981819bb037520126062605c6ea80040104010c94ccc0b14ccc0bc0045288a5014c0103d87a80001301b33030374c00297ae03233300100100800222253330310021001132333004004303500333223233001001005225333036001133037337606ea4010dd4001a5eb7bdb1804c8c8c8c94ccc0dccdc800400109981d99bb037520106ea001c01454ccc0dccdc7804001099299981c1815181c9baa00113303c337606ea4024c0f4c0e8dd5000802080219299981c18150008a60103d87a8000130273303c375000297ae03370000e00226607666ec0dd48011ba800133006006003375a60700066eb8c0d8008c0e8008c0e0004dd718180009bad3031001303300213302f337606ea4008dd3000998030030019bab302c003375c6054004605c00460580026eb8c090004dd5981280098138010800981100099801001181180091191980080099198008008019129998100008a5eb804c8ccc888c8cc00400400c894ccc098004400c4c8cc0a0dd3998141ba90063302830250013302830260014bd7019801801981500118140009bae301f00137566040002660060066048004604400244a66603e00229444c94ccc074c8cdc49bad3007001333008006375c601c0026eb8c028004dd618110010998018018008a5030220012301d301e301e00122232533301a3010301b37540022900009bad301f301c375400264a666034602060366ea8004530103d87a80001323300100137566040603a6ea8008894ccc07c004530103d87a80001323232325333020337220100042a66604066e3c0200084c03ccc090dd4000a5eb80530103d87a8000133006006003375a60420066eb8c07c008c08c008c084004c8cc004004010894ccc0780045300103d87a8000132323232533301f337220100042a66603e66e3c0200084c038cc08cdd3000a5eb80530103d87a8000133006006003375660400066eb8c078008c088008c08000494ccc058c02000452f5bded8c0264646600200297adef6c6022533301c00113301d337609801014000374c00697adef6c60132323232533301d33720910100002133021337609801014000374c00e00a2a66603a66e3d22100002133021337609801014000374c00e00626604266ec0dd48011ba6001330060060033756603c0066eb8c070008c080008c078004c8cc0040052f5bded8c044a66603600226603866ec13001014000375000697adef6c60132323232533301c33720910100002133020337609801014000375000e00a2a66603866e3d22100002133020337609801014000375000e00626604066ec0dd48011ba800133006006003375a603a0066eb8c06c008c07c008c0740048c068c06c004c060c054dd50008b19198008009bac30033015375401a44a66602e002298103d87a80001323253330163375e600c60306ea80080284c014cc0680092f5c026600800800260360046032002264a666026600a60286ea80044cc88c8cc00400400c894ccc068004528099299980c19b8f375c603a00400829444cc00c00c004c074004dd6180c180c980c980c980c980c980c980c980c980a9baa00d375c6030602a6ea800458c94ccc04cc014c050dd5000898011980b980c180a9baa0014bd700a60103d87a8000300230143754600460286ea800cdd2a40004602c002602860226ea800858dc3a4000602460260046022002601a6ea8008dc3a40042c601c601e004601a002601a0046016002600e6ea800452613656375a002ae6955ceaab9e5573eae815d0aba201"; // provide your staking part for the compiled address const stakeHash = "9e8a6e5fcbbb5b84deefc71d7cb6319a3da9cc3d19765efb303647ef"; const blueprint = new SpendingBlueprint("V2", 0, stakeHash); blueprint.paramScript( demoCompiledCode, mPubKeyAddress("aa048e4cc8a1e67e1d97ffbd4be614388014cbc2b2451527202943b6", "9d4dcd7e454d2434164f4efb8edeb358d86a1dad9ec6224cfcbce3e6")], "Mesh" // Mesh data type ); const scriptHash = blueprint.hash; const scriptCbor = blueprint.cbor; const scriptAddress = blueprint.address; ### [Spending Script blueprint - no parameter to script](https://meshjs.dev/apis/utilities/blueprints#spending-script-blueprint---no-parameter-to-script-toc) Creates a spending script blueprint with no parameter to script. const blueprint = new SpendingBlueprint("V2", 0 , stakeHash); blueprint.noParamScript(demoCompiledCode); const scriptHash = blueprint.hash; const scriptCbor = blueprint.cbor; const scriptAddress = bluePrint.address; ; [Minting Script Blueprint](https://meshjs.dev/apis/utilities/blueprints#minting-script-blueprint) -------------------------------------------------------------------------------------------------- `MintingBlueprint` is a class for handling minting blueprint particularly. You can provide `plutusVersion`, for the minting validator to initialize the class. After that, providing the `compiledCode` and parameters to finish the setup. The class then provide easy access to common script information: * Policy ID (i.e Script Hash) * Script Cbor A Minting validator with no parameter, allows to provides only the `compiledCode` instead. ### [Minting Script Blueprint - Apply parameter to script](https://meshjs.dev/apis/utilities/blueprints#minting-script-blueprint---apply-parameter-to-script-toc) Creates a Minting script blueprint with apply parameter to script. const demoCompiledCode = "5906f401010032323232323232223225333005323232323253323300b3001300c37540042646464646464a66602260060022a66602860266ea8024540085854ccc044c01c00454ccc050c04cdd50048a8010b0b18089baa0081533300f30013010375400426464a64666024600860266ea80284c94ccc04cc014c050dd50008991919191919191919299980e1929998100008a5015333020302300114a22940cc88c8cc00400400c894ccc08c00452f5c026464a66604466ebcc048c090dd5180718121baa002005133026002330040040011330040040013027002302500137586018603c6ea8058c030c078dd51804180f1baa0091533301c001100214a02940cc00ccc008dd61802180e9baa01501a30063370666e08dd69803980e9baa00c018482827004cc008cc004dd61801980e1baa014300a301c3754016600a66e00dd69803180e1baa00b3330043756600c60386ea8c018c070dd5003a450048810022323300100100322533302000114bd6f7b63009991299980f99baf300f3021375400400a2646660020020046eacc030c088dd50019112999812801080089919980200218148019991191980080080291299981500089981599bb037520086e9800d2f5bded8c0264646464a66605666e400200084cc0bccdd81ba9008374c00e00a2a66605666e3c0200084c94ccc0b0c078c0b4dd500089981819bb037520126062605c6ea80040104010c94ccc0b14ccc0bc0045288a5014c0103d87a80001301b33030374c00297ae03233300100100800222253330310021001132333004004303500333223233001001005225333036001133037337606ea4010dd4001a5eb7bdb1804c8c8c8c94ccc0dccdc800400109981d99bb037520106ea001c01454ccc0dccdc7804001099299981c1815181c9baa00113303c337606ea4024c0f4c0e8dd5000802080219299981c18150008a60103d87a8000130273303c375000297ae03370000e00226607666ec0dd48011ba800133006006003375a60700066eb8c0d8008c0e8008c0e0004dd718180009bad3031001303300213302f337606ea4008dd3000998030030019bab302c003375c6054004605c00460580026eb8c090004dd5981280098138010800981100099801001181180091191980080099198008008019129998100008a5eb804c8ccc888c8cc00400400c894ccc098004400c4c8cc0a0dd3998141ba90063302830250013302830260014bd7019801801981500118140009bae301f00137566040002660060066048004604400244a66603e00229444c94ccc074c8cdc49bad3007001333008006375c601c0026eb8c028004dd618110010998018018008a5030220012301d301e301e00122232533301a3010301b37540022900009bad301f301c375400264a666034602060366ea8004530103d87a80001323300100137566040603a6ea8008894ccc07c004530103d87a80001323232325333020337220100042a66604066e3c0200084c03ccc090dd4000a5eb80530103d87a8000133006006003375a60420066eb8c07c008c08c008c084004c8cc004004010894ccc0780045300103d87a8000132323232533301f337220100042a66603e66e3c0200084c038cc08cdd3000a5eb80530103d87a8000133006006003375660400066eb8c078008c088008c08000494ccc058c02000452f5bded8c0264646600200297adef6c6022533301c00113301d337609801014000374c00697adef6c60132323232533301d33720910100002133021337609801014000374c00e00a2a66603a66e3d22100002133021337609801014000374c00e00626604266ec0dd48011ba6001330060060033756603c0066eb8c070008c080008c078004c8cc0040052f5bded8c044a66603600226603866ec13001014000375000697adef6c60132323232533301c33720910100002133020337609801014000375000e00a2a66603866e3d22100002133020337609801014000375000e00626604066ec0dd48011ba800133006006003375a603a0066eb8c06c008c07c008c0740048c068c06c004c060c054dd50008b19198008009bac30033015375401a44a66602e002298103d87a80001323253330163375e600c60306ea80080284c014cc0680092f5c026600800800260360046032002264a666026600a60286ea80044cc88c8cc00400400c894ccc068004528099299980c19b8f375c603a00400829444cc00c00c004c074004dd6180c180c980c980c980c980c980c980c980c980a9baa00d375c6030602a6ea800458c94ccc04cc014c050dd5000898011980b980c180a9baa0014bd700a60103d87a8000300230143754600460286ea800cdd2a40004602c002602860226ea800858dc3a4000602460260046022002601a6ea8008dc3a40042c601c601e004601a002601a0046016002600e6ea800452613656375a002ae6955ceaab9e5573eae815d0aba201"; const blueprint = new MintingBlueprint("V2"); blueprint.paramScript( demoCompiledCode, [mPubKeyAddress('aa048e4cc8a1e67e1d97ffbd4be614388014cbc2b2451527202943b6' , '9d4dcd7e454d2434164f4efb8edeb358d86a1dad9ec6224cfcbce3e6'), 100], "Mesh"// Mesh data type ); const policyId = blueprint.hash; const scriptCbor = blueprint.cbor ### [Minting Script blueprint - no parameter to script](https://meshjs.dev/apis/utilities/blueprints#minting-script-blueprint---no-parameter-to-script-toc) Creates a Minting script blueprint with no parameter to script. const blueprint = new MintingBlueprint("V2"); blueprint.noParamScript(demoCompiledCode); const policyId = bluePrint.hash const scriptCbor = bluePrint.cbor [Withdrawal Script Blueprint](https://meshjs.dev/apis/utilities/blueprints#withdrawal-script-blueprint) -------------------------------------------------------------------------------------------------------- `WithdrawalBlueprint` is a class for handling withdrawal blueprint particularly. You can provide `plutusVersion`, and `networkId` for the withdrawal validator to initialize the class. After that, providing the `compiledCode` and parameters to finish the setup. The class then provide easy access to common script information: * Script Hash * Script Cbor * Reward Address A withdrawal validator with no parameter, allows to provides only the `compiledCode` instead. ### [Withdrawal Script Blueprint - Apply parameter to script](https://meshjs.dev/apis/utilities/blueprints#withdrawal-script-blueprint---apply-parameter-to-script-toc) Creates a withdrawal script blueprint with apply parameter to script. import { WithdrawalBlueprint } from "@meshsdk/core"; const blueprint = new WithdrawalBlueprint("V2", 0); blueprint.paramScript( demoCompiledCode, mPubKeyAddress('aa048e4cc8a1e67e1d97ffbd4be614388014cbc2b2451527202943b6', '9d4dcd7e454d2434164f4efb8edeb358d86a1dad9ec6224cfcbce3e6'), 100], "Mesh", // Mesh Data type ) const scripthash = blueprint.hash; const scriptCbor = blueprint.cbor; const rewardAddress = blueprint.address; ### [Withdrawal Script blueprint - No parameter to script](https://meshjs.dev/apis/utilities/blueprints#withdrawal-script-blueprint---no-parameter-to-script-toc) Creates a withdrawal script blueprint with no parameter to script const blueprint = new WithdrawalBlueprint("V2" ,0); blueprint.noParamScript(demoCompiledCode); const scriptHash = bluerint.hash const scriptCbor = bluerint.cbor const rewardAddress = blueprint.address; [Data\ \ Useful utilities to parse and manipulate data](https://meshjs.dev/apis/data) [React Components\ \ Frontend React UI components and React hooks](https://meshjs.dev/react) ### On this page [Spending Script Blueprint](https://meshjs.dev/apis/utilities/blueprints#spending-script-blueprint) [Minting Script Blueprint](https://meshjs.dev/apis/utilities/blueprints#minting-script-blueprint) [Withdrawal Script Blueprint](https://meshjs.dev/apis/utilities/blueprints#withdrawal-script-blueprint) Ask AI --- # Escrow | Mesh SDK [Smart Contracts](https://meshjs.dev/smart-contracts) Escrow ====== Secure exchange of assets between two parties Copy MarkdownOpen The escrow smart contract allows two parties to exchange assets securely. The contract holds the assets until both parties agree and sign off on the transaction. There are 4 actions available to interact with this smart contract: * initiate escrow and deposit assets * deposit assets * complete escrow * cancel escrow ### [Install package](https://meshjs.dev/smart-contracts/escrow#install-package-toc) First you can to install the `@meshsdk/contracts` package: npm install @meshsdk/contract ### [Initialize the contract](https://meshjs.dev/smart-contracts/escrow#initialize-the-contract-toc) To initialize the escrow, we need to initialize a provider, `MeshTxBuilder` and `MeshEscrowContract`. import { MeshEscrowContract } from "@meshsdk/contract"; import { MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshEscrowContract({ mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }); Both on-chain and off-chain codes are open-source and available on [Mesh Github Repository](https://github.com/MeshJS/mesh/tree/main/packages/mesh-contract/src/escrow) . [Initiate Escrow](https://meshjs.dev/smart-contracts/escrow#initiate-escrow) ----------------------------------------------------------------------------- An escrow is initiated by one of the party, user A, by locking assets to the escrow contract. `initiateEscrow()` initiate an escrow. The function accepts the following parameters: * escrowAmount (Asset\[\]) - a list of assets user A is trading The function returns a transaction hex if the escrow is successfully initiated. ### [Initiate Escrow](https://meshjs.dev/smart-contracts/escrow#initiate-escrow-toc) Initiate an escrow, in this demo, person A is initiating the escrow and deposit ADA. **Listing price in Lovelace** `10000000` const escrowAmount: Asset[] = [\ {\ unit: "lovelace",\ quantity: '10000000',\ },\ ]; const tx = await contract.initiateEscrow(escrowAmount); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Recipient Deposit](https://meshjs.dev/smart-contracts/escrow#recipient-deposit) --------------------------------------------------------------------------------- User B can deposit assets into the escrow after initiation step (`initiateEscrow()`). `recipientDeposit()` deposit assets into the escrow. The function accepts the following parameters: * escrowUtxo (UTxO) - the utxo of the transaction on the contract * depositAmount (Asset\[\]) - a list of assets user B is trading We have provided a very handle function, `getUtxoByTxHash`, which will return the UTxO object for a given transaction hash. ### [Recipient Deposit](https://meshjs.dev/smart-contracts/escrow#recipient-deposit-toc) Deposit funds into the escrow for trade. In this demo, person B is depositing an asset into the escrow. **Tx hash:** `Tx hash` **Asset unit** `d9312da562da182b02322fd8acb536f37eb9d29fba7...68546f6b656e` const utxo = await contract.getUtxoByTxHash('');const escrowAmount: Asset[] = [\ {\ unit: 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e',\ quantity: '1',\ },\ ]; const tx = await contract.initiateEscrow(escrowAmount); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Complete Escrow](https://meshjs.dev/smart-contracts/escrow#complete-escrow) ----------------------------------------------------------------------------- A user can complete an escrow if the terms of the agreement are met. The completion can be initiated by any recipient of the escrow. `completeEscrow()` complete an escrow. The function accepts the following parameters: * escrowUtxo (UTxO) - the utxo of the transaction in the script to be completed **Important**: This is a multi-signature transaction. Both users must sign the transaction to complete the escrow. A [successful completion of the escrow](https://preprod.cardanoscan.io/transaction/019b6ba41ee0a9de90068fe5c1eb1fd81489be5d2402bd560b548e1cd7f22056) will result in the assets being swapped between the two parties. ### [Person A signs the transaction](https://meshjs.dev/smart-contracts/escrow#person-a-signs-the-transaction-toc) User A completes the escrow by calling the `completeEscrow()` function and partial sign the transaction. **Tx hash:** `Tx hash` const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.completeEscrow(utxo); const signedTxUserA = await wallet.signTx(tx, true); ### [Person B signs and submits the transaction](https://meshjs.dev/smart-contracts/escrow#person-b-signs-and-submits-the-transaction-toc) The signed transaction will be handled to User B to sign the transaction and submits it to the blockchain to complete the escrow. **Tx hash:** `Tx hash` **Transaction CBOR** `Transaction CBOR` const signedTxUserB = await wallet.signTx(signedTxUserA, true); const txHash = await wallet.submitTx(signedTxUserB); [Cancel Escrow](https://meshjs.dev/smart-contracts/escrow#cancel-escrow) ------------------------------------------------------------------------- A user can cancel an escrow if the other party fails to fulfill the terms of the agreement. Cancel can be initiated by any users who have partcipated in the escrow and can be done at any time before complete. Canceling the escrow will return the assets to the respective users. `cancelEscrow()` cancel an escrow. The function accepts the following parameters: * escrowUtxo (UTxO) - the utxo of the transaction to be canceled We have provided a very handle function, `getUtxoByTxHash`, which will return the UTxO object for a given transaction hash. ### [Cancel Escrow](https://meshjs.dev/smart-contracts/escrow#cancel-escrow-toc) Any users who have partcipated in the escrow and can cancel the trade at any time before complete. **Tx hash:** `Tx hash` const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.cancelEscrow(utxo); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Content Ownership\ \ Manage ownership of digital content and assets](https://meshjs.dev/smart-contracts/content-ownership) [GiftCard\ \ Create a giftcard with native tokens](https://meshjs.dev/smart-contracts/giftcard) ### On this page [Initiate Escrow](https://meshjs.dev/smart-contracts/escrow#initiate-escrow) [Recipient Deposit](https://meshjs.dev/smart-contracts/escrow#recipient-deposit) [Complete Escrow](https://meshjs.dev/smart-contracts/escrow#complete-escrow) [Cancel Escrow](https://meshjs.dev/smart-contracts/escrow#cancel-escrow) Ask AI --- # Hello World | Mesh SDK [Smart Contracts](https://meshjs.dev/smart-contracts) Hello World =========== Simple lock and unlock assets contract Copy MarkdownOpen The Hello World smart contract is a simple lock-and-unlock assets contract, providing a hands-on introduction to end-to-end smart contract validation and transaction building. There are 2 conditions to unlock the assets: * Signer must be the same as the one who locked the assets * Signer must provide the message `Hello, World!` There are 2 actions (or endpoints) available to interact with this smart contract: * Lock assets * Redeem assets ### [Install package](https://meshjs.dev/smart-contracts/hello-world#install-package-toc) First you can to install the `@meshsdk/contracts` package: npm install @meshsdk/contract ### [Initialize the contract](https://meshjs.dev/smart-contracts/hello-world#initialize-the-contract-toc) To initialize the contract, we need to initialize a provider, `MeshTxBuilder` and `MeshGiftCardContract`. import { MeshHelloWorldContract } from "@meshsdk/contract"; import { MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshHelloWorldContract({ mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }); Both on-chain and off-chain codes are open-source and available on [Mesh Github Repository](https://github.com/MeshJS/mesh/tree/main/packages/mesh-contract/src/hello-world) . [Lock Assets](https://meshjs.dev/smart-contracts/hello-world#lock-assets) -------------------------------------------------------------------------- This transaction locks funds into the contract. The datum must match the representation expected by the validator (and as specified in the blueprint), so this is a constructor with a single field that is a byte array. pub type Datum { owner: VerificationKeyHash, } Thus, we provide a hash digest of our public key, which will be needed to unlock the funds. await txBuilder .txOut(scriptAddress, assets) .txOutDatumHashValue(mConStr0([signerHash])) .changeAddress(walletAddress) .selectUtxosFrom(utxos) .complete(); ### [Lock Asset](https://meshjs.dev/smart-contracts/hello-world#lock-asset-toc) Lock asset in the contract **Lovelace amount** `5000000` const assets: Asset[] = [\ {\ unit: "lovelace",\ quantity: '5000000',\ },\ ]; const tx = await contract.lockAsset(assets); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Unlock Assets](https://meshjs.dev/smart-contracts/hello-world#unlock-assets) ------------------------------------------------------------------------------ There are 2 conditions to unlock the assets: * Signer must be the same as the one who locked the assets * Signer must provide the message `Hello, World!` The validator script for the contract checks that the redeemer is the same as the owner of the datum and that the message is `Hello, World!`: validator hello_world { spend( datum_opt: Option, redeemer: Redeemer, _input: OutputReference, tx: Transaction, ) { expect Some(datum) = datum_opt let must_say_hello = redeemer.msg == "Hello, World!" let must_be_signed = list.has(tx.extra_signatories, datum.owner) must_say_hello && must_be_signed } else(_) { fail } } ### [Redeem Giftcard](https://meshjs.dev/smart-contracts/hello-world#redeem-giftcard-toc) Redeem a gift card given the gift card UTxO **Tx hash** `Tx hash` **Message** `Hello, World!` const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.unlockAsset(utxo, 'Hello, World!'); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [GiftCard\ \ Create a giftcard with native tokens](https://meshjs.dev/smart-contracts/giftcard) [Marketplace\ \ Build a NFT marketplace to buy and sell NFTs](https://meshjs.dev/smart-contracts/marketplace) ### On this page [Lock Assets](https://meshjs.dev/smart-contracts/hello-world#lock-assets) [Unlock Assets](https://meshjs.dev/smart-contracts/hello-world#unlock-assets) Ask AI --- # Mint an NFT Collection | Mesh SDK [Learn](https://meshjs.dev/resources) [Guides](https://meshjs.dev/guides) Mint an NFT Collection ====================== Copy MarkdownOpen ### [Course Materials:](https://meshjs.dev/guides/nft-collection#course-materials-toc) 1. Install Bun ([https://bun.sh/docs/installation](https://bun.sh/docs/installation) ) 2. Fund Your Preprod Wallet ([https://docs.cardano.org/cardano-testnets/tools/faucet](https://docs.cardano.org/cardano-testnets/tools/faucet) ) 3. Create a Blockfrost Preprod Project ([https://blockfrost.io/dashboard](https://blockfrost.io/dashboard) ) 4. CIP-20 Definition ([https://cips.cardano.org/cip/CIP-20](https://cips.cardano.org/cip/CIP-20) ) Learn how to mint native assets on the Cardano blockchain. You will: 1. Understand tokens on Cardano. 2. Build simple minting transactions. 3. Understand community standards for NFTs. [Project Setup](https://meshjs.dev/guides/nft-collection#project-setup) ------------------------------------------------------------------------ Install Bun (see course material #1). Initialize a new directory and run: bun init bun install @meshsdk/core Generate and fund a Cardano wallet. Create `/scripts/brew.ts` and use MeshSDK to generate a wallet and log information. import { MeshWallet } from "@meshsdk/core"; const words = MeshWallet.brew() as string[]; const mnemonicString = words.join(" "); console.log("mnemonic:", mnemonicString); const wallet = new MeshWallet({ key: { type: "mnemonic", words }, networkId: 0, }); console.log("Public Change Address:", await wallet.getChangeAddress()); Run the script: bun run scripts/brew.ts Copy your public address and fund the wallet (course material #2). Obtain a Blockfrost Preprod project (course material #3). Copy your mnemonic and Blockfrost key into a `.env` file. [Mint Your Collection](https://meshjs.dev/guides/nft-collection#mint-your-collection) -------------------------------------------------------------------------------------- In `index.ts`, use Mesh building blocks to interact with the blockchain. import { MeshTxBuilder, MeshWallet, BlockfrostProvider } from "@meshsdk/core" const provider = new BlockfrostProvider(process.env.BLOCKFROST_KEY!); const words = process.env.MNEMONIC!.split(" "); const wallet = new MeshWallet({ key: { type: "mnemonic", words }, networkId: 0, fetcher: provider, submitter: provider, }); const txBuilder = new MeshTxBuilder({ fetcher: provider }); const address = await wallet.getChangeAddress(); const utxos = await wallet.getUtxos(); const { pubKeyHash } = deserializeAddress(address); Create a minting ruleset using a native script to derive the policy ID. const nativeScript: NativeScript = { type: "all", scripts: [\ {\ type: "before",\ slot: "90000000", // Any value beyond the current preprod absolute slot. When you read this, it's possible this slot has passed.\ },\ { type: "sig", keyHash: pubKeyHash },\ ], }; const forgeScript = ForgeScript.fromNativeScript(nativeScript); const policyId = resolveScriptHash(forgeScript); Write a function to generate on-chain metadata for image and attributes. type AssetMetadata = { files: { mediaType: string; name: string; src: string; }[]; image: string; mediaType: string; name: string; }; function get721Metadata( name: string, attributes?: Record ): AssetMetadata { return { ...attributes, files: [\ {\ mediaType: "image/png",\ name,\ src: "ipfs://QmPS4PBvpGc2z6Dd6JdYqfHrKnURjtRGPTJWdhnAXNA8bQ",\ },\ ], image: "ipfs://QmPS4PBvpGc2z6Dd6JdYqfHrKnURjtRGPTJWdhnAXNA8bQ", mediaType: "image/png", name, }; } Loop to create 9 unique tokens using the forge script. Commit, sign, and submit the transaction. const metadata: { [policyId: string]: { [assetName: string]: AssetMetadata; }; } = { [policyId]: {} }; for (let i = 1; i < 10; i++) { const tokenName = "Asset #" + i; const tokenHex = stringToHex(tokenName); txBuilder.mint("1", policyId, tokenHex).mintingScript(forgeScript); metadata[policyId]![tokenName] = get721Metadata(tokenName, { Attribute: i }); } const unsignedTx = await txBuilder .metadataValue(721, metadata) .changeAddress(address) .invalidHereafter(90000000) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); console.log("Submitted TX Hash:", txHash); Read the transaction hash and view the transaction on a chain explorer. [Resolve Node-Specific Imports Errors\ \ Previous Page](https://meshjs.dev/guides/node-specific-imports) [Tutorials\ \ Step-by-step tutorials for building Cardano applications with Mesh SDK - from beginner to advanced.](https://meshjs.dev/resources/tutorials) ### On this page [Project Setup](https://meshjs.dev/guides/nft-collection#project-setup) [Mint Your Collection](https://meshjs.dev/guides/nft-collection#mint-your-collection) Ask AI --- # Develop your first Web3 App | Mesh SDK [Learn](https://meshjs.dev/resources) [Guides](https://meshjs.dev/guides) Develop your first Web3 App =========================== Copy MarkdownOpen Set up a Next.js application and connect it to the Cardano blockchain using Mesh. Create a simple application that allows users to connect their wallets and view assets. This guide focuses on Next.js, but Mesh works with Remix, React, Vue, and [Svelte](https://meshjs.dev/svelte) . Follow this guide or use the [Mesh CLI](https://meshjs.dev/) to scaffold a new project. npx meshjs your-app-name [Setup Next.js](https://meshjs.dev/guides/nextjs#setup-nextjs) --------------------------------------------------------------- ### [1\. Create project folder and open Visual Studio Code](https://meshjs.dev/guides/nextjs#1-create-project-folder-and-open-visual-studio-code-toc) Create a new folder. Open Visual Studio Code and drag the folder into it. ### [2\. Create Next.js app](https://meshjs.dev/guides/nextjs#2-create-nextjs-app-toc) Open the **Terminal** and create a new Next.js application: npx create-next-app@latest --typescript . Need to install the following packages: Ok to proceed? (y) ✔ Would you like to use ESLint? … Yes ✔ Would you like to use Tailwind CSS? … Yes ✔ Would you like your code inside a `src/` directory? … Yes ✔ Would you like to use App Router? … No ✔ Would you like to use Turbopack for next dev? … No ✔ Would you like to customize the import alias (@/* by default)? … No ### [3\. Start development server](https://meshjs.dev/guides/nextjs#3-start-development-server-toc) Start the development server: npm run dev Visit [http://localhost:3000](http://localhost:3000/) to view your application. `CTRL+C` to stop. [Setup Mesh](https://meshjs.dev/guides/nextjs#setup-mesh) ---------------------------------------------------------- Install Mesh: npm install @meshsdk/core @meshsdk/react Your application is ready to connect wallets and transact. [Connect wallet and view assets](https://meshjs.dev/guides/nextjs#connect-wallet-and-view-assets) -------------------------------------------------------------------------------------------------- ### [1\. Add MeshProvider](https://meshjs.dev/guides/nextjs#1-add-meshprovider-toc) Open **pages/\_app.tsx**, import and include [MeshProvider](https://meshjs.dev/react/getting-started#meshProvider) : import "../styles/globals.css"; import "@meshsdk/react/styles.css"; import type { AppProps } from "next/app"; import { MeshProvider } from "@meshsdk/react"; function MyApp({ Component, pageProps }: AppProps) { return ( ); } export default MyApp; ### [2\. Add connect wallet component and check wallet's assets](https://meshjs.dev/guides/nextjs#2-add-connect-wallet-component-and-check-wallets-assets-toc) Add the [connect wallet component](https://meshjs.dev/react/ui-components#connectWallet) . Link components to allow users to connect and query assets. Replace **pages/index.tsx** with: import { useState } from "react"; import type { NextPage } from "next"; import { useWallet } from '@meshsdk/react'; import { CardanoWallet } from '@meshsdk/react'; const Home: NextPage = () => { const { connected, wallet } = useWallet(); const [assets, setAssets] = useState(null); const [loading, setLoading] = useState(false); async function getAssets() { if (wallet) { setLoading(true); const _assets = await wallet.getAssets(); setAssets(_assets); setLoading(false); } } return (

Connect Wallet

{connected && ( <>

Get Wallet Assets

{assets ? (
                  
                    {JSON.stringify(assets, null, 2)}
                  
                
) : ( )} )}
); }; export default Home; Start the development server: npm run dev Visit [http://localhost:3000](http://localhost:3000/) to connect available wallets and view assets. Receive test ADA (tADA) from the [official faucet](https://docs.cardano.org/cardano-testnets/tools/faucet) . New to Cardano? Download a wallet. Tall Nupinks' [Cardano Wallets 101 guide](https://cutedumborcs.substack.com/p/cardano-wallets-101) covers the fundamentals. ### [3\. Try on your own](https://meshjs.dev/guides/nextjs#3-try-on-your-own-toc) Implement a component to display the wallet address and lovelace amount. See the [wallet](https://meshjs.dev/apis/wallets/browserwallet) page. [Guides\ \ Guides for web developers and blockchain full-stack developers.](https://meshjs.dev/guides) [Minting Application\ \ Next Page](https://meshjs.dev/guides/minting-on-nodejs) ### On this page [Setup Next.js](https://meshjs.dev/guides/nextjs#setup-nextjs) [Setup Mesh](https://meshjs.dev/guides/nextjs#setup-mesh) [Connect wallet and view assets](https://meshjs.dev/guides/nextjs#connect-wallet-and-view-assets) Ask AI --- # Swap | Mesh SDK [Smart Contracts](https://meshjs.dev/smart-contracts) Swap ==== Swap contract facilitates the exchange of assets between two parties Copy MarkdownOpen Swap contract facilitates the exchange of assets between two parties. This contract is designed to be used in a peer-to-peer exchange scenario where two parties agree to exchange assets. The contract ensures that the assets are locked up until it is accepted by the other party. At any point before it is accepted, one can cancel the swap to retrieve the assets. There are 2 actions (or endpoints) available to interact with this smart contract: * initiate swap * accept asset * cancel swap ### [Install package](https://meshjs.dev/smart-contracts/swap#install-package-toc) First you can to install the `@meshsdk/contracts` package: npm install @meshsdk/contract ### [Initialize the contract](https://meshjs.dev/smart-contracts/swap#initialize-the-contract-toc) To initialize the payment splitter, we need to initialize a [provider](https://meshjs.dev/providers) , `MeshTxBuilder` and `MeshSwapContract`. import { MeshSwapContract } from "@meshsdk/contract"; import { MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshSwapContract({ mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }); Both on-chain and off-chain codes are open-source and available on [Mesh Github Repository](https://github.com/MeshJS/mesh/tree/main/packages/mesh-contract/src/swap) . [Initiate Swap](https://meshjs.dev/smart-contracts/swap#initiate-swap) ----------------------------------------------------------------------- User A can initiate a swap by providing assets to the swap contract. `initiateSwap()` initiate a swap. The function accepts the following parameters: * toProvide (Asset\[\]) - a list of assets user A is trading * toReceive (Asset\[\]) - a list of assets user A is expecting to receive from another user Note that the parameters are arrays, so you can provide multiple assets to the swap, and these assets can be tokens and lovelace. ### [Initiate Swap](https://meshjs.dev/smart-contracts/swap#initiate-swap-toc) Initiate a swap by defining the assets for the swap contract **Amount lovelace to give** `10000000` **Asset to receive** `d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e` const assetToProvide: Asset = { unit: "lovelace", quantity: '10000000', }; const assetToReceive: Asset = { unit: 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e', quantity: "1", }; const tx = await contract.initiateSwap([assetToProvide], [assetToReceive]); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Accept Swap](https://meshjs.dev/smart-contracts/swap#accept-swap) ------------------------------------------------------------------- User B can accept a swap by providing the swap transaction hash to the contract. `acceptSwap()` accept a swap. The function accepts the following parameters: * swapUtxo (UTxO) - the utxo of the transaction in the script for the swap The function accepts a swap transaction hash and returns a transaction hash if the swap is successfully accepted. A [successful transaction](https://preprod.cardanoscan.io/transaction/e266fc6b0b2481988f9742a28b914dabf7da5403a3893d5ba4b05530d2519f3a) will send the assets to the wallet that signed the transaction to accept the swap. ### [Accept Swap](https://meshjs.dev/smart-contracts/swap#accept-swap-toc) Accept a swap by providing the assets to the swap contract **Tx hash** `Tx hash` const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.acceptSwap(utxo); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Cancel Swap](https://meshjs.dev/smart-contracts/swap#cancel-swap) ------------------------------------------------------------------- Any any time before swap is accepted, user A can cancel the swap. `cancelSwap()` cancel a swap. The function accepts the following parameters: * swapUtxo (UTxO) - the utxo of the transaction in the script for the swap The function accepts a swap transaction hash and returns a transaction hash if the swap is successfully canceled. ### [Cancel Swap](https://meshjs.dev/smart-contracts/swap#cancel-swap-toc) Cancel a swap to get your funds back **Tx hash** `Tx hash` const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.cancelSwap(utxo); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Payment Splitter\ \ Split payouts equally among a list of specified payees](https://meshjs.dev/smart-contracts/payment-splitter) [Vesting\ \ Locks up funds and allows the beneficiary to withdraw the funds after the lockup period](https://meshjs.dev/smart-contracts/vesting) ### On this page [Initiate Swap](https://meshjs.dev/smart-contracts/swap#initiate-swap) [Accept Swap](https://meshjs.dev/smart-contracts/swap#accept-swap) [Cancel Swap](https://meshjs.dev/smart-contracts/swap#cancel-swap) Ask AI --- # Project Structure | Mesh SDK [Midnight](https://meshjs.dev/midnight) Midnight Contracts Wizard Project Structure ================= Understanding the generated project structure Copy MarkdownOpen [Generated Structure](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#generated-structure) =================================================================================================================== When you create a project using the Midnight Contracts Wizard, it generates a complete directory structure with all necessary files. [Directory Layout](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#directory-layout) ------------------------------------------------------------------------------------------------------------- my-project/ ├── src/ │ ├── [selected-contracts]/ │ │ └── *.compact │ └── managed/ # Compiled contracts ├── dist/ # Distribution files ├── package.json ├── tsconfig.json ├── tsconfig.build.json └── README.md [Directory Breakdown](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#directory-breakdown) ------------------------------------------------------------------------------------------------------------------- ### [`/src`](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#src) Contains all your contract source files. src/ ├── tokenization/ # If selected │ └── token.compact ├── staking/ # If selected │ └── staking.compact ├── identity/ # If selected │ └── identity.compact ├── oracle/ # If selected │ └── oracle.compact ├── lending/ # If selected │ └── lending.compact └── managed/ # Auto-generated └── *.ts # Compiled TypeScript ### [`/src/managed`](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#srcmanaged) Automatically generated directory containing compiled TypeScript files from your `.compact` contracts. **Do not edit manually** - these files are regenerated on each build. ### [`/dist`](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#dist) Output directory for the final compiled JavaScript and type definitions, ready for distribution or deployment. [Configuration Files](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#configuration-files) ------------------------------------------------------------------------------------------------------------------- ### [`package.json`](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#packagejson) Contains project metadata, dependencies, and build scripts: { "name": "my-project", "version": "1.0.0", "scripts": { "build": "tsc -p tsconfig.build.json", "compile": "compact-cli compile src/**/*.compact", "clean": "rm -rf dist src/managed" }, "dependencies": { "@midnight-ntwrk/compact-runtime": "^0.8.1", "@midnight-ntwrk/midnight-js-types": "^2.0.2" } } ### [`tsconfig.json`](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#tsconfigjson) Main TypeScript configuration for development: { "compilerOptions": { "target": "ES2020", "module": "commonjs", "lib": ["ES2020"], "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "outDir": "./dist", "rootDir": "./src" }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] } ### [`tsconfig.build.json`](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#tsconfigbuildjson) Extends main config for production builds: { "extends": "./tsconfig.json", "compilerOptions": { "declaration": true, "declarationMap": true, "sourceMap": true }, "exclude": ["**/*.test.ts", "**/*.spec.ts"] } [Contract Files](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#contract-files) --------------------------------------------------------------------------------------------------------- Each selected contract includes its `.compact` source file: ### [Example: `src/tokenization/token.compact`](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#example-srctokenizationtokencompact) contract Token { // ZK circuit implementations circuit mint(amount: Secret) -> Public { // Minting logic } circuit transfer(to: Address, amount: Secret) -> Public { // Transfer logic } // Additional circuits... } [README.md](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#readmemd) ---------------------------------------------------------------------------------------------- Each generated project includes a comprehensive README with: * Project overview * Installation instructions * Build commands * Contract descriptions * Usage examples * Deployment guide [Next Steps](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#next-steps) ------------------------------------------------------------------------------------------------- Now that you understand the project structure: * Start modifying contracts in `src/` * Run builds with `npm run build` * Integrate with your dApp * Deploy to Midnight Network [Available Contracts\ \ Explore the smart contract templates available in the Midnight Contracts Wizard](https://meshjs.dev/midnight/midnight-contracts-wizard/contracts) [Yaci\ \ Customizable Cardano devnet for enabling faster iterations](https://meshjs.dev/yaci) ### On this page [Generated Structure](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#generated-structure) [Directory Layout](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#directory-layout) [Directory Breakdown](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#directory-breakdown) [`/src`](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#src) [`/src/managed`](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#srcmanaged) [`/dist`](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#dist) [Configuration Files](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#configuration-files) [`package.json`](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#packagejson) [`tsconfig.json`](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#tsconfigjson) [`tsconfig.build.json`](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#tsconfigbuildjson) [Contract Files](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#contract-files) [Example: `src/tokenization/token.compact`](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#example-srctokenizationtokencompact) [README.md](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#readmemd) [Next Steps](https://meshjs.dev/midnight/midnight-contracts-wizard/project-structure#next-steps) Ask AI --- # Value | Mesh SDK [Mesh API](https://meshjs.dev/apis) Data Value ===== Manipulate Value Easily Copy MarkdownOpen We all know the pain of conducting `Value` operation in Cardano. Mesh provides a full set of value methods to help converting, operating, accessing and comparing Cardano data. ### [Value Types Support](https://meshjs.dev/apis/data/value#value-types-support) **Convertors** Convertor functions provide utilities around round trip among Cardano onchain data and off chain `JSON` and `Data` type. **Operators** Operator functions provide utilities into performing value manipulation. They are useful in apps which check against value payment involving calculation in value. **Accessor** Accessor functions provide utilities in obtaining keys or values of the `Value` type. **Comparator** Comparator functions provide utilities in comparing different `Value`. It helps with offchain validation before using for transaction building. [Convertor - converts assets into Cardano data Value in JSON](https://meshjs.dev/apis/data/value#convertor---converts-assets-into-cardano-data-value-in-json) -------------------------------------------------------------------------------------------------------------------------------------------------------------- `value` converts assets into Cardano data Value in JSON with parameters: * assets - Asset\[\] to convert ### [value](https://meshjs.dev/apis/data/value#value-toc) Converts assets into MeshValue with parameters - asset\[\] e.g. ada value, simple token token, complex value. const val: Asset[] = [{ unit: "lovelace", quantity: "1000000" }]; const datum: Value = value(val); const nameMap = dict([[byteString(""), integer(1000000)]]); const valMap = dict>([[byteString(""), nameMap]]); if (JSON.stringify(datum) === JSON.stringify(valMap)) { return true; [Convertor - converts assets into Cardano data Value in Mesh Data type](https://meshjs.dev/apis/data/value#convertor---converts-assets-into-cardano-data-value-in-mesh-data-type) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- `mValue` converts assets into Cardano data value in Mesh Data type with parameters: * assets - Asset\[\] to convert ### [mValue](https://meshjs.dev/apis/data/value#mvalue-toc) Converts assets into MeshValue with parameters - asset\[\] e.g. ada value, simple token token, complex value. const val: Asset[] = [{ unit: "lovelace", quantity: "1000000" }]; const datum: MValue = mValue(val); const nameMap = new Map().set("", 1000000); const valMap = new Map().set("", nameMap); if (JSON.stringify(datum) === JSON.stringify(valMap)) { return true; [Convertor - converts assets into MeshValue with parameters - asset\[\]](https://meshjs.dev/apis/data/value#convertor---converts-assets-into-meshvalue-with-parameters---asset) -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- `fromAssets` converts assets into MeshValue with parameters: * assets - the assets to convert ### [fromAssets](https://meshjs.dev/apis/data/value#fromassets-toc) Converts assets into MeshValue with parameters - asset\[\] e.g. ada value, simple token token, complex value. import { MeshValue } from "@meshsdk/common"; const assets: Asset[] = [\ { unit: "c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64", quantity: "100" },\ { unit: "lovelace", quantity: "10" },\ ]; const value = MeshValue.fromAssets(assets); return value; [Convertor - converts the MeshValue object into an array of Asset](https://meshjs.dev/apis/data/value#convertor---converts-the-meshvalue-object-into-an-array-of-asset) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ `toAssets` Convert the MeshValue object into an array of Asset ### [toAssets](https://meshjs.dev/apis/data/value#toassets-toc) Converts the MeshValue object into an array of Asset import { MeshValue } from "@meshsdk/common"; const val: Asset[] = [{ unit: "lovelace", quantity: "1000000" }]; const plutusValue: Value = value(val); const assets: Asset[] = MeshValue.fromValue(plutusValue).toAssets(); return assets; [Convertor - converts Value (the JSON representation of Cardano data Value) into MeshValue](https://meshjs.dev/apis/data/value#convertor---converts-value-the-json-representation-of-cardano-data-value-into-meshvalue) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ `fromValue` Convert Value (the JSON representation of Cardano data Value) into MeshValue with parameters: * plutusValue - the value to convert ### [fromValue](https://meshjs.dev/apis/data/value#fromvalue-toc) Convert Value (the JSON representation of Cardano data Value) into MeshValue. import { MeshValue } from "@meshsdk/common"; const val: Asset[] = [{ unit: "lovelace", quantity: "1000000" }]; const plutusValue: Value = value(val); const assets: Asset[] = MeshValue.fromValue(plutusValue).toAssets(); return assets; [Convertor - converts the MeshValue object into Cardano data Value in Mesh Data type](https://meshjs.dev/apis/data/value#convertor---converts-the-meshvalue-object-into-cardano-data-value-in-mesh-data-type) -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- `toData` Convert the MashValue object into Cardano data Value in Mesh Data type ### [toData](https://meshjs.dev/apis/data/value#todata-toc) Converts the MeshValue object into Cardano data Value in Mesh Data type import { MeshValue } from "@meshsdk/common"; const val: Asset[] = [\ {\ unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234",\ quantity: "100",\ },\ {\ unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234",\ quantity: "200",\ },\ ]; const plutusValue: Value = value(val); const data = MeshValue.fromValue(plutusValue).toData(); const expected: MValue = mValue(val); if (JSON.stringify(expected) === JSON.stringify(data)) { return true; [Convertor - converts the MeshValue object into a JSON representation of Cardano data Value](https://meshjs.dev/apis/data/value#convertor---converts-the-meshvalue-object-into-a-json-representation-of-cardano-data-value) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- `toJSON` Converts the MeshValue object into a JSON representation of Cardano data Value ### [toJSON](https://meshjs.dev/apis/data/value#tojson-toc) Converts the MeshValue object into a JSON representation of Cardano data Value import { MeshValue } from "@meshsdk/common"; const assets: Asset[] = [\ { unit: "lovelace", quantity: "1000000" },\ {\ unit: "c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64",\ quantity: "500",\ },\ ]; const expectedValue = assocMap([\ [currencySymbol(""), assocMap([[tokenName(""), integer(1000000)]])],\ [\ currencySymbol(\ "c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c",\ ),\ assocMap([[tokenName("000643b04d65736820676f6f64"), integer(500)]]),\ ],\ ]); const meshValue = new MeshValue(); meshValue.toAssets = () => assets; const jsonValue = meshValue.toJSON(); if (JSON.stringify(jsonValue) === JSON.stringify(expectedValue)) { return true; } [Operator - add an asset to the Value class's value record with parameters - asset](https://meshjs.dev/apis/data/value#operator---add-an-asset-to-the-value-classs-value-record-with-parameters---asset) --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- `addAsset` Add an asset to the Value class's value record with parameters: * asset - Asset to add ### [addAsset](https://meshjs.dev/apis/data/value#addasset-toc) Add an asset to the Value class's value record with parameters - asset import { MeshValue } from "@meshsdk/common"; const value = new MeshValue(); const singleAsset: Asset = { unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234", quantity: "100" }; value.addAsset(singleAsset); return value.value; [Operator - add an array of assets to the Value class's value record with parameters - assets](https://meshjs.dev/apis/data/value#operator---add-an-array-of-assets-to-the-value-classs-value-record-with-parameters---assets) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- `addAssets` Add an array of assets to the Value class's value record with parameters: * assets - Asset\[\] to add ### [addAssets](https://meshjs.dev/apis/data/value#addassets-toc) Add an array of assets to the Value class's value record with parameters - assets import { MeshValue } from "@meshsdk/common"; const value = new MeshValue(); const assets: Asset[] = [\ { unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234", quantity: "100" },\ { unit: "lovelace", quantity: "10" },\ { unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234", quantity: "100" },\ { unit: "lovelace", quantity: "10" },\ ]; value.addAssets(assets); return value.value; [Operator - substract an asset from the Value class's value record with parameters - asset](https://meshjs.dev/apis/data/value#operator---substract-an-asset-from-the-value-classs-value-record-with-parameters---asset) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- `negateAsset` Substract an asset from the Value class's value record with parameters: * asset - Asset to substract ### [negateAsset](https://meshjs.dev/apis/data/value#negateasset-toc) Substract an asset from the Value class's value record with parameters - asset import { MeshValue } from "@meshsdk/common"; const value = new MeshValue(); value.value = { lovelace: 10n }; value.negateAsset({ unit: "lovelace", quantity: "5" }); return value.value; [Operator - substract an array of assets from the Value class's value record with parameters - assets](https://meshjs.dev/apis/data/value#operator---substract-an-array-of-assets-from-the-value-classs-value-record-with-parameters---assets) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- `negateAssets` Substract an array of assets from the Value class's value record with parameters: * assets - Asset\[\] to substract ### [negateAssets](https://meshjs.dev/apis/data/value#negateassets-toc) Substract an array of assets from the Value class's value record with parameters - assets const value = new MeshValue(); value.value = { lovelace: 20n, "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234": 10n }; value.negateAssets([\ { unit: "lovelace", quantity: "5" },\ { unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234", quantity: "3" },\ ]); return value.value; [Operator - merge the given values with parameters - values](https://meshjs.dev/apis/data/value#operator---merge-the-given-values-with-parameters---values) ------------------------------------------------------------------------------------------------------------------------------------------------------------ `merge` Merge the given values * values - The other values to merge [merge](https://meshjs.dev/apis/data/value#merge-toc) ------------------------------------------------------ Merge the given values with parameters - values const value1 = new MeshValue(); value1.value = { lovelace: 20n, "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234": 10n }; const value2 = new MeshValue(); value2.value = { lovelace: 10n, "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234": 5n }; return value1.merge(value2).value; [Accessor - get the quantity of asset object per lovelace unit](https://meshjs.dev/apis/data/value#accessor---get-the-quantity-of-asset-object-per-lovelace-unit) ------------------------------------------------------------------------------------------------------------------------------------------------------------------ `get` get the quantity of asset object per unit, with parameters * unit - the unit to get the quantity of the assets e.g. lovelace ### [get](https://meshjs.dev/apis/data/value#get-toc) Get the quantity of asset object per unit import { MeshValue } from "@meshsdk/common"; const value = new MeshValue({ lovelace: 20n }); value.get("lovelace"); return value; [Accessor - get all asset units with no parameters needed](https://meshjs.dev/apis/data/value#accessor---get-all-asset-units-with-no-parameters-needed) -------------------------------------------------------------------------------------------------------------------------------------------------------- `units` get all asset units with no parameters (e.g. unit) needed ### [units](https://meshjs.dev/apis/data/value#units-toc) Get all asset units with no parameters needed import { MeshValue } from "@meshsdk/common"; const value = new MeshValue({ lovelace: 20n, "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234": 10n, }); return value.units(); [Comparator - check if the value is greater than or equal to another value with parameters - other](https://meshjs.dev/apis/data/value#comparator---check-if-the-value-is-greater-than-or-equal-to-another-value-with-parameters---other) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ `geq` Check if the value is greater than or equal to another value with parameters: * other - The MeshValue to compare against ### [geq](https://meshjs.dev/apis/data/value#geq-toc) Check if the value is greater than or equal to another value with parameters - other import { MeshValue } from "@meshsdk/common"; const value = new MeshValue({ lovelace: 20n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 10n, }); const target = new MeshValue({ lovelace: 10n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 5n, }); return value.geq(target); [Comparator - check if the value is greater than or equal to another value with parameters - unit, other](https://meshjs.dev/apis/data/value#comparator---check-if-the-value-is-greater-than-or-equal-to-another-value-with-parameters---unit-other) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- `geqUnit` Check if the value is greater than or equal to another value with parameters: * unit - The unit to compare * other - The MeshValue to compare against ### [geqUnit](https://meshjs.dev/apis/data/value#gequnit-toc) Check if the value is greater than or equal to another value with parameters - unit, other import { MeshValue } from "@meshsdk/common"; const value = new MeshValue({ lovelace: 20n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 10n, }); const target = new MeshValue({ lovelace: 10n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 5n, }); const resultLovelace = value.geqUnit("lovelace", target); const resultmockvalue = value.geqUnit( "c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64", target, ); return { resultLovelace, resultmockvalue }; } [Comparator - check if the value is less than or equal to another value with parameters - other](https://meshjs.dev/apis/data/value#comparator---check-if-the-value-is-less-than-or-equal-to-another-value-with-parameters---other) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ `leq` Check if the value is less than or equal to another value with parameters: * other - The MeshValue to compare against ### [leq](https://meshjs.dev/apis/data/value#leq-toc) Check if the value is less than or equal to another value with parameters - other import { MeshValue } from "@meshsdk/common"; const value = new MeshValue({ lovelace: 20n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 10n, }); const target = new MeshValue({ lovelace: 30n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 15n, }); return value.leq(target); [Comparator - check if the specific unit of value is less than or equal to that unit of another value with parameters - unit, other](https://meshjs.dev/apis/data/value#comparator---check-if-the-specific-unit-of-value-is-less-than-or-equal-to-that-unit-of-another-value-with-parameters---unit-other) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- `leqUnit` Check if the specific unit of value is less than or equal to that unit of another value with parameters: * unit - The unit to compare * other - The MeshValue to compare against ### [lequnit](https://meshjs.dev/apis/data/value#lequnit-toc) Check if the specific unit of value is less than or equal to that unit of another value with parameters - unit, other import { MeshValue } from "@meshsdk/common"; const value = new MeshValue({ lovelace: 20n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 10n, }); const target = new MeshValue({ lovelace: 30n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 15n, }); const resultLovelace = value.leqUnit("lovelace", target); const resultmockvalue = value.leqUnit( "c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64", target, ); return { resultLovelace, resultmockvalue }; [Comparator - check if the value is empty](https://meshjs.dev/apis/data/value#comparator---check-if-the-value-is-empty) ------------------------------------------------------------------------------------------------------------------------ `isEmpty` Check if the value is empty ### [isEmpty](https://meshjs.dev/apis/data/value#isempty-toc) Check if the value is empty import { MeshValue } from "@meshsdk/common"; const value = new MeshValue(); return value.isEmpty(); ### On this page [Value Types Support](https://meshjs.dev/apis/data/value#value-types-support) [Convertor - converts assets into Cardano data Value in JSON](https://meshjs.dev/apis/data/value#convertor---converts-assets-into-cardano-data-value-in-json) [Convertor - converts assets into Cardano data Value in Mesh Data type](https://meshjs.dev/apis/data/value#convertor---converts-assets-into-cardano-data-value-in-mesh-data-type) [Convertor - converts assets into MeshValue with parameters - asset\[\]](https://meshjs.dev/apis/data/value#convertor---converts-assets-into-meshvalue-with-parameters---asset) [Convertor - converts the MeshValue object into an array of Asset](https://meshjs.dev/apis/data/value#convertor---converts-the-meshvalue-object-into-an-array-of-asset) [Convertor - converts Value (the JSON representation of Cardano data Value) into MeshValue](https://meshjs.dev/apis/data/value#convertor---converts-value-the-json-representation-of-cardano-data-value-into-meshvalue) [Convertor - converts the MeshValue object into Cardano data Value in Mesh Data type](https://meshjs.dev/apis/data/value#convertor---converts-the-meshvalue-object-into-cardano-data-value-in-mesh-data-type) [Convertor - converts the MeshValue object into a JSON representation of Cardano data Value](https://meshjs.dev/apis/data/value#convertor---converts-the-meshvalue-object-into-a-json-representation-of-cardano-data-value) [Operator - add an asset to the Value class's value record with parameters - asset](https://meshjs.dev/apis/data/value#operator---add-an-asset-to-the-value-classs-value-record-with-parameters---asset) [Operator - add an array of assets to the Value class's value record with parameters - assets](https://meshjs.dev/apis/data/value#operator---add-an-array-of-assets-to-the-value-classs-value-record-with-parameters---assets) [Operator - substract an asset from the Value class's value record with parameters - asset](https://meshjs.dev/apis/data/value#operator---substract-an-asset-from-the-value-classs-value-record-with-parameters---asset) [Operator - substract an array of assets from the Value class's value record with parameters - assets](https://meshjs.dev/apis/data/value#operator---substract-an-array-of-assets-from-the-value-classs-value-record-with-parameters---assets) [Operator - merge the given values with parameters - values](https://meshjs.dev/apis/data/value#operator---merge-the-given-values-with-parameters---values) [Accessor - get the quantity of asset object per lovelace unit](https://meshjs.dev/apis/data/value#accessor---get-the-quantity-of-asset-object-per-lovelace-unit) [Accessor - get all asset units with no parameters needed](https://meshjs.dev/apis/data/value#accessor---get-all-asset-units-with-no-parameters-needed) [Comparator - check if the value is greater than or equal to another value with parameters - other](https://meshjs.dev/apis/data/value#comparator---check-if-the-value-is-greater-than-or-equal-to-another-value-with-parameters---other) [Comparator - check if the value is greater than or equal to another value with parameters - unit, other](https://meshjs.dev/apis/data/value#comparator---check-if-the-value-is-greater-than-or-equal-to-another-value-with-parameters---unit-other) [Comparator - check if the value is less than or equal to another value with parameters - other](https://meshjs.dev/apis/data/value#comparator---check-if-the-value-is-less-than-or-equal-to-another-value-with-parameters---other) [Comparator - check if the specific unit of value is less than or equal to that unit of another value with parameters - unit, other](https://meshjs.dev/apis/data/value#comparator---check-if-the-specific-unit-of-value-is-less-than-or-equal-to-that-unit-of-another-value-with-parameters---unit-other) [Comparator - check if the value is empty](https://meshjs.dev/apis/data/value#comparator---check-if-the-value-is-empty) Ask AI --- # Multi-Signatures Transaction | Mesh SDK [Learn](https://meshjs.dev/resources) [Guides](https://meshjs.dev/guides) Multi-Signatures Transaction ============================ Copy MarkdownOpen Multi-signature (multi-sig) transactions require more than one signature before broadcasting. Include two or more signers, such as wallets ([Browser Wallet](https://meshjs.dev/apis/wallets/browserwallet) or [Mesh Wallet](https://meshjs.dev/apis/wallets/meshwallet) ) or Plutus scripts. Build a multi-sig transaction for minting. Two wallets are involved: 1. Client wallet (user buying the asset) 2. Application wallet (holds the forging script) Connect to the user's CIP30 wallet (`BrowserWallet`) to request a minting transaction. The backend application wallet (`MeshWallet`) builds the transaction, and the user signs it. [Check out the code here](https://github.com/MeshJS/mesh/blob/main/apps/playground/src/pages/guides/multisig-minting/demo.tsx) . [Connect wallet (client)](https://meshjs.dev/guides/multisig-minting#connect-wallet-client) -------------------------------------------------------------------------------------------- Connect the client's wallet and obtain their address and UTXOs. Connect with `BrowserWallet`: import { BrowserWallet } from '@meshsdk/core'; const wallet = await BrowserWallet.enable(walletName); Or use the `CardanoWallet` component: import { CardanoWallet, useWallet } from "@meshsdk/react"; export default function Page() { const { wallet, connected } = useWallet(); return } Get the client's address and UTXOs: const recipientAddress = await wallet.getChangeAddress(); const utxos = await wallet.getUtxos(); The change address receives the minted NFTs and change. The client's UTXOs are needed to build the transaction. Select required UTXOs using `experimentalSelectUtxos`: const assetMap = new Map(); assetMap.set("lovelace", mintingFee); const selectedUtxos = experimentalSelectUtxos(assetMap, utxos, "5000000"); `experimentalSelectUtxos` returns required UTXOs. `mintingFee` is the minting cost; `5000000` buffers the transaction fee. Send `selectedUtxos` and `recipientAddress` to the backend. [Build transaction (application)](https://meshjs.dev/guides/multisig-minting#build-transaction-application) ------------------------------------------------------------------------------------------------------------ Build the minting transaction. This guide assumes a backend server (e.g., Vercel API, NestJS, ExpressJS). Initialize a [blockchain provider](https://meshjs.dev/providers) and [Mesh Wallet](https://meshjs.dev/apis/wallets/meshwallet) . const provider = new BlockfrostProvider( '' ); const meshWallet = new MeshWallet({ networkId: 0, fetcher: provider, submitter: provider, key: { type: 'mnemonic', words: yourMnemonic, }, }); Define the forging script: const meshWalletAddress = meshWallet.getChangeAddress(); const forgingScript = ForgeScript.withOneSignature(meshWalletAddress); Define `AssetMetadata`: const assetName = 'MeshToken'; const assetMetadata: AssetMetadata = { name: 'Mesh Token', image: 'ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua', mediaType: 'image/jpg', description: 'This NFT was minted by Mesh (https://meshjs.dev/).', }; Create the `Mint` object: const asset: Mint = { assetName: assetName, assetQuantity: '1', metadata: assetMetadata, label: '721', recipient: recipientAddress, }; Create the transaction. Set inputs, mint asset, send lovelace, set change address, and build: const tx = new Transaction({ initiator: meshWallet }); tx.setTxInputs(userUtxos); tx.mintAsset(forgingScript, asset); tx.sendLovelace(bankWalletAddress, mintingFee); tx.setChangeAddress(recipientAddress); const unsignedTx = await tx.build(); Optionally, mask metadata: originalMetadata = Transaction.readMetadata(unsignedTx); Store `originalMetadata` to merge after user signature. Send the transaction to the client. [Sign transaction (client)](https://meshjs.dev/guides/multisig-minting#sign-transaction-client) ------------------------------------------------------------------------------------------------ Obtain the client's signature. The wallet prompts for a password. Set partial sign to `true`. const signedTx = await wallet.signTx(unsignedTx, true); [Sign transaction (application)](https://meshjs.dev/guides/multisig-minting#sign-transaction-application) ---------------------------------------------------------------------------------------------------------- The backend signs with the application wallet: const meshWalletSignedTx = await systemWallet.signTx(unsignedTx, true); Merge masked metadata if applicable: const signedOriginalTx = Transaction.writeMetadata( unsignedTx, originalMetadata, ); const meshWalletSignedTx = await systemWallet.signTx( signedOriginalTx, true, ); [Submit transaction (application)](https://meshjs.dev/guides/multisig-minting#submit-transaction-application) -------------------------------------------------------------------------------------------------------------- Submit the transaction: const txHash = await wallet.submitTx(signedTx); You can now build multi-sig transactions. [Check out the code here](https://meshjs.dev/guides/multisig-minting#) . [Minting Application\ \ Previous Page](https://meshjs.dev/guides/minting-on-nodejs) [Prove Wallet Ownership\ \ Next Page](https://meshjs.dev/guides/prove-wallet-ownership) ### On this page [Connect wallet (client)](https://meshjs.dev/guides/multisig-minting#connect-wallet-client) [Build transaction (application)](https://meshjs.dev/guides/multisig-minting#build-transaction-application) [Sign transaction (client)](https://meshjs.dev/guides/multisig-minting#sign-transaction-client) [Sign transaction (application)](https://meshjs.dev/guides/multisig-minting#sign-transaction-application) [Submit transaction (application)](https://meshjs.dev/guides/multisig-minting#submit-transaction-application) Ask AI --- # Executing a standalone script | Mesh SDK [Learn](https://meshjs.dev/resources) [Guides](https://meshjs.dev/guides) Executing a standalone script ============================= Copy MarkdownOpen Run JavaScript/TypeScript files directly to interact with the blockchain using the `tsx` package. Set up a simple project using MeshSDK. Create a wallet, build and sign transactions, and submit them to the blockchain. This tutorial covers: * Creating a `package.json` file. * Installing MeshSDK and dependencies. * Writing a script to create a wallet and send a transaction. * Running the project. [System Setup](https://meshjs.dev/guides/standalone#system-setup) ------------------------------------------------------------------ ### [Create `package.json`](https://meshjs.dev/guides/standalone#create-packagejson-toc) Create `package.json` in the project root: { "type": "module", "dependencies": {}, "scripts": { "dev": "tsx index.ts" } } ### [Install Packages](https://meshjs.dev/guides/standalone#install-packages-toc) Install required packages: npm install npm install tsx @meshsdk/core `package.json` should look like this: { "type": "module", "dependencies": { "@meshsdk/core": "^1.5.18", "tsx": "^4.9.4" }, "scripts": { "dev": "tsx index.ts" } } * `@meshsdk/core`: Core functionality. * `tsx`: Runs TypeScript files directly. [Make a Simple Transaction](https://meshjs.dev/guides/standalone#make-a-simple-transaction) -------------------------------------------------------------------------------------------- ### [Create `index.ts`](https://meshjs.dev/guides/standalone#create-indexts-toc) Create `index.ts` and add the following code: import { BlockfrostProvider, MeshWallet, Transaction } from "@meshsdk/core"; // Set up the blockchain provider with your key const provider = new BlockfrostProvider("YOUR_KEY_HERE"); // Initialize the wallet with a mnemonic key const wallet = new MeshWallet({ networkId: 0, fetcher: provider, submitter: provider, key: { type: "mnemonic", words: [\ "your", "mnemonic", "...", "here",\ ], }, }); // Create and send a transaction const tx = new Transaction({ initiator: wallet }).sendLovelace( "addr_test1qp2k7wnshzngpqw0xmy33hvexw4aeg60yr79x3yeeqt3s2uvldqg2n2p8y4kyjm8sqfyg0tpq9042atz0fr8c3grjmysdp6yv3", "1000000" ); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); ### [Run Application](https://meshjs.dev/guides/standalone#run-application-toc) Replace `YOUR_KEY_HERE` with a valid Blockfrost key and the mnemonic words with your own. Get a key from [Blockfrost](https://blockfrost.io/) and generate a mnemonic from [Mesh](https://meshjs.dev/apis/wallets/meshwallet#generate-wallet) . Start the application: npm run dev The transaction hash will log to the console. View the complete code in the [Mesh GitHub repo](https://github.com/MeshJS/standalone-template) . [Aiken Hello World\ \ Previous Page](https://meshjs.dev/guides/aiken) [Vesting Script End-to-End\ \ Next Page](https://meshjs.dev/guides/vesting) ### On this page [System Setup](https://meshjs.dev/guides/standalone#system-setup) [Make a Simple Transaction](https://meshjs.dev/guides/standalone#make-a-simple-transaction) Ask AI --- # Minting Application | Mesh SDK [Learn](https://meshjs.dev/resources) [Guides](https://meshjs.dev/guides) Minting Application =================== Copy MarkdownOpen Mint assets with **MeshWallet** on Node.js. [System setup](https://meshjs.dev/guides/minting-on-nodejs#system-setup) ------------------------------------------------------------------------- ### [1\. Visual Studio Code](https://meshjs.dev/guides/minting-on-nodejs#1-visual-studio-code-toc) Download and install [Visual Studio Code](https://code.visualstudio.com/) . ### [2\. Node.js](https://meshjs.dev/guides/minting-on-nodejs#2-nodejs-toc) Install the Long-Term Support (LTS) version of [Node.js](https://nodejs.org/en) . [Project setup](https://meshjs.dev/guides/minting-on-nodejs#project-setup) --------------------------------------------------------------------------- Create a new folder and initialize a Node.js project: npm init Install **typescript** and **Mesh**: npm install --dev typescript && npm install @meshsdk/core Initialize TypeScript: npx tsc --init Open **tsconfig.json** and define the configurations: { ... "target": "ESNext", "module": "ESNext", "moduleResolution": "Node", "outDir": "dist", ... } Open **package.json** and add the configurations: { ... "type": "module", "scripts": { "start": "tsc && node ./dist/main.js" } ... } [Build the minting transaction](https://meshjs.dev/guides/minting-on-nodejs#build-the-minting-transaction) ----------------------------------------------------------------------------------------------------------- ### [1\. Create list of NFT's metadata](https://meshjs.dev/guides/minting-on-nodejs#1-create-list-of-nfts-metadata-toc) Create `metadata.ts` and define the NFT metadata: export const metadata: { [assetName: string]: any } = { MeshToken01: { name: "Mesh Token 1", image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "Just a purple coin.", artist: "This NFT was minted by Mesh (https://meshjs.dev/).", }, MeshToken02: { name: "Mesh Token 2", image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "This is suppose to be a gold coin.", artist: "This NFT was minted by Mesh (https://meshjs.dev/).", }, MeshToken03: { name: "Mesh Token 3", image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "A coin with a M on it.", artist: "This NFT was minted by Mesh (https://meshjs.dev/).", }, }; ### [2\. Create a list of recipients](https://meshjs.dev/guides/minting-on-nodejs#2-create-a-list-of-recipients-toc) Create `recipients.ts` and specify the recipients: export const recipients: { [recipient: string]: string } = { addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr: "MeshToken01", addr_test1qqlcxawu4gxarenqvdqyw0tqyjy69mrgsmfqhm6h65jwm4vvldqg2n2p8y4kyjm8sqfyg0tpq9042atz0fr8c3grjmyscxry4r: "MeshToken02", addr_test1qq5tay78z9l77vkxvrvtrv70nvjdk0fyvxmqzs57jg0vq6wk3w9pfppagj5rc4wsmlfyvc8xs7ytkumazu9xq49z94pqzl95zt: "MeshToken03", }; ### [3\. Create main.ts and import the packages:](https://meshjs.dev/guides/minting-on-nodejs#3-create-maints-and-import-the-packages-toc) Create `main.ts` and import the required packages and files: import { MeshWallet, Transaction, ForgeScript, BlockfrostProvider, resolveTxHash, } from '@meshsdk/core'; import type { Mint, AssetMetadata } from '@meshsdk/core'; import { metadata } from './metadata.js'; import { recipients } from './recipients.js'; ### [4\. Define variables](https://meshjs.dev/guides/minting-on-nodejs#4-define-variables-toc) Define minting variables. Use your own wallet to mint your own collection. This example uses: const demoCLIKey = { paymentSkey: '5820aaca553a7b95b38b5d9b82a5daa7a27ac8e34f3cf27152a978f4576520dd6503', stakeSkey: '582097c458f19a3111c3b965220b1bef7d548fd75bc140a7f0a4f080e03cce604f0e', }; const networkId = 0; const blockfrostKey = 'BLOCKFROST_KEY_HERE'; ### [5\. Build the minting transaction](https://meshjs.dev/guides/minting-on-nodejs#5-build-the-minting-transaction-toc) This guide builds a minting transaction, but the process applies to any transaction. [Learn more about Transaction](https://meshjs.dev/apis/transaction) . Initialize a blockchain provider. This guide uses **BlockfrostProvider**: const provider = new BlockfrostProvider(blockfrostKey); Initialize **MeshWallet** and its forging script. This example uses CLI generated keys, but you can load your wallet with a private key or mnemonic phrase. [Learn more about MeshWallet](https://meshjs.dev/apis/wallets/meshwallet) . const wallet = new MeshWallet({ networkId: networkId, fetcher: provider, submitter: provider, key: { type: 'cli', payment: demoCLIKey.paymentSkey, stake: demoCLIKey.stakeSkey, }, }); const walletAddress = wallet.getPaymentAddress(); const forgingScript = ForgeScript.withOneSignature(walletAddress); Create a new Transaction, loop through each recipient, and mint assets with **mintAsset** ([Learn more about minting transactions](https://meshjs.dev/apis/transaction) ): const tx = new Transaction({ initiator: wallet }); for (let recipient in recipients) { const recipientAddress = recipient; const assetName = recipients[recipient]; const assetMetadata: AssetMetadata = metadata[assetName]; const asset: Mint = { assetName: assetName, assetQuantity: '1', metadata: assetMetadata, label: '721', recipient: recipientAddress }; tx.mintAsset(forgingScript, asset); } Sign and submit the transaction: const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, false); const txHash = await wallet.submitTx(signedTx); Execute the script: npm start A successful transaction returns a transaction hash, mints multiple assets, and sends them to multiple recipients. [Develop your first Web3 App\ \ Previous Page](https://meshjs.dev/guides/nextjs) [Multi-Signatures Transaction\ \ Next Page](https://meshjs.dev/guides/multisig-minting) ### On this page [System setup](https://meshjs.dev/guides/minting-on-nodejs#system-setup) [Project setup](https://meshjs.dev/guides/minting-on-nodejs#project-setup) [Build the minting transaction](https://meshjs.dev/guides/minting-on-nodejs#build-the-minting-transaction) Ask AI --- # Marketplace | Mesh SDK [Smart Contracts](https://meshjs.dev/smart-contracts) Marketplace =========== Build a NFT marketplace to buy and sell NFTs Copy MarkdownOpen The marketplace smart contract allows users to buy and sell NFTs. A seller list an NFT for sales by specifying a certain price, and anyone can buy it by paying the demanded price. There are 4 actions (or endpoints) available to interact with this smart contract: * list asset * buy asset * updating listing * cancel listing ### [Install package](https://meshjs.dev/smart-contracts/marketplace#install-package-toc) First you can to install the `@meshsdk/contracts` package: npm install @meshsdk/contract ### [Initialize the Marketplace](https://meshjs.dev/smart-contracts/marketplace#initialize-the-marketplace-toc) Utilizing the Marketplace contract requires a blockchain provider and a connected browser wallet. Here is an example how we can initialize the Marketplace. import { MeshMarketplaceContract } from "@meshsdk/contract"; import { MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshMarketplaceContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, 'addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', 200, // 2% fee ); To initialize the Marketplace, we import the `MeshMarketplaceContract`. The first JSON object is the `inputs` for the `MeshTxInitiatorInput`, this requires a `MeshTxBuilder`, a `Provider`, a `Wallet`, and define the network ID. Second and third parameters are the `ownerAddress` and `feePercentageBasisPoint`. The `ownerAddress` is the address of the marketplace owner which will receive the marketplace fee. The `feePercentageBasisPoint` is the percentage of the sale price that the marketplace `owner` will take. The fee numerator is in the order of hundreds, for example `200` implies a fee of `2%`. Both on-chain and off-chain codes are open-source and available on [Mesh Github Repository](https://github.com/MeshJS/mesh/tree/main/packages/mesh-contract/src/marketplace) . [List Asset](https://meshjs.dev/smart-contracts/marketplace#list-asset) ------------------------------------------------------------------------ List an asset on the marketplace. This will allow other users to buy the asset. The seller will receive the listing price in ADA. The seller can cancel the listing at any time. The seller can also update the listing price at any time. `listAsset()` list an asset for sale. The function accepts the following parameters: * asset (string) - the asset's unit to be listed * price (number) - the listing price in Lovelace ### [List Asset](https://meshjs.dev/smart-contracts/marketplace#list-asset-toc) List an asset for sale **Listing price in Lovelace** `10000000` **Asset unit** `d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e` const tx = await contract.listAsset('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e', 10000000); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Buy Asset](https://meshjs.dev/smart-contracts/marketplace#buy-asset) ---------------------------------------------------------------------- Purchase a listed asset from the marketplace. The seller will receive the listed price in ADA and the buyer will receive the asset. The marketplace owner will receive a fee if it is specified. `purchaseAsset()` purchase a listed asset. The function accepts the following parameters: * utxo (UTxO) - unspent transaction output in the script We have provided a very handle function, `getUtxoByTxHash`, which will return the UTxO object for a given transaction hash. A [successful purchase](https://preprod.cardanoscan.io/transaction/f9f7ddbbbe1c34717134c89c343aaa27d4c5f62e6e8a127757400ac8d45e64e8) will send the asset to the wallet that signed the transaction to purchase the asset. ### [Buy Asset](https://meshjs.dev/smart-contracts/marketplace#buy-asset-toc) Purchase a listed asset from the marketplace **Tx hash** `Tx hash` const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.purchaseAsset(utxo); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Update Listing](https://meshjs.dev/smart-contracts/marketplace#update-listing) -------------------------------------------------------------------------------- Update a listing on the marketplace. For the contract, the seller can update the listing price. `relistAsset()` update a listing on the marketplace. The function accepts the following parameters: * utxo (UTxO) - unspent transaction output in the script * newListPrice (number) - the new listing price in Lovelace We have provided a very handle function, `getUtxoByTxHash`, which will return the UTxO object for a given transaction hash. ### [Update Listing](https://meshjs.dev/smart-contracts/marketplace#update-listing-toc) Update the listing price of an asset on the marketplace **Tx hash** `Tx hash` **New listing price in Lovelace** `20000000` const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.relistAsset(utxo, 20000000); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Cancel Listing](https://meshjs.dev/smart-contracts/marketplace#cancel-listing) -------------------------------------------------------------------------------- Cancel a listing on the marketplace. The seller can cancel the listing at any time. The seller will receive the listed asset back. `delistAsset()` cancel a listing on the marketplace. The function accepts the following parameters: * utxo (UTxO) - unspent transaction output in the script We have provided a very handle function, `getUtxoByTxHash`, which will return the UTxO object for a given transaction hash. ### [Cancel Listing](https://meshjs.dev/smart-contracts/marketplace#cancel-listing-toc) Cancel a listing on the marketplace **Tx hash** `Tx hash` const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.delistAsset(utxo); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Hello World\ \ Simple lock and unlock assets contract](https://meshjs.dev/smart-contracts/hello-world) [NFT Minting Machine\ \ Mint NFT that ensure the token name is incremented by a counter](https://meshjs.dev/smart-contracts/plutus-nft) ### On this page [List Asset](https://meshjs.dev/smart-contracts/marketplace#list-asset) [Buy Asset](https://meshjs.dev/smart-contracts/marketplace#buy-asset) [Update Listing](https://meshjs.dev/smart-contracts/marketplace#update-listing) [Cancel Listing](https://meshjs.dev/smart-contracts/marketplace#cancel-listing) Ask AI --- # Yaci Provider | Mesh SDK [Providers](https://meshjs.dev/providers) Yaci Provider ============= Custom Cardano devnet to tailor your devnet needs with a builtin indexer and custom viewer for devnet Copy MarkdownOpen [Yaci DevKit](https://github.com/bloxbean/yaci-devkit) is a development tool designed for rapid and efficient Cardano blockchain development. It allows developers to create and destroy custom Cardano devnets in seconds, providing fast feedback loops and simplifying the iteration process. Get started: import { YaciProvider } from "@meshsdk/core"; const provider = new YaciProvider('', ''); [Get data from URL](https://meshjs.dev/providers/yaci#get-data-from-url) ------------------------------------------------------------------------- You can fetch any data from the blockchain by providing the URL path. await provider.get('/addresses/addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9/transactions') [Fetch Account Info](https://meshjs.dev/providers/yaci#fetch-account-info) --------------------------------------------------------------------------- Obtain information about a specific stake account. await provider.fetchAccountInfo('stake_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n') [Fetch Address Assets](https://meshjs.dev/providers/yaci#fetch-address-assets) ------------------------------------------------------------------------------- Fetch assets from an address. await provider.fetchAddressAssets('addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') ### [Fetch Address UTxOs](https://meshjs.dev/providers/yaci#fetch-address-utxos-toc) Fetch UTxOs from address await provider.fetchAddressAssets( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); ### [Fetch assets from address](https://meshjs.dev/providers/yaci#fetch-assets-from-address-toc) Fetch assets given an address await provider.fetchAddressAssets( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', ); [Fetch Address UTxOs](https://meshjs.dev/providers/yaci#fetch-address-utxos) ----------------------------------------------------------------------------- Fetch UTxOs controlled by an address. await provider.fetchAddressUTxOs('addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') Optionally, you can filter UTXOs containing a particular `asset` by providing asset, where it is the concatenation of policy ID and asset. await fetchAddressUTxOs(address: string, asset?: string) ### [Fetch Address UTxOs](https://meshjs.dev/providers/yaci#fetch-address-utxos-toc-1) Fetch UTxOs from address await provider.fetchAddressUTxOs( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); ### [Fetch UTxOs with Asset](https://meshjs.dev/providers/yaci#fetch-utxos-with-asset-toc) Fetch UTxOs from address with asset await provider.fetchAddressUTxOs( 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e' ); [Fetch Asset Addresses](https://meshjs.dev/providers/yaci#fetch-asset-addresses) --------------------------------------------------------------------------------- Fetch a list of a addresses containing a specific `asset` where it is the concatenation of policy ID and asset. await provider.fetchAssetAddresses('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') [Fetch Asset Metadata](https://meshjs.dev/providers/yaci#fetch-asset-metadata) ------------------------------------------------------------------------------- Fetch the asset metadata by providing asset's `unit`, which is the concatenation of policy ID and asset name in hex. await provider.fetchAssetMetadata('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') [Fetch Block Info](https://meshjs.dev/providers/yaci#fetch-block-info) ----------------------------------------------------------------------- Fetch block infomation. You can get the hash from `fetchTxInfo()`. await provider.fetchBlockInfo('79f60880b097ec7dabb81f75f0b52fedf5e922d4f779a11c0c432dcf22c56089') [Fetch Collection Assets](https://meshjs.dev/providers/yaci#fetch-collection-assets) ------------------------------------------------------------------------------------- Fetch a list of assets belonging to a collection by providing its Policy ID. await provider.fetchCollectionAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527') The API will return a list of `assets` and a cursor `next`. If the cursor is not null, you can use it to fetch the next page of results. Here is an example of the response. { "assets": [\ {\ "unit": "d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527",\ "quantity": "1"\ },\ ], "next": 2 } The `fetchCollectionAssets` function also accepts an optional `cursor` parameter to fetch the next page of results. The default value is `1`. await fetchCollectionAssets( policyId: string, cursor = 1 ) [Fetch Handle Address](https://meshjs.dev/providers/yaci#fetch-handle-address) ------------------------------------------------------------------------------- [ADA Handle](https://handle.me/) allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. We can resolve the handle's address with `fetchHandleAddress`. // Handle: `meshsdk` await provider.fetchHandleAddress('meshsdk') [Fetch Handle](https://meshjs.dev/providers/yaci#fetch-handle) --------------------------------------------------------------- [ADA Handle](https://handle.me/) allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. ADA Handle also released a CIP68 handle and this function will fetch the metadata of the handle. // Handle: `meshsdk` await provider.fetchHandle('meshsdk') [Fetch Protocol Parameters](https://meshjs.dev/providers/yaci#fetch-protocol-parameters) ----------------------------------------------------------------------------------------- Fetch the latest protocol parameters. await provider.fetchProtocolParameters() Optionally, you can provide an epoch number to fetch the protocol parameters of that epoch. [Fetch Transaction Info](https://meshjs.dev/providers/yaci#fetch-transaction-info) ----------------------------------------------------------------------------------- Fetch transaction infomation. Only confirmed transaction can be retrieved. await provider.fetchTxInfo('f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159') [Fetch UTxOs](https://meshjs.dev/providers/yaci#fetch-utxos) ------------------------------------------------------------- Get UTxOs for a given hash. // Hash: `dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70` await provider.fetchUTxOs('dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70') Optionally, you can specify the index of the index output. await provider.fetchUTxOs('hash_here', 0) [Fetch Proposal Info](https://meshjs.dev/providers/yaci#fetch-proposal-info) ----------------------------------------------------------------------------- Get information for a given governance proposal, identified by the txHash and proposal index await provider.fetchGovernanceProposal('372d688faa77e146798b581b322c0f2981a9023764736ade5d12e0e4e796af8c', 0) [Evaluate Transaction](https://meshjs.dev/providers/yaci#evaluate-transaction) ------------------------------------------------------------------------------- `evaluateTx()` accepts an unsigned transaction (`unsignedTx`) and it evaluates the resources required to execute the transaction. Note that, this is only valid for transaction interacting with redeemer (smart contract). By knowing the budget required, you can use this to adjust the redeemer's budget so you don't spend more than you need to execute transactions for this smart contract. const unsignedTx = await tx.build(); const evaluateTx = await provider.evaluateTx(unsignedTx); Example responses from unlocking assets from the always succeed smart contract. [\ {\ "index": 0,\ "tag": "SPEND",\ "budget": {\ "mem": 1700,\ "steps": 368100\ }\ }\ ] With the `mem` and `steps`, you can refine the budget for the redeemer. For example: const redeemer = { data: { alternative: 0, fields: [...] }, budget: { mem: 1700, steps: 368100, }, }; [Submit Transaction](https://meshjs.dev/providers/yaci#submit-transaction) --------------------------------------------------------------------------- Submit a serialized transaction to the network. await provider.submitTx(signedTx); [On Transaction Confirmed](https://meshjs.dev/providers/yaci#on-transaction-confirmed) --------------------------------------------------------------------------------------- Allow you to listen to a transaction confirmation. Upon confirmation, the callback will be called. const tx = new Transaction({ initiator: wallet }); tx.sendLovelace('addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', '5000000'); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); provider.onTxConfirmed(txHash, () => { // Transaction confirmed }); [Admin Get Devnet Info](https://meshjs.dev/providers/yaci#admin-get-devnet-info) --------------------------------------------------------------------------------- Get information about the devnet. await provider.getDevnetInfo() Example response: { "nodePort": 0, "submitApiPort": 0, "socketPath": "string", "protocolMagic": 0, "slotLength": 0, "blockTime": 0, "epochLength": 0, "p2pEnabled": true, "startTime": 0, "masterNode": true, "adminNodeUrl": "string", "era": "Byron", "genesisProfile": "zero_fee", "ogmiosPort": 0, "kupoPort": 0, "yaciStorePort": 0, "socatPort": 0, "prometheusPort": 0, "blockProducer": true } [Admin Get Genesis Info By Era](https://meshjs.dev/providers/yaci#admin-get-genesis-info-by-era) ------------------------------------------------------------------------------------------------- You can topup ADA for any address. To topup ADA in your wallet, run the following command from devnet: await provider.getGenesisByEra() Example response: { "activeSlotsCoeff": 1, "epochLength": 500, "genDelegs": { "337bc5ef0f1abf205624555c13a37258c42b46b1259a6b1a6d82574e": { "delegate": "41fd6bb31f34469320aa47cf6ccc3918e58a06d60ea1f2361efe2458", "vrf": "7053e3ecd2b19db13e5338aa75fb518fc08b6c218f56ad65760d3eb074be95d4" } }, "initialFunds": { "60ba957a0fff6816021b2afa7900beea68fd10f2d78fb5b64de0d2379c": 3000000000000000, "007290ea8fa9433c1045a4c8473959ad608e6c03a58c7de33bdbd3ce6f295b987135610616f3c74e11c94d77b6ced5ccc93a7d719cfb135062": 300000000000, "605276322ac7882434173dcc6441905f6737689bd309b68ad8b3614fd8": 3000000000000000, "60a0f1aa7dca95017c11e7e373aebcf0c4568cf47ec12b94f8eb5bba8b": 3000000000000000, "005867c3b8e27840f556ac268b781578b14c5661fc63ee720dbeab663f9d4dcd7e454d2434164f4efb8edeb358d86a1dad9ec6224cfcbce3e6": 1000000000 }, "maxKESEvolutions": 60, "maxLovelaceSupply": 45000000000000000, "networkId": "Testnet", "networkMagic": 42, "protocolParams": { "a0": 0, "decentralisationParam": 0, "eMax": 18, "extraEntropy": { "tag": "NeutralNonce" }, "keyDeposit": 2000000, "maxBlockBodySize": 65536, "maxBlockHeaderSize": 1100, "maxTxSize": 16384, "minFeeA": 0, "minFeeB": 0, "minPoolCost": 340000000, "minUTxOValue": 1000000, "nOpt": 100, "poolDeposit": 500000000, "protocolVersion": { "major": 8, "minor": 0 }, "rho": 0.003, "tau": 0.2 }, "securityParam": 300, "slotLength": 1, "slotsPerKESPeriod": 129600, "staking": { "pools": { "7301761068762f5900bde9eb7c1c15b09840285130f5b0f53606cc57": { "cost": 340000000, "margin": 0, "metadata": null, "owners": [], "pledge": 0, "publicKey": "7301761068762f5900bde9eb7c1c15b09840285130f5b0f53606cc57", "relays": [], "rewardAccount": { "credential": { "keyHash": "11a14edf73b08a0a27cb98b2c57eb37c780df18fcfcf6785ed5df84a" }, "network": "Testnet" }, "vrf": "c2b62ffa92ad18ffc117ea3abeb161a68885000a466f9c71db5e4731d6630061" } }, "stake": { "9d4dcd7e454d2434164f4efb8edeb358d86a1dad9ec6224cfcbce3e6": "7301761068762f5900bde9eb7c1c15b09840285130f5b0f53606cc57" } }, "systemStart": "2024-10-30T05:11:07.442512Z", "updateQuorum": 1 } [Admin Address Topup](https://meshjs.dev/providers/yaci#admin-address-topup) ----------------------------------------------------------------------------- You can topup ADA for any address. To topup ADA in your wallet, run the following command from devnet: await provider.addressTopup(
, ) [Topup Address](https://meshjs.dev/providers/yaci#topup-address-toc) --------------------------------------------------------------------- Admin function to topup address with ADA **Address** `addr_test1qpvx....9uu0nq93swx9` **Amount** `20000000` await provider.addressTopup('addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', '20000000'); [UTxORPC Provider\ \ Highly efficient through gRPC, using a compact and high-performance binary format](https://meshjs.dev/providers/utxorpc) [OfflineFetcher\ \ An offline blockchain data provider for testing, development and offline scenarios.](https://meshjs.dev/providers/offline-fetcher) ### On this page [Get data from URL](https://meshjs.dev/providers/yaci#get-data-from-url) [Fetch Account Info](https://meshjs.dev/providers/yaci#fetch-account-info) [Fetch Address Assets](https://meshjs.dev/providers/yaci#fetch-address-assets) [Fetch Address UTxOs](https://meshjs.dev/providers/yaci#fetch-address-utxos) [Fetch Asset Addresses](https://meshjs.dev/providers/yaci#fetch-asset-addresses) [Fetch Asset Metadata](https://meshjs.dev/providers/yaci#fetch-asset-metadata) [Fetch Block Info](https://meshjs.dev/providers/yaci#fetch-block-info) [Fetch Collection Assets](https://meshjs.dev/providers/yaci#fetch-collection-assets) [Fetch Handle Address](https://meshjs.dev/providers/yaci#fetch-handle-address) [Fetch Handle](https://meshjs.dev/providers/yaci#fetch-handle) [Fetch Protocol Parameters](https://meshjs.dev/providers/yaci#fetch-protocol-parameters) [Fetch Transaction Info](https://meshjs.dev/providers/yaci#fetch-transaction-info) [Fetch UTxOs](https://meshjs.dev/providers/yaci#fetch-utxos) [Fetch Proposal Info](https://meshjs.dev/providers/yaci#fetch-proposal-info) [Evaluate Transaction](https://meshjs.dev/providers/yaci#evaluate-transaction) [Submit Transaction](https://meshjs.dev/providers/yaci#submit-transaction) [On Transaction Confirmed](https://meshjs.dev/providers/yaci#on-transaction-confirmed) [Admin Get Devnet Info](https://meshjs.dev/providers/yaci#admin-get-devnet-info) [Admin Get Genesis Info By Era](https://meshjs.dev/providers/yaci#admin-get-genesis-info-by-era) [Admin Address Topup](https://meshjs.dev/providers/yaci#admin-address-topup) Ask AI --- # Cardano Course | Mesh SDK [Learn](https://meshjs.dev/resources) Cardano Course ============== A comprehensive course for building Cardano applications with Mesh SDK and Aiken smart contracts. Copy MarkdownOpen Welcome to the Cardano Course! This comprehensive course will guide you through building Cardano applications, from basic wallet interactions to advanced smart contract development with Aiken. [Course Structure](https://meshjs.dev/resources/cardano-course#course-structure) --------------------------------------------------------------------------------- This course is divided into lessons covering everything you need to become a proficient Cardano developer. ### [Lessons](https://meshjs.dev/resources/cardano-course#lessons) The course includes 10 detailed lessons covering: 1. **Hello World** - Install Mesh SDK and learn wallet basics 2. **Multi-signature Transactions** - Build multi-sig transactions 3. **Aiken Contracts** - Introduction to Aiken smart contracts 4. **Contract Testing** - Testing strategies for smart contracts 5. **Avoid Redundant Validation** - Smart contract optimization patterns 6. **Interpreting Blueprint** - Understanding Aiken blueprints 7. **Vesting Contract** - Build a token vesting contract 8. **Plutus NFT Contract** - Create NFT minting contracts 9. **Hydra End-to-End** - Layer 2 scaling with Hydra 10. **Web3 Services** - Wallet-as-a-service and transaction sponsorship [Getting Started](https://meshjs.dev/resources/cardano-course#getting-started) ------------------------------------------------------------------------------- Begin with [Lesson 1: Hello World](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace) to set up your development environment and create your first Cardano transaction. [Prerequisites](https://meshjs.dev/resources/cardano-course#prerequisites) --------------------------------------------------------------------------- * Basic understanding of TypeScript/JavaScript * Node.js v20+ installed * Familiarity with blockchain concepts (helpful but not required) [What You'll Learn](https://meshjs.dev/resources/cardano-course#what-youll-learn) ---------------------------------------------------------------------------------- * Building Cardano dApps with Mesh SDK * Creating and deploying Aiken smart contracts * Transaction building and wallet integration * Smart contract testing and optimization * NFT minting and token management * Layer 2 scaling solutions Start your journey into Cardano development today! [Learn\ \ Comprehensive courses, tutorials, and resources for Cardano developers.](https://meshjs.dev/resources) [Course Lessons\ \ Step-by-step lessons for mastering Cardano development with Mesh SDK and Aiken.](https://meshjs.dev/resources/cardano-course/lessons) ### On this page [Course Structure](https://meshjs.dev/resources/cardano-course#course-structure) [Lessons](https://meshjs.dev/resources/cardano-course#lessons) [Getting Started](https://meshjs.dev/resources/cardano-course#getting-started) [Prerequisites](https://meshjs.dev/resources/cardano-course#prerequisites) [What You'll Learn](https://meshjs.dev/resources/cardano-course#what-youll-learn) Ask AI --- # Vesting Script End-to-End | Mesh SDK [Learn](https://meshjs.dev/resources) [Guides](https://meshjs.dev/guides) Vesting Script End-to-End ========================= Copy MarkdownOpen A vesting contract locks funds and allows beneficiary withdrawal after a lockup period. Organizations use vesting contracts to incentivize retention. Funds deposited are accessible to employees after a predetermined period. [On-Chain Code](https://meshjs.dev/guides/vesting#on-chain-code) ----------------------------------------------------------------- Define the datum shape to configure vesting parameters. pub type VestingDatum { /// POSIX time in milliseconds, e.g. 1672843961000 lock_until: Int, /// Owner's credentials owner: ByteArray, /// Beneficiary's credentials beneficiary: ByteArray, } The `VestingDatum` contains: * `lock_until`: POSIX timestamp (ms) for lock expiration. * `owner`: Owner credentials (public key hash). * `beneficiary`: Beneficiary credentials (public key hash). Source: `aiken-vesting/aiken-workspace/lib/vesting/types.ak`. Define the spend validator: use aiken/transaction.{ScriptContext, Spend} use vesting/types.{VestingDatum} use vodka_extra_signatories.{key_signed} use vodka_validity_range.{valid_after} validator { pub fn vesting(datum: VestingDatum, _redeemer: Data, ctx: ScriptContext) { // In principle, scripts can be used for different purpose (e.g. minting // assets). Here we make sure it's only used when 'spending' from a eUTxO when ctx.purpose is { Spend(_) -> or { key_signed(ctx.transaction.extra_signatories, datum.owner), and { key_signed(ctx.transaction.extra_signatories, datum.beneficiary), valid_after(ctx.transaction.validity_range, datum.lock_until), }, } _ -> False } } } The `vesting` validator ensures: * The transaction is signed by the owner. * OR: * The transaction is signed by the beneficiary AND valid after the lockup period. Source: `aiken-vesting/aiken-workspace/validators/vesting.ak`. ### [How It Works](https://meshjs.dev/guides/vesting#how-it-works-toc) The owner deposits funds, locked until the period expires. Transactions include validity intervals. The ledger verifies these bounds before script execution. This incorporates time while maintaining determinism. Since the upper bound is uncontrolled, execution can occur long after the delay. This is acceptable. The beneficiary (potentially different from the owner) withdraws funds after expiration. [Testing](https://meshjs.dev/guides/vesting#testing) ----------------------------------------------------- Run comprehensive tests with `aiken check`. Test cases include: * Success unlocking. * Success unlocking with only owner signature. * Success unlocking with beneficiary signature and time passed. * Fail unlocking with only beneficiary signature. * Fail unlocking with only time passed. See `aiken-vesting/aiken-workspace/validators/tests/vesting.ak`. [Compile and Build Script](https://meshjs.dev/guides/vesting#compile-and-build-script) --------------------------------------------------------------------------------------- Compile the script: aiken build Generates a CIP-0057 Plutus blueprint in `aiken-vesting/aiken-workspace/plutus.json`. [Off-Chain Code](https://meshjs.dev/guides/vesting#off-chain-code) ------------------------------------------------------------------- ### [Deposit Funds](https://meshjs.dev/guides/vesting#deposit-funds-toc) The owner deposits funds, specifying the lockup period and beneficiary. const assets: Asset[] = [\ {\ unit: "lovelace",\ quantity: "10000000",\ },\ ]; const lockUntilTimeStamp = new Date(); lockUntilTimeStamp.setMinutes(lockUntilTimeStamp.getMinutes() + 1); const beneficiary = "addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9"; Deposit 10 ADA, locked for 1 minute. Prepare transaction variables: wallet address, UTXOs, script address, and public key hashes. const { utxos, walletAddress } = await getWalletInfoForTx(); const { scriptAddr } = getScript(); const { pubKeyHash: ownerPubKeyHash } = deserializeAddress(walletAddress); const { pubKeyHash: beneficiaryPubKeyHash } = deserializeAddress(beneficiary); Construct the deposit transaction. Specify script address, amount, lockup period, owner, and beneficiary. const txBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); await txBuilder .txOut(scriptAddr, amount) .txOutInlineDatumValue( mConStr0([lockUntilTimeStampMs, ownerPubKeyHash, beneficiaryPubKeyHash]) ) .changeAddress(walletAddress) .selectUtxosFrom(utxos) .complete(); const unsignedTx = txBuilder.txHex; Sign and submit. const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); Ensure the Blockfrost key is in `.env` and mnemonic in `aiken-vesting/src/configs.ts`. Run the deposit code: npm run deposit Save the returned transaction hash for withdrawal. See [successful deposit transaction](https://preprod.cardanoscan.io/transaction/ede9f8176fe41f0c84cfc9802b693dedb5500c0cbe4377b7bb0d57cf0435200b) . ### [Withdraw Funds](https://meshjs.dev/guides/vesting#withdraw-funds-toc) Beneficiaries (or owners) withdraw funds after expiration. Fetch UTxOs containing locked funds using the deposit transaction hash. const txHashFromDesposit = "ede9f8176fe41f0c84cfc9802b693dedb5500c0cbe4377b7bb0d57cf0435200b"; const utxos = await provider.fetchUTxOs(txHash); const vestingUtxo = utxos[0]; Prepare transaction variables. const { utxos, walletAddress, collateral } = await getWalletInfoForTx(); const { input: collateralInput, output: collateralOutput } = collateral; const { scriptAddr, scriptCbor } = getScript(); const { pubKeyHash } = deserializeAddress(walletAddress); Prepare the datum and validity interval slot. Set the valid interval to start after the lockup period. const datum = deserializeDatum(vestingUtxo.output.plutusData!); const invalidBefore = unixTimeToEnclosingSlot( Math.min(datum.fields[0].int as number, Date.now() - 15000), SLOT_CONFIG_NETWORK.preprod ) + 1; Construct the withdrawal transaction. Specify the UTxO, script address, recipient address, and validity interval. const txBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); await txBuilder .spendingPlutusScriptV2() .txIn( vestingUtxo.input.txHash, vestingUtxo.input.outputIndex, vestingUtxo.output.amount, scriptAddr ) .spendingReferenceTxInInlineDatumPresent() .spendingReferenceTxInRedeemerValue("") .txInScript(scriptCbor) .txOut(walletAddress, []) .txInCollateral( collateralInput.txHash, collateralInput.outputIndex, collateralOutput.amount, collateralOutput.address ) .invalidBefore(invalidBefore) .requiredSignerHash(pubKeyHash) .changeAddress(walletAddress) .selectUtxosFrom(utxos) .complete(); const unsignedTx = txBuilder.txHex; Sign and submit. Enable partial signing (`true`) for validator unlocking. const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); Update `aiken-vesting/src/withdraw-fund.ts` with the deposit transaction hash. Run: npm run withdraw See [successful withdraw transaction](https://preprod.cardanoscan.io/transaction/b108f91a1dcd1b4c0bc978fb7557fc23ad052f1681cca078aa2515f8ab01e05e) . [Executing a standalone script\ \ Previous Page](https://meshjs.dev/guides/standalone) [Resolve Node-Specific Imports Errors\ \ Next Page](https://meshjs.dev/guides/node-specific-imports) ### On this page [On-Chain Code](https://meshjs.dev/guides/vesting#on-chain-code) [Testing](https://meshjs.dev/guides/vesting#testing) [Compile and Build Script](https://meshjs.dev/guides/vesting#compile-and-build-script) [Off-Chain Code](https://meshjs.dev/guides/vesting#off-chain-code) Ask AI --- # Resolve Node-Specific Imports Errors | Mesh SDK [Learn](https://meshjs.dev/resources) [Guides](https://meshjs.dev/guides) Resolve Node-Specific Imports Errors ==================================== Copy MarkdownOpen Resolve Node-Specific Imports Errors (e.g., Buffer, TextEncoder) in Browser-Based Projects. Web-based projects (React, Vue, Svelte, Angular) may encounter errors like: Uncaught ReferenceError: Buffer is not defined or Module not found: Can't resolve 'buffer' or ReferenceError: TextEncoder is not defined These errors occur when code relies on Node.js-specific modules unavailable in browsers. Common examples: * `Buffer` * `TextEncoder` / `TextDecoder` * `crypto` * `process` * Node’s built-in modules (`fs`, `path`, `stream`) Modern bundlers (Webpack 5, Vite, Next.js) do **not** automatically include Node polyfills. Use these guidelines to fix errors. [1\. General Concepts](https://meshjs.dev/guides/node-specific-imports#1-general-concepts-toc) ----------------------------------------------------------------------------------------------- 1. **Polyfill**: Implements missing functionality (e.g., `buffer` package). 2. **Fallback configuration**: Replaces Node modules with browser-friendly versions. 3. **npm dependencies**: Install equivalents: npm install buffer process stream-browserify crypto-browserify --save 4. **ES Modules vs CommonJS**: Ensure imports match bundler expectations. [2\. Webpack](https://meshjs.dev/guides/node-specific-imports#2-webpack-toc) ----------------------------------------------------------------------------- ### [2.1 Webpack 5 and Above](https://meshjs.dev/guides/node-specific-imports#21-webpack-5-and-above-toc) Webpack 5 excludes Node polyfills. Two approaches exist: **Approach A: Use NodePolyfillPlugin** Install the plugin: npm install node-polyfill-webpack-plugin --save-dev Add to `webpack.config.js`: const NodePolyfillPlugin = require('node-polyfill-webpack-plugin'); module.exports = { // ...your existing config plugins: [\ new NodePolyfillPlugin(),\ // ...other plugins\ ], }; This plugin injects common polyfills. **Approach B: Use `resolve.fallback`** For granular control, configure fallbacks manually: Install polyfills: npm install buffer process stream-browserify --save Edit `webpack.config.js`: module.exports = { // ... resolve: { fallback: { buffer: require.resolve('buffer/'), // or 'buffer' process: require.resolve('process/browser'), stream: require.resolve('stream-browserify'), // ...add more if needed }, }, }; Import polyfills if needed: import { Buffer } from 'buffer'; global.Buffer = global.Buffer || Buffer; [3\. Vite](https://meshjs.dev/guides/node-specific-imports#3-vite) ------------------------------------------------------------------- Vite uses [Rollup](https://rollupjs.org/) , which lacks automatic Node polyfills. Use a Rollup plugin. Install the plugin: npm install rollup-plugin-polyfill-node --save-dev Add to `vite.config.js`: import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' // or react, svelte, etc. import rollupNodePolyFill from 'rollup-plugin-polyfill-node' export default defineConfig({ plugins: [\ vue(),\ // any other plugins\ ], build: { rollupOptions: { plugins: [\ rollupNodePolyFill()\ ], }, }, resolve: { alias: { // Optionally, if you want the polyfill for `buffer` and `process` as top-level buffer: 'rollup-plugin-polyfill-node/polyfills/buffer-es6', process: 'rollup-plugin-polyfill-node/polyfills/process-es6', // Add more if needed }, }, }) Use the polyfilled global if necessary: import { Buffer } from 'buffer'; globalThis.Buffer = globalThis.Buffer || Buffer; [4\. Next.js](https://meshjs.dev/guides/node-specific-imports#4-nextjs) ------------------------------------------------------------------------ Next.js uses Webpack. Use `node-polyfill-webpack-plugin` or configure `resolve.fallback`. Example with `node-polyfill-webpack-plugin`: // next.config.js const NodePolyfillPlugin = require('node-polyfill-webpack-plugin') module.exports = { webpack: (config, { isServer }) => { if (!isServer) { config.plugins.push(new NodePolyfillPlugin()) } return config }, } Node modules like `Buffer` or `process` are now polyfilled. [5\. Create React App (CRA)](https://meshjs.dev/guides/node-specific-imports#5-create-react-app-cra) ----------------------------------------------------------------------------------------------------- Create React App **v5** uses Webpack 5. Use `react-app-rewired` or `craco` to override config. ### [5.1 Example with craco](https://meshjs.dev/guides/node-specific-imports#51-example-with-craco-toc) Install craco: npm install @craco/craco --save-dev Update `package.json` scripts: { "scripts": { "start": "craco start", "build": "craco build", "test": "craco test" } } Create `craco.config.js`: const NodePolyfillPlugin = require('node-polyfill-webpack-plugin'); module.exports = { webpack: { plugins: { add: [\ new NodePolyfillPlugin()\ ], }, configure: (webpackConfig) => { // Optionally, if you want to set fallback manually: webpackConfig.resolve.fallback = { ...webpackConfig.resolve.fallback, buffer: require.resolve('buffer'), process: require.resolve('process/browser'), } return webpackConfig; } }, }; Use polyfills: import { Buffer } from 'buffer'; global.Buffer = global.Buffer || Buffer; [6\. Angular](https://meshjs.dev/guides/node-specific-imports#6-angular) ------------------------------------------------------------------------- Angular CLI uses Webpack. Polyfill Node modules: Install polyfills: npm install buffer process stream-browserify --save Edit `angular.json` or use `ngx-build-plus`. Example with `ngx-build-plus`: npm install ngx-build-plus --save-dev In `angular.json`: { "projects": { "my-app": { "architect": { "build": { "builder": "ngx-build-plus:browser", "options": { // ... }, "configurations": { "production": { // ... } } }, "serve": { "builder": "ngx-build-plus:dev-server", "options": { // ... } } } } } } Create or update `webpack.config.js`: const NodePolyfillPlugin = require('node-polyfill-webpack-plugin'); module.exports = { plugins: [\ new NodePolyfillPlugin(),\ ], resolve: { fallback: { buffer: require.resolve('buffer'), process: require.resolve('process/browser'), // ... }, }, }; Run Angular commands via `ng build --extra-webpack-config webpack.config.js --output-hashing=none`. [7\. Svelte](https://meshjs.dev/guides/node-specific-imports#7-svelte) ----------------------------------------------------------------------- SvelteKit uses Vite or Rollup. Use Vite instructions (Section 3) or add the plugin to Rollup config: // rollup.config.js import nodePolyfills from 'rollup-plugin-polyfill-node' export default { plugins: [\ nodePolyfills(),\ // ...\ ], // ... } [Vesting Script End-to-End\ \ Previous Page](https://meshjs.dev/guides/vesting) [Mint an NFT Collection\ \ Next Page](https://meshjs.dev/guides/nft-collection) ### On this page [3\. Vite](https://meshjs.dev/guides/node-specific-imports#3-vite) [4\. Next.js](https://meshjs.dev/guides/node-specific-imports#4-nextjs) [5\. Create React App (CRA)](https://meshjs.dev/guides/node-specific-imports#5-create-react-app-cra) [6\. Angular](https://meshjs.dev/guides/node-specific-imports#6-angular) [7\. Svelte](https://meshjs.dev/guides/node-specific-imports#7-svelte) Ask AI --- # Content Ownership | Mesh SDK [Smart Contracts](https://meshjs.dev/smart-contracts) Content Ownership ================= Manage ownership of digital content and assets Copy MarkdownOpen This contract allows you to create a content registry and users can create content that is stored in the registry. It facilitates on-chain record of content (i.e. file on IPFS) ownership and transfer. While one cannot prefer others from obtaining a copy of the content, the app owner of the contract can serve the single source of truth of who owns the content. With the blockchain trace and record in place, it provides a trustless way to verify the ownership of the content and facilitates further application logics such as royalties, licensing, etc. ### [Install package](https://meshjs.dev/smart-contracts/content-ownership#install-package-toc) First you can to install the `@meshsdk/contracts` package: npm install @meshsdk/contract ### [Initialize the contract](https://meshjs.dev/smart-contracts/content-ownership#initialize-the-contract-toc) To initialize the contract, we need to initialize a [provider](https://meshjs.dev/providers) , `MeshTxBuilder` and `MeshContentOwnershipContract`. import { MeshContentOwnershipContract } from "@meshsdk/contract"; import { MeshTxBuilder, BlockfrostProvider } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshContentOwnershipContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, { operationAddress: operationAddress, // the address of the app owner, where most of the actions should be signed by the spending key of this address paramUtxo: { outputIndex: 0, txHash: "0000000000000000000000000000000000000000000000000000000000000000" }, // you can get this from the output of mintOneTimeMintingPolicy() transaction refScriptUtxos?: { // you can get these from the output of sendRefScriptOnchain() transactions contentRegistry: { outputIndex: 0, txHash: "0000000000000000000000000000000000000000000000000000000000000000" }, contentRefToken: { outputIndex: 0, txHash: "0000000000000000000000000000000000000000000000000000000000000000" }, ownershipRegistry: { outputIndex: 0, txHash: "0000000000000000000000000000000000000000000000000000000000000000" }, ownershipRefToken: { outputIndex: 0, txHash: "0000000000000000000000000000000000000000000000000000000000000000" }, }, }, ); Both on-chain and off-chain codes are open-source and available on [Mesh Github Repository](https://github.com/MeshJS/mesh/tree/main/packages/mesh-contract/src/content-ownership) . [Mint One Time Minting Policy](https://meshjs.dev/smart-contracts/content-ownership#mint-one-time-minting-policy) ------------------------------------------------------------------------------------------------------------------ This is the first transaction you need to setup the contract. This transaction mints the one-time minting policy (a NFT) for the contract. It will be attached with the datum which serves as the single source of truth for the contract oracle. Note: You must save the `paramUtxo` for future transactions. ### [Mint One Time Minting Policy](https://meshjs.dev/smart-contracts/content-ownership#mint-one-time-minting-policy-toc) This transaction mints the one-time minting policy (a NFT) for the contract. **Operation address** `addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr` const { tx, paramUtxo } = await contract.mintOneTimeMintingPolicy(); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Setup Oracle Utxo](https://meshjs.dev/smart-contracts/content-ownership#setup-oracle-utxo) -------------------------------------------------------------------------------------------- This transaction send the NFT to a oracle contract locking the datum, which serves as the single source of truth for the contract oracle with data integrity. This is the second transaction you need to setup the contract. Note: You must provide the `paramUtxo` from the `mintOneTimeMintingPolicy` transaction. ### [Setup Oracle Utxo](https://meshjs.dev/smart-contracts/content-ownership#setup-oracle-utxo-toc) This transaction send the NFT to a oracle contract locking the datum. **Operation address** `addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr` **Param UTxO** `{"outputIndex":0,"txHash":"2aba4d6705cfe6405cf02...f3f8bded3df2359"}` const tx = await contract.setupOracleUtxo(); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Send Ref-Script Onchain](https://meshjs.dev/smart-contracts/content-ownership#send-ref-script-onchain) -------------------------------------------------------------------------------------------------------- This are the next transactions you need to setup the contract. You need to run once for each script, and you would likely have to run one after the previous one is confirmed. This transaction sends the reference scripts to the blockchain for later transactions, boosting efficiency and avoid exceeding 16kb of transaction size limits enforced by protocol parameter. Note: You must provide the `paramUtxo` from the `mintOneTimeMintingPolicy` transaction. Note: You must save txHash (after signed and submitted) for `ContentRegistry`, `ContentRefToken`, `OwnershipRegistry`,`OwnershipRefToken` transactions for future transactions. ### [Send Ref-Script Onchain](https://meshjs.dev/smart-contracts/content-ownership#send-ref-script-onchain-toc) This transaction sends the reference scripts to the blockchain for later transactions. **Operation address** `addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr` **Param UTxO** `{"outputIndex":0,"txHash":"2aba4d6705cfe6405cf02...f3f8bded3df2359"}` **Select script index** `OracleNFT` const tx = await contract.sendRefScriptOnchain('OracleNFT'); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Create Content Registry](https://meshjs.dev/smart-contracts/content-ownership#create-content-registry) -------------------------------------------------------------------------------------------------------- This is the next transaction you need to setup the contract after completing all the `sendRefScriptOnchain` transactions. This transaction creates one content registry. Each registry should comes in pair with one ownership registry and each pair of registry serves around 50 records of content ownership. The application can be scaled indefinitely according to the number of parallelization needed and volumes of content expected to be managed. Note: You must provide the `paramUtxo` from the `mintOneTimeMintingPolicy` transaction. Note: You must provide the txHash `forContentRegistry`, `ContentRefToken`, `OwnershipRegistry`, `OwnershipRefToken` transactions. ### [Create Ownership Registry](https://meshjs.dev/smart-contracts/content-ownership#create-ownership-registry-toc) This transaction creates one content registry **Operation address** `addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr` **Param UTxO** `{"outputIndex":0,"txHash":"2aba4d6705cfe6405cf02...f3f8bded3df2359"}` **Content Registry Tx Hash** `dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70` **Content Ref Token Tx Hash** `8f731be135171df172c07578a5d74589ec8fb30b37c12fdbe2639d69b7587f5e` **Ownership Registry Tx Hash** `ec874b61eec4e5e8e395dead6c9bb18690e6d6ea64d773760c5e654ec9ff5f97` **Ownership Ref Token Tx Hash** `e1bdfc7ae6929f934cf9d418273dde143cbb65ec0eec23bdb6c342e4cd91dbd0` const tx = await contract.createContentRegistry(); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Create Ownership Registry](https://meshjs.dev/smart-contracts/content-ownership#create-ownership-registry) ------------------------------------------------------------------------------------------------------------ This is the last transaction you need to setup the contract after completing all the `sendRefScriptOnchain` transactions. This transaction creates one content registry. Each registry should comes in pair with one content registry and each pair of registry serves around 50 records of content ownership. The application can be scaled indefinitely according to the number of parallelization needed and volumes of content expected to be managed. **Note**: You must provide the `paramUtxo` from the `mintOneTimeMintingPolicy` transaction. **Note**: You must provide the txHash for `ContentRegistry`, `ContentRefToken`, `OwnershipRegistry`,`OwnershipRefToken` transactions. ### [Create Ownership Registry](https://meshjs.dev/smart-contracts/content-ownership#create-ownership-registry-toc-1) This transaction creates one content registry **Operation address** `addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr` **Param UTxO** `{"outputIndex":0,"txHash":"2aba4d6705cfe6405cf02e4e2c8b7...ed3df2359"}` **Content Registry Tx Hash** `dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70` **Content Ref Token Tx Hash** `8f731be135171df172c07578a5d74589ec8fb30b37c12fdbe2639d69b7587f5e` **Ownership Registry Tx Hash** `ec874b61eec4e5e8e395dead6c9bb18690e6d6ea64d773760c5e654ec9ff5f97` **Ownership Ref Token Tx Hash** `e1bdfc7ae6929f934cf9d418273dde143cbb65ec0eec23bdb6c342e4cd91dbd0` const tx = await contract.createOwnershipRegistry(); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Get Oracle Data](https://meshjs.dev/smart-contracts/content-ownership#get-oracle-data) ---------------------------------------------------------------------------------------- Getting the oracle data is essential to fetch the current state of the registry. To facilitate this process, you must provide the `paramUtxo` that contains the output index and transaction hash of the NFT minting policy. The `getOracleData()` function will return the current oracle data. const oracleData = await contract.getOracleData(); For example: { "contentNumber": 2, "ownershipNumber": 2 } [Mint User Token](https://meshjs.dev/smart-contracts/content-ownership#mint-user-token) ---------------------------------------------------------------------------------------- This transaction mints a token that users can use to create content. Note that you can actually use any tokens for `createContent()`, this `mintUserToken()` function is just helpful if you want to mint a token specifically for this purpose. Note that you signTx with `true` to mint the token to enable partial signing. ### [Mint User Token](https://meshjs.dev/smart-contracts/content-ownership#mint-user-token-toc) Mint a token that users can use to create content **Operation address** `addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr` **Param UTxO** `{"outputIndex":0,"txHash":"2aba4d6705cfe6405cf02e4e2c8b7...ed3df2359"}` const tx = await contract.mintUserToken("MeshContentOwnership", { name: "Mesh Content Ownership", description: "Demo at https://meshjs.dev/smart-contracts/content-ownership", }); const signedTx = await wallet.signTx(tx, true); const txHash = await wallet.submitTx(signedTx); [Create Content](https://meshjs.dev/smart-contracts/content-ownership#create-content) -------------------------------------------------------------------------------------- This transaction creates a content attached to the registry reference by a token. You can use any token for `ownerAssetHex` and the `contentHashHex` is a string to identify the content. **Note**: You must provide the `paramUtxo` from the `mintOneTimeMintingPolicy` transaction. **Note**: You must provide the txHash for `ContentRegistry`, `ContentRefToken`, `OwnershipRegistry`,`OwnershipRefToken` transactions. ### [Create Content](https://meshjs.dev/smart-contracts/content-ownership#create-content-toc) For users to create a content attached to the registry reference by a token **Operation address** `addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr` **Param UTxO** `{"outputIndex":0,"txHash":"2aba4d6705cfe6405cf02e4e2c8b7...ed3df2359"}` **Content Registry Tx Hash** `dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70` **Content Ref Token Tx Hash** `8f731be135171df172c07578a5d74589ec8fb30b37c12fdbe2639d69b7587f5e` **Ownership Registry Tx Hash** `ec874b61eec4e5e8e395dead6c9bb18690e6d6ea64d773760c5e654ec9ff5f97` **Ownership Ref Token Tx Hash** `e1bdfc7ae6929f934cf9d418273dde143cbb65ec0eec23bdb6c342e4cd91dbd0` const asset = demoAsset; const contentHashHex = "ipfs://contentHashHex"; const registryNumber = 0; const tx = await contract.createContent( asset, contentHashHex, registryNumber, ); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Get Content](https://meshjs.dev/smart-contracts/content-ownership#get-content) -------------------------------------------------------------------------------- This transaction fetches the content data from the registry. ### [Get Oracle Data](https://meshjs.dev/smart-contracts/content-ownership#get-oracle-data-toc) Fetch the current oracle data **Operation address** `addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr` **Param UTxO** `{"outputIndex":0,"txHash":"2aba4d6705cfe6405cf02e4e2c8b7...ed3df2359"}` **Content Registry Tx Hash** `dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70` **Content Ref Token Tx Hash** `8f731be135171df172c07578a5d74589ec8fb30b37c12fdbe2639d69b7587f5e` **Ownership Registry Tx Hash** `ec874b61eec4e5e8e395dead6c9bb18690e6d6ea64d773760c5e654ec9ff5f97` **Ownership Ref Token Tx Hash** `e1bdfc7ae6929f934cf9d418273dde143cbb65ec0eec23bdb6c342e4cd91dbd0` const content = await contract.getContent(0, 0); [Smart Contracts\ \ Open-source smart contracts, complete with documentation, and live demos](https://meshjs.dev/smart-contracts) [Escrow\ \ Secure exchange of assets between two parties](https://meshjs.dev/smart-contracts/escrow) ### On this page [Mint One Time Minting Policy](https://meshjs.dev/smart-contracts/content-ownership#mint-one-time-minting-policy) [Setup Oracle Utxo](https://meshjs.dev/smart-contracts/content-ownership#setup-oracle-utxo) [Send Ref-Script Onchain](https://meshjs.dev/smart-contracts/content-ownership#send-ref-script-onchain) [Create Content Registry](https://meshjs.dev/smart-contracts/content-ownership#create-content-registry) [Create Ownership Registry](https://meshjs.dev/smart-contracts/content-ownership#create-ownership-registry) [Get Oracle Data](https://meshjs.dev/smart-contracts/content-ownership#get-oracle-data) [Mint User Token](https://meshjs.dev/smart-contracts/content-ownership#mint-user-token) [Create Content](https://meshjs.dev/smart-contracts/content-ownership#create-content) [Get Content](https://meshjs.dev/smart-contracts/content-ownership#get-content) Ask AI --- # Staking Transactions | Mesh SDK [Transaction Builder](https://meshjs.dev/apis/txbuilder) Staking Transactions ==================== Transactions for delegating ADA and managing stakepools Copy MarkdownOpen In the code snippet, you will find `txBuilder`, which is an instance of `MeshTxBuilder`, with powerful low-level APIs that allow you to build transactions. Here's how to initialize **MeshTxBuilder**. const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); [Register Stake Address](https://meshjs.dev/apis/txbuilder/staking#register-stake-address) ------------------------------------------------------------------------------------------- Same as Transaction, with `MeshTxBuilder`, you have to register a stake address before delegating to stakepools. Here are the 2 APIs you need: txBuilder .registerStakeCertificate(rewardAddress) .delegateStakeCertificate(rewardAddress, poolIdHash) Since we need to provide the deserialize hash of pool ID, we can use the following util to get it: const poolIdHash = deserializePoolId( "pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx", ); ### [Register Stake Address](https://meshjs.dev/apis/txbuilder/staking#register-stake-address-toc) Register a stake address before delegating to a stakepool. **Pool ID** `pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx` const utxos = await wallet.getUtxos(); const address = await wallet.getChangeAddress(); const addresses = await wallet.getRewardAddresses(); const rewardAddress = addresses[0]!; const poolIdHash = deserializePoolId("pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx"); if (rewardAddress === undefined) { throw "No address found"; } const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .registerStakeCertificate(rewardAddress) .delegateStakeCertificate(rewardAddress, poolIdHash) .selectUtxosFrom(utxos) .changeAddress(address) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Delegate Stake](https://meshjs.dev/apis/txbuilder/staking#delegate-stake) --------------------------------------------------------------------------- Stake delegation with `MeshTxBuilder` is the same as the first delegate, but without registering the stake key, so only one API call is needed: txBuilder .delegateStakeCertificate(rewardAddress, poolIdHash) ### [Delegate Stake](https://meshjs.dev/apis/txbuilder/staking#delegate-stake-toc) Delegate stake to a stake pool **Pool ID** `pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx` const utxos = await wallet.getUtxos(); const address = await wallet.getChangeAddress(); const addresses = await wallet.getRewardAddresses(); const rewardAddress = addresses[0]!; const poolIdHash = deserializePoolId("pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx"); if (rewardAddress === undefined) { throw "No address found"; } const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .delegateStakeCertificate(rewardAddress, poolIdHash) .selectUtxosFrom(utxos) .changeAddress(address) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Withdraw Rewards](https://meshjs.dev/apis/txbuilder/staking#withdraw-rewards) ------------------------------------------------------------------------------- Use MeshTxBuilder’s withdrawal method to specify the reward address and amount. * rewardAddress (string) - the reward address to withdraw from * lovelace (number) - the amount to withdraw in Lovelace txBuilder .withdrawal(rewardAddress, lovelace) ### [Withdraw Rewards](https://meshjs.dev/apis/txbuilder/staking#withdraw-rewards-toc) Withdraw staking rewards. **Amount in lovelace:** `1000000` const utxos = await wallet.getUtxos(); const address = await wallet.getChangeAddress(); const addresses = await wallet.getRewardAddresses(); const rewardAddress = addresses[0]!; if (rewardAddress === undefined) { throw "No address found"; } const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .withdrawal(rewardAddress, "1000000") .selectUtxosFrom(utxos) .changeAddress(address) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Deregister Stake](https://meshjs.dev/apis/txbuilder/staking#deregister-stake) ------------------------------------------------------------------------------- To deregister a stake address with MeshTxBuilder, use the following method: * rewardAddress (string) - the bech32 reward address to deregister txBuilder .deregisterStakeCertificate(rewardAddress: string) ### [Deregister Stake](https://meshjs.dev/apis/txbuilder/staking#deregister-stake-toc) Deregister a stake address. const utxos = await wallet.getUtxos(); const address = await wallet.getChangeAddress(); const addresses = await wallet.getRewardAddresses(); const rewardAddress = addresses[0]!; if (rewardAddress === undefined) { throw "No address found"; } const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .deregisterStakeCertificate(rewardAddress) .selectUtxosFrom(utxos) .changeAddress(address) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Script Withdrawal - Supporting Withdraw Zero](https://meshjs.dev/apis/txbuilder/staking#script-withdrawal---supporting-withdraw-zero) --------------------------------------------------------------------------------------------------------------------------------------- Withdrawal from a script is supported by `MeshTxBuilder` with this set of APIs: txBuilder .withdrawalPlutusScriptV2() .withdrawal(rewardAddress, withdrawalAmount) .withdrawalScript(stakeScriptCbor) .withdrawalRedeemerValue(redeemer) **Withdraw Zero** This is a technique commonly used on Cardano to prove control of a stake key without actually withdrawing any rewards from its withdrawal account. To perform a "withdraw zero", you have to follow these steps: * Register script stake key txBuilder .registerStakeCertificate(stakeScriptHash) * Withdraw Zero txBuilder .withdrawalPlutusScriptV2() .withdrawal(rewardAddress, "0") .withdrawalScript(stakeScriptCbor) .withdrawalRedeemerValue(redeemer) ### [Register Script Stake Key](https://meshjs.dev/apis/txbuilder/staking#register-script-stake-key-toc) One off setup before triggering withdraw zero const utxos = await wallet.getUtxos(); const address = await wallet.getChangeAddress(); const txBuilder = getTxBuilder(); const stakeScriptCbor = alwaysSucceedMintingStakingScriptCbor( deserializeAddress(address).pubKeyHash, ); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .registerStakeCertificate(resolveScriptHash(stakeScriptCbor, "V2")) .selectUtxosFrom(utxos) .changeAddress(address) .complete(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); ### [Withdraw Zero](https://meshjs.dev/apis/txbuilder/staking#withdraw-zero-toc) Actual withdrawal of zero to trigger script validation const utxos = await wallet.getUtxos(); const collateral = await wallet.getCollateral(); const address = await wallet.getChangeAddress(); const stakeScriptCbor = alwaysSucceedMintingStakingScriptCbor( deserializeAddress(address).pubKeyHash, ); const rewardAddress = serializeRewardAddress( resolveScriptHash(stakeScriptCbor, "V2"), true, 0, ); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .withdrawalPlutusScriptV2() .withdrawal(rewardAddress, "0") .withdrawalScript(stakeScriptCbor) .withdrawalRedeemerValue("") .selectUtxosFrom(utxos) .changeAddress(address) .txInCollateral(...utxoToTxIn(collateral[0]!)) .complete(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); [Smart Contracts\ \ Transactions to work with smart contracts](https://meshjs.dev/apis/txbuilder/smart-contracts) [Governance Transactions\ \ Transactions for participating in Cardano's on-chain governance](https://meshjs.dev/apis/txbuilder/governance) ### On this page [Register Stake Address](https://meshjs.dev/apis/txbuilder/staking#register-stake-address) [Delegate Stake](https://meshjs.dev/apis/txbuilder/staking#delegate-stake) [Withdraw Rewards](https://meshjs.dev/apis/txbuilder/staking#withdraw-rewards) [Deregister Stake](https://meshjs.dev/apis/txbuilder/staking#deregister-stake) [Script Withdrawal - Supporting Withdraw Zero](https://meshjs.dev/apis/txbuilder/staking#script-withdrawal---supporting-withdraw-zero) Ask AI --- # NFT Minting Machine | Mesh SDK [Smart Contracts](https://meshjs.dev/smart-contracts) NFT Minting Machine =================== Mint NFT that ensure the token name is incremented by a counter Copy MarkdownOpen This NFT minting script enables users to mint NFTs with an automatically incremented index, which increases by one for each newly minted NFT. To facilitate this process, the first step is to set up a one-time minting policy by minting an oracle token. This oracle token is essential as it holds the current state and index of the NFTs, acting as a reference for the minting sequence. With each new NFT minted, the token index within the oracle is incremented by one, ensuring a consistent and orderly progression in the numbering of the NFTs. There are 3 actions available to interact with this smart contract: * **Setup Oracle:** Mint one-time minting policy to set up the oracle * **Mint Token:** Mint NFT that ensures the token name is incremented by a counter * **Get Oracle Data:** Fetch the current oracle data to get the current NFT index and other information ### [Install package](https://meshjs.dev/smart-contracts/plutus-nft#install-package-toc) First you can to install the `@meshsdk/contracts` package: npm install @meshsdk/contract Both on-chain and off-chain codes are open-source and available on [Mesh Github Repository](https://github.com/MeshJS/mesh/tree/main/packages/mesh-contract/src/plutus-nft) . [Setup Oracle](https://meshjs.dev/smart-contracts/plutus-nft#setup-oracle) --------------------------------------------------------------------------- First, we need to set up a one-time minting policy by minting an oracle token. This oracle token is essential as it holds the current state and index of the NFTs, acting as a reference for the minting sequence. We need to provide 2 parameters to setup the oracle, the price of the NFT in lovelace and the collection name. The collection name is used when initializing `MeshPlutusNFTContract` which is used to derive the script CBOR. The price of the NFT in lovelace is used in `setupOracle()` function which will be added into the oracle token. const contract = new MeshPlutusNFTContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, { collectionName: 'collectionName', // your nft collection name }, ); const { tx, paramUtxo } = await contract.setupOracle(15000000); // price in lovelace The `setupOracle()` function will return a transaction CBOR and a `paramUtxo`. The `paramUtxo` will be used in the minting transaction of the NFT, so it is important to store it. Here is an example of the `paramUtxo`: { "outputIndex": 0, "txHash": "63dbd563ee9979574401599a42841e0d5b63a691af95df863cbf37d5cb44a558" } The transaction CBOR can be signed and submitted using the following code: const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); ### [Setup Oracle](https://meshjs.dev/smart-contracts/plutus-nft#setup-oracle-toc) Mint one time minting policy to set up the oracle **NFT Price in Lovelace** `10000000` **Collection Name** `mesh` const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, verbose: true, }); const contract = new MeshPlutusNFTContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, { collectionName: 'mesh', }, ); const { tx, paramUtxo } = await contract.setupOracle(10000000); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Mint Token](https://meshjs.dev/smart-contracts/plutus-nft#mint-token) ----------------------------------------------------------------------- This NFT minting script enables users to mint NFTs with an automatically incremented index, which increases by one for each newly minted NFT. To facilitate this process, you must provide the `paramUtxo` that contains the output index and transaction hash of the NFT minting policy. const contract = new MeshPlutusNFTContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, { collectionName: 'collectionName', paramUtxo: {"outputIndex":0,"txHash":"63dbd563ee9979574401599a42841e0d5b63a691af95df863cbf37d5cb44a558"}, }, ); The `mintPlutusNFT()` function mints an NFT with asset metadata, which is a JSON object containing the NFT metadata. You can use the `getOracleData()` function to fetch the oracle data, which includes the current NFT index. This index will be helpful if you need to define the NFT name and its metadata. Here is an example of the how we can define the asset metadata: const oracleData = await contract.getOracleData(); const assetMetadata = { ...demoAssetMetadata, name: `Mesh Token ${oracleData.nftIndex}`, }; The `mintPlutusNFT()` function will return a transaction object that can be signed and submitted using the following code: const tx = await contract.mintPlutusNFT(assetMetadata); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); ### [Mint Token](https://meshjs.dev/smart-contracts/plutus-nft#mint-token-toc) Mint an NFT with asset metadata **Collection Name** `mesh` **Param UTxO** `{"outputIndex":0,"txHash":"63dbd563ee9979574401599a...37d5cb44a558"}` const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, verbose: true, }); const contract = new MeshPlutusNFTContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, { collectionName: 'mesh', paramUtxo: {"outputIndex":0,"txHash":"63dbd563ee9979574401599a42841e0d5b63a691af95df863cbf37d5cb44a558"}, }, ); // Get Oracle Data const oracleData = await contract.getOracleData(); // see getOracleData() // define your NFT metadata here const assetMetadata = { ...demoAssetMetadata, name: `Mesh Token ${oracleData.nftIndex}`, }; const tx = await contract.mintPlutusNFT(assetMetadata); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Get Oracle Data](https://meshjs.dev/smart-contracts/plutus-nft#get-oracle-data) --------------------------------------------------------------------------------- Getting the oracle data is essential to fetch the current NFT index. To facilitate this process, you must provide the `paramUtxo` that contains the output index and transaction hash of the NFT minting policy. const contract = new MeshPlutusNFTContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, { collectionName: 'collectionName', paramUtxo: {"outputIndex":0,"txHash":"63dbd563ee9979574401599a42841e0d5b63a691af95df863cbf37d5cb44a558"}, }, ); The `getOracleData()` function will return the current oracle data. const oracleData = await contract.getOracleData(); ### [Get Oracle Data](https://meshjs.dev/smart-contracts/plutus-nft#get-oracle-data-toc) Fetch the current oracle data to get the current NFT index and other information **Collection Name** `mesh` **Param UTxO** `{"outputIndex":0,"txHash":"63dbd563ee9979574401599a...37d5cb44a558"}` const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, verbose: true, }); const contract = new MeshPlutusNFTContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, { collectionName: 'mesh', paramUtxo: {"outputIndex":0,"txHash":"63dbd563ee9979574401599a42841e0d5b63a691af95df863cbf37d5cb44a558"}, }, ); // Get Oracle Data const oracleData = await contract.getOracleData(); [Marketplace\ \ Build a NFT marketplace to buy and sell NFTs](https://meshjs.dev/smart-contracts/marketplace) [Payment Splitter\ \ Split payouts equally among a list of specified payees](https://meshjs.dev/smart-contracts/payment-splitter) ### On this page [Setup Oracle](https://meshjs.dev/smart-contracts/plutus-nft#setup-oracle) [Mint Token](https://meshjs.dev/smart-contracts/plutus-nft#mint-token) [Get Oracle Data](https://meshjs.dev/smart-contracts/plutus-nft#get-oracle-data) Ask AI --- # Developer Resources | Mesh SDK [Learn](https://meshjs.dev/resources) Developer Resources =================== Essential tools, communities, and resources for Cardano developers using Mesh SDK. Copy MarkdownOpen Your central hub for tools, communities, learning materials, and ecosystem resources to accelerate your Cardano development journey with Mesh. [Official Mesh Resources](https://meshjs.dev/resources/developer-resources#official-mesh-resources) ---------------------------------------------------------------------------------------------------- ### [Documentation & Learning](https://meshjs.dev/resources/developer-resources#documentation--learning) * **[Mesh Documentation](https://meshjs.dev/docs) ** - Comprehensive guides and API references * **[Getting Started Guide](https://meshjs.dev/guides) ** - Your first steps with Mesh * **[API Reference](https://meshjs.dev/apis) ** - Complete API documentation * **[Smart Contracts](https://meshjs.dev/smart-contracts) ** - Build with Plutus and Aiken * **[React Components](https://meshjs.dev/react) ** - UI components for your dApp ### [Code & Examples](https://meshjs.dev/resources/developer-resources#code--examples) * **[GitHub Repository](https://github.com/MeshJS/mesh) ** - Source code and contributions * **[Example Projects](https://github.com/MeshJS/examples) ** - Working code samples * **[Starter Templates](https://github.com/MeshJS/mesh-starter) ** - Boilerplate projects * **[Code Playground](https://meshjs.dev/apis) ** - Interactive code editor on every API page ### [Stay Updated](https://meshjs.dev/resources/developer-resources#stay-updated) * **[GitHub Milestones](https://github.com/MeshJS/mesh/milestones) ** - Current development roadmap * **[Release Notes](https://github.com/MeshJS/mesh/releases) ** - Latest updates and changes * **[NPM Package](https://www.npmjs.com/package/@meshsdk/core) ** - Package downloads and versions [Community & Support](https://meshjs.dev/resources/developer-resources#community--support) ------------------------------------------------------------------------------------------- ### [Join the Conversation](https://meshjs.dev/resources/developer-resources#join-the-conversation) Discord Community Join our active Discord server for real-time help, discussions, and updates. [Join Discord →](https://discord.gg/dH48jH3BKa) Twitter / X Follow [@meshsdk](https://twitter.com/meshsdk) for announcements, tips, and community highlights. [Follow on Twitter →](https://twitter.com/meshsdk) GitHub Discussions Participate in longer-form discussions, ask questions, and share ideas. [Join Discussions →](https://github.com/MeshJS/mesh/discussions) Stack Overflow Ask technical questions tagged with `meshsdk` for searchable Q&A. [View Questions →](https://stackoverflow.com/questions/tagged/meshsdk) ### [Get Help](https://meshjs.dev/resources/developer-resources#get-help) * **[FAQ](https://meshjs.dev/resources/faq) ** - Frequently asked questions * **[GitHub Issues](https://github.com/MeshJS/mesh/issues) ** - Report bugs or request features * **[Community Support](https://discord.gg/dH48jH3BKa) ** - Free community help via Discord [Cardano Ecosystem](https://meshjs.dev/resources/developer-resources#cardano-ecosystem) ---------------------------------------------------------------------------------------- ### [Official Cardano Resources](https://meshjs.dev/resources/developer-resources#official-cardano-resources) * **[Cardano.org](https://cardano.org/) ** - Official Cardano website * **[Cardano Documentation](https://docs.cardano.org/) ** - Official protocol documentation * **[Cardano Forum](https://forum.cardano.org/) ** - Community discussions * **[Cardano Stack Exchange](https://cardano.stackexchange.com/) ** - Technical Q&A ### [Block Explorers](https://meshjs.dev/resources/developer-resources#block-explorers) * **[CardanoScan](https://cardanoscan.io/) ** - Comprehensive Cardano blockchain explorer * **[AdaStat](https://adastat.net/) ** - Analytics and statistics * **[Pool.pm](https://pool.pm/) ** - Native assets and NFT explorer * **[Cexplorer](https://cexplorer.io/) ** - Detailed blockchain data [Learning Resources](https://meshjs.dev/resources/developer-resources#learning-resources) ------------------------------------------------------------------------------------------ ### [Courses & Bootcamps](https://meshjs.dev/resources/developer-resources#courses--bootcamps) * **[Emurgo Academy](https://education.emurgo.io/) ** - Professional Cardano development courses * **[IOG Academy](https://www.iohkacademy.io/) ** - Official Cardano education platform * **[Gimbalabs](https://gimbalabs.com/) ** - Community-driven learning platform * **[Plutus Pioneers Program](https://plutus-pioneer-program.readthedocs.io/) ** - Learn Plutus smart contracts ### [Books & Written Content](https://meshjs.dev/resources/developer-resources#books--written-content) * **[Cardano Developer Portal](https://developers.cardano.org/) ** - Comprehensive development guides * **[Essential Cardano](https://essentialcardano.io/) ** - Curated Cardano resources * **[Building on Cardano](https://builtoncardano.com/) ** - Showcase of Cardano projects [Mesh AI Features](https://meshjs.dev/resources/developer-resources#mesh-ai-features) -------------------------------------------------------------------------------------- Mesh includes AI-powered development assistance: * **[AI Chat Assistant](https://meshjs.dev/ai) ** - Ask questions and get instant answers * **AI Code Generation** - Generate Mesh code from natural language * **Documentation Search** - Semantic search across all docs * **Context-Aware Help** - Get relevant suggestions as you code Access Mesh AI directly from our documentation using the sparkle icon ✨ or visit the [AI page](https://meshjs.dev/ai) . [Open Source Contributions](https://meshjs.dev/resources/developer-resources#open-source-contributions) -------------------------------------------------------------------------------------------------------- ### [How to Contribute](https://meshjs.dev/resources/developer-resources#how-to-contribute) 1. **Code Contributions**: Fork the repo, make changes, submit PR 2. **Documentation**: Improve or add to our docs 3. **Bug Reports**: Help us identify and fix issues 4. **Feature Requests**: Suggest new capabilities 5. **Community Help**: Answer questions on Discord See our [Contributing Guide](https://github.com/MeshJS/mesh/blob/main/CONTRIBUTING.md) for details. ### [Financial Support](https://meshjs.dev/resources/developer-resources#financial-support) Support Mesh development: * **[GitHub Sponsors](https://github.com/sponsors/MeshJS) ** - Monthly sponsorships * **[Support Page](https://meshjs.dev/about/support-us) ** - Various support options [Newsletter & Updates](https://meshjs.dev/resources/developer-resources#newsletter--updates) --------------------------------------------------------------------------------------------- Stay informed about Mesh and Cardano development: * Subscribe to our newsletter (coming soon) * Follow [@meshsdk](https://twitter.com/meshsdk) on Twitter * Star our [GitHub repo](https://github.com/MeshJS/mesh) for updates * Join [Discord](https://discord.gg/dH48jH3BKa) announcements channel [Quick Links](https://meshjs.dev/resources/developer-resources#quick-links) ---------------------------------------------------------------------------- [📚 Guides\ \ Step-by-step tutorials](https://meshjs.dev/guides) [⚡ API Docs\ \ Complete API reference](https://meshjs.dev/apis) [❓ FAQ\ \ Common questions](https://meshjs.dev/resources/faq) [💻 Examples\ \ Working code samples](https://github.com/MeshJS/examples) [💬 Discord\ \ Community chat](https://discord.gg/dH48jH3BKa) [❤️ Support\ \ Help Mesh grow](https://meshjs.dev/about/support-us) * * * **Ready to build?** Start with our [Getting Started Guide](https://meshjs.dev/guides) or jump into the [API Documentation](https://meshjs.dev/apis) . Need help? [Join our Discord community](https://discord.gg/dH48jH3BKa) - we're here to help! [Use Cases & Showcases\ \ Discover real-world applications and projects built with Mesh - from DeFi platforms to NFT marketplaces and enterprise solutions on Cardano.](https://meshjs.dev/resources/use-cases) [Frequently Asked Questions\ \ Common questions and answers about Mesh - the TypeScript SDK for Cardano blockchain development.](https://meshjs.dev/resources/faq) ### On this page [Official Mesh Resources](https://meshjs.dev/resources/developer-resources#official-mesh-resources) [Documentation & Learning](https://meshjs.dev/resources/developer-resources#documentation--learning) [Code & Examples](https://meshjs.dev/resources/developer-resources#code--examples) [Stay Updated](https://meshjs.dev/resources/developer-resources#stay-updated) [Community & Support](https://meshjs.dev/resources/developer-resources#community--support) [Join the Conversation](https://meshjs.dev/resources/developer-resources#join-the-conversation) [Get Help](https://meshjs.dev/resources/developer-resources#get-help) [Cardano Ecosystem](https://meshjs.dev/resources/developer-resources#cardano-ecosystem) [Official Cardano Resources](https://meshjs.dev/resources/developer-resources#official-cardano-resources) [Block Explorers](https://meshjs.dev/resources/developer-resources#block-explorers) [Learning Resources](https://meshjs.dev/resources/developer-resources#learning-resources) [Courses & Bootcamps](https://meshjs.dev/resources/developer-resources#courses--bootcamps) [Books & Written Content](https://meshjs.dev/resources/developer-resources#books--written-content) [Mesh AI Features](https://meshjs.dev/resources/developer-resources#mesh-ai-features) [Open Source Contributions](https://meshjs.dev/resources/developer-resources#open-source-contributions) [How to Contribute](https://meshjs.dev/resources/developer-resources#how-to-contribute) [Financial Support](https://meshjs.dev/resources/developer-resources#financial-support) [Newsletter & Updates](https://meshjs.dev/resources/developer-resources#newsletter--updates) [Quick Links](https://meshjs.dev/resources/developer-resources#quick-links) Ask AI --- # Resolvers | Mesh SDK [Utilities](https://meshjs.dev/apis/utilities) Resolvers ========= Converts between different formats. Copy MarkdownOpen [Resolve Private Key](https://meshjs.dev/apis/utilities/resolvers#resolve-private-key) --------------------------------------------------------------------------------------- Provide the mnemonic phrases and `resolvePrivateKey` will return a private key. ### [Resolve Private Key](https://meshjs.dev/apis/utilities/resolvers#resolve-private-key-toc) Convert mnemonic to private key **Mnemonic** [\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution",\ "solution"\ ] resolvePrivateKey(["solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution"]); [Resolve Transaction Hash](https://meshjs.dev/apis/utilities/resolvers#resolve-transaction-hash) ------------------------------------------------------------------------------------------------- Provide a `cborTx`, `resolveTxHash` will return the transaction hash. This hash is useful for creating chain transactions. ### [Resolve Transaction Hash](https://meshjs.dev/apis/utilities/resolvers#resolve-transaction-hash-toc) Convert transaction cborTx to transaction hash const tx = new Transaction({ initiator: wallet }); tx.sendLovelace('addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', '1500000'); const unsignedTx = await tx.build(); const hash1 = resolveTxHash(unsignedTx); const signedTx = await wallet.signTx(unsignedTx, false); const hash2 = resolveTxHash(signedTx); const txHash = await wallet.submitTx(signedTx); // txHash == hash1 == hash2 [Resolve Data Hash](https://meshjs.dev/apis/utilities/resolvers#resolve-data-hash) ----------------------------------------------------------------------------------- Converts datum into hash. Getting the hash is useful when you need to query for the UTXO that contain the assets you need for your transaction's input. Explore [Transaction](https://meshjs.dev/apis/transaction) to learn more about designing Datum, and learn how to query for UTXOs containing the datum hash. ### [Resolve Data Hash](https://meshjs.dev/apis/utilities/resolvers#resolve-data-hash-toc) Convert datum into hash **Datum:** `supersecretdatum` resolveDataHash('supersecretdatum'); [Resolve Native Script Hash](https://meshjs.dev/apis/utilities/resolvers#resolve-native-script-hash) ----------------------------------------------------------------------------------------------------- Converts NativeScript into hash. ### [Resolve Native Script Hash](https://meshjs.dev/apis/utilities/resolvers#resolve-native-script-hash-toc) Convert NativeScript to hash **Address** `addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr` const keyHash = resolvePaymentKeyHash('addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr'); const nativeScript: NativeScript = { type: "all", scripts: [\ {\ type: "sig",\ keyHash: keyHash,\ },\ ], }; resolveNativeScriptHash(nativeScript); [Resolve Script Hash](https://meshjs.dev/apis/utilities/resolvers#resolve-script-hash) --------------------------------------------------------------------------------------- `resolveScriptHash` will return a script hash. For example, this is useful when you want to convert a script to a policy ID. ### [Resolve Script Hash](https://meshjs.dev/apis/utilities/resolvers#resolve-script-hash-toc) Convert script to hash (like policy ID) **script address** `8200581c5867c3b8e27840f556ac268b781578b14c5661fc63ee720dbeab663f` resolveScriptHash('8200581c5867c3b8e27840f556ac268b781578b14c5661fc63ee720dbeab663f') [Resolve Stake Address](https://meshjs.dev/apis/utilities/resolvers#resolve-stake-address) ------------------------------------------------------------------------------------------- Provide a wallet address, and `resolveRewardAddress` will return a staking address in bech32 format. ### [Resolve Stake Address](https://meshjs.dev/apis/utilities/resolvers#resolve-stake-address-toc) Convert wallet address to staking address **Address** `addr_test1qpvx0sacuf...swx9` resolveRewardAddress('addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9'); [Resolve Fingerprint](https://meshjs.dev/apis/utilities/resolvers#resolve-fingerprint) --------------------------------------------------------------------------------------- Takes policy ID and asset name, and return asset fingerprint based on [CIP-14](https://cips.cardano.org/cip/cip-14) . [Resolve Asset Fingerprint](https://meshjs.dev/apis/utilities/resolvers#resolve-asset-fingerprint-toc) ------------------------------------------------------------------------------------------------------- Convert asset policy ID and asset name to asset fingerprint. **Policy ID** `426117329844ccb3b0ba877220ff06a5bdf21eab3fb33e2f3a3f8e69` **Asset Name** `4d657368546f6b656e` resolveFingerprint( '426117329844ccb3b0ba877220ff06a5bdf21eab3fb33e2f3a3f8e69', '4d657368546f6b656e' ) [Resolve Stake Key Hash](https://meshjs.dev/apis/utilities/resolvers#resolve-stake-key-hash) --------------------------------------------------------------------------------------------- Provide a stake address, and `resolveStakeKeyHash` will return the pub key hash of the stake address. This key hash is useful for building the NativeScript. [Resolve Stake Key Hash](https://meshjs.dev/apis/utilities/resolvers#resolve-stake-key-hash-toc) ------------------------------------------------------------------------------------------------- Convert stake address to pub key hash **Address** `stake_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n` resolveStakeKeyHash('stake_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n'); [Resolve Rep Id](https://meshjs.dev/apis/utilities/resolvers#resolve-rep-id) ----------------------------------------------------------------------------- Resolve Rep Id from scrip hash. ### [Resolve Rep Id](https://meshjs.dev/apis/utilities/resolvers#resolve-rep-id-toc) Resolve rep id from scrip hash let script: NativeScript = { type: "all", scripts: [\ {\ type: "sig",\ keyHash: 'aa048e4cc8a1e67e1d97ffbd4be614388014cbc2b2451527202943b6'\ },\ ], }; resolveScriptHashDRepId(resolveNativeScriptHash(script)); [Resolve Epoch Number](https://meshjs.dev/apis/utilities/resolvers#resolve-epoch-number) ----------------------------------------------------------------------------------------- With `resolveEpochNo`, you can get the current epoch with: import { resolveEpochNo } from '@meshsdk/core'; const epoch = resolveEpochNo('preprod'); You can also provide date in `milliseconds` to get epoch in the past or the future. For example, get the epoch 1 year from now: import { resolveEpochNo } from '@meshsdk/core'; let oneYearFromNow = new Date(); oneYearFromNow.setFullYear(oneYearFromNow.getFullYear() + 1); const epoch = resolveEpochNo('preprod', oneYearFromNow.getTime()); ### [Resolve Epoch number](https://meshjs.dev/apis/utilities/resolvers#resolve-epoch-number-toc) Get the epoch number for the network **Select network** `preprod` resolveEpochNo('preprod'); ### [Resolve Epoch number 1 year from now](https://meshjs.dev/apis/utilities/resolvers#resolve-epoch-number-1-year-from-now-toc) Get the epoch number for the network 1 year from now **Select network** `preprod` let oneYearFromNow = new Date() oneYearFromNow.setFullYear(oneYearFromNow.getFullYear() + 1); resolveEpochNo(userInput, oneYearFromNow.getTime()); [Resolve Slot Number](https://meshjs.dev/apis/utilities/resolvers#resolve-slot-number) --------------------------------------------------------------------------------------- With `resolveSlotNo`, you can get the current slot number with: import { resolveSlotNo } from '@meshsdk/core'; const slot = resolveSlotNo('preprod'); You can also provide date in `milliseconds` to get slots in the past or the future. For example, get the slot number 1 year from now: import { resolveSlotNo } from '@meshsdk/core'; let oneYearFromNow = new Date(); oneYearFromNow.setFullYear(oneYearFromNow.getFullYear() + 1); const slot = resolveSlotNo('preprod', oneYearFromNow.getTime()); ### [Resolve Slot number](https://meshjs.dev/apis/utilities/resolvers#resolve-slot-number-toc) Get the Slot number for the network **Select network** `preprod` resolveSlotNo('preprod'); ### [Resolve Slot number 1 year from now](https://meshjs.dev/apis/utilities/resolvers#resolve-slot-number-1-year-from-now-toc) Get the Slot number for the network 1 year from now **Select network** `preprod` let oneYearFromNow = new Date() oneYearFromNow.setFullYear(oneYearFromNow.getFullYear() + 1); resolveSlotNo(userInput, oneYearFromNow.getTime()); [Deserializers\ \ Parse CBOR or bech32 into objects](https://meshjs.dev/apis/utilities/deserializers) [Data\ \ Useful utilities to parse and manipulate data](https://meshjs.dev/apis/data) ### On this page [Resolve Private Key](https://meshjs.dev/apis/utilities/resolvers#resolve-private-key) [Resolve Transaction Hash](https://meshjs.dev/apis/utilities/resolvers#resolve-transaction-hash) [Resolve Data Hash](https://meshjs.dev/apis/utilities/resolvers#resolve-data-hash) [Resolve Native Script Hash](https://meshjs.dev/apis/utilities/resolvers#resolve-native-script-hash) [Resolve Script Hash](https://meshjs.dev/apis/utilities/resolvers#resolve-script-hash) [Resolve Stake Address](https://meshjs.dev/apis/utilities/resolvers#resolve-stake-address) [Resolve Fingerprint](https://meshjs.dev/apis/utilities/resolvers#resolve-fingerprint) [Resolve Stake Key Hash](https://meshjs.dev/apis/utilities/resolvers#resolve-stake-key-hash) [Resolve Rep Id](https://meshjs.dev/apis/utilities/resolvers#resolve-rep-id) [Resolve Epoch Number](https://meshjs.dev/apis/utilities/resolvers#resolve-epoch-number) [Resolve Slot Number](https://meshjs.dev/apis/utilities/resolvers#resolve-slot-number) Ask AI --- # Browser Wallet | Mesh SDK [Wallets](https://meshjs.dev/apis/wallets) Browser Wallet ============== For connecting, querying and performing wallet functions in accordance to CIP-30. Copy MarkdownOpen `BrowserWallet` provides APIs for interacting with browser-based wallets in accordance with CIP-30. This standard defines the communication protocol between applications and user wallets, ensuring compatibility and security. In addition to the CIP-30 APIs, `BrowserWallet` includes utility functions that simplify common tasks such as retrieving wallet balances, signing transactions, and managing UTXOs. This section allows you to explore and test the available APIs for browser wallets, enabling seamless integration into your applications. [Get Available Wallets](https://meshjs.dev/apis/wallets/browserwallet#get-available-wallets) --------------------------------------------------------------------------------------------- Returns a list of wallets available on user's device. Each wallet is an object with the following properties: * A name is provided to display wallet's name on the user interface. * A version is provided to display wallet's version on the user interface. * An icon is provided to display wallet's icon on the user interface. #### [Get Available Wallets](https://meshjs.dev/apis/wallets/browserwallet#get-available-wallets-toc) Get a list of wallets on user's device import { BrowserWallet } from 'meshsdk/core'; await BrowserWallet.getAvailableWallets() Example response: [\ {\ "name": "eternl",\ "icon": "data:image/png;base64,ICONBASE64HERE",\ "version": "0.1.0"\ }\ ] [Connect Wallet](https://meshjs.dev/apis/wallets/browserwallet#connect-wallet) ------------------------------------------------------------------------------- This is the entry point to start communication with the user's wallet. The wallet should request the user's permission to connect the web page to the user's wallet, and if permission has been granted, the wallet will be returned, exposing the full API for the app to use. Query `BrowserWallet.getAvailableWallets()` to get a list of available wallets, then provide the wallet `name` for which wallet the user would like to connect with. You can also provide an `extensions` object to enable specific CIPs. For example, to enable CIP95, you would pass: await BrowserWallet.enable('eternl', [95]); #### [Connect Wallet](https://meshjs.dev/apis/wallets/browserwallet#connect-wallet-toc) Connect to a CIP30 compatible wallet import { BrowserWallet } from '@meshsdk/core'; const wallet = await BrowserWallet.enable('eternl'); [Get Balance](https://meshjs.dev/apis/wallets/browserwallet#get-balance) ------------------------------------------------------------------------- This API retrieves a list of all assets in the connected wallet. Each asset is represented as an object containing the following properties: * Unit: A unique identifier for the asset, which can be used to display its name in the user interface. * Quantity: The amount of the asset held in the wallet. This information is useful for applications that need to display wallet balances or perform operations involving specific assets. #### [Get Balance](https://meshjs.dev/apis/wallets/browserwallet#get-balance-toc) Get all assets in the connected wallet await wallet.getBalance(); Example response: [\ {\ "unit": "lovelace",\ "quantity": "796105407"\ },\ {\ "unit": "0f5560dbc05282e05507aedb02d823d9d9f0e583cce579b81f9d1cd8",\ "quantity": "1"\ },\ {\ "unit": "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d4d657368546f6b656e",\ "quantity": "2"\ },\ ] [Get Change Address](https://meshjs.dev/apis/wallets/browserwallet#get-change-address) --------------------------------------------------------------------------------------- This API returns an address owned by the wallet that should be used as a change address. A change address is where leftover assets from a transaction are returned during its creation. This ensures that any unspent assets are sent back to the connected wallet. Applications can use this API to manage transaction outputs effectively, ensuring proper handling of change during transactions. #### [Get Change Address](https://meshjs.dev/apis/wallets/browserwallet#get-change-address-toc) Get address that should be used for transaction's change await wallet.getChangeAddress(); [Get Collateral](https://meshjs.dev/apis/wallets/browserwallet#get-collateral) ------------------------------------------------------------------------------- This API retrieves a list of UTXOs (unspent transaction outputs), controlled by the wallet, that can be used as collateral inputs for transactions involving Plutus scripts. The returned UTXOs must meet or exceed the specified ADA value target. If the target cannot be met, an error message will be returned explaining the issue. Wallets may return UTXOs with a greater total ADA value than requested, but must never return UTXOs with a smaller total value. This functionality is essential for applications that need to create transactions requiring collateral inputs. #### [Get Collateral](https://meshjs.dev/apis/wallets/browserwallet#get-collateral-toc) Get list of UTXOs that used as collateral inputs for transactions with plutus script inputs await wallet.getCollateral(); Example response: [\ {\ "input": {\ "outputIndex": 1,\ "txHash": "ff8d1e97c60989b4f...02ee937595ad741ff597af1"\ },\ "output": {\ "address": "addr_test1qzm...z0fr8c3grjmysm5e6yx",\ "amount": [ { "unit": "lovelace", "quantity": "5000000" } ]\ }\ }\ ] [Get Network ID](https://meshjs.dev/apis/wallets/browserwallet#get-network-id) ------------------------------------------------------------------------------- This API retrieves the network ID of the currently connected account. The network ID indicates the blockchain network the wallet is connected to. For example: * 0: Testnet * 1: Mainnet Other network IDs may be returned by wallets, but these are not governed by CIP-30. The network ID remains consistent unless the connected account changes. Applications can use this information to ensure compatibility with the connected network. #### [Get Network ID](https://meshjs.dev/apis/wallets/browserwallet#get-network-id-toc) Get currently connected network await wallet.getNetworkId(); [Get Reward Addresses](https://meshjs.dev/apis/wallets/browserwallet#get-reward-addresses) ------------------------------------------------------------------------------------------- Returns a list of reward addresses owned by the wallet. A reward address is a stake address that is used to receive rewards from staking, generally starts from `stake` prefix. #### [Get Reward Addresses](https://meshjs.dev/apis/wallets/browserwallet#get-reward-addresses-toc) Get stake addresses await wallet.getRewardAddresses(); Example response: [\ "stake_test1uzx0ksy9f4qnj2mzfdncqyjy84sszh64w43853nug5pedjgytgke9"\ ] [Get Unused Addresses](https://meshjs.dev/apis/wallets/browserwallet#get-unused-addresses) ------------------------------------------------------------------------------------------- Returns a list of unused addresses controlled by the wallet. #### [Get Unused Addresses](https://meshjs.dev/apis/wallets/browserwallet#get-unused-addresses-toc) Get addresses that are unused await wallet.getUnusedAddresses(); Example response: [\ "addr_test1qzk9x08mtre4jp8f7j8zu8802...r8c3grjmys7fl22c",\ "addr_test1qrmf35xyw2petfr0e0p4at0r7...8sc3grjmysm73dk8",\ "addr_test1qq6ts58hdaasd2q78fdjj0arm...i8c3grjmys85k8mf",\ ] [Get Used Addresses](https://meshjs.dev/apis/wallets/browserwallet#get-used-addresses) --------------------------------------------------------------------------------------- Returns a list of used addresses controlled by the wallet. #### [Get Used Addresses](https://meshjs.dev/apis/wallets/browserwallet#get-used-addresses-toc) Get addresses that are used await wallet.getUsedAddresses(); Example response: [\ "addr_test1qzk9x08mtre4jp8f7j8zu8802...r8c3grjmys7fl88a",\ "addr_test1qrmf35xyw2petfr0e0p4at0r7...8sc3grjmysm76gt3",\ "addr_test1qq6ts58hdaasd2q78fdjj0arm...i8c3grjmys85dn39",\ ] [Get UTXOs](https://meshjs.dev/apis/wallets/browserwallet#get-utxos) --------------------------------------------------------------------- Return a list of all UTXOs (unspent transaction outputs) controlled by the wallet. #### [Get UTXOs](https://meshjs.dev/apis/wallets/browserwallet#get-utxos-toc) Get UTXOs of the connected wallet const utxos = await wallet.getUtxos(); Example response: [\ {\ "input": {\ "outputIndex": 0,\ "txHash": "16dcbb1f93b4f9d5e...9106c7b121463c210ba"\ },\ "output": {\ "address": "addr_test1qzag7whju08xwrq...z0fr8c3grjmysgaw9y8",\ "amount": [\ {\ "unit": "lovelace",\ "quantity": "1314550"\ },\ {\ "unit": "f05c91a850...3d824d657368546f6b656e3032",\ "quantity": "1"\ }\ ]\ }\ }\ ] [Sign Data](https://meshjs.dev/apis/wallets/browserwallet#sign-data) --------------------------------------------------------------------- This endpoint uses CIP-8 message signing to sign arbitrary data and verify that the signature comes from the holder of the corresponding private key. `signData` takes two arguments, the first one is the payload to sign and the second one is the address (optional). By default, we get the first wallet's address with `wallet.getRewardAddresses()`, alternativelly you can specify the address to use. #### [Sign Data](https://meshjs.dev/apis/wallets/browserwallet#sign-data-toc) Define a payload and sign it with wallet. `Payload: mesh` const signature = await wallet.signData(mesh); Example response: { "signature": "845846a2012...f9119a18e8977d436385cecb08", "key": "a4010103272006215...b81a7f6ed4fa29cc7b33186c" } Check out [this guide](https://meshjs.dev/guides/prove-wallet-ownership#server-verify-signature) to learn how to verify the signature. [Sign Transaction](https://meshjs.dev/apis/wallets/browserwallet#sign-transaction) ----------------------------------------------------------------------------------- Requests user to sign the provided transaction (`tx`). The wallet should ask the user for permission, and if given, try to sign the supplied body and return a signed transaction. `partialSign` should be `true` if the transaction provided requires multiple signatures. #### [Sign Transaction](https://meshjs.dev/apis/wallets/browserwallet#sign-transaction-toc) Create a transaction and sign it const signedTx = await wallet.signTx(tx, partialSign?); Check out [Transaction](https://docs.meshjs.dev/transactions) to learn more on how to use this API. [Submit Transaction](https://meshjs.dev/apis/wallets/browserwallet#submit-transaction) --------------------------------------------------------------------------------------- This API lets applications ask a wallet to submit signed transactions. On success, the wallet returns a transaction ID for tracking. On failure, it returns error details. #### [Submit Transaction](https://meshjs.dev/apis/wallets/browserwallet#submit-transaction-toc) Submit a signed transaction with wallet const txHash = await wallet.submitTx(signedTx); Check out [Transaction](https://docs.meshjs.dev/transactions) to learn more on how to use this API. [Get Assests](https://meshjs.dev/apis/wallets/browserwallet#get-assests) ------------------------------------------------------------------------- Returns a list of assets in the wallet, excluding lovelace. #### [Get Assets](https://meshjs.dev/apis/wallets/browserwallet#get-assets-toc) Get assets in the connected wallet const assets = await wallet.getAssets(); Example response: [\ {\ "unit": "1207329a668cf5c42b80a220a8c85d5e82ac0b6f5ecedda4c07a8acc4d657368486f6e6f72546f6b656e2d3530343935",\ "policyId": "1207329a668cf5c42b80a220a8c85d5e82ac0b6f5ecedda4c07a8acc",\ "assetName": "Mesh Token Of Appreciation",\ "fingerprint": "asset1dw74h0w0meqg9cxkc9sezp8zqcxu8nl93fzfpz",\ "quantity": "1"\ }\ {\ "unit": "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d4d657368546f6b656e",\ "policyId": "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d",\ "assetName": "MeshToken",\ "fingerprint": "asset177e7535dclmkkph8ewt9fsghllkwmpspa3n98p",\ "quantity": "10"\ }\ ] [Get Lovelace](https://meshjs.dev/apis/wallets/browserwallet#get-lovelace) --------------------------------------------------------------------------- This API retrieves the Lovelace balance in the connected wallet. Lovelace is the smallest denomination of ADA, where 1 ADA equals 1,000,000 Lovelace. Applications can use this information to display the wallet's balance or perform operations involving ADA. #### [Get Lovelace](https://meshjs.dev/apis/wallets/browserwallet#get-lovelace-toc) Get amount of ADA in the connected wallet await wallet.getLovelace(); [Get Policy IDs](https://meshjs.dev/apis/wallets/browserwallet#get-policy-ids) ------------------------------------------------------------------------------- This API retrieves a list of policy IDs for all assets in the connected wallet. A policy ID is a unique identifier for a group of assets, often used to manage collections or verify asset ownership. Applications can use this information to query assets belonging to specific policy IDs or display asset details to the user. #### [Get Policy IDs](https://meshjs.dev/apis/wallets/browserwallet#get-policy-ids-toc) Get a list of policy IDs from all assets in wallet await wallet.getPolicyIds(); Example response: [\ "0f5560dbc05282e05507aedb02d823d9d9f0e583cce579b81f9d1cd8",\ "5bed9e89299c69d9a54bbc82d88aa5a86698b2b7b9d0ed030fc4b0ff",\ "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d",\ ] [Get a Collection of Assets](https://meshjs.dev/apis/wallets/browserwallet#get-a-collection-of-assets) ------------------------------------------------------------------------------------------------------- This API retrieves a list of assets associated with a specific policy ID. If no assets in the wallet belong to the specified policy ID, an empty list is returned. Applications can use this API to query assets belonging to a particular policy ID, which is useful for managing collections of assets or verifying ownership. To obtain a list of all policy IDs in the wallet, use `wallet.getPolicyIds()`. #### [Get a Collection of Assets](https://meshjs.dev/apis/wallets/browserwallet#get-a-collection-of-assets-toc) Get a list of assets belonging to the policy ID `Policy ID: d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527` await wallet.getPolicyIdAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527'); [Get Supported Extensions](https://meshjs.dev/apis/wallets/browserwallet#get-supported-extensions) --------------------------------------------------------------------------------------------------- `getSupportedExtensions` is a static function that returns a list of CIPs that are supported by a wallet. You can query this function without connecting to a wallet, by providing the wallet name. You can get the list of wallet on user's device with `await BrowserWallet.getAvailableWallets()`. #### [Get Supported Extensions](https://meshjs.dev/apis/wallets/browserwallet#get-supported-extensions-toc) Get a list of CIPs that are supported by a wallet `Wallet Name: eternl` await wallet.getSupportedExtensions('eternl'); [Get Extensions](https://meshjs.dev/apis/wallets/browserwallet#get-extensions) ------------------------------------------------------------------------------- This API retrieves a list of CIP-30 extensions enabled by the connected wallet. CIP-30 extensions define additional capabilities that wallets can support, enhancing their functionality. Applications can use this information to determine the features supported by the wallet and adapt their behavior accordingly. #### [Get Extensions](https://meshjs.dev/apis/wallets/browserwallet#get-extensions-toc) Get a list of CIPs that are supported by the connected wallet await wallet.getExtensions(); Example response: [\ {\ "cip": 30\ }\ ] [Get DRep](https://meshjs.dev/apis/wallets/browserwallet#get-drep) ------------------------------------------------------------------- This API retrieves the key, hash, and bech32 encoding of the DRep ID associated with the wallet. The DRep ID is a unique identifier used for delegation representation in the Cardano blockchain. Applications can use this information to interact with delegation-related features or display the DRep ID details to the user. #### [Get DRep ID Key](https://meshjs.dev/apis/wallets/browserwallet#get-drep-id-key-toc) Get the key, hash, and bech32 address of the DRep ID await wallet.getDRep(); Example response: { "publicKey": "6984e406dd81...39e43d798fe1a89ab", "publicKeyHash": "9f7f4b78...df83bd227e943e9808450", "dRepIDCip105": "drep1vz0h7jmc...0axqgg5q4dls5u" } [Get Registered Pub Stake Keys](https://meshjs.dev/apis/wallets/browserwallet#get-registered-pub-stake-keys) ------------------------------------------------------------------------------------------------------------- Get a list of registered public stake keys. #### [Get Registered Pub Stake Keys](https://meshjs.dev/apis/wallets/browserwallet#get-registered-pub-stake-keys-toc) Get a list of registered public stake keys await wallet.getRegisteredPubStakeKeys(); Example response: { "pubStakeKeys": [\ "d7eb3004c14647646...40f89c1a4b8a2eb0a3"\ ], "pubStakeKeyHashes": [\ "8cfb40854d41392b..5575627a467c450396c9"\ ] } [Get Unregistered Pub Stake Keys](https://meshjs.dev/apis/wallets/browserwallet#get-unregistered-pub-stake-keys) ----------------------------------------------------------------------------------------------------------------- Get a list of unregistered public stake keys. #### [Get Unregistered Pub Stake Keys](https://meshjs.dev/apis/wallets/browserwallet#get-unregistered-pub-stake-keys-toc) Get a list of unregistered public stake keys await wallet.getUnregisteredPubStakeKeys(); [Wallets\ \ Wallets APIs for interacting with the blockchain.](https://meshjs.dev/apis/wallets) [Mesh Wallet\ \ Mesh Wallet provides a set of APIs to interact with the blockchain. This wallet is compatible with Mesh transaction builders.](https://meshjs.dev/apis/wallets/meshwallet) ### On this page [Get Available Wallets](https://meshjs.dev/apis/wallets/browserwallet#get-available-wallets) [Connect Wallet](https://meshjs.dev/apis/wallets/browserwallet#connect-wallet) [Get Balance](https://meshjs.dev/apis/wallets/browserwallet#get-balance) [Get Change Address](https://meshjs.dev/apis/wallets/browserwallet#get-change-address) [Get Collateral](https://meshjs.dev/apis/wallets/browserwallet#get-collateral) [Get Network ID](https://meshjs.dev/apis/wallets/browserwallet#get-network-id) [Get Reward Addresses](https://meshjs.dev/apis/wallets/browserwallet#get-reward-addresses) [Get Unused Addresses](https://meshjs.dev/apis/wallets/browserwallet#get-unused-addresses) [Get Used Addresses](https://meshjs.dev/apis/wallets/browserwallet#get-used-addresses) [Get UTXOs](https://meshjs.dev/apis/wallets/browserwallet#get-utxos) [Sign Data](https://meshjs.dev/apis/wallets/browserwallet#sign-data) [Sign Transaction](https://meshjs.dev/apis/wallets/browserwallet#sign-transaction) [Submit Transaction](https://meshjs.dev/apis/wallets/browserwallet#submit-transaction) [Get Assests](https://meshjs.dev/apis/wallets/browserwallet#get-assests) [Get Lovelace](https://meshjs.dev/apis/wallets/browserwallet#get-lovelace) [Get Policy IDs](https://meshjs.dev/apis/wallets/browserwallet#get-policy-ids) [Get a Collection of Assets](https://meshjs.dev/apis/wallets/browserwallet#get-a-collection-of-assets) [Get Supported Extensions](https://meshjs.dev/apis/wallets/browserwallet#get-supported-extensions) [Get Extensions](https://meshjs.dev/apis/wallets/browserwallet#get-extensions) [Get DRep](https://meshjs.dev/apis/wallets/browserwallet#get-drep) [Get Registered Pub Stake Keys](https://meshjs.dev/apis/wallets/browserwallet#get-registered-pub-stake-keys) [Get Unregistered Pub Stake Keys](https://meshjs.dev/apis/wallets/browserwallet#get-unregistered-pub-stake-keys) Ask AI --- # Vesting | Mesh SDK [Smart Contracts](https://meshjs.dev/smart-contracts) Vesting ======= Locks up funds and allows the beneficiary to withdraw the funds after the lockup period Copy MarkdownOpen When a new employee joins an organization, they typically receive a promise of compensation to be disbursed after a specified duration of employment. This arrangement often involves the organization depositing the funds into a vesting contract, with the employee gaining access to the funds upon the completion of a predetermined lockup period. Through the utilization of vesting contracts, organizations establish a mechanism to encourage employee retention by linking financial rewards to tenure. There are 2 actions (or endpoints) available to interact with this smart contract: * deposit asset * withdraw asset ### [Install package](https://meshjs.dev/smart-contracts/vesting#install-package-toc) First you can to install the `@meshsdk/contracts` package: npm install @meshsdk/contract ### [Initialize the contract](https://meshjs.dev/smart-contracts/vesting#initialize-the-contract-toc) To initialize the contract, we need to initialize a [provider](https://meshjs.dev/providers) , `MeshTxBuilder` and `MeshVestingContract`. import { MeshVestingContract } from "@meshsdk/contract"; import { MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshVestingContract({ mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }); Both on-chain and off-chain codes are open-source and available on [Mesh Github Repository](https://github.com/MeshJS/mesh/tree/main/packages/mesh-contract/src/vesting) . [Deposit Fund](https://meshjs.dev/smart-contracts/vesting#deposit-fund) ------------------------------------------------------------------------ After the lockup period has expired, the beneficiary can withdraw the funds from the vesting contract. `withdrawFund()` withdraw funds from a vesting contract. The function accepts the following parameters: * vestingUtxo (UTxO) - unspent transaction output in the script ### [Deposit Fund](https://meshjs.dev/smart-contracts/vesting#deposit-fund-toc) Deposit funds into a vesting contract with a locking period for a beneficiary **Amount in lovelace** `5000000` **Beneficiary address** `addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr` const assets: Asset[] = [\ {\ unit: "lovelace",\ quantity: '5000000',\ },\ ]; const lockUntilTimeStamp = new Date(); lockUntilTimeStamp.setMinutes(lockUntilTimeStamp.getMinutes() + 1); const beneficiary = 'addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr'; const tx = await contract.depositFund( assets, lockUntilTimeStamp.getTime(), beneficiary, ); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); [Withdraw Fund](https://meshjs.dev/smart-contracts/vesting#withdraw-fund) -------------------------------------------------------------------------- After the lockup period has expired, the beneficiary can withdraw the funds from the vesting contract. `withdrawFund()` withdraw funds from a vesting contract. The function accepts the following parameters: * vestingUtxo (UTxO) - unspent transaction output in the script A [successful withdrawal](https://preprod.cardanoscan.io/transaction/e61815bcfe46ababf3d024ae470f779fa738cded55f02127b9e211847c77af8b) will send the funds to the wallet that signed the transaction to withdraw the funds. ### [Withdraw Fund](https://meshjs.dev/smart-contracts/vesting#withdraw-fund-toc) Withdraw funds from a vesting contract **Tx hash** `Tx hash` const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.withdrawFund(utxo); const signedTx = await wallet.signTx(tx, true); const txHash = await wallet.submitTx(signedTx); [Full Tutorial](https://meshjs.dev/smart-contracts/vesting#full-tutorial) -------------------------------------------------------------------------- Vesting contract is a smart contract that locks up funds for a period of time and allows the beneficiary to withdraw the funds after the lockup period. Usually, vesting contract defines a beneficiary who can be different from the original owner. When a new employee joins an organization, they typically receive a promise of compensation to be disbursed after a specified duration of employment. This arrangement often involves the organization depositing the funds into a vesting contract, with the employee gaining access to the funds upon the completion of a predetermined lockup period. Through the utilization of vesting contracts, organizations establish a mechanism to encourage employee retention by linking financial rewards to tenure. ### [On-Chain code](https://meshjs.dev/smart-contracts/vesting#on-chain-code-toc) First, we define the datum's shape, as this datum serves as configuration and contains the different parameters of our vesting operation. pub type VestingDatum { /// POSIX time in milliseconds, e.g. 1672843961000 lock_until: Int, /// Owner's credentials owner: ByteArray, /// Beneficiary's credentials beneficiary: ByteArray, } In this example, we define a `VestingDatum` that contains the following fields: * `lock_until`: The POSIX timestamp in milliseconds until which the funds are locked. * `owner`: The credentials (public key hash) of the owner of the funds. * `beneficiary`: The credentials (public key hash) of the beneficiary of the funds. This datum can be found in `aiken-vesting/aiken-workspace/lib/vesting/types.ak`. Next, we define the spend validator. use aiken/transaction.{ScriptContext, Spend} use vesting/types.{VestingDatum} use vodka_extra_signatories.{key_signed} use vodka_validity_range.{valid_after} validator { pub fn vesting(datum: VestingDatum, _redeemer: Data, ctx: ScriptContext) { // In principle, scripts can be used for different purpose (e.g. minting // assets). Here we make sure it's only used when 'spending' from a eUTxO when ctx.purpose is { Spend(_) -> or { key_signed(ctx.transaction.extra_signatories, datum.owner), and { key_signed(ctx.transaction.extra_signatories, datum.beneficiary), valid_after(ctx.transaction.validity_range, datum.lock_until), }, } _ -> False } } } In this example, we define a `vesting` validator that ensures the following conditions are met: * The transaction must be signed by owner Or: * The transaction must be signed by beneficiary * The transaction must be valid after the lockup period This validator can be found in `aiken-vesting/aiken-workspace/validators/vesting.ak`. ### [How it works](https://meshjs.dev/smart-contracts/vesting#how-it-works-toc) The owner of the funds deposits the funds into the vesting contract. The funds are locked up until the lockup period expires. Transactions can include validity intervals that specify when the transaction is valid, both from and until a certain time. The ledger verifies these validity bounds before executing a script and will only proceed if they are legitimate. This approach allows scripts to incorporate a sense of time while maintaining determinism within the script's context. For instance, if a transaction has a lower bound `A`, we can infer that the current time is at least `A`. It's important to note that since we don't control the upper bound, a transaction might be executed even 30 years after the vesting delay. However, from the script's perspective, this is entirely acceptable. The beneficiary can withdraw the funds after the lockup period expires. The beneficiary can also be different from the owner of the funds. ### [Testing](https://meshjs.dev/smart-contracts/vesting#testing-toc) To test the vesting contract, we have provided the a comphrehensive test script,you can run tests with `aiken check`. The test script includes the following test cases: * success unlocking * success unlocking with only owner signature * success unlocking with beneficiary signature and time passed * fail unlocking with only beneficiary signature * fail unlocking with only time passed We recommend you to check out `aiken-vesting/aiken-workspace/validators/tests/vesting.ak` to learn more. ### [Compile and build script](https://meshjs.dev/smart-contracts/vesting#compile-and-build-script-toc) To compile the script, run the following command: aiken build This command will generate a CIP-0057 Plutus blueprint, which you can find in `aiken-vesting/aiken-workspace/plutus.json`. [Off-Chain code](https://meshjs.dev/smart-contracts/vesting#off-chain-code-toc) -------------------------------------------------------------------------------- ### [Deposit funds](https://meshjs.dev/smart-contracts/vesting#deposit-funds-toc) First, the owner can deposit funds into the vesting contract. The owner can specify the lockup period and the beneficiary of the funds. const assets: Asset[] = [\ {\ unit: "lovelace",\ quantity: "10000000",\ },\ ]; const lockUntilTimeStamp = new Date(); lockUntilTimeStamp.setMinutes(lockUntilTimeStamp.getMinutes() + 1); const beneficiary = "addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9"; In this example, we deposit 10 ADA into the vesting contract. The funds are locked up for 1 minute, and the beneficiary is specified. Then, we prepare a few variables to be used in the transaction. We get the wallet address and the UTXOs of the wallet. We also get the script address of the vesting contract, to send the funds to the script address. We also get the owner and beneficiary public key hashes. const { utxos, walletAddress } = await getWalletInfoForTx(); const { scriptAddr } = getScript(); const { pubKeyHash: ownerPubKeyHash } = deserializeAddress(walletAddress); const { pubKeyHash: beneficiaryPubKeyHash } = deserializeAddress(beneficiary); Next, we construct the transaction to deposit the funds into the vesting contract. const txBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); await txBuilder .txOut(scriptAddr, amount) .txOutInlineDatumValue( mConStr0([lockUntilTimeStampMs, ownerPubKeyHash, beneficiaryPubKeyHash]) ) .changeAddress(walletAddress) .selectUtxosFrom(utxos) .complete(); const unsignedTx = txBuilder.txHex; In this example, we construct the transaction to deposit the funds into the vesting contract. We specify the script address of the vesting contract, the amount to deposit, and the lockup period, owner, and beneficiary of the funds. Finally, we sign and submit the transaction. const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); To execute this code, ensure you have defined blockfrost key in the `.env` file. You can also define your wallet mnemonic in `aiken-vesting/src/configs.ts` file. You can run the following command execute the deposit funds code: npm run deposit Upon successful execution, you will receive a transaction hash. Save this transaction hash for withdrawing the funds. Example of a [successful deposit transaction](https://preprod.cardanoscan.io/transaction/ede9f8176fe41f0c84cfc9802b693dedb5500c0cbe4377b7bb0d57cf0435200b) . ### [Withdraw funds](https://meshjs.dev/smart-contracts/vesting#withdraw-funds-toc) After the lockup period expires, the beneficiary can withdraw the funds from the vesting contract. The owner can also withdraw the funds from the vesting contract. First, let's look for the UTxOs containing the funds locked in the vesting contract. const txHashFromDesposit = "ede9f8176fe41f0c84cfc9802b693dedb5500c0cbe4377b7bb0d57cf0435200b"; const utxos = await provider.fetchUTxOs(txHash); const vestingUtxo = utxos[0]; In this example, we fetch the UTxOs containing the funds locked in the vesting contract. We specify the transaction hash of the deposit transaction. Like before, we prepare a few variables to be used in the transaction. We get the wallet address and the UTXOs of the wallet. We also get the script address of the vesting contract, to send the funds to the script address. We also get the owner and beneficiary public key hashes. const { utxos, walletAddress, collateral } = await getWalletInfoForTx(); const { input: collateralInput, output: collateralOutput } = collateral; const { scriptAddr, scriptCbor } = getScript(); const { pubKeyHash } = deserializeAddress(walletAddress); Next, we prepare the datum and the slot number to set the transaction valid interval to be valid only after the slot. const datum = deserializeDatum(vestingUtxo.output.plutusData!); const invalidBefore = unixTimeToEnclosingSlot( Math.min(datum.fields[0].int as number, Date.now() - 15000), SLOT_CONFIG_NETWORK.preprod ) + 1; In this example, we prepare the datum and the slot number to set the transaction valid interval to be valid only after the slot. We get the lockup period from the datum and set the transaction valid interval to be valid only after the lockup period. Next, we construct the transaction to withdraw the funds from the vesting contract. const txBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); await txBuilder .spendingPlutusScriptV2() .txIn( vestingUtxo.input.txHash, vestingUtxo.input.outputIndex, vestingUtxo.output.amount, scriptAddr ) .spendingReferenceTxInInlineDatumPresent() .spendingReferenceTxInRedeemerValue("") .txInScript(scriptCbor) .txOut(walletAddress, []) .txInCollateral( collateralInput.txHash, collateralInput.outputIndex, collateralOutput.amount, collateralOutput.address ) .invalidBefore(invalidBefore) .requiredSignerHash(pubKeyHash) .changeAddress(walletAddress) .selectUtxosFrom(utxos) .complete(); const unsignedTx = txBuilder.txHex; In this example, we construct the transaction to withdraw the funds from the vesting contract. We specify the UTxO containing the funds locked in the vesting contract, the script address of the vesting contract, the wallet address to send the funds to, and the transaction valid interval. Finally, we sign and submit the transaction. Notice that since we are unlocking fund from validator, partial sign has to be specified by passing a `true` parameter into `wallet.signTx`. const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); To execute this code, update `aiken-vesting/src/withdraw-fund.ts` with the transaction hash from the deposit transaction. Ensure you have defined blockfrost key in the `.env` file. You can also define your wallet mnemonic in `aiken-vesting/src/configs.ts` file. Run the following command: npm run withdraw Example of a [successful withdraw transaction](https://preprod.cardanoscan.io/transaction/b108f91a1dcd1b4c0bc978fb7557fc23ad052f1681cca078aa2515f8ab01e05e) . [Swap\ \ Swap contract facilitates the exchange of assets between two parties](https://meshjs.dev/smart-contracts/swap) [Aiken\ \ A programming language and toolkit for developing smart contracts](https://meshjs.dev/aiken) ### On this page [Deposit Fund](https://meshjs.dev/smart-contracts/vesting#deposit-fund) [Withdraw Fund](https://meshjs.dev/smart-contracts/vesting#withdraw-fund) [Full Tutorial](https://meshjs.dev/smart-contracts/vesting#full-tutorial) Ask AI --- # Smart Contracts | Mesh SDK [Transaction Builder](https://meshjs.dev/apis/txbuilder) Smart Contracts =============== Transactions to work with smart contracts Copy MarkdownOpen In this guide, you will understand how to interact with smart contracts through `MeshTxBuilder`. In the code snippet, you will find `txBuilder`, which is an instance of `MeshTxBuilder`, with powerful low-level APIs that allow you to build transactions. Here's how to initialize **MeshTxBuilder**. const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); In Cardano, whenever you need the nodes' computing power to execute a smart contract, you need to provide collateral to prevent spamming. You will see this is everywhere when script execution is needed in examples below, and here's how you can do so: txBuilder .txInCollateral(txHash: string, txIndex: number, amount?: Asset[], address?: string) [Lock Assets](https://meshjs.dev/apis/txbuilder/smart-contracts#lock-assets) ----------------------------------------------------------------------------- Locking assets meaning sending value to a script address with datum. Same as the `Transaction` demo, we will lock selected assets from your wallet in an always-succeed smart contract. We use one API to represent sending value, another API to represent attaching datum to complete the locking assets process: // For inline datumtxBuilder .txOut(address, assets) .txOutInlineDatumValue(data) // For datum hashtxBuilder .txOut(address, assets) .txOutDatumHashValue(data) The lower level APIs support providing your datum in all Mesh `Data` (default), JSON and CBOR representations. For details and helper utilities, please check [Data section](https://meshjs.dev/apis/data) . // For inline datum provided in JSONtxBuilder .txOut(address, assets) .txOutInlineDatumValue(jsonData, "JSON") ### [Lock Assets](https://meshjs.dev/apis/txbuilder/smart-contracts#lock-assets-toc) Lock assets in a Plutus script **Asset unit** `d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e` **Datum:** `meshsecretcode` const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const script: PlutusScript = { code: demoPlutusAlwaysSucceedScript, version: "V2", }; const { address: scriptAddress } = serializePlutusScript(script); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .txOut(scriptAddress, [{ unit: "d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e", quantity: "1" }]) .txOutInlineDatumValue("meshsecretcode") .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Unlock Assets](https://meshjs.dev/apis/txbuilder/smart-contracts#unlock-assets) --------------------------------------------------------------------------------- Unlocking assets from a Plutus script, with `MeshTxBuilder`, starts with any of the following script version indicators: .spendingPlutusScriptV1() .spendingPlutusScriptV2() .spendingPlutusScriptV3() Followed by specifying the exact script input to spend with: .txIn(txHash: string, txIndex: number, amount?: Asset[], address?: string) In Cardano, if you want to unlock assets from a script address, you have to provide 3 other necessary information apart from `.txIn()` itself. They are: * Actual script * Datum of the input * Redeemer of the unlock **Actual script** The actual script can be either provided by transaction builder or referenced from an UTxO onchain. * (i) Reference script .spendingTxInReference() * (ii) Supplying script .txInScript(scriptCbor: string) **Datum of the input** Similar to script, datum can also either be provided by transaction builder or as inline datum. * (i) Referencing inline datum .txInInlineDatumPresent() * (ii) Supplying datum .txInDatumValue(datum: Data | object | string, type?: "Mesh" | "CBOR" | "JSON") **Redeemer of the unlock** Redeemer can be provided in different [data types](https://meshjs.dev/apis/data) . If your MeshTxBuilder does not include an `evaluator` instance, you can also provide your budget for the unlock with this redeemer endpoint .txInRedeemerValue(redeemer: Data | object | string, type: "Mesh" | "CBOR" | "JSON", exUnits?: Budget) An example of complete set of endpoints to unlock assets from a script address: const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .spendingPlutusScriptV2() .txIn(txHash: string, txIndex: number, amount?: Asset[], address?: string) .txInInlineDatumPresent() // or .txInDatumValue(datum: Data | string | object) .txInRedeemerValue(redeemer: Data | object | string, type?: string, exUnits?: Budget) .spendingTxInReference(txHash: string, txIndex: number, spendingScriptHash?: string) // or supplying script ### [Unlock Assets](https://meshjs.dev/apis/txbuilder/smart-contracts#unlock-assets-toc) Unlock assets in a Plutus script **Asset unit** `d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e` **Datum:** `meshsecretcode` const utxos = await wallet.getUtxos(); const collateral = await wallet.getCollateral(); const changeAddress = await wallet.getChangeAddress(); const script: PlutusScript = { code: demoPlutusAlwaysSucceedScript, version: "V2", }; const { address: scriptAddress } = serializePlutusScript(script); const assetUtxo = await fetchAssetUtxo({ address: scriptAddress, asset: userInput, datum: userInput2, }); if (assetUtxo === undefined) { throw "Asset UTXO not found"; } const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .spendingPlutusScriptV2() .txIn(assetUtxo.input.txHash, assetUtxo.input.outputIndex) .txInInlineDatumPresent() .txInRedeemerValue(mConStr0([])) .txInScript(demoPlutusAlwaysSucceedScript) .changeAddress(changeAddress) .txInCollateral( collateral[0]?.input.txHash!, collateral[0]?.input.outputIndex!, collateral[0]?.output.amount!, collateral[0]?.output.address!, ) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Minting Assets with Plutus Script](https://meshjs.dev/apis/txbuilder/smart-contracts#minting-assets-with-plutus-script) ------------------------------------------------------------------------------------------------------------------------- Minting Plutus tokens with `MeshTxBuilder` starts with any of the following script version indicators: .mintPlutusScriptV1() .mintPlutusScriptV2() .mintPlutusScriptV3() Followed by specifying the minting information: .mint(quantity: string, policy: string, name: string) Similar to unlocking assets, minting or burning Plutus tokens require providing redeemer and scripts. However, no datum information is needed in minting or burning. **Script of the token** The actual script can be either provided by transaction builder or referenced from an UTxO onchain. * (i) Reference script .mintTxInReference(txHash: string, txIndex: number) * (ii) Supplying script .mintingScript(scriptCbor: string) **Redeemer of the mint** Redeemer can be provided in different [data types](https://meshjs.dev/apis/data) . If your MeshTxBuilder does not include an `evaluator` instance, you can also provide your budget for the unlock with this redeemer endpoint .mintRedeemerValue(redeemer: Data | object | string, type: "Mesh" | "CBOR" | "JSON", exUnits?: Budget) ### [Mint Assets with Plutus Script](https://meshjs.dev/apis/txbuilder/smart-contracts#mint-assets-with-plutus-script-toc) Mint native assets with Plutus Script. For this example, the Plutus script expects a data field of 'mesh'. **Redeemer value:** `mesh` const utxos = await wallet.getUtxos(); const collateral: UTxO = (await wallet.getCollateral())[0]!; const changeAddress = await wallet.getChangeAddress(); const policyId = resolveScriptHash(demoPlutusMintingScript, "V2"); const tokenName = 'mesh'; const tokenNameHex = stringToHex(tokenName); const metadata = { [policyId]: { [tokenName]: { ...demoAssetMetadata } } }; const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mintPlutusScriptV2() .mint("1", policyId, tokenNameHex) .mintingScript(demoPlutusMintingScript) .mintRedeemerValue(mConStr0(['mesh'])) .metadataValue(721, metadata) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .txInCollateral( collateral.input.txHash, collateral.input.outputIndex, collateral.output.amount, collateral.output.address, ) .complete(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); [Send Reference Scripts Onchain](https://meshjs.dev/apis/txbuilder/smart-contracts#send-reference-scripts-onchain) ------------------------------------------------------------------------------------------------------------------- For all smart contract executions, you have option to provide script as referencing onchain. To do so, you must send the script onchain first. You can attach the script like attaching datum to a output with this: .txOutReferenceScript(scriptCbor: string, version?: LanguageVersion) ### [Send Reference Script](https://meshjs.dev/apis/txbuilder/smart-contracts#send-reference-script-toc) Provide script as referencing onchain const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .txOut("addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr", []) .txOutReferenceScript("4e4d01000033222220051200120011", "V2") .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Mint and Burn Assets\ \ Minting and burning assets with Native Script and Plutus Script](https://meshjs.dev/apis/txbuilder/minting) [Staking Transactions\ \ Transactions for delegating ADA and managing stakepools](https://meshjs.dev/apis/txbuilder/staking) ### On this page [Lock Assets](https://meshjs.dev/apis/txbuilder/smart-contracts#lock-assets) [Unlock Assets](https://meshjs.dev/apis/txbuilder/smart-contracts#unlock-assets) [Minting Assets with Plutus Script](https://meshjs.dev/apis/txbuilder/smart-contracts#minting-assets-with-plutus-script) [Send Reference Scripts Onchain](https://meshjs.dev/apis/txbuilder/smart-contracts#send-reference-scripts-onchain) Ask AI --- # Mesh Wallet | Mesh SDK [Wallets](https://meshjs.dev/apis/wallets) Mesh Wallet =========== Mesh Wallet provides a set of APIs to interact with the blockchain. This wallet is compatible with Mesh transaction builders. Copy MarkdownOpen Whether you are building a minting script, or an application that requires multi-signature, `MeshWallet` is all you need to get started. [Initialize Wallet](https://meshjs.dev/apis/wallets/meshwallet#initialize-wallet) ---------------------------------------------------------------------------------- This API enables applications to load and initialize a wallet connection. It provides access to the wallet's capabilities, such as signing transactions, submitting transactions, and querying blockchain data. The wallet connection is established securely, ensuring that sensitive operations are handled by the wallet and not exposed to the application directly. This is crucial for maintaining security and user trust. Applications can use this functionality to integrate wallet features seamlessly, enabling blockchain interactions without requiring users to manage private keys manually. You can initialize Mesh Wallet with: * Mnemonic Phrases * Private Keys * Cardano CLI Generated Keys * Address (Read Only Wallet) First, we initialize a new Provider. MaestroBlockfrostKoiosUTxORPC import { MaestroProvider } from '@meshsdk/core'; const provider = new MaestroProvider({ network: 'Preprod', apiKey: '', // Get yours by visiting https://docs.gomaestro.org/. turboSubmit: false }); import { BlockfrostProvider } from '@meshsdk/core'; const provider = new BlockfrostProvider(''); import { KoiosProvider } from '@meshsdk/core'; const provider = new KoiosProvider('', ''); import { U5CProvider } from "@meshsdk/core"; const provider = new U5CProvider({ url: "http://localhost:5005U5c", headers: { "dmtr-api-key": "", }, }); ### [Mnemonic Phrases](https://meshjs.dev/apis/wallets/meshwallet#mnemonic-phrases) We can load a wallet with mnemonic phrases, and assign our provider to the `fetcher` and `submitter`: import { MeshWallet } from '@meshsdk/core'; const wallet = new MeshWallet({ networkId: 0, // 0: testnet, 1: mainnet fetcher: provider, submitter: provider, key: { type: 'mnemonic', words: ["solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution"], }, }); With the `wallet` loaded, you can sign transactions, we will see how to do this in the next section, for now lets get the wallet's address: const address = wallet.getChangeAddress(); ### [Private Keys](https://meshjs.dev/apis/wallets/meshwallet#private-keys) We can load a wallet with private keys: import { MeshWallet } from '@meshsdk/core'; const wallet = new MeshWallet({ networkId: 0, // 0: testnet, 1: mainnet fetcher: provider, submitter: provider, key: { type: 'root', bech32: 'xprv1cqa46gk29plgkg98upclnjv5t425fcpl4rgf9mq2txdxuga7jfq5shk7np6l55nj00sl3m4syzna3uwgrwppdm0azgy9d8zahyf32s62klfyhe0ayyxkc7x92nv4s77fa0v25tufk9tnv7x6dgexe9kdz5gpeqgu', }, }); ### [Cardano CLI generated skeys](https://meshjs.dev/apis/wallets/meshwallet#cardano-cli-generated-skeys) We can load a wallet with CLI-generated keys by providing the `skey` generated by Cardano CLI. There are two files generated by Cardano CLI, by default, it is named `signing.skey` and `stake.skey`. Opening the `signing.skey` file should show: { "type": "PaymentSigningKeyShelley_ed25519", "description": "Payment Signing Key", "cborHex": "5820aaca553a7b95b38b5d9b82a5daa7a27ac8e34f3cf27152a978f4576520dd6503" } We can get the `cborHex` from the `signing.skey` file, and load wallet with Cardano CLI generated skeys. Stake key is optional, but without it, you cannot sign staking transactions. import { MeshWallet } from '@meshsdk/core'; const wallet = new MeshWallet({ networkId: 0, // 0: testnet, 1: mainnet fetcher: provider, submitter: provider, key: { type: 'cli', payment: '5820aaca553a7b95b38b5d9b82a5daa7a27ac8e34f3cf27152a978f4576520dd6503', stake: '582097c458f19a3111c3b965220b1bef7d548fd75bc140a7f0a4f080e03cce604f0e', }, }); ### [Address](https://meshjs.dev/apis/wallets/meshwallet#address) We can load a wallet with address, this is useful for read-only wallets. A read-only wallet can only query the blockchain, it cannot sign transactions. This is useful for monitoring wallets. We can load wallet with the `address` type: import { MeshWallet } from '@meshsdk/core'; const wallet = new MeshWallet({ networkId: 0, // 0: testnet, 1: mainnet fetcher: provider, key: { type: 'address', address: 'addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', }, }); ### [Initialize Wallet](https://meshjs.dev/apis/wallets/meshwallet#initialize-wallet-1) After creating the wallet, we need to initialize it. This will initialize the cryptography library. await wallet.init() With the `wallet` loaded, you can sign transactions, we will see how to do this in the [Sign Transaction](https://meshjs.dev/apis/wallets/meshwallet#sign-transaction) section, for now lets get the wallet's address: const address = wallet.getChangeAddress(); [Generate Wallet](https://meshjs.dev/apis/wallets/meshwallet#generate-wallet) ------------------------------------------------------------------------------ You can generate deterministic keys based on the `Bitcoin BIP39`. These mnemonic phrases are essential for recovering your wallet and ensuring secure access to your funds. const mnemonic = MeshWallet.brew(); Once you have your mnemonic phrase, you can use it to generate deterministic keys. These keys include a series of private and public keys, which are crucial for managing your cryptocurrencies securely. Alternatively, you can generate private keys directly by passing `true` to the `brew` function. This approach is useful for scenarios where you need immediate access to private keys without mnemonic phrases. const privatekey = MeshWallet.brew(true); [Get Balance](https://meshjs.dev/apis/wallets/meshwallet#get-balance) ---------------------------------------------------------------------- This API returns a comprehensive list of all assets in the wallet, including lovelace. Each asset is represented as an object with the following properties: * `unit`: A unique identifier for the asset, often used for display purposes. * `quantity`: The amount of the asset held in the wallet. ### [Get Balance](https://meshjs.dev/apis/wallets/meshwallet#get-balance-toc) Get all assets in the connected wallet const balance = await wallet.getBalance(); Example response: [\ {\ "unit": "lovelace",\ "quantity": "796105407"\ },\ {\ "unit": "0f5560dbc05282e05507aedb02d823d9d9f0e583cce579b81f9d1cd8",\ "quantity": "1"\ },\ {\ "unit": "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d4d657368546f6b656e",\ "quantity": "2"\ },\ ] [Get Change Address](https://meshjs.dev/apis/wallets/meshwallet#get-change-address) ------------------------------------------------------------------------------------ This API returns an address owned by the wallet which is essential during transaction creation to ensure leftover assets are securely returned to the connected wallet. The change address helps maintain the integrity of transactions by preventing asset loss and ensuring proper allocation of funds. ### [Get Change Address](https://meshjs.dev/apis/wallets/meshwallet#get-change-address-toc) Get address that should be used for transaction's change const changeAddress = await wallet.getChangeAddress(); [Get Collateral](https://meshjs.dev/apis/wallets/meshwallet#get-collateral) ---------------------------------------------------------------------------- This API retrieves a list of UTXOs (unspent transaction outputs) controlled by the wallet that are suitable for use as collateral inputs in transactions involving Plutus script inputs. Collateral UTXOs are pure ADA-only UTXOs required to meet the specified ADA value target. If the target cannot be met, an error message explaining the issue will be returned. Wallets may return UTXOs exceeding the target value but must never return UTXOs below the specified value. This API accepts the `addressType` parameter, where you can specify the type of address you want to get. The available options are: * payment (default) * enterprise ### [Get Collateral](https://meshjs.dev/apis/wallets/meshwallet#get-collateral-toc) Get list of UTXOs that used as collateral inputs for transactions with plutus script inputs const collateralUtxos = await wallet.getCollateral(); Example response: [\ {\ "input": {\ "outputIndex": 1,\ "txHash": "ff8d1e97c60989b4f...02ee937595ad741ff597af1"\ },\ "output": {\ "address": "addr_test1qzm...z0fr8c3grjmysm5e6yx",\ "amount": [ { "unit": "lovelace", "quantity": "5000000" } ]\ }\ }\ ] [Get Network ID](https://meshjs.dev/apis/wallets/meshwallet#get-network-id) ---------------------------------------------------------------------------- This API returns the network ID of the currently connected account. The network ID indicates the environment in which the wallet is operating: * `0`: Testnet * `1`: Mainnet Other network IDs may be returned by wallets, but these are not governed by CIP-30. The network ID remains consistent unless the connected account changes. ### [Get Network ID](https://meshjs.dev/apis/wallets/meshwallet#get-network-id-toc) Get currently connected network const networkId = wallet.getNetworkId(); [Get Reward Addresses](https://meshjs.dev/apis/wallets/meshwallet#get-reward-addresses) ---------------------------------------------------------------------------------------- This API retrieves a list of reward addresses owned by the wallet. Reward addresses are stake addresses used to receive rewards from staking activities. Reward addresses typically start with the `stake` prefix, making them easily identifiable. These addresses are essential for tracking staking rewards and managing staking operations. ### [Get Reward Addresses](https://meshjs.dev/apis/wallets/meshwallet#get-reward-addresses-toc) Get stake addresses const rewardAddresses = wallet.getRewardAddresses(); Example response: [\ "stake_test1uzx0ksy9f4qnj2mzfdncqyjy84sszh64w43853nug5pedjgytgke9"\ ] [Get Unused Addresses](https://meshjs.dev/apis/wallets/meshwallet#get-unused-addresses) ---------------------------------------------------------------------------------------- This API retrieves a list of unused addresses controlled by the wallet. Unused addresses are wallet-controlled addresses that have not been involved in any transactions. Unused addresses are important for maintaining privacy and security in transactions. They can be used for new transactions without revealing previous activity. ### [Get Unused Addresses](https://meshjs.dev/apis/wallets/meshwallet#get-unused-addresses-toc) Get addresses that are unused const unusedAddresses = wallet.getUnusedAddresses(); Example response: [\ "addr_test1qzk9x08mtre4jp8f7j8zu8802...r8c3grjmys7fl22c",\ "addr_test1qrmf35xyw2petfr0e0p4at0r7...8sc3grjmysm73dk8",\ "addr_test1qq6ts58hdaasd2q78fdjj0arm...i8c3grjmys85k8mf",\ ] [Get Used Addresses](https://meshjs.dev/apis/wallets/meshwallet#get-used-addresses) ------------------------------------------------------------------------------------ This API retrieves a list of used addresses controlled by the wallet. Used addresses are wallet-controlled addresses that have been involved in transactions. Tracking used addresses is essential for analyzing transaction history and managing wallet activity. These addresses provide insights into past transactions. ### [Get Used Addresses](https://meshjs.dev/apis/wallets/meshwallet#get-used-addresses-toc) Get addresses that are used const usedAddresses = wallet.getUsedAddresses(); Example response: [\ "addr_test1qzk9x08mtre4jp8f7j8zu8802...r8c3grjmys7fl88a",\ "addr_test1qrmf35xyw2petfr0e0p4at0r7...8sc3grjmysm76gt3",\ "addr_test1qq6ts58hdaasd2q78fdjj0arm...i8c3grjmys85dn39",\ ] [Get UTXOs](https://meshjs.dev/apis/wallets/meshwallet#get-utxos) ------------------------------------------------------------------ This API retrieves a list of all UTXOs (unspent transaction outputs) controlled by the wallet. UTXOs are essential for constructing transactions and managing wallet balances. Each UTXO includes details such as the transaction hash, output index, address, and amount. These details are crucial for identifying and utilizing unspent outputs. This API accepts the addressType parameter, where you can specify the type of address you want to get. The available options are: * payment (default) * enterprise ### [Get UTXOs](https://meshjs.dev/apis/wallets/meshwallet#get-utxos-toc) Get UTXOs of the connected wallet const utxos = await wallet.getUtxos(); Example response: [\ {\ "input": {\ "outputIndex": 0,\ "txHash": "16dcbb1f93b4f9d5e...9106c7b121463c210ba"\ },\ "output": {\ "address": "addr_test1qzag7whju08xwrq...z0fr8c3grjmysgaw9y8",\ "amount": [\ {\ "unit": "lovelace",\ "quantity": "1314550"\ },\ {\ "unit": "f05c91a850...3d824d657368546f6b656e3032",\ "quantity": "1"\ }\ ]\ }\ }\ ] [Sign Data](https://meshjs.dev/apis/wallets/meshwallet#sign-data) ------------------------------------------------------------------ This API allows applications to request the signing of arbitrary data using the private keys managed by the connected wallet. This is useful for verifying the authenticity of data or creating cryptographic proofs. The wallet ensures that the signing process is secure and that private keys are not exposed during the operation. The signed data can be used for various purposes, such as authentication, data integrity checks, or blockchain interactions. This functionality is essential for applications that require secure and verifiable data signing capabilities. ### [Sign Data](https://meshjs.dev/apis/wallets/meshwallet#sign-data-toc) Define a payload and sign it with wallet. `Payload: mesh` const signature = await wallet.signData('mesh'); Check out [this guide](https://meshjs.dev/guides/prove-wallet-ownership#server-verify-signature) to learn how to verify the signature. Example response: { "signature": "845846a2012...f9119a18e8977d436385cecb08", "key": "a4010103272006215...b81a7f6ed4fa29cc7b33186c" } [Sign Transaction](https://meshjs.dev/apis/wallets/meshwallet#sign-transaction) -------------------------------------------------------------------------------- This API enables applications to request the signing of a transaction using the private keys managed by the connected wallet. Signing a transaction is a critical step in ensuring its authenticity and authorization. The wallet ensures that the transaction is signed securely, preventing unauthorized access to private keys. Once signed, the transaction can be submitted to the blockchain network for processing. This functionality is vital for applications that need to interact with the blockchain securely, as it delegates sensitive operations to the wallet. ### [Sign Transaction](https://meshjs.dev/apis/wallets/meshwallet#sign-transaction-toc) Create a transaction and sign it Check out [MeshWallet](https://docs.meshjs.dev/wallets/classes/MeshWallet#signTx) documentation to learn more on how to use this API. const signedTx = await wallet.signTx(tx, partialSign?); [Submit Transaction](https://meshjs.dev/apis/wallets/meshwallet#submit-transaction) ------------------------------------------------------------------------------------ This API allows applications to request the submission of a signed transaction through the connected wallet. The wallet will attempt to send the transaction to the blockchain network. If the transaction is successfully submitted, the wallet returns the transaction ID, which can be used by the application to track its status on the blockchain. In case of an error during submission, the wallet provides error messages or failure details. This functionality is essential for applications that rely on wallet integration to handle transaction submission securely and efficiently. ### [Submit Transaction](https://meshjs.dev/apis/wallets/meshwallet#submit-transaction-toc) Submit a signed transaction with wallet Check out [MeshWallet](https://docs.meshjs.dev/wallets/classes/MeshWallet#submitTx) documentation to learn more on how to use this API. const txHash = await wallet.submitTx(signedTx); [Create Collateral UTXO](https://meshjs.dev/apis/wallets/meshwallet#create-collateral-utxo) -------------------------------------------------------------------------------------------- Collateral is a monetary guarantee provided by the user to ensure the integrity of smart contracts and compensate nodes in case phase-2 validation fails. It is specified during transaction construction by adding collateral inputs to the transaction. The total balance in the UTXOs corresponding to these inputs represents the transaction's collateral amount. If the contract executes successfully, the collateral remains safe. This mechanism ensures that contracts are carefully designed and thoroughly tested. const txhash = await wallet.createCollateral(); [Get Assets](https://meshjs.dev/apis/wallets/meshwallet#get-assets) -------------------------------------------------------------------- This API retrieves a list of assets in the wallet, excluding lovelace. Each asset is represented as an object with the following properties: * `unit`: A unique identifier for the asset. * `policyId`: The policy ID associated with the asset. * `assetName`: The name of the asset. * `fingerprint`: A unique fingerprint for the asset. * `quantity`: The amount of the asset held in the wallet. ### [Get Assets](https://meshjs.dev/apis/wallets/meshwallet#get-assets-toc) Get all assets in the connected wallet const assets = await wallet.getAssets(); Example response: [\ {\ "unit": "1207329a668cf5c42b80a220a8c85d5e82ac0b6f5ecedda4c07a8acc4d657368486f6e6f72546f6b656e2d3530343935",\ "policyId": "1207329a668cf5c42b80a220a8c85d5e82ac0b6f5ecedda4c07a8acc",\ "assetName": "Mesh Token Of Appreciation",\ "fingerprint": "asset1dw74h0w0meqg9cxkc9sezp8zqcxu8nl93fzfpz",\ "quantity": "1"\ }\ {\ "unit": "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d4d657368546f6b656e",\ "policyId": "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d",\ "assetName": "MeshToken",\ "fingerprint": "asset177e7535dclmkkph8ewt9fsghllkwmpspa3n98p",\ "quantity": "10"\ }\ ] [Get Lovelace](https://meshjs.dev/apis/wallets/meshwallet#get-lovelace) ------------------------------------------------------------------------ This API retrieves the lovelace balance in the wallet. Lovelace is the smallest unit of ADA, where 1 ADA equals 1,000,000 lovelace. Knowing the lovelace balance is essential for managing wallet funds and performing transactions. ### [Get Lovelace](https://meshjs.dev/apis/wallets/meshwallet#get-lovelace-toc) Get lovelace balance in the connected wallet const lovelace = await wallet.getLovelace(); [Get Policy IDs](https://meshjs.dev/apis/wallets/meshwallet#get-policy-ids) ---------------------------------------------------------------------------- This API retrieves a list of policy IDs from all assets in the wallet. A policy ID is a unique identifier that groups assets under a common policy. Policy IDs are useful for querying assets associated with specific policies. For example, you can use a policy ID to retrieve all assets belonging to that policy. ### [Get Policy IDs](https://meshjs.dev/apis/wallets/meshwallet#get-policy-ids-toc) Get a list of policy IDs from all assets in wallet const policyIds = await wallet.getPolicyIds(); Example response: [\ "0f5560dbc05282e05507aedb02d823d9d9f0e583cce579b81f9d1cd8",\ "5bed9e89299c69d9a54bbc82d88aa5a86698b2b7b9d0ed030fc4b0ff",\ "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d",\ ] [Get a Collection of Assets](https://meshjs.dev/apis/wallets/meshwallet#get-a-collection-of-assets) ---------------------------------------------------------------------------------------------------- This API retrieves a list of assets associated with a specific policy ID. A policy ID is a unique identifier that groups assets under a common policy. If no assets in the wallet belong to the specified policy ID, an empty list is returned. To query for available policy IDs, use `wallet.getPolicyIds()`. ### [Get a Collection of Assets](https://meshjs.dev/apis/wallets/meshwallet#get-a-collection-of-assets-toc) Get a list of assets belonging to the policy ID `Policy ID: d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527` const assets = await wallet.getPolicyIdAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527'); [Get DRep](https://meshjs.dev/apis/wallets/meshwallet#get-drep) ---------------------------------------------------------------- The DRep ID is a unique identifier for the user's wallet. It consists of three components: * `publicKey`: The public key associated with the wallet. * `publicKeyHash`: A hash of the public key for verification purposes. * `dRepIDCip105`: The bech32 encoding of the DRep ID. ### [Get DRep](https://meshjs.dev/apis/wallets/meshwallet#get-drep-toc) Get the key, hash, and bech32 address of the DRep ID await wallet.getDRep(); Example response: { "publicKey": "6984e406dd81...39e43d798fe1a89ab", "publicKeyHash": "9f7f4b78...df83bd227e943e9808450", "dRepIDCip105": "drep1vz0h7jmc...0axqgg5q4dls5u" } [Browser Wallet\ \ For connecting, querying and performing wallet functions in accordance to CIP-30.](https://meshjs.dev/apis/wallets/browserwallet) [Transaction Builder\ \ Build transactions with Cardano-CLI like APIs](https://meshjs.dev/apis/txbuilder) ### On this page [Initialize Wallet](https://meshjs.dev/apis/wallets/meshwallet#initialize-wallet) [Mnemonic Phrases](https://meshjs.dev/apis/wallets/meshwallet#mnemonic-phrases) [Private Keys](https://meshjs.dev/apis/wallets/meshwallet#private-keys) [Cardano CLI generated skeys](https://meshjs.dev/apis/wallets/meshwallet#cardano-cli-generated-skeys) [Address](https://meshjs.dev/apis/wallets/meshwallet#address) [Initialize Wallet](https://meshjs.dev/apis/wallets/meshwallet#initialize-wallet-1) [Generate Wallet](https://meshjs.dev/apis/wallets/meshwallet#generate-wallet) [Get Balance](https://meshjs.dev/apis/wallets/meshwallet#get-balance) [Get Change Address](https://meshjs.dev/apis/wallets/meshwallet#get-change-address) [Get Collateral](https://meshjs.dev/apis/wallets/meshwallet#get-collateral) [Get Network ID](https://meshjs.dev/apis/wallets/meshwallet#get-network-id) [Get Reward Addresses](https://meshjs.dev/apis/wallets/meshwallet#get-reward-addresses) [Get Unused Addresses](https://meshjs.dev/apis/wallets/meshwallet#get-unused-addresses) [Get Used Addresses](https://meshjs.dev/apis/wallets/meshwallet#get-used-addresses) [Get UTXOs](https://meshjs.dev/apis/wallets/meshwallet#get-utxos) [Sign Data](https://meshjs.dev/apis/wallets/meshwallet#sign-data) [Sign Transaction](https://meshjs.dev/apis/wallets/meshwallet#sign-transaction) [Submit Transaction](https://meshjs.dev/apis/wallets/meshwallet#submit-transaction) [Create Collateral UTXO](https://meshjs.dev/apis/wallets/meshwallet#create-collateral-utxo) [Get Assets](https://meshjs.dev/apis/wallets/meshwallet#get-assets) [Get Lovelace](https://meshjs.dev/apis/wallets/meshwallet#get-lovelace) [Get Policy IDs](https://meshjs.dev/apis/wallets/meshwallet#get-policy-ids) [Get a Collection of Assets](https://meshjs.dev/apis/wallets/meshwallet#get-a-collection-of-assets) [Get DRep](https://meshjs.dev/apis/wallets/meshwallet#get-drep) Ask AI --- # Transaction Basics | Mesh SDK [Transaction Builder](https://meshjs.dev/apis/txbuilder) Transaction Basics ================== Working with transactions and its various options Copy MarkdownOpen In the code snippet, you will find `txBuilder`, which is an instance of `MeshTxBuilder`, with powerful low-level APIs that allow you to build transactions. Here's how to initialize **MeshTxBuilder**. const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); The `MeshTxBuilder` is a powerful interface where the higher level `Transaction` class is indeed a pre-built combination of the `MeshTxBuilder` APIs. With these lower level APIs, it builds the object to be passing to the serialization libraries like `cardano-sdk` and `Whisky SDK` to construct transactions. In this page, we will cover how to initialize the `MeshTxBuilder` and the basic operations of building a transaction. [Initialize Tx Builder](https://meshjs.dev/apis/txbuilder/basics#initialize-tx-builder) ---------------------------------------------------------------------------------------- To start building a customized transaction, you need to first initialize `MeshTxBuilder`: import { BlockfrostProvider, MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true, }); The `MeshTxBuilder` instance has the following signature: { fetcher?: IFetcher; submitter?: ISubmitter; evaluator?: IEvaluator; serializer?: IMeshTxSerializer; isHydra?: boolean; params?: Partial; verbose?: boolean; } There are 6 optional fields to pass in when initializing a new instance: * `serializer`: The default serializer is `CSLSerializer`. You can pass in your own serializer instance. * `fetcher`: When you build the transaction without sufficient fields as required by the serialization library, we would index the blockchain to fill the information for you. Affected APIs are `txIn`, `txInCollateral`, `spendingTxInReference`. * `submitter`: It is used if you would like to use the `submitter` submitTx API directly from the instance. * `evaluator`: It would perform redeemer execution unit optimization, returning error message in case of invalid transaction. * `isHydra`: Use another set of default protocol parameters for building transactions. * `params`: You can pass in the protocol parameters directly. * `verbose`: Set to `true` to enable verbose logging. [Send Value](https://meshjs.dev/apis/txbuilder/basics#send-value) ------------------------------------------------------------------ Sending value with `MeshTxBuilder` is done using the `.txOut()` endpoint: .txOut(address: string, amount: Asset[]) To send value in a transaction, you must first fund it. There are 2 ways: * Specifying which input to spend .txIn(txHash: string, txIndex: number, amount?: Asset[], address?: string) * Providing an array of UTxOs, and perform auto UTxO selection: .selectUtxosFrom(extraInputs: UTxO[]) Since the input and output values might not be the same, we have to specify the address (usually the wallet's own address) to receive the change: .changeAddress(addr: string) The following shows a simple example of building a transaction to send values with UTxO selection: txBuilder .txOut(address, [{ unit: "lovelace", quantity: amount }]) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); ### [Send Value](https://meshjs.dev/apis/txbuilder/basics#send-value-toc) Send assests to a recipient **Address**: `addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr` **Amount**: `1000000` const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .txOut('addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', [{ unit: "lovelace", quantity: '1000000' }]) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Multi-signature Transaction](https://meshjs.dev/apis/txbuilder/basics#multi-signature-transaction) ---------------------------------------------------------------------------------------------------- The main idea of a multi-signature (multisig) transaction is to have multiple signatures to authorize a transaction. const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mint("1", policyId, stringToHex("MeshToken")) .mintingScript(forgingScript) .metadataValue(721, { [policyId]: { [assetName]: demoAssetMetadata } }) .changeAddress(address) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet1.signTx(unsignedTx, true); const signedTx2 = await mintingWallet.signTx(signedTx, true); const txHash = await wallet.submitTx(signedTx2); In the above code snippet, we are signing the transaction with the user wallet and then signing the transaction with the minting wallet. The `signTx` function is used to sign the transaction. The second argument is a boolean value that indicates whether the transaction is a multi-signature transaction. await wallet.signTx(unsignedTx, true); ### [Multi-signature Transaction](https://meshjs.dev/apis/txbuilder/basics#multi-signature-transaction-toc) Create a multi-signature transaction. In this demo, we will create a transaction with two signatures, where one signature is from the user's wallet and the other is from a minting wallet. const mintingWallet = new MeshWallet({ networkId: 0, fetcher: provider, submitter: provider, key: { type: "mnemonic", words: ['your','mnemonic','here'], }, }); const forgingScript = ForgeScript.withOneSignature( await mintingWallet.getChangeAddress(), ); const assetName = "MeshToken"; const policyId = resolveScriptHash(forgingScript); const usedAddress = await wallet.getUsedAddresses(); const utxos = await wallet.getUtxos(); const address = usedAddress[0]!; const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mint("1", policyId, stringToHex("MeshToken")) .mintingScript(forgingScript) .metadataValue(721, { [policyId]: { [assetName]: demoAssetMetadata } }) .changeAddress(address) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx, true); const signedTx2 = await mintingWallet.signTx(signedTx, true); const txHash = await wallet.submitTx(signedTx2); [Multi-signature Transaction with Native Script](https://meshjs.dev/apis/txbuilder/basics#multi-signature-transaction-with-native-script) ------------------------------------------------------------------------------------------------------------------------------------------ Here is an example of creating a multi-signature (multisig) transaction with a native script, where you need to spend from a script address. **Create native script** First, we need to create a native script. In this example, we will create a native script with two signatures. That means we need to get the key hashes of the two wallets. const { pubKeyHash: keyHash1 } = deserializeAddress(walletAddress1); const { pubKeyHash: keyHash2 } = deserializeAddress(walletAddress2); Next, we will create a native script object with the two key hashes. The native script object will be used to create a multi-signature transaction. const nativeScript: NativeScript = { type: "all", scripts: [\ {\ type: "sig",\ keyHash: keyHash1,\ },\ {\ type: "sig",\ keyHash: keyHash2,\ },\ ], }; The native script object is then serialized into a CBOR object and an address. const { address: scriptAddress, scriptCbor } = serializeNativeScript(nativeScript); **Create transaction** Now that we have the native script, we can create a transaction with the script. We first need to get the UTXO from the script address. // get utxo from script const utxos = await provider.fetchAddressUTxOs(scriptAddress); const utxo = utxos[0]; // create tx const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .txIn( utxo.input.txHash, utxo.input.outputIndex, utxo.output.amount, utxo.output.address, ) .txInScript(scriptCbor) .txOut( "addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr", [{ unit: "lovelace", quantity: "2000000" }], ) .changeAddress(scriptAddress) .selectUtxosFrom(utxos) .complete(); Finally, we sign the transaction with the two wallets and submit the transaction. const signedTx1 = await wallet1.signTx(unsignedTx, true); const signedTx2 = await wallet2.signTx(signedTx1, true); const txHash = await wallet.submitTx(signedTx2); [Build with Object](https://meshjs.dev/apis/txbuilder/basics#build-with-object) -------------------------------------------------------------------------------- One alternative to use the lower level APIs is to build the transaction with JSON. The following shows a simple example of building a transaction to send values to a recipient: const meshTxBody: Partial = { outputs: [\ {\ address: address,\ amount: [{ unit: "lovelace", quantity: amount }],\ },\ ], changeAddress: changeAddress, extraInputs: utxos, selectionConfig: { threshold: "5000000", strategy: "largestFirst", includeTxFees: true, }, }; const unsignedTx = await txBuilder.complete(meshTxBody); [Coin selection](https://meshjs.dev/apis/txbuilder/basics#coin-selection) -------------------------------------------------------------------------- You can select UTxOs from a list of UTxOs using the `selectUtxosFrom` method. This method allows you to specify the conditions for selecting UTxOs. The method signature is as follows: selectUtxosFrom( extraInputs: UTxO[] strategy?: UtxoSelectionStrategy threshold?: string includeTxFees?: boolean ) The second parameter of `selectUtxosFrom` is the strategy to be used for selecting UTxOs. There are 4 strategies (`UtxoSelectionStrategy`) available for selecting UTxOs: * experimental * keepRelevant * largestFirst * largestFirstMultiAsset We may introduce more strategies in the future. Check the [Mesh Docs](https://docs.meshjs.dev/) for more details. The `threshold` parameter is used to specify the minimum amount of lovelace to be selected. You may specify a larger amount too if the transactions requires it. The last parameter is `includeTxFees` which is a boolean value to include transaction fees in the selection. [Set Metadata - Transaction message](https://meshjs.dev/apis/txbuilder/basics#set-metadata---transaction-message) ------------------------------------------------------------------------------------------------------------------ Add messages / comments / memos as transaction metadata. This is useful for attaching additional information to a transaction. This is an example of setting a metadata with transaction message. txBuilder .metadataValue(label, metadata) The specification for individual strings follows the general JSON metadata design, which is currently used on the Cardano blockchain. The used metadatum label is `674`: this number was chosen because it is the T9 encoding of the string `msg`. The message content has the key `msg`: and consists of an array of individual message-strings. The number of theses message-strings must be at least one for a single message, more for multiple messages/lines. Each of theses individual message-strings array entries must be at most 64 bytes when UTF-8 encoded. ### [Transaction message](https://meshjs.dev/apis/txbuilder/basics#transaction-message-toc) Add messages/comments/memos as transaction metadata **Message (breakline for new line)** Invoice-No: 1234567890 Customer-No: 555-1234 const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const label = 674; const metadata = { msg: [\ 'Invoice-No: 1234567890',\ 'Customer-No: 555-1234',\ ], }); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .changeAddress(changeAddress) .metadataValue(label, metadata) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Set Required Signers](https://meshjs.dev/apis/txbuilder/basics#set-required-signers) -------------------------------------------------------------------------------------- Sets the required signers for the transaction. This is useful when you want to include multiple signers, such as in a multi-signature transaction or smart contracts. txBuilder .requiredSignerHash(pubKeyHash) [Set Start and Expire Time](https://meshjs.dev/apis/txbuilder/basics#set-start-and-expire-time) ------------------------------------------------------------------------------------------------ We can define the time-to-live (TTL) for the transaction. TTL is the time limit for our transaction to be included in a blockchain, if it is not in a blockchain by then the transaction will be cancelled. This time limit is defined as `slot`. In order to get the `slot` of the time you wish the transaction would expire, you can use `resolveSlotNo`. For example, if you would like the transaction to expire in 5 minutes, you can get the `slot` in the following way: import { resolveSlotNo } from '@meshsdk/core'; let minutes = 5; // add 5 minutes let nowDateTime = new Date(); let dateTimeAdd5Min = new Date(nowDateTime.getTime() + minutes*60000); const slot = resolveSlotNo('mainnet', dateTimeAdd5Min.getTime()); Next, we set the TTL by calling `invalidHereafter(slot)`. A transaction submitted after this value is invalid: txBuilder .invalidHereafter(Number(slot)); Likewise, we can call `invalidBefore(slot)` to specify the validity start interval. A transaction submitted before this value is invalid: txBuilder .invalidBefore(Number(slot)); [Set Network](https://meshjs.dev/apis/txbuilder/basics#set-network) -------------------------------------------------------------------- Sets the network to use, this is mainly to know the cost models to be used to calculate script integrity hash. You can set the network for the transaction with `setNetwork`. txBuilder.setNetwork(network: Network) The network parameter is a string that can be one of the following: "testnet" | "preview" | "preprod" | "mainnet" [Set Fee](https://meshjs.dev/apis/txbuilder/basics#set-fee) ------------------------------------------------------------ Set the fee for the transaction in lovelace. .setFee(fee: string) The following shows a simple example of building a transaction to send values with UTxO selection: const unsignedTx = await txBuilder .txOut(...) .changeAddress(...) .setFee("0") .complete(); [Custom Protocol Parameter](https://meshjs.dev/apis/txbuilder/basics#custom-protocol-parameter) ------------------------------------------------------------------------------------------------ Custom protocol parameters can be fetched from the provider and passed to the transaction builder. This is useful when the provider does not provide the protocol parameters, or when the user wants to use a custom set of parameters. const pp = await provider.fetchProtocolParameters(); const txBuilder = new MeshTxBuilder({ fetcher: provider, params: pp, }); [Transaction Builder\ \ Build transactions with Cardano-CLI like APIs](https://meshjs.dev/apis/txbuilder) [Mint and Burn Assets\ \ Minting and burning assets with Native Script and Plutus Script](https://meshjs.dev/apis/txbuilder/minting) ### On this page [Initialize Tx Builder](https://meshjs.dev/apis/txbuilder/basics#initialize-tx-builder) [Send Value](https://meshjs.dev/apis/txbuilder/basics#send-value) [Multi-signature Transaction](https://meshjs.dev/apis/txbuilder/basics#multi-signature-transaction) [Multi-signature Transaction with Native Script](https://meshjs.dev/apis/txbuilder/basics#multi-signature-transaction-with-native-script) [Build with Object](https://meshjs.dev/apis/txbuilder/basics#build-with-object) [Coin selection](https://meshjs.dev/apis/txbuilder/basics#coin-selection) [Set Metadata - Transaction message](https://meshjs.dev/apis/txbuilder/basics#set-metadata---transaction-message) [Set Required Signers](https://meshjs.dev/apis/txbuilder/basics#set-required-signers) [Set Start and Expire Time](https://meshjs.dev/apis/txbuilder/basics#set-start-and-expire-time) [Set Network](https://meshjs.dev/apis/txbuilder/basics#set-network) [Set Fee](https://meshjs.dev/apis/txbuilder/basics#set-fee) [Custom Protocol Parameter](https://meshjs.dev/apis/txbuilder/basics#custom-protocol-parameter) Ask AI --- # Governance Transactions | Mesh SDK [Transaction Builder](https://meshjs.dev/apis/txbuilder) Governance Transactions ======================= Transactions for participating in Cardano's on-chain governance Copy MarkdownOpen In **CIP-1694**, Cardano's on-chain governance system was proposed to allow the community to vote on proposals and protocol updates. This system is designed to be decentralized and transparent, allowing the community to have a say in the future of the network. In the code snippet, you will find `txBuilder`, which is an instance of `MeshTxBuilder`, a powerful low-level APIs that allows you to build transactions. Learn how to initialize [MeshTxBuilder](https://meshjs.dev/apis/txbuilder/basics#initialize-tx-builder) const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); This page list the governance transactions that can be created using the Mesh SDK. [Vote Delegation](https://meshjs.dev/apis/txbuilder/governance#vote-delegation) -------------------------------------------------------------------------------- Any wallet can delegate its voting power to another DRep. This is done by creating a vote delegation certificate and submitting it to the blockchain. First we need to get the wallet information. This includes the UTXOs, the reward address, and the change address. const utxos = await wallet.getUtxos(); const rewardAddresses = await wallet.getRewardAddresses(); const rewardAddress = rewardAddresses[0]; const changeAddress = await wallet.getChangeAddress(); Next we need to select the UTXOs to use to pay for the transaction. We will select the UTXOs that have at least 5 ADA. Though the fee is less than 1 ADA. We can now start building the transaction. We will add the selected UTXOs as inputs to the transaction. We will also add the vote delegation certificate to the transaction. The vote delegation certificate requires the DRep ID of the DRep to delegate to and the reward address of the delegator. Note that we would need to have at least 5 ADA for the certificate delegation, in the `selectUtxosFrom` we will configure 10 ADA as threshold buffer. txBuilder .voteDelegationCertificate( { dRepId: dRepId, }, rewardAddress, ) .changeAddress(changeAddress) .selectUtxosFrom(utxos) Finally we can build, sign the transaction and submit it to the blockchain. const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); The transaction will be submitted to the blockchain and the DRep will be registered. The deposit will be taken from the DRep owner and the DRep will be added to the list of registered DReps. [DRep Vote Delegation](https://meshjs.dev/apis/txbuilder/governance#drep-vote-delegation-toc) ---------------------------------------------------------------------------------------------- Delegate your voting power to another DRep **DRep ID** `drep1yv4uesaj92wk8ljlsh4p7jzndnzrflchaz5fzug3zxg4naqkpeas3` const utxos = await wallet.getUtxos(); const rewardAddresses = await wallet.getRewardAddresses(); const rewardAddress = rewardAddresses[0]; const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .voteDelegationCertificate( { dRepId: 'drep1yv4uesaj92wk8ljlsh4p7jzndnzrflchaz5fzug3zxg4naqkpeas3', }, rewardAddress, ) .changeAddress(changeAddress) .selectUtxosFrom(utxos) const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [DRep Registration](https://meshjs.dev/apis/txbuilder/governance#drep-registration) ------------------------------------------------------------------------------------ In Voltaire, stake credentials can delegate their stake to Decentralized Representatives (DReps) for voting, in addition to the current delegation to stake pools for block production. This DRep delegation will work similarly to the current stake delegation process, using on-chain certificates. Registering as a DRep will also follow the same process as stake registration. However, registered DReps need to vote regularly to remain active. If a DRep does not vote for a set number of epochs (defined by the new protocol parameter, drepActivity), they are considered inactive and will not count towards the active voting stake. To become active again, DReps need to vote on governance actions or submit a DRep update certificate within the drepActivity period. A DRep registration certificates include: * a DRep ID * a deposit * an optional anchor An anchor is a pair of: * a URL to a JSON payload of metadata * a hash of the contents of the metadata URL First we need to get the DRep ID of the DRep we want to register. We can do this by calling `getDRep` method on the wallet. This will return the DRep object which contains the DRep ID. const dRep = await wallet.getDRep(); const dRepId = dRep.dRepIDCip105; Next we need to get the hash of the anchor. We can do this by calling the `getMeshJsonHash` function. This function fetches the anchor from the given URL and returns the hash of the anchor. async function getMeshJsonHash(url: string) { var drepAnchor = getFile(url); const anchorObj = JSON.parse(drepAnchor); return hashDrepAnchor(anchorObj); } const anchorUrl = "https://meshjs.dev/governance/meshjs.jsonld"; const anchorHash = await getMeshJsonHash(anchorUrl); We can now build the transaction by adding the DRep registration certificate to the transaction. We also need to add the change address and the selected UTxOs to the transaction. Note that the deposit for registering a DRep is 500 ADA, we would set 505 ADA as UTxO selection threshold. const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .drepRegistrationCertificate(dRepId, { anchorUrl: anchorUrl, anchorDataHash: anchorHash, }) .changeAddress(changeAddress) .selectUtxosFrom(selectedUtxos); Finally we can sign the transaction and submit it to the blockchain. const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); The transaction will be submitted to the blockchain and the DRep will be registered. The deposit will be taken from the DRep owner and the DRep will be added to the list of registered DReps. ### [DRep Registration](https://meshjs.dev/apis/txbuilder/governance#drep-registration-toc) Register a DRep certificate and pay the deposit **Anchor Url:** `eg: https://path.to/file-name.jsonld` const dRep = await wallet.getDRep(); const dRepId = dRep.dRepIDCip105; const anchorUrl = ''; const anchorHash = await getMeshJsonHash(anchorUrl); // get utxo to pay for the registration const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .drepRegistrationCertificate(dRepId, { anchorUrl: anchorUrl, anchorDataHash: anchorHash, }) .changeAddress(changeAddress) .selectUtxosFrom(utxos); const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [DRep Update](https://meshjs.dev/apis/txbuilder/governance#drep-update) ------------------------------------------------------------------------ Updating a DRep is similar to registering. We build the transaction by adding the DRep update certificate to the transaction, providing the change address and the UTxOs needed for the transaction's fees. const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .drepUpdateCertificate(dRepId, { anchorUrl: anchorUrl, anchorDataHash: anchorHash, }) .changeAddress(utxos) .selectUtxosFrom(selectedUtxos); This [transaction](https://preprod.cardanoscan.io/transaction/4527e43097fb6135cf820a90f7cd30dba0b6463078ba9fa61305cbd7d1fa4e2f) is an example of a successful DRep update for [DRep ID](https://preprod.cardanoscan.io/drep/drep1ytk3r5ddfk2cq66ygdtkwf9yck6hhy7uzhk2tgl5d53448skyutw7?tab=dRepUpdates) . ### [DRep Update](https://meshjs.dev/apis/txbuilder/governance#drep-update-toc) Update DRep metadata **Anchor Url:** `eg: https://path.to/file-name.jsonld` const dRep = await wallet.getDRep(); const dRepId = dRep.dRepIDCip105; const anchorUrl = ''; const anchorHash = await getMeshJsonHash(anchorUrl); const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .drepUpdateCertificate(dRepId, { anchorUrl: anchorUrl, anchorDataHash: anchorHash, }) .changeAddress(changeAddress) .selectUtxosFrom(utxos); const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [DRep Retirement](https://meshjs.dev/apis/txbuilder/governance#drep-retirement) -------------------------------------------------------------------------------- A DRep is retired right away when the blockchain accepts a retirement certificate. The deposit is refunded immediately as part of the transaction that submits the retirement certificate, just like how deposits are returned when a stake credential is unregistered. First we need to get the DRep ID of the DRep we want to retire. We can do this by calling `getDRep` method on the wallet. This will return the DRep object which contains the DRep ID. const dRep = await wallet.getDRep(); const dRepId = dRep.dRepIDCip105; We then need to initialize the transaction builder by creating a new instance of `MeshTxBuilder`. We need to pass the [blockchain provider](https://meshjs.dev/providers) to the constructor. const changeAddress = await wallet.getChangeAddress(); const utxos = await wallet.getUtxos(); const provider = new BlockfrostProvider(''); We can now build the transaction by adding the UTxOs as inputs to the transaction and adding the DRep deregistration certificate to the transaction. const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .drepDeregistrationCertificate(dRepId) .selectUtxosFrom(selectedUtxos) .changeAddress(changeAddress); const unsignedTx = await txBuilder.complete(); Finally we can sign the transaction and submit it to the blockchain. const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); The transaction will be submitted to the blockchain and the DRep will be retired. The deposit will be refunded to the DRep owner. ### [DRep Retirement](https://meshjs.dev/apis/txbuilder/governance#drep-retirement-toc) Retire a DRep certificate and return the deposit const dRep = await wallet.getDRep(); const dRepId = dRep.dRepIDCip105; const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .drepDeregistrationCertificate(dRepId) .selectUtxosFrom(utxos) .changeAddress(changeAddress); const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Vote](https://meshjs.dev/apis/txbuilder/governance#vote) ---------------------------------------------------------- Each vote transaction consists of the following: * a governance action ID * a role - constitutional committee member, DRep, or SPO * a governance credential witness for the role * an optional anchor (as defined above) for information that is relevant to the vote * a 'Yes'/'No'/'Abstain' vote First, we get the DRep ID from the wallet, the DRep ID voting for this governance action. const dRep = await wallet.getDRep(); const dRepId = dRep.dRepIDCip105; Then we get the utxos and the change address from the wallet. const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); We then create the vote transaction using the `vote()` function. txBuilder .vote( { type: "DRep", drepId: dRepId, }, { txHash: 'aff2909f8175ee02a8c1bf96ff516685d25bf0c6b95aac91f4dfd53a5c0867cc', txIndex: 0, }, { voteKind: "Yes", }, ) .selectUtxosFrom(utxos) .changeAddress(changeAddress); The `vote()` takes 3 parameters: * `voter` - The voter, can be a Constitutional Commitee, a DRep or a StakePool * `govActionId` - The transaction hash and transaction id of the governance action * `votingProcedure` - The voting kind (Yes, No, Abstain) with an optional anchor Check the [full documentation](https://docs.meshjs.dev/transactions/classes/MeshTxBuilder) or the source code for more details. Finally, we sign the transaction and submit it to the blockchain. const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); You can check [here](https://preprod.cardanoscan.io/transaction/278d887adc913416e6851106e7ce6e89f29aa7531b93d11e1986550e7a128a2f?tab=votes) a successful vote transaction for this [governance action](https://preprod.cardanoscan.io/govAction/gov_action14lefp8upwhhq92xph7t075txshf9huxxh9d2ey05ml2n5hqgvlxqqp92kfl?tab=votes) . Here is another example of a vote transaction: txBuilder .changeAddress( "addr_test1qpsmz8q2xj43wg597pnpp0ffnlvr8fpfydff0wcsyzqyrxguk5v6wzdvfjyy8q5ysrh8wdxg9h0u4ncse4cxhd7qhqjqk8pse6", ) .txIn( "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85", 3, [\ {\ unit: "lovelace",\ quantity: "9891607895",\ },\ ], "addr_test1vru4e2un2tq50q4rv6qzk7t8w34gjdtw3y2uzuqxzj0ldrqqactxh", ) .vote( { type: "DRep", drepId: "drep1j6257gz2swty9ut46lspyvujkt02pd82am2zq97p7p9pv2euzs7", }, { txHash: "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85", txIndex: 3, }, { voteKind: "Yes", anchor: { anchorUrl: "https://path-to.jsonld", anchorDataHash: "2aef51273a566e529a2d5958d981d7f0b3c7224fc2853b6c4922e019657b5060", }, }, ) And another example of a vote transaction with a Plutus script and a redeemer: txBuilder .changeAddress( "addr_test1qpsmz8q2xj43wg597pnpp0ffnlvr8fpfydff0wcsyzqyrxguk5v6wzdvfjyy8q5ysrh8wdxg9h0u4ncse4cxhd7qhqjqk8pse6", ) .txIn( "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85", 3, [\ {\ unit: "lovelace",\ quantity: "9891607895",\ },\ ], "addr_test1vru4e2un2tq50q4rv6qzk7t8w34gjdtw3y2uzuqxzj0ldrqqactxh", ) .txInCollateral( "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85", 3, [\ {\ unit: "lovelace",\ quantity: "9891607895",\ },\ ], "addr_test1vru4e2un2tq50q4rv6qzk7t8w34gjdtw3y2uzuqxzj0ldrqqactxh", ) .votePlutusScriptV3() .vote( { type: "DRep", drepId: resolveScriptHashDRepId( resolveScriptHash( applyCborEncoding( "5834010100323232322533300232323232324a260106012004600e002600e004600a00260066ea8004526136565734aae795d0aba201", ), "V3", ), ), }, { txHash: "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85", txIndex: 3, }, { voteKind: "Yes", anchor: { anchorUrl: "https://path-to.jsonld", anchorDataHash: "2aef51273a566e529a2d5958d981d7f0b3c7224fc2853b6c4922e019657b5060", }, }, ) .voteScript( applyCborEncoding( "5834010100323232322533300232323232324a260106012004600e002600e004600a00260066ea8004526136565734aae795d0aba201", ), ) .voteRedeemerValue("") ### [Vote](https://meshjs.dev/apis/txbuilder/governance#vote-toc) Vote on a governance action const dRep = await wallet.getDRep(); const dRepId = dRep.dRepIDCip105; const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .vote( { type: "DRep", drepId: dRepId, }, { txHash: 'aff2909f8175ee02a8c1bf96ff516685d25bf0c6b95aac91f4dfd53a5c0867cc', txIndex: 0, }, { voteKind: "Yes", }, ) .selectUtxosFrom(utxos) .changeAddress(changeAddress); const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Staking Transactions\ \ Transactions for delegating ADA and managing stakepools](https://meshjs.dev/apis/txbuilder/staking) [Transaction Parser\ \ Parse transactions for testing and rebuilding](https://meshjs.dev/apis/txparser) ### On this page [Vote Delegation](https://meshjs.dev/apis/txbuilder/governance#vote-delegation) [DRep Registration](https://meshjs.dev/apis/txbuilder/governance#drep-registration) [DRep Update](https://meshjs.dev/apis/txbuilder/governance#drep-update) [DRep Retirement](https://meshjs.dev/apis/txbuilder/governance#drep-retirement) [Vote](https://meshjs.dev/apis/txbuilder/governance#vote) Ask AI --- # Lace Wallet Integration | Mesh SDK [Midnight](https://meshjs.dev/midnight) Midnight Setup Lace Wallet Integration ======================= Complete Lace Beta Wallet integration for Midnight Network dApps Copy MarkdownOpen This project includes a complete Lace Beta Wallet integration for Midnight Network, enabling seamless wallet connectivity and transaction management. [Wallet Features](https://meshjs.dev/midnight/midnight-setup/wallet#wallet-features) ------------------------------------------------------------------------------------- | Feature | Description | Implementation | | --- | --- | --- | | Connect Wallet | Connect to Lace Beta Wallet | `wallet.enable()` | | Disconnect Wallet | Disconnect from wallet | `wallet.disconnect()` | | Get Wallet State | Retrieve wallet address and keys | `wallet.state()` | | Deploy Contract | Deploy contracts through wallet | `wallet.submitTransaction()` | | Join Contract | Join existing contracts | `wallet.balanceAndProveTransaction()` | | Balance Transactions | Balance and prove transactions | Wallet API integration | [Wallet Provider Setup](https://meshjs.dev/midnight/midnight-setup/wallet#wallet-provider-setup) ------------------------------------------------------------------------------------------------- ### [Basic Connection](https://meshjs.dev/midnight/midnight-setup/wallet#basic-connection) Connect to Lace Wallet and get wallet state: // Check if Lace wallet is available const wallet = window.midnight?.mnLace; if (!wallet) { throw new Error('Please install Lace Beta Wallet for Midnight Network'); } // Enable wallet and get state const walletAPI = await wallet.enable(); const walletState = await walletAPI.state(); const uris = await wallet.serviceUriConfig(); ### [When to Use Each Method](https://meshjs.dev/midnight/midnight-setup/wallet#when-to-use-each-method) * **`wallet.enable()`** - Use when you need to connect to the wallet for the first time * **`wallet.state()`** - Use to get current wallet information (address, keys, etc.) * **`wallet.serviceUriConfig()`** - Use to get network service URLs (indexer, prover, etc.) * **`wallet.disconnect()`** - Use when user wants to disconnect from the wallet [React Wallet Hook](https://meshjs.dev/midnight/midnight-setup/wallet#react-wallet-hook) ----------------------------------------------------------------------------------------- ### [Hook Implementation](https://meshjs.dev/midnight/midnight-setup/wallet#hook-implementation) Complete implementation of the `useMidnightWallet` hook: import { useState, useCallback } from 'react'; export const useMidnightWallet = () => { const [walletState, setWalletState] = useState(null); const [isConnected, setIsConnected] = useState(false); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const connectWallet = useCallback(async () => { setIsLoading(true); setError(null); try { const wallet = window.midnight?.mnLace; if (!wallet) { throw new Error('Please install Lace Beta Wallet for Midnight Network'); } const walletAPI = await wallet.enable(); const state = await walletAPI.state(); const uris = await wallet.serviceUriConfig(); setWalletState({ state, uris, walletAPI }); setIsConnected(true); } catch (err) { setError(err.message); throw err; } finally { setIsLoading(false); } }, []); const disconnectWallet = useCallback(async () => { try { const wallet = window.midnight?.mnLace; if (wallet) { await wallet.disconnect(); setWalletState(null); setIsConnected(false); setError(null); } } catch (err) { setError(err.message); } }, []); return { connectWallet, disconnectWallet, walletState, isConnected, isLoading, error }; }; ### [Using the Hook](https://meshjs.dev/midnight/midnight-setup/wallet#using-the-hook) import { useMidnightWallet } from './hooks/useMidnightWallet'; function App() { const { connectWallet, disconnectWallet, walletState, isConnected, isLoading, error } = useMidnightWallet(); return (
{error &&
Error: {error}
} {isConnected ? (

Connected: {walletState?.state?.address}

) : ( )}
); } [Provider Setup](https://meshjs.dev/midnight/midnight-setup/wallet#provider-setup) ----------------------------------------------------------------------------------- ### [Complete Provider Configuration](https://meshjs.dev/midnight/midnight-setup/wallet#complete-provider-configuration) Set up all necessary providers for Midnight Network integration: import { FetchZkConfigProvider } from "@midnight-ntwrk/midnight-js-fetch-zk-config-provider"; import { httpClientProofProvider } from "@midnight-ntwrk/midnight-js-http-client-proof-provider"; import { indexerPublicDataProvider } from "@midnight-ntwrk/midnight-js-indexer-public-data-provider"; import { levelPrivateStateProvider } from "@midnight-ntwrk/midnight-js-level-private-state-provider"; import type { MidnightSetupContractProviders } from "@meshsdk/midnight-setup"; export async function setupProviders(): Promise { const wallet = window.midnight?.mnLace; if (!wallet) { throw new Error("Please install Lace Beta Wallet for Midnight Network"); } const walletAPI = await wallet.enable(); const walletState = await walletAPI.state(); const uris = await wallet.serviceUriConfig(); return { privateStateProvider: levelPrivateStateProvider({ privateStateStoreName: "my-dapp-state", }), zkConfigProvider: new FetchZkConfigProvider( window.location.origin, fetch.bind(window), ), proofProvider: httpClientProofProvider(uris.proverServerUri), publicDataProvider: indexerPublicDataProvider( uris.indexerUri, uris.indexerWsUri, ), walletProvider: { coinPublicKey: walletState.coinPublicKey, encryptionPublicKey: walletState.encryptionPublicKey, balanceTx: (tx, newCoins) => { return walletAPI.balanceAndProveTransaction(tx, newCoins); }, }, midnightProvider: { submitTx: (tx) => { return walletAPI.submitTransaction(tx); }, }, }; } ### [Provider Explanation](https://meshjs.dev/midnight/midnight-setup/wallet#provider-explanation) * **`privateStateProvider`** - Manages private state storage * **`zkConfigProvider`** - Handles zero-knowledge proof configuration * **`proofProvider`** - Manages proof generation and verification * **`publicDataProvider`** - Fetches public blockchain data from indexer * **`walletProvider`** - Integrates with Lace wallet for transactions * **`midnightProvider`** - Handles transaction submission to Midnight Network [Basic Usage Example](https://meshjs.dev/midnight/midnight-setup/wallet#basic-usage-example) --------------------------------------------------------------------------------------------- ### [Complete Workflow](https://meshjs.dev/midnight/midnight-setup/wallet#complete-workflow) Here's a complete example showing the full workflow from wallet connection to contract interaction: import { useMidnightWallet } from './hooks/useMidnightWallet'; import { setupProviders } from './lib/providers'; import { MidnightSetupAPI } from '@meshsdk/midnight-setup'; function CompleteExample() { const { connectWallet, disconnectWallet, walletState, isConnected, isLoading, error } = useMidnightWallet(); const [contractApi, setContractApi] = useState(null); const [contractState, setContractState] = useState(null); // Step 1: Connect wallet const handleConnectWallet = async () => { try { await connectWallet(); console.log('✅ Wallet connected successfully'); } catch (error) { console.error('❌ Wallet connection failed:', error.message); } }; // Step 2: Setup providers and deploy contract const handleDeployContract = async () => { if (!isConnected) { alert('Please connect wallet first'); return; } try { console.log('🔄 Setting up providers...'); const providers = await setupProviders(); console.log('🔄 Deploying contract...'); const contractInstance = new MyContract({}); const api = await MidnightSetupAPI.deployContract(providers, contractInstance); setContractApi(api); console.log('✅ Contract deployed at:', api.deployedContractAddress); } catch (error) { console.error('❌ Contract deployment failed:', error.message); } }; // Step 3: Get contract state const handleGetContractState = async () => { if (!contractApi) { alert('Please deploy or join a contract first'); return; } try { console.log('🔄 Getting contract state...'); const state = await contractApi.getContractState(); setContractState(state); console.log('✅ Contract state:', state); } catch (error) { console.error('❌ Failed to get contract state:', error.message); } }; // Step 4: Join existing contract const handleJoinContract = async (contractAddress) => { if (!isConnected) { alert('Please connect wallet first'); return; } try { console.log('🔄 Setting up providers...'); const providers = await setupProviders(); console.log('🔄 Joining contract...'); const contractInstance = new MyContract({}); const api = await MidnightSetupAPI.joinContract(providers, contractInstance, contractAddress); setContractApi(api); console.log('✅ Joined contract:', contractAddress); } catch (error) { console.error('❌ Failed to join contract:', error.message); } }; return (

Complete Midnight Network Example

{error && (
Error: {error}
)}

Step 1: Connect Wallet

{!isConnected ? ( ) : (

✅ Wallet connected: {walletState?.state?.address}

)}

Step 2: Deploy Contract

Step 3: Join Contract

Step 4: Get Contract State

{contractState && (

Contract State:

{JSON.stringify(contractState, null, 2)}
)}
); } export default CompleteExample; ### [Step-by-Step Breakdown](https://meshjs.dev/midnight/midnight-setup/wallet#step-by-step-breakdown) 1. **Connect Wallet** - Use `useMidnightWallet` hook to connect to Lace Beta Wallet 2. **Setup Providers** - Call `setupProviders()` to configure all necessary providers 3. **Deploy Contract** - Use `MidnightSetupAPI.deployContract()` to deploy a new contract 4. **Join Contract** - Use `MidnightSetupAPI.joinContract()` to connect to existing contract 5. **Get State** - Use `api.getContractState()` to retrieve contract information 6. **Handle Errors** - Implement proper error handling throughout the workflow [Error Handling](https://meshjs.dev/midnight/midnight-setup/wallet#error-handling) ----------------------------------------------------------------------------------- ### [Common Wallet Errors](https://meshjs.dev/midnight/midnight-setup/wallet#common-wallet-errors) const handleWalletError = (error) => { switch (error.message) { case 'Please install Lace Beta Wallet for Midnight Network': return 'Please install Lace Beta Wallet'; case 'User rejected': return 'Transaction was rejected by user'; case 'Insufficient funds': return 'Insufficient funds for transaction'; case 'Wallet is disconnected': return 'Wallet is disconnected. Please reconnect.'; default: return 'An unexpected error occurred'; } }; ### [Error Handling in Components](https://meshjs.dev/midnight/midnight-setup/wallet#error-handling-in-components) const handleConnect = async () => { try { await connectWallet(); console.log('Wallet connected successfully'); } catch (error) { const errorMessage = handleWalletError(error); console.error('Connection failed:', errorMessage); // Show error to user } }; [Core API Methods\ \ Complete reference for MidnightSetupAPI methods and provider setup](https://meshjs.dev/midnight/midnight-setup/api) [Integration Examples\ \ The fastest way to build on Midnight Network with pre-built smart contracts, complete API, and ready-to-use code snippets](https://meshjs.dev/midnight/midnight-setup/examples) ### On this page [Wallet Features](https://meshjs.dev/midnight/midnight-setup/wallet#wallet-features) [Wallet Provider Setup](https://meshjs.dev/midnight/midnight-setup/wallet#wallet-provider-setup) [Basic Connection](https://meshjs.dev/midnight/midnight-setup/wallet#basic-connection) [When to Use Each Method](https://meshjs.dev/midnight/midnight-setup/wallet#when-to-use-each-method) [React Wallet Hook](https://meshjs.dev/midnight/midnight-setup/wallet#react-wallet-hook) [Hook Implementation](https://meshjs.dev/midnight/midnight-setup/wallet#hook-implementation) [Using the Hook](https://meshjs.dev/midnight/midnight-setup/wallet#using-the-hook) [Provider Setup](https://meshjs.dev/midnight/midnight-setup/wallet#provider-setup) [Complete Provider Configuration](https://meshjs.dev/midnight/midnight-setup/wallet#complete-provider-configuration) [Provider Explanation](https://meshjs.dev/midnight/midnight-setup/wallet#provider-explanation) [Basic Usage Example](https://meshjs.dev/midnight/midnight-setup/wallet#basic-usage-example) [Complete Workflow](https://meshjs.dev/midnight/midnight-setup/wallet#complete-workflow) [Step-by-Step Breakdown](https://meshjs.dev/midnight/midnight-setup/wallet#step-by-step-breakdown) [Error Handling](https://meshjs.dev/midnight/midnight-setup/wallet#error-handling) [Common Wallet Errors](https://meshjs.dev/midnight/midnight-setup/wallet#common-wallet-errors) [Error Handling in Components](https://meshjs.dev/midnight/midnight-setup/wallet#error-handling-in-components) Ask AI --- # Smart Contract Transactions | Mesh SDK [Learn](https://meshjs.dev/resources) [Guides](https://meshjs.dev/guides) Smart Contract Transactions =========================== Copy MarkdownOpen Build a marketplace where users list assets for sale and purchase listed assets. Sellers can update or cancel listings. [Initialize the Plutus script](https://meshjs.dev/guides/smart-contract-transactions#initialize-the-plutus-script) ------------------------------------------------------------------------------------------------------------------- Initialize the Plutus script. The compiled Plutus smart contract script CBOR is: const scriptCbor = '59079559079201000033232323232323232323232323232332232323232323232222232325335333006300800530070043333573466e1cd55cea80124000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4060064d5d0a80619a80c00c9aba1500b33501801a35742a014666aa038eb9406cd5d0a804999aa80e3ae501b35742a01066a0300466ae85401cccd54070091d69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b9d69aba15002302f357426ae8940088c98c80c8cd5ce01981901809aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a8173ad35742a004605e6ae84d5d1280111931901919ab9c033032030135573ca00226ea8004d5d09aba2500223263202e33573805e05c05826aae7940044dd50009aba1500533501875c6ae854010ccd540700808004d5d0a801999aa80e3ae200135742a00460446ae84d5d1280111931901519ab9c02b02a028135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00460246ae84d5d1280111931900e19ab9c01d01c01a101b13263201b3357389201035054350001b135573ca00226ea80054049404448c88c008dd6000990009aa80a911999aab9f0012500a233500930043574200460066ae880080548c8c8cccd5cd19b8735573aa004900011991091980080180118061aba150023005357426ae8940088c98c8054cd5ce00b00a80989aab9e5001137540024646464646666ae68cdc39aab9d5004480008cccc888848cccc00401401000c008c8c8c8cccd5cd19b8735573aa0049000119910919800801801180a9aba1500233500f014357426ae8940088c98c8068cd5ce00d80d00c09aab9e5001137540026ae854010ccd54021d728039aba150033232323333573466e1d4005200423212223002004357426aae79400c8cccd5cd19b875002480088c84888c004010dd71aba135573ca00846666ae68cdc3a801a400042444006464c6403866ae700740700680640604d55cea80089baa00135742a00466a016eb8d5d09aba2500223263201633573802e02c02826ae8940044d5d1280089aab9e500113754002266aa002eb9d6889119118011bab00132001355012223233335573e0044a010466a00e66442466002006004600c6aae754008c014d55cf280118021aba200301313574200222440042442446600200800624464646666ae68cdc3a800a40004642446004006600a6ae84d55cf280191999ab9a3370ea0049001109100091931900899ab9c01201100f00e135573aa00226ea80048c8c8cccd5cd19b875001480188c848888c010014c01cd5d09aab9e500323333573466e1d400920042321222230020053009357426aae7940108cccd5cd19b875003480088c848888c004014c01cd5d09aab9e500523333573466e1d40112000232122223003005375c6ae84d55cf280311931900899ab9c01201100f00e00d00c135573aa00226ea80048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931900699ab9c00e00d00b135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98c802ccd5ce00600580489baa001232323232323333573466e1d4005200c21222222200323333573466e1d4009200a21222222200423333573466e1d400d2008233221222222233001009008375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c4664424444444660040120106eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc8848888888cc018024020c030d5d0a8049bae357426ae8940248cccd5cd19b875006480088c848888888c01c020c034d5d09aab9e500b23333573466e1d401d2000232122222223005008300e357426aae7940308c98c8050cd5ce00a80a00900880800780700680609aab9d5004135573ca00626aae7940084d55cf280089baa0012323232323333573466e1d400520022333222122333001005004003375a6ae854010dd69aba15003375a6ae84d5d1280191999ab9a3370ea0049000119091180100198041aba135573ca00c464c6401a66ae7003803402c0284d55cea80189aba25001135573ca00226ea80048c8c8cccd5cd19b875001480088c8488c00400cdd71aba135573ca00646666ae68cdc3a8012400046424460040066eb8d5d09aab9e500423263200a33573801601401000e26aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6401666ae7003002c02402001c4d55cea80089baa0012323333573466e1d40052002212200223333573466e1d40092000212200123263200733573801000e00a00826aae74dd5000891999ab9a3370e6aae74dd5000a40004008464c6400866ae700140100092612001490103505431001123230010012233003300200200122212200201'; Initialize the Plutus script: const script: PlutusScript = { code: scriptCbor, version: 'V2', }; Resolve the Plutus script address using `resolvePlutusScriptAddress`. Input the `PlutusScript` and `network` (0 for testnet): const scriptAddress = resolvePlutusScriptAddress(script, 0); [Listing Asset for Sale](https://meshjs.dev/guides/smart-contract-transactions#listing-asset-for-sale) ------------------------------------------------------------------------------------------------------- Get the seller's address from the connected wallet: const addr = (await wallet.getUsedAddresses())[0]; Create the datum schema: const datumConstr: Data = { alternative: 0, fields: [\ resolvePaymentKeyHash(addr), // seller address as pubkeyhash\ listPriceInLovelace, // price\ policyId, // policy ID of token\ assetId, // asset name of token in hex\ ], }; Create a transaction using `sendAssets()` to send the asset to the script address with the defined datum. `policyId + assetId` is the asset name in hex. Build, sign, and submit the transaction. const tx = new Transaction({ initiator: wallet }) .sendAssets( { address: scriptAddress, datum: { value: datumConstr, }, }, [\ {\ unit: policyId + assetId,\ quantity: '1',\ },\ ] ); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); Implement your own marketplace. Note: A database may be required to store listing information. Full code for listing an asset: const addr = (await wallet.getUsedAddresses())[0]; const datumConstr: Data = { alternative: 0, fields: [\ resolvePaymentKeyHash(addr),\ listPriceInLovelace,\ policyId,\ assetId,\ ], }; const tx = new Transaction({ initiator: wallet }) .sendAssets( { address: scriptAddress, datum: { value: datumConstr, }, }, [\ {\ unit: policyId + assetId,\ quantity: '1',\ },\ ] ); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Cancel the Listing](https://meshjs.dev/guides/smart-contract-transactions#cancel-the-listing) ----------------------------------------------------------------------------------------------- Cancel the listing. Only the seller can cancel. Define the datum: const datumConstr: Data = { alternative: 0, fields: [\ resolvePaymentKeyHash(addr), // seller address as pubkeyhash\ listPriceInLovelace, // price\ policyId, // policy ID of token\ assetId, // asset name of token in hex\ ], }; Cancel, update, and purchase endpoints require the UTxO in the script address. Use `fetchAddressUTxOs()` to query UTxOs containing the asset. Filter by datum hash using `resolveDataHash()` (see [resolvers](https://meshjs.dev/apis/utilities/resolvers) ). Implementation for `_getAssetUtxo()`: async function _getAssetUtxo({ scriptAddress, asset, datum }) { const utxos = await blockchainFetcher.fetchAddressUTxOs( scriptAddress, asset ); if (utxos.length == 0) { throw 'No listing found.'; } const dataHash = resolveDataHash(datum); let utxo = utxos.find((utxo: any) => { return utxo.output.dataHash == dataHash; }); return utxo; } Define the redeemer for cancellation: const redeemer = { data: { alternative: 1, fields: [] } }; Build the transaction. Use `redeemValue()` to redeem the UTxO and send the value back to the seller. Set required signers to the seller's address. const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datumConstr, redeemer: redeemer, }) .sendValue(addr, assetUtxo) .setRequiredSigners([addr]); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); Full code for cancellation: const addr = (await wallet.getUsedAddresses())[0]; const datumConstr: Data = { alternative: 0, fields: [\ resolvePaymentKeyHash(addr),\ listPriceInLovelace,\ policyId,\ assetId,\ ], }; const assetUtxo = await _getAssetUtxo({ scriptAddress: scriptAddress, asset: 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e', datum: datumConstr, }); if (assetUtxo === undefined) { throw 'No listing found.'; } const redeemer = { data: { alternative: 1, fields: [] } }; const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datumConstr, redeemer: redeemer, }) .sendValue(addr, assetUtxo) .setRequiredSigners([addr]); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); [Purchase the Listed Asset](https://meshjs.dev/guides/smart-contract-transactions#purchase-the-listed-asset) ------------------------------------------------------------------------------------------------------------- Purchase the listed asset. The endpoint requires the asset, price, and seller address to create the validator datum. Successful purchase transfers the asset to the buyer and price to the seller. Get the buyer's address: const addr = (await wallet.getUsedAddresses())[0]; // buyer's address Create the validator datum using the seller's address: const datumConstr: Data = { alternative: 0, fields: [\ resolvePaymentKeyHash(sellerAddr), // seller address as pubkeyhash\ listPriceInLovelace, // price\ policyId, // policy ID of token\ assetId, // asset name of token in hex\ ], }; Define the redeemer: const redeemer = { data: { alternative: 0, fields: [] } }; Build and submit the transaction. Use `redeemValue()` to redeem the asset, `sendValue()` to transfer to the buyer, and `sendLovelace()` to pay the seller: const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datumConstr, redeemer: redeemer, }) .sendValue(addr, assetUtxo) .sendLovelace(sellerAddr, listPriceInLovelace.toString()) .setRequiredSigners([addr]); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); Full code for purchase: const addr = (await wallet.getUsedAddresses())[0]; // buyer's address const datumConstr: Data = { alternative: 0, fields: [\ resolvePaymentKeyHash(sellerAddr),\ listPriceInLovelace,\ policyId,\ assetId,\ ], }; const assetUtxo = await _getAssetUtxo({ scriptAddress: scriptAddress, asset: 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e', datum: datumConstr, }); const redeemer = { data: { alternative: 0, fields: [] } }; const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datumConstr, redeemer: redeemer, }) .sendValue(addr, assetUtxo) .sendLovelace(sellerAddr, listPriceInLovelace.toString()) .setRequiredSigners([addr]); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); [Update the Listing](https://meshjs.dev/guides/smart-contract-transactions#update-the-listing) ----------------------------------------------------------------------------------------------- Update the listing. Only the seller can update. Define the original datum: const datumConstr: Data = { alternative: 0, fields: [\ resolvePaymentKeyHash(addr), // seller address as pubkeyhash\ listPriceInLovelace, // listed price\ policyId, // policy ID of token\ assetId, // asset name of token in hex\ ], }; Create the updated datum with the new price: const datumConstrNew: Data = { alternative: 0, fields: [\ resolvePaymentKeyHash(addr), // seller address as pubkeyhash\ updatedPriceInLovelace, // updated price\ policyId, // policy ID of token\ assetId, // asset name of token in hex\ ], }; Define the redeemer for update: const redeemer = { data: { alternative: 1, fields: [] } }; Build the transaction. Redeem the UTxO with the original datum and send the NFT to the script address with the new datum using `sendAssets()`. const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datumConstr, redeemer: redeemer, }) .setRequiredSigners([addr]) .sendAssets( { address: scriptAddress, datum: { value: datumConstrNew, }, }, [\ {\ unit: 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e',\ quantity: '1',\ },\ ] ); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); Full code for update: const addr = (await wallet.getUsedAddresses())[0]; const datumConstr: Data = { alternative: 0, fields: [\ resolvePaymentKeyHash(addr),\ listPriceInLovelace,\ policyId,\ assetId,\ ], }; const datumConstrNew: Data = { alternative: 0, fields: [\ resolvePaymentKeyHash(addr),\ updatedPriceInLovelace,\ policyId,\ assetId,\ ], }; const assetUtxo = await _getAssetUtxo({ scriptAddress: scriptAddress, asset: 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e', datum: datumConstr, }); const redeemer = { data: { alternative: 1, fields: [] } }; const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datumConstr, redeemer: redeemer, }) .setRequiredSigners([addr]) .sendAssets( { address: scriptAddress, datum: { value: datumConstrNew, }, }, [\ {\ unit: 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e',\ quantity: '1',\ },\ ] ); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); This serves as a starting point for building apps with smart contracts. [Implement Custom Provider\ \ Previous Page](https://meshjs.dev/guides/custom-provider) [Aiken Hello World\ \ Next Page](https://meshjs.dev/guides/aiken) ### On this page [Initialize the Plutus script](https://meshjs.dev/guides/smart-contract-transactions#initialize-the-plutus-script) [Listing Asset for Sale](https://meshjs.dev/guides/smart-contract-transactions#listing-asset-for-sale) [Cancel the Listing](https://meshjs.dev/guides/smart-contract-transactions#cancel-the-listing) [Purchase the Listed Asset](https://meshjs.dev/guides/smart-contract-transactions#purchase-the-listed-asset) [Update the Listing](https://meshjs.dev/guides/smart-contract-transactions#update-the-listing) Ask AI --- # Integration Examples | Mesh SDK [Midnight](https://meshjs.dev/midnight) Midnight Setup Integration Examples ==================== The fastest way to build on Midnight Network with pre-built smart contracts, complete API, and ready-to-use code snippets Copy MarkdownOpen The fastest way to build on Midnight Network with pre-built smart contract, complete API, and ready-to-use code snippets. Full React integration example and a Compact contract: [midnight-setup](https://github.com/MeshJS/midnight-setup) [Installation](https://meshjs.dev/midnight/midnight-setup/examples#installation) --------------------------------------------------------------------------------- npm install @meshsdk/midnight-setup \ @midnight-ntwrk/dapp-connector-api@3.0.0 \ @midnight-ntwrk/midnight-js-fetch-zk-config-provider@2.0.2 \ @midnight-ntwrk/midnight-js-http-client-proof-provider@2.0.2 \ @midnight-ntwrk/midnight-js-indexer-public-data-provider@2.0.2 \ @midnight-ntwrk/midnight-js-level-private-state-provider@2.0.2 \ @midnight-ntwrk/midnight-js-network-id@2.0.2 [Features](https://meshjs.dev/midnight/midnight-setup/examples#features) ------------------------------------------------------------------------- * **Type-safe SDK** - Full TypeScript support * **Provider abstraction** - Easy wallet and network integration * **Contract state management** - Query contract and ledger states * **Flexible contract support** - Works with any Midnight smart contract * **Lightweight** - Only 10.4 KB package size * **ESM & CJS** - Supports both module systems [Quick Start](https://meshjs.dev/midnight/midnight-setup/examples#quick-start) ------------------------------------------------------------------------------- ### [1\. Setup Providers](https://meshjs.dev/midnight/midnight-setup/examples#1-setup-providers) import { FetchZkConfigProvider } from "@midnight-ntwrk/midnight-js-fetch-zk-config-provider"; import { httpClientProofProvider } from "@midnight-ntwrk/midnight-js-http-client-proof-provider"; import { indexerPublicDataProvider } from "@midnight-ntwrk/midnight-js-indexer-public-data-provider"; import { levelPrivateStateProvider } from "@midnight-ntwrk/midnight-js-level-private-state-provider"; import type { MidnightSetupContractProviders } from "@meshsdk/midnight-setup"; export async function setupProviders(): Promise { const wallet = window.midnight?.mnLace; if (!wallet) { throw new Error("Please install Lace Beta Wallet for Midnight Network"); } const walletAPI = await wallet.enable(); const walletState = await walletAPI.state(); const uris = await wallet.serviceUriConfig(); return { privateStateProvider: levelPrivateStateProvider({ privateStateStoreName: "my-dapp-state", }), zkConfigProvider: new FetchZkConfigProvider( window.location.origin, fetch.bind(window), ), proofProvider: httpClientProofProvider(uris.proverServerUri), publicDataProvider: indexerPublicDataProvider( uris.indexerUri, uris.indexerWsUri, ), walletProvider: { coinPublicKey: walletState.coinPublicKey, encryptionPublicKey: walletState.encryptionPublicKey, balanceTx: (tx, newCoins) => { return walletAPI.balanceAndProveTransaction(tx, newCoins); }, }, midnightProvider: { submitTx: (tx) => { return walletAPI.submitTransaction(tx); }, }, }; } ### [2\. Deploy a Contract](https://meshjs.dev/midnight/midnight-setup/examples#2-deploy-a-contract) import { MidnightSetupAPI } from "@meshsdk/midnight-setup"; import { setupProviders } from "./providers"; async function deployContract() { const providers = await setupProviders(); const contractInstance = new MyContract({}); const api = await MidnightSetupAPI.deployContract( providers, contractInstance, ); console.log("Contract deployed at:", api.deployedContractAddress); return api; } ### [3\. Join Existing Contract](https://meshjs.dev/midnight/midnight-setup/examples#3-join-existing-contract) async function joinContract(contractAddress: string) { const providers = await setupProviders(); const contractInstance = new MyContract({}); const api = await MidnightSetupAPI.joinContract( providers, contractInstance, contractAddress, ); return api; } ### [4\. Read Contract State](https://meshjs.dev/midnight/midnight-setup/examples#4-read-contract-state) // Get contract state const contractState = await api.getContractState(); console.log("Contract data:", contractState.data); // Get ledger state const ledgerState = await api.getLedgerState(); console.log("Message:", ledgerState.ledgerState?.message); [API Reference](https://meshjs.dev/midnight/midnight-setup/examples#api-reference) ----------------------------------------------------------------------------------- ### [MidnightSetupAPI](https://meshjs.dev/midnight/midnight-setup/examples#midnightsetupapi) #### [Static Methods](https://meshjs.dev/midnight/midnight-setup/examples#static-methods) ##### [`deployContract(providers, contractInstance, logger?)`](https://meshjs.dev/midnight/midnight-setup/examples#deploycontractproviders-contractinstance-logger) Deploys a new smart contract to Midnight Network. **Parameters:** * `providers`: `MidnightSetupContractProviders` - Network and wallet providers * `contractInstance`: `ContractInstance` - Your compiled contract instance * `logger?`: `Logger` - Optional Pino logger **Returns:** `Promise` ##### [`joinContract(providers, contractInstance, contractAddress, logger?)`](https://meshjs.dev/midnight/midnight-setup/examples#joincontractproviders-contractinstance-contractaddress-logger) Connects to an existing deployed contract. **Parameters:** * `providers`: `MidnightSetupContractProviders` - Network and wallet providers * `contractInstance`: `ContractInstance` - Your compiled contract instance * `contractAddress`: `string` - Address of the deployed contract * `logger?`: `Logger` - Optional Pino logger **Returns:** `Promise` #### [Instance Methods](https://meshjs.dev/midnight/midnight-setup/examples#instance-methods) * **`getContractState()`** - Gets the current state of the contract * **Returns:** `Promise` * **`getLedgerState()`** - Gets and parses the ledger state * **Returns:** `Promise` [TypeScript Types](https://meshjs.dev/midnight/midnight-setup/examples#typescript-types) ----------------------------------------------------------------------------------------- import type { ContractInstance, ContractStateData, DeployedContract, DeployedMidnightSetupAPI, LedgerStateData, MidnightSetupContractProviders, } from "@meshsdk/midnight-setup"; [Requirements](https://meshjs.dev/midnight/midnight-setup/examples#requirements) --------------------------------------------------------------------------------- * **Node.js** v18 or higher * **Midnight Lace Wallet** browser extension * **TypeScript** (recommended) [React Integration Example](https://meshjs.dev/midnight/midnight-setup/examples#react-integration-example) ----------------------------------------------------------------------------------------------------------- ### [Complete React Hook](https://meshjs.dev/midnight/midnight-setup/examples#complete-react-hook) import { useState, useCallback } from 'react'; import { MidnightSetupAPI } from '@meshsdk/midnight-setup'; import { setupProviders } from './providers'; export const useMidnightContract = () => { const [api, setApi] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const deployContract = useCallback(async (contractInstance) => { setIsLoading(true); setError(null); try { const providers = await setupProviders(); const newApi = await MidnightSetupAPI.deployContract(providers, contractInstance); setApi(newApi); return newApi; } catch (err) { setError(err.message); throw err; } finally { setIsLoading(false); } }, []); const joinContract = useCallback(async (contractInstance, address) => { setIsLoading(true); setError(null); try { const providers = await setupProviders(); const newApi = await MidnightSetupAPI.joinContract(providers, contractInstance, address); setApi(newApi); return newApi; } catch (err) { setError(err.message); throw err; } finally { setIsLoading(false); } }, []); const getContractState = useCallback(async () => { if (!api) throw new Error('No contract API available'); return await api.getContractState(); }, [api]); const getLedgerState = useCallback(async () => { if (!api) throw new Error('No contract API available'); return await api.getLedgerState(); }, [api]); return { api, deployContract, joinContract, getContractState, getLedgerState, isLoading, error }; }; ### [React Component Example](https://meshjs.dev/midnight/midnight-setup/examples#react-component-example) import React, { useState } from 'react'; import { useMidnightContract } from './hooks/useMidnightContract'; function ContractManager() { const { api, deployContract, joinContract, getContractState, getLedgerState, isLoading, error } = useMidnightContract(); const [contractAddress, setContractAddress] = useState(''); const [contractState, setContractState] = useState(null); const handleDeploy = async () => { try { const contractInstance = new MyContract({}); const newApi = await deployContract(contractInstance); console.log('Deployed:', newApi.deployedContractAddress); } catch (err) { console.error('Deploy failed:', err); } }; const handleJoin = async () => { try { const contractInstance = new MyContract({}); await joinContract(contractInstance, contractAddress); console.log('Joined contract:', contractAddress); } catch (err) { console.error('Join failed:', err); } }; const handleGetState = async () => { try { const state = await getContractState(); setContractState(state); } catch (err) { console.error('Get state failed:', err); } }; return (

Contract Manager

{error && (
Error: {error}
)}
setContractAddress(e.target.value)} />
{api && ( )}
{contractState && (

Contract State

{JSON.stringify(contractState, null, 2)}
)}
); } [Error Handling](https://meshjs.dev/midnight/midnight-setup/examples#error-handling) ------------------------------------------------------------------------------------- ### [Common Error Patterns](https://meshjs.dev/midnight/midnight-setup/examples#common-error-patterns) const handleMidnightError = (error: Error) => { if (error.message.includes('Please install Lace Beta Wallet')) { return 'Please install Lace Beta Wallet for Midnight Network'; } if (error.message.includes('Insufficient funds')) { return 'Insufficient funds for transaction'; } if (error.message.includes('Contract not found')) { return 'Contract address not found or invalid'; } return 'An unexpected error occurred'; }; ### [Error Boundary Component](https://meshjs.dev/midnight/midnight-setup/examples#error-boundary-component) import React from 'react'; interface ErrorBoundaryState { hasError: boolean; error?: Error; } interface ErrorBoundaryProps { children: React.ReactNode; fallback?: React.ComponentType<{ error: Error }>; } export class MidnightErrorBoundary extends React.Component< ErrorBoundaryProps, ErrorBoundaryState > { constructor(props: ErrorBoundaryProps) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error: Error): ErrorBoundaryState { return { hasError: true, error }; } componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { console.error('Midnight Error Boundary caught an error:', error, errorInfo); } render() { if (this.state.hasError) { const FallbackComponent = this.props.fallback || DefaultErrorFallback; return ; } return this.props.children; } } const DefaultErrorFallback: React.FC<{ error: Error }> = ({ error }) => (

Something went wrong with Midnight Network

{error.message}

); [Best Practices](https://meshjs.dev/midnight/midnight-setup/examples#best-practices) ------------------------------------------------------------------------------------- 1. **Always handle errors** - Wrap API calls in try-catch blocks 2. **Use TypeScript** - Leverage type safety for better development experience 3. **Validate inputs** - Ensure contract instances and addresses are valid 4. **Monitor state changes** - Listen for contract state updates 5. **Test thoroughly** - Use testnet before deploying to mainnet 6. **Implement retry logic** - Allow users to retry failed operations 7. **Secure key handling** - Never store private keys in localStorage [Lace Wallet Integration\ \ Complete Lace Beta Wallet integration for Midnight Network dApps](https://meshjs.dev/midnight/midnight-setup/wallet) [Overview\ \ A CLI tool to create new Midnight contracts projects with selected smart contracts](https://meshjs.dev/midnight/midnight-contracts-wizard) ### On this page [Installation](https://meshjs.dev/midnight/midnight-setup/examples#installation) [Features](https://meshjs.dev/midnight/midnight-setup/examples#features) [Quick Start](https://meshjs.dev/midnight/midnight-setup/examples#quick-start) [1\. Setup Providers](https://meshjs.dev/midnight/midnight-setup/examples#1-setup-providers) [2\. Deploy a Contract](https://meshjs.dev/midnight/midnight-setup/examples#2-deploy-a-contract) [3\. Join Existing Contract](https://meshjs.dev/midnight/midnight-setup/examples#3-join-existing-contract) [4\. Read Contract State](https://meshjs.dev/midnight/midnight-setup/examples#4-read-contract-state) [API Reference](https://meshjs.dev/midnight/midnight-setup/examples#api-reference) [MidnightSetupAPI](https://meshjs.dev/midnight/midnight-setup/examples#midnightsetupapi) [Static Methods](https://meshjs.dev/midnight/midnight-setup/examples#static-methods) [`deployContract(providers, contractInstance, logger?)`](https://meshjs.dev/midnight/midnight-setup/examples#deploycontractproviders-contractinstance-logger) [`joinContract(providers, contractInstance, contractAddress, logger?)`](https://meshjs.dev/midnight/midnight-setup/examples#joincontractproviders-contractinstance-contractaddress-logger) [Instance Methods](https://meshjs.dev/midnight/midnight-setup/examples#instance-methods) [TypeScript Types](https://meshjs.dev/midnight/midnight-setup/examples#typescript-types) [Requirements](https://meshjs.dev/midnight/midnight-setup/examples#requirements) [React Integration Example](https://meshjs.dev/midnight/midnight-setup/examples#react-integration-example) [Complete React Hook](https://meshjs.dev/midnight/midnight-setup/examples#complete-react-hook) [React Component Example](https://meshjs.dev/midnight/midnight-setup/examples#react-component-example) [Error Handling](https://meshjs.dev/midnight/midnight-setup/examples#error-handling) [Common Error Patterns](https://meshjs.dev/midnight/midnight-setup/examples#common-error-patterns) [Error Boundary Component](https://meshjs.dev/midnight/midnight-setup/examples#error-boundary-component) [Best Practices](https://meshjs.dev/midnight/midnight-setup/examples#best-practices) Ask AI --- # Mint and Burn Assets | Mesh SDK [Transaction Builder](https://meshjs.dev/apis/txbuilder) Mint and Burn Assets ==================== Minting and burning assets with Native Script and Plutus Script Copy MarkdownOpen Minting and burning assets with Native Script and Plutus Script Minting and burning assets is a common operation in blockchain applications. In the Cardano ecosystem, minting and burning are achieved through Native Scripts and Plutus Scripts. To view a video demonstration of this feature of the MeshSDK, navigate to the video guide [Mint an NFT Collection](https://meshjs.dev/guides/nft-collection) . In the code snippet, you will find `txBuilder`, which is an instance of `MeshTxBuilder`, with powerful low-level APIs that allow you to build transactions. Here's how to initialize **MeshTxBuilder**. const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); In this page, you will find the APIs to create transactions for minting and burning assets. [Minting with One Signature](https://meshjs.dev/apis/txbuilder/minting#minting-with-one-signature) --------------------------------------------------------------------------------------------------- In this section, we will see how to mint native assets with a `MeshTxBuilder`. For minting assets with a smart contract visit [this documentation](https://meshjs.dev/apis/txbuilder/smart-contracts#minting-assets-with-plutus-script) . Firstly, we need to define the `forgingScript` with `ForgeScript`. We use the first wallet address as the "minting address" (you can use other addresses). const changeAddress = await wallet.getChangeAddress(); const forgingScript = ForgeScript.withOneSignature(changeAddress); Then, we define the metadata. const demoAssetMetadata = { name: "Mesh Token", image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "This NFT was minted by Mesh (https://meshjs.dev/).", }; const policyId = resolveScriptHash(forgingScript); const tokenName = "MeshToken"; const tokenNameHex = stringToHex(tokenName); const metadata = { [policyId]: { [tokenName]: { ...demoAssetMetadata } } }; Finally, we create a transaction and mint the asset with the `MeshTxBuilder` lower level APIs. const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .txIn(utxo.input.txHash, utxo.input.outputIndex) .mint("1", policyId, tokenName) .mintingScript(forgingScript) .changeAddress(changeAddress) .complete(); ### [Mint Asset](https://meshjs.dev/apis/txbuilder/minting#mint-asset) Mint an asset with a native script import { MeshTxBuilder, ForgeScript, resolveScriptHash, stringToHex } from '@meshsdk/core'; import type { Asset } from '@meshsdk/core'; // See https://meshjs.dev/apis/wallets/meshwallet for how to create a new wallet instance const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const forgingScript = ForgeScript.withOneSignature(changeAddress); const demoAssetMetadata = { name: "Mesh Token", image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "This NFT was minted by Mesh (https://meshjs.dev/).", }; const policyId = resolveScriptHash(forgingScript); const tokenName = "MeshToken"; const tokenNameHex = stringToHex(tokenName); const metadata = { [policyId]: { [tokenName]: { ...demoAssetMetadata } } }; const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mint("1", policyId, tokenNameHex) .mintingScript(forgingScript) .metadataValue(721, metadata) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Minting Multiple Assets](https://meshjs.dev/apis/txbuilder/minting#minting-multiple-assets) --------------------------------------------------------------------------------------------- Minting multiple assets with a single transaction is a common operation in blockchain applications. Like minting single assets, you can mint multiple assets by calling `mint()` and `mintingScript` multiple times. const metadata = {}; metadata[policyId] = {}; for (let i = 1; i < 3; i++) { const tokenName = `MeshToken${i}`; const tokenNameHex = stringToHex(tokenName); metadata[policyId][tokenName] = { ...demoAssetMetadata, name: tokenName, }; txBuilder.mint("1", policyId, tokenNameHex); txBuilder.mintingScript(forgingScript); } You add the metadata object by calling the `metadataValue()` method. const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .metadataValue(721, metadata) .changeAddress(changeAddress) .selectUtxosFrom(utxos); const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); ### [Mint Multiple Assets](https://meshjs.dev/apis/txbuilder/minting#mint-multiple-assets-toc) Mint multiple assets with a single transaction import { MeshTxBuilder, ForgeScript, resolveScriptHash, stringToHex } from '@meshsdk/core'; import type { Asset } from '@meshsdk/core'; import { useWallet } from "@meshsdk/react"; const { wallet, connected } = useWallet(); const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const forgingScript = ForgeScript.withOneSignature(changeAddress); const policyId = resolveScriptHash(forgingScript); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const metadata = {}; metadata[policyId] = {}; for (let i = 1; i < 3; i++) { const tokenName = `MeshToken${i}`; const tokenNameHex = stringToHex(tokenName); metadata[policyId][tokenName] = { ...demoAssetMetadata, name: tokenName, }; txBuilder.mint("1", policyId, tokenNameHex); txBuilder.mintingScript(forgingScript); } txBuilder .metadataValue(721, metadata) .changeAddress(changeAddress) .selectUtxosFrom(utxos); const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Burning assets](https://meshjs.dev/apis/txbuilder/minting#burning-assets) --------------------------------------------------------------------------- Like minting assets, we need to define the `forgingScript` with `ForgeScript`. We use the first wallet address as the "minting address". Note that, assets can only be burned by its minting address. const usedAddress = await wallet.getUsedAddresses(); const address = usedAddress[0]; const forgingScript = ForgeScript.withOneSignature(address); Then, we resolve the policy ID and hex of the token name by calling `txBuilder.mint("-1", policyId, tokenNameHex)` const policyId = resolveScriptHash(forgingScript); const tokenNameHex = stringToHex("MeshToken"); Finally, we create a transaction and burn the asset with the lower level APIs. const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mint("-1", policyId, tokenNameHex) .mintingScript(forgingScript) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); ### [Burn Native Assets](https://meshjs.dev/apis/txbuilder/minting#burn-native-assets-toc) Burn native assets **Asset Unit** `d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e` import { ForgeScript, resolveScriptHash, stringToHex } from "@meshsdk/core"; import { useWallet } from "@meshsdk/react"; const { wallet, connected } = useWallet(); const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const forgingScript = ForgeScript.withOneSignature(changeAddress); const policyId = resolveScriptHash(forgingScript); const tokenNameHex = stringToHex("MeshToken"); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mint("-1", policyId, tokenNameHex) .mintingScript(forgingScript) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Minting Assets with Native Script](https://meshjs.dev/apis/txbuilder/minting#minting-assets-with-native-script) ----------------------------------------------------------------------------------------------------------------- The minting and burning examples above demonstrate using a one-signature native script. Here we explain the underlying logic for native script minting. With `MeshTxBuilder`, you just need to call `.mint()` and provide a script to mint or burn native script tokens: txBuilder .mint("1", policyId, tokenNameHex) .mintingScript(forgingScript) On top of these two core steps, you can attach metadata with .metadataValue() and then construct the transaction as needed. ### [Mint Assets with Native Script](https://meshjs.dev/apis/txbuilder/minting#mint-assets-with-native-script-toc) Mint native assets with Native Script const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const { pubKeyHash: keyHash } = deserializeAddress(changeAddress); const nativeScript: NativeScript = { type: "all", scripts: [\ {\ type: "before",\ slot: "99999999",\ },\ {\ type: "sig",\ keyHash: keyHash,\ },\ ], }; const forgingScript = ForgeScript.fromNativeScript(nativeScript); const policyId = resolveScriptHash(forgingScript); const tokenName = "MeshToken"; const tokenNameHex = stringToHex(tokenName); const metadata = { [policyId]: { [tokenName]: { ...demoAssetMetadata } } }; const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mint("1", policyId, tokenNameHex) .mintingScript(forgingScript) .metadataValue(721, metadata) .changeAddress(changeAddress) .invalidHereafter(99999999) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Minting Assets with Plutus Script](https://meshjs.dev/apis/txbuilder/minting#minting-assets-with-plutus-script) ----------------------------------------------------------------------------------------------------------------- Plutus script minting with `MeshTxBuilder` starts with any of the below script version indicators: .mintPlutusScriptV1() .mintPlutusScriptV2() .mintPlutusScriptV3() Followed by specifying the minting information: .mint(quantity: string, policy: string, name: string) Similar to unlocking, minting or burning tokens, the Plutus script requires providing a redeemer and the script itself. However, no datum information is needed in minting or burning. **Providing a Script** The actual script can be either provided through `mintTxInReference` method by attaching an on-chain UTxO reference, or by providing a Cbor encoded script. * (i) Reference script .mintTxInReference(txHash: string, txIndex: number) * (ii) Supplying script .mintingScript(scriptCbor: string) **Minting Redeemer** Redeemer can be provided in different **data types**. If your MeshTxBuilder does not include an `evaluator` instance, you can also provide your budget for the unlock with this redeemer endpoint .mintRedeemerValue(redeemer: Data | object | string, type: "Mesh" | "CBOR" | "JSON", exUnits?: Budget) ### [Mint Assets with Plutus Script](https://meshjs.dev/apis/txbuilder/minting#mint-assets-with-plutus-script-toc) Mint native assets with Plutus Script. For this example, the Plutus script expects a data field of 'mesh'. **Redeemer value:** `mesh` const utxos = await wallet.getUtxos(); const collateral: UTxO = (await wallet.getCollateral())[0]!; const changeAddress = await wallet.getChangeAddress(); const policyId = resolveScriptHash(demoPlutusMintingScript, "V2"); const tokenName = 'mesh'; const tokenNameHex = stringToHex(tokenName); const metadata = { [policyId]: { [tokenName]: { ...demoAssetMetadata } } }; const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mintPlutusScriptV2() .mint("1", policyId, tokenNameHex) .mintingScript(demoPlutusMintingScript) .mintRedeemerValue(mConStr0(['mesh'])) .metadataValue(721, metadata) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .txInCollateral( collateral.input.txHash, collateral.input.outputIndex, collateral.output.amount, collateral.output.address, ) .complete(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); [Minting Assets with CIP-68 Metadata standard](https://meshjs.dev/apis/txbuilder/minting#minting-assets-with-cip-68-metadata-standard) --------------------------------------------------------------------------------------------------------------------------------------- Minting CIP-68 tokens with `MeshTxBuilder` means 2 consecutive sets of minting APIs. The first is to mint the token with the `100` label, and the second is to mint the token with the `222` label: txBuilder .mintPlutusScriptV2() .mint("1", policyId, CIP68_100(tokenNameHex)) .mintingScript(scriptCode) .mintRedeemerValue(mConStr0([])) .mintPlutusScriptV2() .mint("1", policyId, CIP68_222(tokenNameHex)) .mintingScript(scriptCode) .mintRedeemerValue(mConStr0([])) A side note, Mesh also provides the utility function of `CIP68_100(tokenNameHex: string)` and `CIP68_222(tokenNameHex: string)` to help easily construct the token names as needed. So you dont have to memorize the prefix bytes to correctly mint the CIP68-compliant tokens. ### [Mint Assets with CIP68 metadata standard](https://meshjs.dev/apis/txbuilder/minting#mint-assets-with-cip68-metadata-standard-toc) Mint assets with CIP68 metadata standard where two assets are issued, one referencing the other user token. **Token Name:** `Test1` const usedAddress = await wallet.getUsedAddresses(); const address = usedAddress[0]; if (address === undefined) { throw "Address not found"; } const userTokenMetadata = { name: userInput, image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "Hello world - CIP68", }; const alawysSucceedPlutusScript: PlutusScript = { code: demoPlutusAlwaysSucceedScript, version: "V1", }; const { address: scriptAddress } = serializePlutusScript( alawysSucceedPlutusScript, ); const utxos = await wallet.getUtxos(); if (!utxos || utxos.length <= 0) { throw "No UTxOs found in wallet"; } const scriptCode = applyParamsToScript(oneTimeMintingPolicy, [\ mTxOutRef(utxos[0]?.input.txHash!, utxos[0]?.input.outputIndex!),\ ]); const collateral: UTxO = (await wallet.getCollateral())[0]!; const changeAddress = await wallet.getChangeAddress(); const policyId = resolveScriptHash(scriptCode, "V2"); const tokenName = 'Test1'; const tokenNameHex = stringToHex(tokenName); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .txIn( utxos[0]?.input.txHash!, utxos[0]?.input.outputIndex!, utxos[0]?.output.amount!, utxos[0]?.output.address!, ) .mintPlutusScriptV2() .mint("1", policyId, CIP68_100(tokenNameHex)) .mintingScript(scriptCode) .mintRedeemerValue(mConStr0([])) .mintPlutusScriptV2() .mint("1", policyId, CIP68_222(tokenNameHex)) .mintingScript(scriptCode) .mintRedeemerValue(mConStr0([])) .txOut(scriptAddress, [\ { unit: policyId + CIP68_100(tokenNameHex), quantity: "1" },\ ]) .txOutInlineDatumValue(metadataToCip68(userTokenMetadata)) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .txInCollateral( collateral.input.txHash, collateral.input.outputIndex, collateral.output.amount, collateral.output.address, ) .complete(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); [Minting Royalty Token](https://meshjs.dev/apis/txbuilder/minting#minting-royalty-token) ----------------------------------------------------------------------------------------- Royalty tokens are a special type of token that allow the creator to collect a royalty fee. This proposed standard will allow for uniform royalty distributions across the secondary market space. Read CIP-27 for more information. The implementation of royalty tokens is very simple – minting a token with the `777` label, with "rate", and "addr" in the metadata. Here is the example of the metadata: const assetMetadata = { rate: '0.2', addr: 'addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr' }; ### [Mint Native Assets](https://meshjs.dev/apis/txbuilder/minting#mint-native-assets-toc) Mint native assets with ForgeScript **Rate:** `0.2` **Address:** `addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr` const utxos = await wallet.getUtxos(); const usedAddress = await wallet.getUsedAddresses(); const address = usedAddress[0]; if (address === undefined) { throw "No address found"; } const forgingScript = ForgeScript.withOneSignature(address); const policyId = resolveScriptHash(forgingScript); const assetMetadata: RoyaltiesStandard = { rate: '0.2', address: 'addr_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', }; const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mint("1", policyId, "") .mintingScript(forgingScript) .metadataValue(777, assetMetadata) .changeAddress(address) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); [Transaction Basics\ \ Working with transactions and its various options](https://meshjs.dev/apis/txbuilder/basics) [Smart Contracts\ \ Transactions to work with smart contracts](https://meshjs.dev/apis/txbuilder/smart-contracts) ### On this page [Minting with One Signature](https://meshjs.dev/apis/txbuilder/minting#minting-with-one-signature) [Mint Asset](https://meshjs.dev/apis/txbuilder/minting#mint-asset) [Minting Multiple Assets](https://meshjs.dev/apis/txbuilder/minting#minting-multiple-assets) [Burning assets](https://meshjs.dev/apis/txbuilder/minting#burning-assets) [Minting Assets with Native Script](https://meshjs.dev/apis/txbuilder/minting#minting-assets-with-native-script) [Minting Assets with Plutus Script](https://meshjs.dev/apis/txbuilder/minting#minting-assets-with-plutus-script) [Minting Assets with CIP-68 Metadata standard](https://meshjs.dev/apis/txbuilder/minting#minting-assets-with-cip-68-metadata-standard) [Minting Royalty Token](https://meshjs.dev/apis/txbuilder/minting#minting-royalty-token) Ask AI --- # End-to-End Hydra Happy Flow | Mesh SDK [Learn](https://meshjs.dev/resources) [Cardano Course](https://meshjs.dev/resources/cardano-course) [Lessons](https://meshjs.dev/resources/cardano-course/lessons) End-to-End Hydra Happy Flow =========================== Layer 2 scaling solution for Cardano, an end-to-end tutorial for state channel between two participants using the Hydra Head protocol. Copy MarkdownOpen > **Note:** Work in progress, come back later. [Plutus NFT Contract\ \ Plutus NFT smart contract enforces non-fungibility and uniqueness of the NFT under the same policy.](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft) [Web3 Services\ \ Onboard seamlessly with non-custodial wallet-as-a-service and transaction sponsorship.](https://meshjs.dev/resources/cardano-course/lessons/10-web3-services) Ask AI --- # Web3 Services | Mesh SDK [Learn](https://meshjs.dev/resources) [Cardano Course](https://meshjs.dev/resources/cardano-course) [Lessons](https://meshjs.dev/resources/cardano-course/lessons) Web3 Services ============= Onboard seamlessly with non-custodial wallet-as-a-service and transaction sponsorship. Copy MarkdownOpen [Wallet as a Service](https://meshjs.dev/resources/cardano-course/lessons/10-web3-services#wallet-as-a-service) ---------------------------------------------------------------------------------------------------------------- wallet-as-a-service (WaaS) solution provide a seamless way for users to transact on-chain. Developers can integrate social logins and other familiar experiences into their applications, making onboarding fast and effortless. Users can create non-custodial wallets (the user owns the key and have full control over their digital assets) instantly without needing to manage private keys. Users can also recover their wallets and export their private keys at any time. Wallet key management system uses Shamir's Secret Sharing to split the private key into multiple parts. The parts are stored in different locations, such as the user's device and encrypted in the server. Neither UTXOS nor the developer's application has access to the user's keys. The private key is reconstructed only on the user's device during transaction signing, in an isolated iframe, which persists in-memory and is destroyed after the transaction is signed. Overall, the integration with a wallet-as-a-service solution provides a self-custody wallet to end users and accelerates the time-to-market for developers. Visit [UTXOS wallet documentation](https://docs.utxos.dev/wallet/usage) for the latest tutorial on how to integrate UTXOS wallet into your application. [Transaction Sponsorship](https://meshjs.dev/resources/cardano-course/lessons/10-web3-services#transaction-sponsorship) ------------------------------------------------------------------------------------------------------------------------ Network fees are the costs required to execute transactions, compensating network validators for processing and securing the blockchain. These fees are paid in the network's native token, such as ADA on Cardano. While essential for incentivizing validators and maintaining network security, network fees can pose a challenge for end users, as they must hold tokens to cover these costs when interacting with applications. Sponsorship enables developers to create seamless user experiences by eliminating the need for end-users to hold tokens in their wallets for transactions. Instead, transactions inputs and network fees are deducted from the developer's wallet, solving one of the most significant challenges in blockchain application development and enabling frictionless onboarding and interaction for end-users. Visit [UTXOS sponsorship documentation](https://docs.utxos.dev/sponsor/usage) for the latest tutorial on how to integrate UTXOS wallet into your application. [End-to-End Hydra Happy Flow\ \ Layer 2 scaling solution for Cardano, an end-to-end tutorial for state channel between two participants using the Hydra Head protocol.](https://meshjs.dev/resources/cardano-course/lessons/09-hydra) [Guides\ \ Guides for web developers and blockchain full-stack developers.](https://meshjs.dev/guides) ### On this page [Wallet as a Service](https://meshjs.dev/resources/cardano-course/lessons/10-web3-services#wallet-as-a-service) [Transaction Sponsorship](https://meshjs.dev/resources/cardano-course/lessons/10-web3-services#transaction-sponsorship) Ask AI --- # Course Lessons | Mesh SDK [Learn](https://meshjs.dev/resources) [Cardano Course](https://meshjs.dev/resources/cardano-course) Course Lessons ============== Step-by-step lessons for mastering Cardano development with Mesh SDK and Aiken. Copy MarkdownOpen Master Cardano development through our comprehensive lesson series. Each lesson builds upon the previous one, taking you from basic concepts to advanced smart contract development. [Lesson Overview](https://meshjs.dev/resources/cardano-course/lessons#lesson-overview) --------------------------------------------------------------------------------------- ### [Getting Started](https://meshjs.dev/resources/cardano-course/lessons#getting-started) * [Lesson 1: Hello World](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace) - Set up Mesh SDK and send your first transaction * [Lesson 2: Multi-signature Transactions](https://meshjs.dev/resources/cardano-course/lessons/02-multisig) - Build transactions requiring multiple signatures ### [Smart Contract Development](https://meshjs.dev/resources/cardano-course/lessons#smart-contract-development) * [Lesson 3: Aiken Contracts](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts) - Introduction to Aiken smart contract development * [Lesson 4: Contract Testing](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing) - Testing strategies and best practices * [Lesson 5: Avoid Redundant Validation](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation) - Optimization patterns for efficient contracts * [Lesson 6: Interpreting Blueprint](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint) - Understanding and using Aiken blueprints ### [Advanced Contracts](https://meshjs.dev/resources/cardano-course/lessons#advanced-contracts) * [Lesson 7: Vesting Contract](https://meshjs.dev/resources/cardano-course/lessons/07-vesting) - Build a token vesting smart contract * [Lesson 8: Plutus NFT Contract](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft) - Create NFT minting contracts with auto-increment ### [Scaling & Services](https://meshjs.dev/resources/cardano-course/lessons#scaling--services) * [Lesson 9: Hydra End-to-End](https://meshjs.dev/resources/cardano-course/lessons/09-hydra) - Layer 2 scaling with Hydra Head protocol * [Lesson 10: Web3 Services](https://meshjs.dev/resources/cardano-course/lessons/10-web3-services) - Wallet-as-a-service and transaction sponsorship [Learning Path](https://meshjs.dev/resources/cardano-course/lessons#learning-path) ----------------------------------------------------------------------------------- We recommend following the lessons in order, as each builds upon concepts introduced in previous lessons. However, if you're already familiar with certain topics, feel free to jump to specific lessons that interest you. [Support](https://meshjs.dev/resources/cardano-course/lessons#support) ----------------------------------------------------------------------- If you have questions or need help with any lesson, join our community channels or check out the [Developer Resources](https://meshjs.dev/resources/developer-resources) page for additional support options. [Cardano Course\ \ A comprehensive course for building Cardano applications with Mesh SDK and Aiken smart contracts.](https://meshjs.dev/resources/cardano-course) [Hello World\ \ Install Mesh SDK and learn how to send assets using the Mesh wallet.](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace) ### On this page [Lesson Overview](https://meshjs.dev/resources/cardano-course/lessons#lesson-overview) [Getting Started](https://meshjs.dev/resources/cardano-course/lessons#getting-started) [Smart Contract Development](https://meshjs.dev/resources/cardano-course/lessons#smart-contract-development) [Advanced Contracts](https://meshjs.dev/resources/cardano-course/lessons#advanced-contracts) [Scaling & Services](https://meshjs.dev/resources/cardano-course/lessons#scaling--services) [Learning Path](https://meshjs.dev/resources/cardano-course/lessons#learning-path) [Support](https://meshjs.dev/resources/cardano-course/lessons#support) Ask AI --- # Avoid Redundant Validation | Mesh SDK [Learn](https://meshjs.dev/resources) [Cardano Course](https://meshjs.dev/resources/cardano-course) [Lessons](https://meshjs.dev/resources/cardano-course/lessons) Avoid Redundant Validation ========================== Key contract best practice - reduce redundant validation logics being run onchain. Copy MarkdownOpen Do you have a question about the previous lessons - why have we performed even minting and state update in spending validators with withdrawal script? We know that every time we spend a UTxO from a spending validator would trigger checks, why can't I validate the counter update in the spending validator directly? [A Transaction with Multiple Script Validation](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#a-transaction-with-multiple-script-validation) --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Imagine there is a complex transaction that involves multiple script validations. For example, a transaction that mints tokens, unlocking multiple script UTxOs, and withdraws funds. Each of these actions may require its own set of checks and validations. graph TB %% Layout subgraph for labels at top with horizontal alignment subgraph Checks[" Common Validations "] direction LR C1["C1: Check if owner signature exists"] ~~~ C2["C2: Check if not expired"] ~~~ C3["C3: Any other common checks"] end %% Remove the connecting lines between checks linkStyle 0 stroke-width:0px linkStyle 1 stroke-width:0px %% Connect checks to components with dotted lines Checks -.-> A1 Checks -.-> A2 Checks -.-> A3 Checks -.-> M Checks -.-> W %% Inputs on left A1[Script Input 1] --> TX A2[Script Input 2] --> TX A3[Script Input 3] --> TX %% Center transaction TX((Transaction)) %% Mint on top M[Token Minting] --> TX %% Withdraw at bottom W[Withdrawal Script] --> TX %% Clear styling with bright colors and black text style TX fill:#FFA07A,stroke:#333,stroke-width:2px,color:#000 style M fill:#87CEEB,stroke:#333,stroke-width:2px,color:#000 style W fill:#DDA0DD,stroke:#333,stroke-width:2px,color:#000 style A1 fill:#E0E0E0,stroke:#333,stroke-width:2px,color:#000 style A2 fill:#E0E0E0,stroke:#333,stroke-width:2px,color:#000 style A3 fill:#E0E0E0,stroke:#333,stroke-width:2px,color:#000 style C1 fill:#FFFFFF,stroke:#333,stroke-width:1px,color:#000 style C2 fill:#FFFFFF,stroke:#333,stroke-width:1px,color:#000 style C3 fill:#FFFFFF,stroke:#333,stroke-width:1px,color:#000 %% Positioning classDef default text-align:center If we enforced all the common checks in each of the scripts, we would end up with redundant validations that are executed multiple times, leading to inefficiencies and increased transaction costs. [How can we do better?](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#how-can-we-do-better) -------------------------------------------------------------------------------------------------------------------------------- We can avoid redundant validations by centralizing the common checks in a single script, which is executed only once. This way, we can ensure that all the necessary validations are performed without duplicating the logic across multiple scripts. graph TB %% Layout subgraph for labels at top with horizontal alignment subgraph Checks[" Common Validations "] direction LR C1["C1: Check if owner signature exists"] ~~~ C2["C2: Check if not expired"] ~~~ C3["C3: Any other common checks"] end %% Add spacing WithdrawalCheck[" Check for Withdrawal Script Validating "] %% Organize layout with invisible connections for spacing Checks ~~~ WithdrawalCheck %% Connect validation flows Checks -.-> W WithdrawalCheck -.-> A1 WithdrawalCheck -.-> A2 WithdrawalCheck -.-> A3 WithdrawalCheck -.-> M %% Inputs on left with consistent arrows A1[Script Input 1] --> TX A2[Script Input 2] --> TX A3[Script Input 3] --> TX %% Transaction and other components TX((Transaction)) M[Token Minting] --> TX W[Withdrawal Script] --> TX %% Styling style TX fill:#FFA07A,stroke:#333,stroke-width:2px,color:#000 style M fill:#87CEEB,stroke:#333,stroke-width:2px,color:#000 style W fill:#DDA0DD,stroke:#333,stroke-width:2px,color:#000 style A1 fill:#E0E0E0,stroke:#333,stroke-width:2px,color:#000 style A2 fill:#E0E0E0,stroke:#333,stroke-width:2px,color:#000 style A3 fill:#E0E0E0,stroke:#333,stroke-width:2px,color:#000 style C1 fill:#FFFFFF,stroke:#333,stroke-width:1px,color:#000 style C2 fill:#FFFFFF,stroke:#333,stroke-width:1px,color:#000 style C3 fill:#FFFFFF,stroke:#333,stroke-width:1px,color:#000 style WithdrawalCheck fill:#FFFFFF,stroke:#333,stroke-width:1px,color:#000 %% Remove visible connections between check boxes linkStyle 0 stroke-width:0px linkStyle 1 stroke-width:0px linkStyle 2 stroke-width:0px In the architecture above, we have a single `WithdrawalCheck` script that performs the common validations. This script is executed once, and it checks the conditions for all the other scripts involved in the transaction. [Example: Continue from Lesson 4](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#example-continue-from-lesson-4) ---------------------------------------------------------------------------------------------------------------------------------------------------- Let's assume we have all the common logics checked in the lesson 4's withdrawal script. Rather than copy pasting all checks from withdrawal script to the spending and minting validators, we can do this instead to avoid redundant validations: ### [Spending](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#spending) use aiken/crypto.{ScriptHash} use cardano/transaction.{OutputReference, Transaction} use cocktail.{withdrawal_script_validated} validator spending_logics_delegated( delegated_withdrawal_script_hash: ScriptHash, ) { spend( _datum_opt: Option, _redeemer: Data, _input: OutputReference, tx: Transaction, ) { withdrawal_script_validated( tx.withdrawals, delegated_withdrawal_script_hash, ) } else(_) { fail @"unsupported purpose" } } ### [Minting](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#minting) use aiken/crypto.{ScriptHash} use cardano/assets.{PolicyId} use cardano/transaction.{Transaction} use cocktail.{withdrawal_script_validated} validator minting_logics_delegated( delegated_withdrawal_script_hash: ScriptHash, ) { mint(_redeemer: Data, _policy_id: PolicyId, tx: Transaction) { withdrawal_script_validated( tx.withdrawals, delegated_withdrawal_script_hash, ) } else(_) { fail @"unsupported purpose" } } [Why delegate to withdrawal script?](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#why-delegate-to-withdrawal-script) ---------------------------------------------------------------------------------------------------------------------------------------------------------- You might notice that we are delegating the validation to the withdrawal script. This is a common pattern in Cardano smart contracts, where a withdrawal script is used to perform common validations for multiple scripts. However, validation delegation can happen in different ways. For example, you can delegate all checks to a spending or minting validator as well, why would we prefer withdrawal script most of the time? ### [Clean trigger](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#clean-trigger) Recall that spending validation is triggered when a UTxO is spent, and minting validation is triggered when a token is minted. By delegating to a withdrawal script, we can ensure that the common validations are performed only once, regardless of how many scripts are involved in the transaction. And the withdrawal script can be triggered by withdrawing 0 lovelace, aka the community call it [`withdraw 0 trick`](https://aiken-lang.org/fundamentals/common-design-patterns#forwarding-validation--other-withdrawal-tricks) . It is a clean way to trigger the validation without affecting the transaction's logic or state. [Simplified Explanation](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#simplified-explanation) ----------------------------------------------------------------------------------------------------------------------------------- ### [Why Avoid Redundant Validation?](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#why-avoid-redundant-validation) When multiple scripts are involved in a transaction, repeating the same checks in each script leads to inefficiencies and higher costs. Instead, centralizing common checks in a single script ensures that validations are performed only once, saving resources and simplifying logic. ### [Centralized Validation](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#centralized-validation) By using a single script, such as a withdrawal script, we can delegate common checks to it. This script acts as a central validator for all other scripts in the transaction. ### [Example Flow](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#example-flow) Imagine a transaction with multiple scripts: * **Minting Script**: Handles token creation. * **Spending Script**: Manages UTxO spending. * **Withdrawal Script**: Performs common checks. Instead of duplicating checks in each script, the withdrawal script validates all common conditions, ensuring efficiency. ### [Delegation in Practice](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#delegation-in-practice) Here’s how delegation works: * **Spending Validator**: Delegates validation to the withdrawal script. * **Minting Validator**: Also delegates validation to the withdrawal script. This approach reduces redundancy and keeps the logic clean and maintainable. ### [Clean Trigger with Withdrawal Script](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#clean-trigger-with-withdrawal-script) The withdrawal script can be triggered using the [`withdraw 0 trick`](https://aiken-lang.org/fundamentals/common-design-patterns#forwarding-validation--other-withdrawal-tricks) , which allows validation without affecting the transaction state. This method is widely used for its simplicity and effectiveness. ### [Key Benefits](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#key-benefits) * **Efficiency**: Reduces redundant checks. * **Cost-Effective**: Lowers transaction fees. * **Maintainability**: Simplifies script logic. By following this pattern, developers can create smarter and more efficient Cardano contracts. [Contract Testing\ \ Testing Aiken smart contracts.](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing) [Interpreting Blueprint\ \ Understanding, interpreting, and translating Aiken blueprint into offchain code.](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint) ### On this page [A Transaction with Multiple Script Validation](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#a-transaction-with-multiple-script-validation) [How can we do better?](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#how-can-we-do-better) [Example: Continue from Lesson 4](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#example-continue-from-lesson-4) [Spending](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#spending) [Minting](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#minting) [Why delegate to withdrawal script?](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#why-delegate-to-withdrawal-script) [Clean trigger](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#clean-trigger) [Simplified Explanation](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#simplified-explanation) [Why Avoid Redundant Validation?](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#why-avoid-redundant-validation) [Centralized Validation](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#centralized-validation) [Example Flow](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#example-flow) [Delegation in Practice](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#delegation-in-practice) [Clean Trigger with Withdrawal Script](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#clean-trigger-with-withdrawal-script) [Key Benefits](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation#key-benefits) Ask AI --- # Aiken Contracts | Mesh SDK [Learn](https://meshjs.dev/resources) [Cardano Course](https://meshjs.dev/resources/cardano-course) [Lessons](https://meshjs.dev/resources/cardano-course/lessons) Aiken Contracts =============== Building Aiken smart contracts. Copy MarkdownOpen From lesson 3 to lesson 6, we will explore the core concepts of building Aiken smart contracts. Some materials are abstracted from [Andamio's AikenPBL](https://app.andamio.io/course/db22e013578fcead6c2fed5446d61891ad31f3cb4955e88d980107e7) . ### [Overview](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#overview) * **Hello Cardano Course**: Explains selected vital concepts of Aiken smart contract development. * **AikenPBL**: A complete end-to-end project-based learning course covering essential and basic concepts. Aiken smart contract development is a specialized field. To dive deeper and start a career as a Cardano on-chain developer, we recommend completing both courses. [System Setup](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#system-setup) ---------------------------------------------------------------------------------------------------- Before we begin, let's prepare our system for development. We will use Aiken for this course. Follow one of these guides to set up your system: 1. [Aiken Official Installation Guide](https://aiken-lang.org/installation-instructions) 2. [Andamio's AikenPBL Setup Guide](https://app.andamio.io/course/db22e013578fcead6c2fed5446d61891ad31f3cb4955e88d980107e7/101/lesson/1) ### [Set Up an Empty Aiken Project](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#set-up-an-empty-aiken-project) Run the following command to create a new Aiken project using Mesh's template: npx meshjs 03-aiken-contracts Select the `Aiken` template when prompted. ![Select at CLI](https://meshjs.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fmesh-aiken-template.61c7781d.png&w=3840&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) After installation, a new folder `03-aiken-contracts` will be created with the following structure: 03-aiken-contracts ├── aiken-workspace // Main Aiken project folder used in lessons └── mesh // Folder for equivalent Mesh off-chain code (not used in lessons) ### [Optional: Install Cardano-Bar](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#optional-install-cardano-bar) If you use VSCode as your IDE, install the [Cardano-Bar](https://marketplace.visualstudio.com/items/?itemName=sidan-lab.cardano-bar-vscode) extension for code snippets to follow the course more easily. ![Aiken script info](https://meshjs.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fcardano-bar.0958dfa0.png&w=3840&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) [Understanding Transaction Context](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#understanding-transaction-context) ---------------------------------------------------------------------------------------------------------------------------------------------- Cardano contracts are not like traditional smart contracts on other blockchains. They are more like a set of rules governing how transactions are validated. **Validator** is a better term to describe Cardano contracts. To build Cardano validators, we need to understand how transactions work. Refer to the [Aiken documentation](https://aiken-lang.github.io/stdlib/cardano/transaction.html#Transaction) for details on the `Transaction` structure. ![Aiken Tx](https://meshjs.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Faiken-tx.b39df177.png&w=3840&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) ### [Inputs & Outputs](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#inputs--outputs) All Cardano transactions must have inputs and outputs: * **Inputs**: UTXOs being spent in the transaction. * **Outputs**: UTXOs being created in the transaction. Refer to [Aiken documentation](https://aiken-lang.github.io/stdlib/cardano/transaction.html#Input) for types: ![Input](https://meshjs.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Finput.f2c81c6f.png&w=3840&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) ![Output](https://meshjs.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Foutput.2da1f68d.png&w=3840&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) Key concepts: * An input references an output of a previous transaction, identified by `output_reference`. * Validators can check: * If an input spends from a specific address. * If an input spends a specific asset. * If an output sends to a specific address. * If an output sends a specific asset. * If input/output datum contains specific information. ### [Reference Inputs](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#reference-inputs) `reference_inputs` in `Transaction` are inputs not spent but referenced in the validator. Useful for reading datum from a UTXO without spending it. ### [Mint](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#mint) `mint` in `Transaction` lists assets being minted or burned. Useful for creating or burning tokens. ### [Signatures](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#signatures) `extra_signatories` in `Transaction` lists public key hashes required to sign the transaction. Useful for enforcing specific users to sign. ### [Time](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#time) `validity_range` in `Transaction` specifies the range of slots the transaction is valid for. Useful for enforcing time locks. [Types of Scripts](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#types-of-scripts) ------------------------------------------------------------------------------------------------------------ Refer to [Aiken documentation](https://aiken-lang.github.io/stdlib/cardano/script_context.html#ScriptContext) for types of scripts in Cardano. Common types: * **Minting** * **Spending** * **Withdrawing** ![Aiken script info](https://meshjs.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fscriptinfo.a851ba5e.png&w=3840&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) ### [Minting Script](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#minting-script) Minting script validation logic is triggered when assets are minted or burned under the script's policy. Example: `/aiken-workspace/validators/mint.ak`: use cardano/assets.{PolicyId} use cardano/transaction.{Transaction, placeholder} validator always_succeed { mint(_redeemer: Data, _policy_id: PolicyId, _tx: Transaction) { True } else(_) { fail @"unsupported purpose" } } test test_always_succeed_minting_policy() { let data = Void always_succeed.mint(data, #"", placeholder) } This script compiles into a script with hash `def68337867cb4f1f95b6b811fedbfcdd7780d10a95cc072077088ea`, also called `policy Id`. It validates transactions minting or burning assets under this policy. #### [Parameters](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#parameters) Upgrade the script to allow minting/burning only when signed by a specific key: validator minting_policy(owner_vkey: VerificationKeyHash) { mint(_redeemer: Data, _policy_id: PolicyId, tx: Transaction) { key_signed(tx.extra_signatories, owner_vkey) } else(_) { fail @"unsupported purpose" } } * `owner_vkey`: Public key hash of the owner allowed to mint/burn assets. * Use `key_signed` from [vodka](https://github.com/sidan-lab/vodka) for validation. #### [Redeemer](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#redeemer) Extend the policy to include a redeemer specifying the transaction action (minting or burning): pub type MyRedeemer { MintToken BurnToken } validator minting_policy( owner_vkey: VerificationKeyHash, minting_deadline: Int, ) { mint(redeemer: MyRedeemer, policy_id: PolicyId, tx: Transaction) { when redeemer is { MintToken -> { let before_deadline = valid_before(tx.validity_range, minting_deadline) let is_owner_signed = key_signed(tx.extra_signatories, owner_vkey) before_deadline? && is_owner_signed? } BurnToken -> check_policy_only_burn(tx.mint, policy_id) } } else(_) { fail @"unsupported purpose" } } ### [Spending Script](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#spending-script) Spending script validation is triggered when a UTXO is spent in the transaction. Example: `/aiken-workspace/validators/spend.ak`: pub type Datum { oracle_nft: PolicyId, } validator hello_world { spend( datum_opt: Option, _redeemer: Data, _input: OutputReference, tx: Transaction, ) { when datum_opt is { Some(datum) -> when inputs_with_policy(tx.reference_inputs, datum.oracle_nft) is { [_ref_input] -> True _ -> False } None -> False } } else(_) { fail @"unsupported purpose" } } #### [Datum](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#datum) * `Datum`: Data attached to UTXOs at script addresses. * Common design pattern: Use an oracle NFT (state thread token) to ensure UTXO uniqueness. ### [Withdrawing Script](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#withdrawing-script) Withdrawal script validation is triggered when withdrawing from a reward account. Example: `/aiken-workspace/validators/withdraw.ak`: use aiken/crypto.{VerificationKeyHash} use cardano/address.{Credential, Script} use cardano/certificate.{Certificate} use cardano/transaction.{Transaction, placeholder} validator always_succeed(_key_hash: VerificationKeyHash) { withdraw(_redeemer: Data, _credential: Credential, _tx: Transaction) { True } publish(_redeemer: Data, _certificate: Certificate, _tx: Transaction) { True } else(_) { fail @"unsupported purpose" } } test test_always_succeed_withdrawal_policy() { let data = Void always_succeed.withdraw("", data, Script(#""), placeholder) } #### [Handling Publishing](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#handling-publishing) All withdrawal scripts must be registered on-chain before they can be used. This is done by publishing a registration certificate with the script hash as the stake credential. The publishing of the script is also validated by the `publish` function in the withdrawal script, which is triggered whenever the current withdrawal script is being registered or deregistered. #### [When withdrawal script is used?](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#when-withdrawal-script-is-used) For most Cardano users, we would just use a normal payment key to stake and withdraw rewards. However, it is very popular for Cardano DApps to build withdrawal scripts to enhance the efficiency of validation. We will cover this trick in [lesson 5](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation) . [Multi-signature Transactions\ \ Learn to build multi-signature transactions on Cardano.](https://meshjs.dev/resources/cardano-course/lessons/02-multisig) [Contract Testing\ \ Testing Aiken smart contracts.](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing) ### On this page [Overview](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#overview) [System Setup](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#system-setup) [Set Up an Empty Aiken Project](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#set-up-an-empty-aiken-project) [Optional: Install Cardano-Bar](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#optional-install-cardano-bar) [Understanding Transaction Context](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#understanding-transaction-context) [Inputs & Outputs](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#inputs--outputs) [Reference Inputs](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#reference-inputs) [Mint](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#mint) [Signatures](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#signatures) [Time](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#time) [Types of Scripts](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#types-of-scripts) [Minting Script](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#minting-script) [Parameters](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#parameters) [Redeemer](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#redeemer) [Spending Script](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#spending-script) [Datum](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#datum) [Withdrawing Script](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#withdrawing-script) [Handling Publishing](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#handling-publishing) [When withdrawal script is used?](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts#when-withdrawal-script-is-used) Ask AI --- # Interpreting Blueprint | Mesh SDK [Learn](https://meshjs.dev/resources) [Cardano Course](https://meshjs.dev/resources/cardano-course) [Lessons](https://meshjs.dev/resources/cardano-course/lessons) Interpreting Blueprint ====================== Understanding, interpreting, and translating Aiken blueprint into offchain code. Copy MarkdownOpen In this lesson, we will explore how to interpret the blueprint generated from onchain code development and translate it into offchain code. This blueprint serves as a bridge between the onchain and offchain worlds, enabling seamless interaction with smart contracts. [What is a Blueprint?](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#what-is-a-blueprint) -------------------------------------------------------------------------------------------------------------------------- A blueprint is a standardized JSON file introduced by [CIP57](https://cips.cardano.org/cip/CIP-57) . It is the ultimate output of Cardano smart contract development and contains essential information about the contract. Regardless of the development method, the blueprint includes: * **`preamble`**: Meta-information about the contract. * **`validators`**: Named validators with type definitions and compiled code. * **`definitions`**: A registry of reusable definitions across the specification. ### [Generating a Blueprint](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#generating-a-blueprint) To generate a blueprint using Aiken, follow these steps: 1. Build your contracts by running: aiken build 2. Locate the blueprint in the `plutus.json` file at the root of your project. [Understanding the Blueprint](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#understanding-the-blueprint) ----------------------------------------------------------------------------------------------------------------------------------------- ### [`preamble`](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#preamble) The `preamble` section contains meta-information about the contract, such as its name, description, version, and Plutus version. The Plutus version is particularly important for preparing offchain code. Example: { "preamble": { "title": "meshsdk/aiken-template", "description": "Aiken contracts for project 'meshsdk/aiken-template'", "version": "0.0.0", "plutusVersion": "v3", // Key information for offchain code "compiler": { "name": "Aiken", "version": "v1.1.16+23061c0" }, "license": "Apache-2.0" } } ### [`validators`](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#validators) The `validators` section includes type information for `datum`, `redeemer`, and `parameters`, along with the compiled validator code. These definitions may reference reusable types in the `definitions` section. Example: { "title": "spend.spending_logics_delegated.spend", "datum": { "title": "_datum_opt", "schema": { "$ref": "#/definitions/Data" } }, "redeemer": { "title": "_redeemer", "schema": { "$ref": "#/definitions/Data" } }, "parameters": [\ {\ "title": "delegated_withdrawal_script_hash",\ "schema": {\ "$ref": "#/definitions/aiken~1crypto~1ScriptHash"\ }\ }\ ], "compiledCode": "58ac010100229800aba2aba1aba0aab9faab9eaab9dab9a9bae0024888888896600264646644b30013370e900118039baa001899914c004c03400a601a601c0052259800800c528456600266ebc00cc02cc03c00629462660040046020002805100d2444660020026eacc040c044c044c044c044c044c044c034dd518080048c020dd500099ba548008cc028dd4802a5eb822c8030c024004c024c028004c024004c010dd5004c52689b2b200401", "hash": "9c9666ddc12fc42f0151cd029c150c7d410ede9fe3885c248c8c26a0" } Notice the `spend.spending_logics_delegated.else` compiles to the same hash as the `spend.spending_logics_delegated.spend` function. This is because the `else` branch is not executed in this case, but it is still part of the validator code. So when we are building multiple purposes validators, they will compile to the same hash, i.e. same script, which can be utilitized in certain architectures. { "title": "spend.spending_logics_delegated.else", "redeemer": { "schema": {} }, "parameters": [\ {\ "title": "delegated_withdrawal_script_hash",\ "schema": {\ "$ref": "#/definitions/aiken~1crypto~1ScriptHash"\ }\ }\ ], "compiledCode": "58ac010100229800aba2aba1aba0aab9faab9eaab9dab9a9bae0024888888896600264646644b30013370e900118039baa001899914c004c03400a601a601c0052259800800c528456600266ebc00cc02cc03c00629462660040046020002805100d2444660020026eacc040c044c044c044c044c044c044c034dd518080048c020dd500099ba548008cc028dd4802a5eb822c8030c024004c024c028004c024004c010dd5004c52689b2b200401", "hash": "9c9666ddc12fc42f0151cd029c150c7d410ede9fe3885c248c8c26a0" } ### [`definitions`](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#definitions) The `definitions` section provides reusable type definitions referenced in the `validators` section. This is where you can find schemas for types used in the contract. Example: { "definitions": { "Data": { "title": "Data", "description": "Any Plutus data." }, "aiken/crypto/ScriptHash": { "title": "ScriptHash", "dataType": "bytes" }, "cardano/assets/PolicyId": { "title": "PolicyId", "dataType": "bytes" }, "withdraw/MyRedeemer": { "title": "MyRedeemer", "anyOf": [\ {\ "title": "ContinueCounting",\ "dataType": "constructor",\ "index": 0,\ "fields": []\ },\ {\ "title": "StopCounting",\ "dataType": "constructor",\ "index": 1,\ "fields": []\ }\ ] } } } [Automating Offchain Code Generation](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#automating-offchain-code-generation) --------------------------------------------------------------------------------------------------------------------------------------------------------- Translating the blueprint into offchain code manually can be time-consuming. Fortunately, the Mesh community has developed a tool in the [`Cardano Bar VSCode Extension`](https://marketplace.visualstudio.com/items/?itemName=sidan-lab.cardano-bar-vscode) to automate this process. In Mesh community, we have developed a tool in [`Cardano Bar VSCode Extension`](https://marketplace.visualstudio.com/items/?itemName=sidan-lab.cardano-bar-vscode) that can automate this process. By running the following below steps, you can generate the offchain code that corresponds to the blueprint: 1. Create a new TypeScript file, e.g., `offchain.ts`. 2. Open the command palette in VSCode (Ctrl+Shift+P or Cmd+Shift+P). 3. Type `Parse blueprint to Typescript - Mesh` and select it. ![VSCode command palette](https://meshjs.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fvscode-command.54d91255.png&w=3840&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) 4. Select the `plutus.json` file that contains the blueprint. ![VSCode command palette](https://meshjs.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fselect-blueprint.d509cbfb.png&w=3840&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) The generated `offchain.ts` file will include all necessary functions to interact with the onchain code, such as spending, minting, and querying the contract. For more details, refer to the [Mesh SDK documentation](https://meshjs.dev/apis/utilities/blueprints) . [Conclusion](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#conclusion) ------------------------------------------------------------------------------------------------------- Understanding and interpreting the blueprint is a vital skill for Cardano developers. With tools like the Mesh `Blueprint` class, you can streamline the process and focus on building robust applications. [Avoid Redundant Validation\ \ Key contract best practice - reduce redundant validation logics being run onchain.](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation) [Vesting Contract\ \ Vesting smart contract that locks up funds and allows the beneficiary to withdraw the funds after the lockup period.](https://meshjs.dev/resources/cardano-course/lessons/07-vesting) ### On this page [What is a Blueprint?](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#what-is-a-blueprint) [Generating a Blueprint](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#generating-a-blueprint) [Understanding the Blueprint](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#understanding-the-blueprint) [`preamble`](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#preamble) [`validators`](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#validators) [`definitions`](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#definitions) [Automating Offchain Code Generation](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#automating-offchain-code-generation) [Conclusion](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint#conclusion) Ask AI --- # Getting Started | Mesh SDK [Midnight](https://meshjs.dev/midnight) Midnight Setup Getting Started =============== Install and set up @meshsdk/midnight-setup for building zero-knowledge privacy dApps on Midnight Network Copy MarkdownOpen This guide will help you get started with building dApps on Midnight Network using the `@meshsdk/midnight-setup` package. Midnight Network is a zero-knowledge privacy network that enables confidential smart contracts and transactions. [Installation](https://meshjs.dev/midnight/midnight-setup/getting-started#installation) ---------------------------------------------------------------------------------------- Install the Midnight setup package using your preferred package manager: # Using npm npm install @meshsdk/midnight-setup # Using yarn yarn add @meshsdk/midnight-setup [Quick Start](https://meshjs.dev/midnight/midnight-setup/getting-started#quick-start) -------------------------------------------------------------------------------------- ### [Basic Usage](https://meshjs.dev/midnight/midnight-setup/getting-started#basic-usage) import { MidnightSetupAPI } from '@meshsdk/midnight-setup'; // Deploy a new contract const api = await MidnightSetupAPI.deployContract(providers, contractInstance); // Join an existing contract const api = await MidnightSetupAPI.joinContract(providers, contractInstance, contractAddress); // Get contract state const state = await api.getContractState(); // Get ledger state const ledgerState = await api.getLedgerState(); [What's Included](https://meshjs.dev/midnight/midnight-setup/getting-started#whats-included) --------------------------------------------------------------------------------------------- This monorepo contains everything you need to build Midnight Network dApps: Example repository: [midnight-setup](https://github.com/MeshJS/midnight-setup) * **@meshsdk/midnight-setup** - Main npm package with API and types * **packages/ui** - Example React application * **packages/cli** - Command-line tools * **packages/api** - Core API implementation * \*\*packages/contract/ - Compact contracts [Project Structure](https://meshjs.dev/midnight/midnight-setup/getting-started#project-structure) -------------------------------------------------------------------------------------------------- ├── packages/ │ ├── api/ # Core API implementation │ ├── ui/ # React example app │ └── cli/ # Command-line tools │ └── contract/ # Compact contracts ├── compact/ # Smart contract source └── README.md [Key Features](https://meshjs.dev/midnight/midnight-setup/getting-started#key-features) ---------------------------------------------------------------------------------------- * **Zero-knowledge privacy** - Built for Midnight Network * **TypeScript support** - Full type safety * **React hooks** - Easy integration * **Wallet integration** - Lace Beta Wallet support * **CLI tools** - Development utilities * **Compact contract** - Compact contract integration [Next Steps](https://meshjs.dev/midnight/midnight-setup/getting-started#next-steps) ------------------------------------------------------------------------------------ * Learn about the [Core API Methods](https://meshjs.dev/midnight/api) * Set up [Lace Wallet Integration](https://meshjs.dev/midnight/wallet) * Explore [Integration Examples](https://meshjs.dev/midnight/examples) [Resources](https://meshjs.dev/midnight/midnight-setup/getting-started#resources) ---------------------------------------------------------------------------------- * [Midnight Network Documentation](https://docs.midnight.network/) * [Mesh SDK Documentation](https://midnight.meshjs.dev/en) * [Lace Beta Wallet](https://chromewebstore.google.com/detail/lace-midnight-preview/hgeekaiplokcnmakghbdfbgnlfheichg) [Overview\ \ Complete development setup for building Midnight Network dApps](https://meshjs.dev/midnight/midnight-setup) [Core API Methods\ \ Complete reference for MidnightSetupAPI methods and provider setup](https://meshjs.dev/midnight/midnight-setup/api) ### On this page [Installation](https://meshjs.dev/midnight/midnight-setup/getting-started#installation) [Quick Start](https://meshjs.dev/midnight/midnight-setup/getting-started#quick-start) [Basic Usage](https://meshjs.dev/midnight/midnight-setup/getting-started#basic-usage) [What's Included](https://meshjs.dev/midnight/midnight-setup/getting-started#whats-included) [Project Structure](https://meshjs.dev/midnight/midnight-setup/getting-started#project-structure) [Key Features](https://meshjs.dev/midnight/midnight-setup/getting-started#key-features) [Next Steps](https://meshjs.dev/midnight/midnight-setup/getting-started#next-steps) [Resources](https://meshjs.dev/midnight/midnight-setup/getting-started#resources) Ask AI --- # Vesting Contract | Mesh SDK [Learn](https://meshjs.dev/resources) [Cardano Course](https://meshjs.dev/resources/cardano-course) [Lessons](https://meshjs.dev/resources/cardano-course/lessons) Vesting Contract ================ Vesting smart contract that locks up funds and allows the beneficiary to withdraw the funds after the lockup period. Copy MarkdownOpen Vesting contracts are a type of smart contract designed to lock funds for a specified period, ensuring that only the designated beneficiary can withdraw them after the lockup period ends. This lesson will guide you through the process of understanding, implementing, and interacting with a vesting contract on Cardano. [Overview](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#overview) ------------------------------------------------------------------------------------ ### [What is a Vesting Contract?](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#what-is-a-vesting-contract) A vesting contract locks funds and allows the beneficiary to withdraw them after a specified lockup period. It ensures security and control over fund distribution. ### [Key Features:](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#key-features) * **Lockup Period**: Funds are locked until a specific timestamp. * **Owner and Beneficiary**: The owner deposits funds, and the beneficiary withdraws them after the lockup period. [Smart Contract Details](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#smart-contract-details) ---------------------------------------------------------------------------------------------------------------- ### [Datum Definition](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#datum-definition) The datum serves as the configuration for the vesting contract. It includes: * **`lock_until`**: The timestamp until which funds are locked. * **`owner`**: Credentials of the fund owner. * **`beneficiary`**: Credentials of the beneficiary. First, we define the datum's shape, as this datum serves as configuration and contains the different parameters of our vesting operation. pub type VestingDatum { /// POSIX time in milliseconds, e.g. 1672843961000 lock_until: Int, /// Owner's credentials owner: ByteArray, /// Beneficiary's credentials beneficiary: ByteArray, } This datum can be found in `aiken-vesting/aiken-workspace/lib/vesting/types.ak`. Next, we define the spend validator. validator vesting { spend( datum_opt: Option, _redeemer: Data, _input: OutputReference, tx: Transaction, ) { // In principle, scripts can be used for different purpose (e.g. minting // assets). Here we make sure it's only used when 'spending' from a eUTxO expect Some(datum) = datum_opt or { key_signed(tx.extra_signatories, datum.owner), and { key_signed(tx.extra_signatories, datum.beneficiary), valid_after(tx.validity_range, datum.lock_until), }, } } else(_) { fail } } In this example, we define a `vesting` validator that ensures the following conditions are met: * The transaction must be signed by owner Or: * The transaction must be signed by beneficiary * The transaction must be valid after the lockup period ### [How it works](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#how-it-works) The owner of the funds deposits the funds into the vesting contract. The funds are locked up until the lockup period expires. Transactions can include validity intervals that specify when the transaction is valid, both from and until a certain time. The ledger verifies these validity bounds before executing a script and will only proceed if they are legitimate. This approach allows scripts to incorporate a sense of time while maintaining determinism within the script's context. For instance, if a transaction has a lower bound `A`, we can infer that the current time is at least `A`. It's important to note that since we don't control the upper bound, a transaction might be executed even 30 years after the vesting delay. However, from the script's perspective, this is entirely acceptable. The beneficiary can withdraw the funds after the lockup period expires. The beneficiary can also be different from the owner of the funds. ### [Testing](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#testing) To test the vesting contract, we have provided the a comphrehensive test script,you can run tests with `aiken check`. The test script includes the following test cases: * success unlocking * success unlocking with only owner signature * success unlocking with beneficiary signature and time passed * fail unlocking with only beneficiary signature * fail unlocking with only time passed We recommend you to check out [`vesting.ak`](https://github.com/cardanobuilders/cardanobuilders.github.io/blob/main/codes/course-hello-cardano/03-vesting/src/aiken-workspace/validators/vesting.ak) to learn more. ### [Compile and build script](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#compile-and-build-script) To compile the script, run the following command: aiken build This command will generate a CIP-0057 Plutus blueprint, which you can find in [`plutus.json`](https://github.com/cardanobuilders/cardanobuilders.github.io/blob/main/codes/course-hello-cardano/03-vesting/src/aiken-workspace/plutus.json) . [Deposit funds](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#deposit-funds) ---------------------------------------------------------------------------------------------- First, the owner can deposit funds into the vesting contract. The owner can specify the lockup period. const assets: Asset[] = [\ {\ unit: "lovelace",\ quantity: "10000000",\ },\ ]; const lockUntilTimeStamp = new Date(); lockUntilTimeStamp.setMinutes(lockUntilTimeStamp.getMinutes() + 1); In this example, we deposit 10 ADA into the vesting contract. The funds are locked up for 1 minute, and the beneficiary is specified. // app wallet const wallet = new MeshWallet({ networkId: 0, key: { type: "mnemonic", words: appWallet, }, fetcher: provider, submitter: provider, }); const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const { pubKeyHash: ownerPubKeyHash } = deserializeAddress(changeAddress); const { pubKeyHash: beneficiaryPubKeyHash } = deserializeAddress(beneficiaryAddress); For this tutorial, we use another wallet to fund the deposit. We get the UTXOs from the app wallet and the change address. We also need both the owner and beneficiary's public key hashes. We can get the public key hash from the address using `deserializeAddress`. const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true, }); const unsignedTx = await txBuilder .txOut(script.address, amount) .txOutInlineDatumValue( mConStr0([lockUntilTimeStampMs, ownerPubKeyHash, beneficiaryPubKeyHash]) ) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); We construct the transaction to deposit the funds into the vesting contract. We specify the script address of the vesting contract, the amount to deposit, and the lockup period, owner, and beneficiary of the funds. Finally, we sign and submit the transaction. const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); Upon successful execution, you will receive a transaction hash. Save this transaction hash for withdrawing the funds. Example of a [successful deposit transaction](https://preprod.cardanoscan.io/transaction/556f2bfcd447e146509996343178c046b1b9ad4ac091a7a32f85ae206345e925) . [Withdraw funds](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#withdraw-funds) ------------------------------------------------------------------------------------------------ After the lockup period expires, the beneficiary can withdraw the funds from the vesting contract. The owner can also withdraw the funds from the vesting contract. First, let's look for the UTxOs containing the funds locked in the vesting contract. const txHashFromDesposit = "556f2bfcd447e146509996343178c046b1b9ad4ac091a7a32f85ae206345e925"; const utxos = await provider.fetchUTxOs(txHash); const vestingUtxo = utxos[0]; We fetch the UTxOs containing the funds locked in the vesting contract. We specify the transaction hash of the deposit transaction. Like before, we prepare a few variables to be used in the transaction. We get the wallet address and the UTXOs of the wallet. We also get the script address of the vesting contract, to send the funds to the script address. We also get the owner and beneficiary public key hashes. Next, we prepare the datum and the slot number to set the transaction valid interval to be valid only after the slot. const datum = deserializeDatum(vestingUtxo.output.plutusData!); const invalidBefore = unixTimeToEnclosingSlot( Math.min(datum.fields[0].int as number, Date.now() - 15000), SLOT_CONFIG_NETWORK.preprod ) + 1; We prepare the datum and the slot number to set the transaction valid interval to be valid only after the slot. We get the lockup period from the datum and set the transaction valid interval to be valid only after the lockup period. Next, we construct the transaction to withdraw the funds from the vesting contract. const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true, }); const unsignedTx = await txBuilder .spendingPlutusScript("V3") .txIn( vestingUtxo.input.txHash, vestingUtxo.input.outputIndex, vestingUtxo.output.amount, script.address ) .spendingReferenceTxInInlineDatumPresent() .spendingReferenceTxInRedeemerValue("") .txInScript(script.cbor) .txOut(walletAddress, []) .txInCollateral( collateralInput.txHash, collateralInput.outputIndex, collateralOutput.amount, collateralOutput.address ) .invalidBefore(invalidBefore) .requiredSignerHash(pubKeyHash) .changeAddress(walletAddress) .selectUtxosFrom(inputUtxos) .complete(); we construct the transaction to withdraw the funds from the vesting contract. We specify the UTxO containing the funds locked in the vesting contract, the script address of the vesting contract, the wallet address to send the funds to, and the transaction valid interval. Finally, we sign and submit the transaction. Example of a [successful withdraw transaction](https://preprod.cardanoscan.io/transaction/13d6b2258680bbdf08f50a3bbc03e7ed674f5614844ce773fc191c9582282b04) . [Source code](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#source-code) ------------------------------------------------------------------------------------------ The source code for this lesson is available on [GitHub](https://github.com/cardanobuilders/cardanobuilders.github.io/tree/main/codes/course-hello-cardano/03-vesting) . [Challenge](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#challenge) -------------------------------------------------------------------------------------- Change the vesting contract to gradual vesting schedule where instead of a single unlock date, implement gradual vesting where funds are released on a schedule. Or add a cliff feature where the beneficiary must wait for a minimum period before any tokens become available. [Interpreting Blueprint\ \ Understanding, interpreting, and translating Aiken blueprint into offchain code.](https://meshjs.dev/resources/cardano-course/lessons/06-interpreting-blueprint) [Plutus NFT Contract\ \ Plutus NFT smart contract enforces non-fungibility and uniqueness of the NFT under the same policy.](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft) ### On this page [Overview](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#overview) [What is a Vesting Contract?](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#what-is-a-vesting-contract) [Key Features:](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#key-features) [Smart Contract Details](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#smart-contract-details) [Datum Definition](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#datum-definition) [How it works](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#how-it-works) [Testing](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#testing) [Compile and build script](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#compile-and-build-script) [Deposit funds](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#deposit-funds) [Withdraw funds](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#withdraw-funds) [Source code](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#source-code) [Challenge](https://meshjs.dev/resources/cardano-course/lessons/07-vesting#challenge) Ask AI --- # Multi-signature Transactions | Mesh SDK [Learn](https://meshjs.dev/resources) [Cardano Course](https://meshjs.dev/resources/cardano-course) [Lessons](https://meshjs.dev/resources/cardano-course/lessons) Multi-signature Transactions ============================ Learn to build multi-signature transactions on Cardano. Copy MarkdownOpen A multi-signature (multi-sig) transaction requires more than one user to sign a transaction before it is broadcast on the blockchain. Think of it like a joint savings account where both parties must approve spending. Multi-sig transactions can include two or more required signers, which can be wallets or scripts. In this lesson, you'll learn how to: * Build multi-signature transactions to mint a token. * Set up a NextJS app with a simple web interface to interact with the Cardano blockchain. [System setup](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#system-setup) --------------------------------------------------------------------------------------------- ### [Download CIP30 Wallet Extension](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#download-cip30-wallet-extension) To interact with the blockchain, you'll need a wallet extension that supports the CIP30 standard. Choose and download one [here](https://developers.cardano.org/showcase/?tags=wallet) . After downloading the wallet, restore it using the seed phrase you created in the previous lesson. ### [Set Up NextJS and Mesh](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#set-up-nextjs-and-mesh) Open your terminal and run the following command to create a new NextJS application: npx create-next-app@latest --typescript mesh-multisig Follow the prompts: Need to install the following packages: Ok to proceed? (y) ✔ Would you like to use ESLint? … Yes ✔ Would you like to use Tailwind CSS? … Yes ✔ Would you like your code inside a `src/` directory? … Yes ✔ Would you like to use App Router? … No ✔ Would you like to use Turbopack for next dev? … No ✔ Would you like to customize the import alias (@/* by default)? … No Navigate to the newly created folder: cd mesh-multisig Install the latest version of Mesh: npm install @meshsdk/core @meshsdk/react ### [Add MeshProvider](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#add-meshprovider) To use Mesh React, wrap your application with the `MeshProvider` component. Open the `src/app/layout.tsx` file and add: import "@/styles/globals.css"; import type { AppProps } from "next/app"; import "@meshsdk/react/styles.css"; import { MeshProvider } from "@meshsdk/react"; export default function App({ Component, pageProps }: AppProps) { return ( ); } ### [Add CardanoWallet Component](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#add-cardanowallet-component) Add a wallet React component to connect to the wallet and interact with the blockchain. Open the `src/pages/index.tsx` file, delete the existing code, and replace it with: import { CardanoWallet, useWallet } from "@meshsdk/react"; export default function Home() { const { wallet, connected } = useWallet(); return (
); } Start the development server: npm run dev Visit [](http://localhost:3000/) [http://localhost:3000](http://localhost:3000/) to view your application. Press **CTRL+C** to stop the server. You should see a "Connect Wallet" component. Try connecting to your wallet. [Minting Script](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#minting-script) ------------------------------------------------------------------------------------------------- In this section, you'll create a minting script to mint a token using a multi-signature transaction. ### [Define the Minting Script](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#define-the-minting-script) Set up constants for the minting script: const provider = new BlockfrostProvider("YOUR_KEY_HERE"); const demoAssetMetadata = { name: "Mesh Token", image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "This NFT was minted by Mesh (https://meshjs.dev/).", }; const mintingWallet = ["your", "mnemonic", "...", "here"]; * Replace `YOUR_KEY_HERE` with your Blockfrost API key. * Define asset metadata in `demoAssetMetadata`. * Use a mnemonic for the minting wallet. ### [Create Minting Application Wallet](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#create-minting-application-wallet) Create a function to build the minting transaction: async function buildMintTx(inputs: UTxO[], changeAddress: string) { const wallet = new MeshWallet({ networkId: 0, key: { type: "mnemonic", words: mintingWallet, }, }); const { pubKeyHash: keyHash } = deserializeAddress( await wallet.getChangeAddress() ); } * `inputs`: UTxOs from your wallet to pay minting fees. * Initialize the wallet with the mnemonic. * Derive the `pubKeyHash` for the minting script. ### [Create Native Script](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#create-native-script) Define the native script: const nativeScript: NativeScript = { type: "all", scripts: [\ {\ type: "before",\ slot: "99999999",\ },\ {\ type: "sig",\ keyHash: keyHash,\ },\ ], }; const forgingScript = ForgeScript.fromNativeScript(nativeScript); * `nativeScript`: Parameters for the script. * `ForgeScript.fromNativeScript`: Create the forging script. ### [Define Asset Metadata](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#define-asset-metadata) Set up asset metadata: const policyId = resolveScriptHash(forgingScript); const tokenName = "MeshToken"; const tokenNameHex = stringToHex(tokenName); const metadata = { [policyId]: { [tokenName]: { ...demoAssetMetadata } } }; * `policyId`: Derived from the forging script. * `tokenName`: Name of the token. * `metadata`: Asset metadata. ### [Create Transaction](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#create-transaction) Build the minting transaction: const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true, }); const unsignedTx = await txBuilder .mint("1", policyId, tokenNameHex) .mintingScript(forgingScript) .metadataValue(721, metadata) .changeAddress(changeAddress) .invalidHereafter(99999999) .requiredSignerHash(keyHash) .selectUtxosFrom(inputs) .complete(); * `mint`: Add token details. * `mintingScript`: Attach the minting script. * `metadataValue`: Add asset metadata. * `changeAddress`: Specify the change address. * `invalidHereafter`: Set transaction expiry. * `selectUtxosFrom`: Use UTxOs for fees. * `requiredSignerHash` to declare that the minter wallet pub key hash is required. * `complete`: Finalize the transaction. ### [Sign the Transaction](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#sign-the-transaction) Sign the transaction with the minting wallet: const signedTx = await wallet.signTx(unsignedTx, true); ### [Source code](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#source-code) Here is the complete code for building the minting transaction: async function buildMintTx(inputs: UTxO[], changeAddress: string) { // minting wallet const wallet = new MeshWallet({ networkId: 0, key: { type: "mnemonic", words: mintingWallet, }, }); const { pubKeyHash: keyHash } = deserializeAddress( await wallet.getChangeAddress() ); // create minting script const nativeScript: NativeScript = { type: "all", scripts: [\ {\ type: "before",\ slot: "99999999",\ },\ {\ type: "sig",\ keyHash: keyHash,\ },\ ], }; const forgingScript = ForgeScript.fromNativeScript(nativeScript); // create metadata const policyId = resolveScriptHash(forgingScript); const tokenName = "MeshToken"; const tokenNameHex = stringToHex(tokenName); const metadata = { [policyId]: { [tokenName]: { ...demoAssetMetadata } } }; // create transaction const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true, }); const unsignedTx = await txBuilder .mint("1", policyId, tokenNameHex) .mintingScript(forgingScript) .metadataValue(721, metadata) .changeAddress(changeAddress) .invalidHereafter(99999999) .requiredSignerHash(keyHash) .selectUtxosFrom(inputs) .complete(); const signedTx = await wallet.signTx(unsignedTx, true); return signedTx; } [Execute the transaction](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#execute-the-transaction) ------------------------------------------------------------------------------------------------------------------- Now that we have the minting transaction, we can execute it. async function mint() { if (connected) { const inputs = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const tx = await buildMintTx(inputs, changeAddress); const signedTx = await wallet.signTx(tx, true); const txHash = await wallet.submitTx(signedTx); console.log("Transaction hash:", txHash); } } * Check wallet connection. * Get UTxOs and change address. * Build, sign, and submit the transaction. [Source code](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#source-code-1) --------------------------------------------------------------------------------------------- The source code for this lesson is available on [GitHub](https://github.com/cardanobuilders/cardanobuilders.github.io/tree/main/codes/course-hello-cardano/02-multisig) . [Challenge](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#challenge) --------------------------------------------------------------------------------------- Create a multi-signature wallet requiring 2 out of 3 signers to approve a transaction. Build and sign a transaction with two signers, submit it, and verify success. [Hello World\ \ Install Mesh SDK and learn how to send assets using the Mesh wallet.](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace) [Aiken Contracts\ \ Building Aiken smart contracts.](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts) ### On this page [System setup](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#system-setup) [Download CIP30 Wallet Extension](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#download-cip30-wallet-extension) [Set Up NextJS and Mesh](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#set-up-nextjs-and-mesh) [Add MeshProvider](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#add-meshprovider) [Add CardanoWallet Component](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#add-cardanowallet-component) [Minting Script](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#minting-script) [Define the Minting Script](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#define-the-minting-script) [Create Minting Application Wallet](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#create-minting-application-wallet) [Create Native Script](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#create-native-script) [Define Asset Metadata](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#define-asset-metadata) [Create Transaction](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#create-transaction) [Sign the Transaction](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#sign-the-transaction) [Source code](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#source-code) [Execute the transaction](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#execute-the-transaction) [Source code](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#source-code-1) [Challenge](https://meshjs.dev/resources/cardano-course/lessons/02-multisig#challenge) Ask AI --- # Hello World | Mesh SDK [Learn](https://meshjs.dev/resources) [Cardano Course](https://meshjs.dev/resources/cardano-course) [Lessons](https://meshjs.dev/resources/cardano-course/lessons) Hello World =========== Install Mesh SDK and learn how to send assets using the Mesh wallet. Copy MarkdownOpen Welcome to the first lesson of the Cardano Application Development Course! In this session, you'll set up the [Mesh SDK](https://meshjs.dev/) and learn how to create a wallet using `MeshWallet` and send assets using `MeshTxBuilder`. [System setup](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#system-setup) --------------------------------------------------------------------------------------------------------- Before we begin, let's prepare our system for development. We will be using Node.js v24+ in this course. We recommend [nvm to manage your node versions](https://github.com/nvm-sh/nvm) . ### [Create a package.json file](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#create-a-packagejson-file) First, create a new `package.json` file in the root of your project with the following content: { "type": "module", "dependencies": {}, "scripts": {} } ### [Install the necessary packages](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#install-the-necessary-packages) Open your terminal and run these commands to install the MeshSDK: npm install npm install @meshsdk/core Here's how your `package.json` file should look after installing the package: { "type": "module", "dependencies": { "@meshsdk/core": "^1.9.0", }, "scripts": {} } * `@meshsdk/core`: Core functionality for network interactions, wallets, and transactions. [Create a wallet](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#create-a-wallet) --------------------------------------------------------------------------------------------------------------- We will use [`MeshWallet`](https://meshjs.dev/apis/wallets/meshwallet) . This class provides methods to create a new wallet, generate mnemonic phrases, and get the wallet address. ### [Generate mnemonic phrases](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#generate-mnemonic-phrases) To create a new wallet, we need to generate a mnemonic phrase. A mnemonic phrase is a set of words that can be used to recover your wallet. It is important to keep your mnemonic phrase safe and secure, as it can be used to access your funds. To create a new wallet mnemonic, do the following: import { MeshWallet } from "@meshsdk/core"; // Generate new mnemonic phrases for your wallet const mnemonic = MeshWallet.brew(); console.log("Your mnemonic phrases are:", mnemonic); * Use the `brew` method to generate a new mnemonic phrase. ### [Initialize the wallet and get the wallet address](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#initialize-the-wallet-and-get-the-wallet-address) Now that we have generated a mnemonic phrase, we can initialize the wallet with it. The `MeshWallet` class provides a method to create a new wallet using the mnemonic phrase. // Initialize the wallet with a mnemonic key const wallet = new MeshWallet({ networkId: 0, // preprod testnet key: { type: "mnemonic", words: mnemonic as string[], }, }); // Get the wallet address const address = await wallet.getChangeAddress(); console.log("Your wallet address is:", address); * `networkId`: Specify the network, 0 for preprod testnet. * `key`: Specify the key type and mnemonic phrases. * `getChangeAddress`: Method to get the wallet address. ### [Run the code](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#run-the-code) Here is the source code. Create a new file `mnemonic.ts` and copy the code into it: import { MeshWallet } from "@meshsdk/core"; // Generate new mnemonic phrases for your wallet const mnemonic = MeshWallet.brew(); console.log("Your mnemonic phrases are:", mnemonic); // Initialize the wallet with a mnemonic key const wallet = new MeshWallet({ networkId: 0, // preprod testnet key: { type: "mnemonic", words: mnemonic as string[], }, }); // Get the wallet address const address = await wallet.getChangeAddress(); console.log("Your wallet address is:", address); Update the `package.json` file to add a script to run the code: { "type": "module", "dependencies": { "@meshsdk/core": "^1.9.0", }, "scripts": { "mnemonic": "node mnemonic.ts" } } Run the script: npm run mnemonic This will generate a new mnemonic phrase and wallet address for you. The output will look something like this: > mnemonic > node mnemonic.ts Your mnemonic phrases are: [\ 'access', 'spawn', 'taxi',\ 'prefer', 'fortune', 'sword',\ 'nerve', 'price', 'valid',\ 'panther', 'sure', 'hello',\ 'layer', 'try', 'grace',\ 'seven', 'fossil', 'voice',\ 'tobacco', 'circle', 'measure',\ 'solar', 'pride', 'together'\ ] Your wallet address is: addr_test1qptwuv6dl863u3k93mjrg0hgs0ahl08lfhsudxrwshcsx59cjxatme29s6cl7drjceknunry049shu9eudnsjvwqq9qsuem66d [Send lovelace](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#send-lovelace) ----------------------------------------------------------------------------------------------------------- Now that we have a wallet and some lovelace, let's learn how to send lovelace using the Mesh SDK. We will use the `MeshTxBuilder` class to create a transaction and send it to the network. ### [Get lovelace from faucet](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#get-lovelace-from-faucet) To get some lovelace for testing, you can use the [Cardano Preprod Testnet Faucet](https://docs.cardano.org/cardano-testnets/tools/faucet) . Paste your wallet address and click on the "Request funds" button. You should receive some lovelace in your wallet shortly. ### [Get Blockfrost API key](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#get-blockfrost-api-key) In order to create transactions, we need to use APIs to get UTXOs from the network. For this, we will use Blockfrost to get UTXOs and submit transactions. Sign up for a free account and get your API key [here](https://blockfrost.io/) . You should get the preprod API key, which starts with `preprod`. You can find the API key in the "Projects" section of your Blockfrost account. ### [Get wallet information](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#get-wallet-information) Now, let's get the wallet information using the `MeshWallet` class. // Get wallet data needed for the transaction const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); * `getUtxos`: Method to get the UTXOs from the wallet. * `getChangeAddress`: Method to get the change address. ### [Create a transaction to send lovelace](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#create-a-transaction-to-send-lovelace) Now, we will create a transaction to send lovelace using the [`MeshTxBuilder`](https://meshjs.dev/apis/txbuilder) class. // Create the transaction const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true, // optional, prints the transaction body }); const unsignedTx = await txBuilder .txOut( "addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9", [{ unit: "lovelace", quantity: "1500000" }] ) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); * `txOut`: Add the recipient address and amount. * `changeAddress`: Set the change address. * `selectUtxosFrom`: Provide wallet UTXOs into the transaction as inputs. * `complete`: Create the transaction. ### [Sign and submit the transaction](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#sign-and-submit-the-transaction) Now that we have created the transaction, we need to sign it and submit it to the network. const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); console.log("Transaction hash:", txHash); * `signTx`: Method to sign the transaction, which will return the signed transaction. * `submitTx`: Method to submit the transaction to the network. ### [Run the code](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#run-the-code-1) Here is the source code. Create a new file `send-lovelace.ts` and copy the code into it: import { BlockfrostProvider, MeshTxBuilder, MeshWallet } from "@meshsdk/core"; // Set up the blockchain provider with your key const provider = new BlockfrostProvider("YOUR_KEY_HERE"); // Initialize the wallet with a mnemonic key const wallet = new MeshWallet({ networkId: 0, fetcher: provider, submitter: provider, key: { type: "mnemonic", words: ["your", "mnemonic", "...", "here"], }, }); // Get wallet data needed for the transaction const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); // Create the transaction const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true, // optional, prints the transaction body }); const unsignedTx = await txBuilder .txOut( "addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9", [{ unit: "lovelace", quantity: "1500000" }] ) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); console.log("Transaction hash:", txHash); Update the `package.json` file to add a script to run the code: { "type": "module", "dependencies": { "@meshsdk/core": "^1.9.0", }, "scripts": { "mnemonic": "node mnemonic.ts", "send-lovelace": "node send-lovelace.ts" } } Run the script: npm run send-lovelace This will create a transaction to send lovelace to the recipient address and submit it to the network. The output will look something like this: > send-lovelace > node send-lovelace.ts txBodyJson - before coin selection {"inputs":[],"outputs":[{"address":"addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9","amount":[{"unit":"lovelace","quantity":"1500000"}]}],"fee":"0","collaterals":[],"requiredSignatures":[],"referenceInputs":[],"mints":[],"changeAddress":"addr_test1qp2k7wnshzngpqw0xmy33hvexw4aeg60yr79x3yeeqt3s2uvldqg2n2p8y4kyjm8sqfyg0tpq9042atz0fr8c3grjmysdp6yv3","metadata":{},"validityRange":{},"certificates":[],"withdrawals":[],"votes":[],"signingKey":[],"chainedTxs":[],"inputsForEvaluation":{},"network":"mainnet","expectedNumberKeyWitnesses":0,"expectedByronAddressWitnesses":[]} txBodyJson - after coin selection {"inputs":[{"type":"PubKey","txIn":{"txHash":"99d859b305ab8021e497fad0dc55373e50fffd3e7026142fa3cf5accfe0d3aab","txIndex":1,"amount":[{"unit":"lovelace","quantity":"9823719"}],"address":"addr_test1qp2k7wnshzngpqw0xmy33hvexw4aeg60yr79x3yeeqt3s2uvldqg2n2p8y4kyjm8sqfyg0tpq9042atz0fr8c3grjmysdp6yv3"}}],"outputs":[{"address":"addr_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9","amount":[{"unit":"lovelace","quantity":"1500000"}]},{"address":"addr_test1qp2k7wnshzngpqw0xmy33hvexw4aeg60yr79x3yeeqt3s2uvldqg2n2p8y4kyjm8sqfyg0tpq9042atz0fr8c3grjmysdp6yv3","amount":[{"unit":"lovelace","quantity":"8153730"}]}],"fee":"169989","collaterals":[],"requiredSignatures":[],"referenceInputs":[],"mints":[],"changeAddress":"addr_test1qp2k7wnshzngpqw0xmy33hvexw4aeg60yr79x3yeeqt3s2uvldqg2n2p8y4kyjm8sqfyg0tpq9042atz0fr8c3grjmysdp6yv3","metadata":{},"validityRange":{},"certificates":[],"withdrawals":[],"votes":[],"signingKey":[],"chainedTxs":[],"inputsForEvaluation":{"99d859b305ab8021e497fad0dc55373e50fffd3e7026142fa3cf5accfe0d3aab1":{"input":{"outputIndex":1,"txHash":"99d859b305ab8021e497fad0dc55373e50fffd3e7026142fa3cf5accfe0d3aab"},"output":{"address":"addr_test1qp2k7wnshzngpqw0xmy33hvexw4aeg60yr79x3yeeqt3s2uvldqg2n2p8y4kyjm8sqfyg0tpq9042atz0fr8c3grjmysdp6yv3","amount":[{"unit":"lovelace","quantity":"9823719"}]}}},"network":"mainnet","expectedNumberKeyWitnesses":0,"expectedByronAddressWitnesses":[]} Transaction hash: 62a825c607e4ca5766325c2fccd7ee98313ff81b7e8a4af67eac421b0f0866ff You should see the transaction hash in the output. Note, in the `MeshTxBuilder` class, we have set `verbose: true`, which will print the transaction body before and after coin selection. This is useful for debugging and understanding how the transaction is built. [Source code](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#source-code) ------------------------------------------------------------------------------------------------------- The source code for this lesson is available on [GitHub](https://github.com/cardanobuilders/cardanobuilders.github.io/tree/main/codes/course-hello-cardano/01-wallet-send-lovelace) . [Challenge](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#challenge) --------------------------------------------------------------------------------------------------- Create a transaction that sends multiple assets to multiple addresses. Explore the Mesh SDK docs for more! [Course Lessons\ \ Step-by-step lessons for mastering Cardano development with Mesh SDK and Aiken.](https://meshjs.dev/resources/cardano-course/lessons) [Multi-signature Transactions\ \ Learn to build multi-signature transactions on Cardano.](https://meshjs.dev/resources/cardano-course/lessons/02-multisig) ### On this page [System setup](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#system-setup) [Create a package.json file](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#create-a-packagejson-file) [Install the necessary packages](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#install-the-necessary-packages) [Create a wallet](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#create-a-wallet) [Generate mnemonic phrases](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#generate-mnemonic-phrases) [Initialize the wallet and get the wallet address](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#initialize-the-wallet-and-get-the-wallet-address) [Run the code](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#run-the-code) [Send lovelace](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#send-lovelace) [Get lovelace from faucet](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#get-lovelace-from-faucet) [Get Blockfrost API key](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#get-blockfrost-api-key) [Get wallet information](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#get-wallet-information) [Create a transaction to send lovelace](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#create-a-transaction-to-send-lovelace) [Sign and submit the transaction](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#sign-and-submit-the-transaction) [Run the code](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#run-the-code-1) [Source code](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#source-code) [Challenge](https://meshjs.dev/resources/cardano-course/lessons/01-wallet-send-lovelace#challenge) Ask AI --- # Contract Testing | Mesh SDK [Learn](https://meshjs.dev/resources) [Cardano Course](https://meshjs.dev/resources/cardano-course) [Lessons](https://meshjs.dev/resources/cardano-course/lessons) Contract Testing ================ Testing Aiken smart contracts. Copy MarkdownOpen Testing Aiken contracts is crucial to ensure they behave as expected. In this lesson, we will cover: * Preparing a complex contract for testing * Building mock transactions in Aiken and running tests [Preparing a Complex Contract](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#preparing-a-complex-contract) ------------------------------------------------------------------------------------------------------------------------------------- We will enhance the withdrawal contract from the previous lesson to include two user actions: `ContinueCounting` or `StopCounting`. 1. **ContinueCounting**: * Verify the transaction is signed by the app owner. * Ensure the app is not expired (using a POSIX timestamp). * Carry forward the state thread token to the output. * Increment the count in the state thread token's datum by 1. 2. **StopCounting**: * Verify the transaction is signed by the app owner. * Ensure the state thread token is burned (not carried forward to any output). ### [Contract Code](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#contract-code) use aiken/crypto.{VerificationKeyHash} use cardano/address.{Address, Credential} use cardano/assets.{PolicyId} use cardano/certificate.{Certificate} use cardano/transaction.{Transaction} use cocktail.{input_inline_datum, inputs_with_policy, key_signed, valid_before} pub type OracleDatum { app_owner: VerificationKeyHash, app_expiry: Int, spending_validator_address: Address, state_thread_token_policy_id: PolicyId, } pub type MyRedeemer { ContinueCounting StopCounting } validator complex_withdrawal_contract(oracle_nft: PolicyId) { withdraw(redeemer: MyRedeemer, _credential: Credential, tx: Transaction) { let Transaction { reference_inputs, mint, extra_signatories, validity_range, .. } = tx expect [oracle_ref_input] = inputs_with_policy(reference_inputs, oracle_nft) expect OracleDatum { app_owner, app_expiry, .. } = input_inline_datum(oracle_ref_input) let is_app_owner_signed = key_signed(extra_signatories, app_owner) when redeemer is { ContinueCounting -> { let is_app_not_expired = valid_before(validity_range, app_expiry) let is_nothing_minted = mint == assets.zero is_app_owner_signed? && is_app_not_expired? && is_nothing_minted? } StopCounting -> todo } } publish(_redeemer: Data, _credential: Certificate, _tx: Transaction) { True } else(_) { fail @"unsupported purpose" } } In this setup, we define 2 potential user action with `MyRedeemer`, either to `ContinueCounting` or `StopCounting`. We built the partial logics for `ContinueCounting` action, which we put all the logics we have learnt from lesson 3. ### [`expect`](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#expect) Notice we touch on the syntax of `expect` the first time here. `expect` is used to enforce the exact pattern for a variable. In above example, `inputs_with_policy(reference_inputs, oracle_nft)` returns `List`. However, since in this application we are confident that there is always one item in the list, perhaps since `oracle_nft` is unique, it is impossible to obtain two inputs with `oracle_nft` in value. So that we can use `expect` here. ### [`?` operator](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#-operator) In the last line of `ContinueCounting` branch, you may notice the use of `?` operator. This operator is a tracing operator that helps to trace which condition fails when the validator fails. For example, if `is_app_owner_signed` is false, then the validator will fail with message `is_app_owner_signed?` which helps to identify the root cause of failure. [Validating Input & Output](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#validating-input--output) ------------------------------------------------------------------------------------------------------------------------------ We complete the contract by validating inputs and outputs: use aiken/crypto.{VerificationKeyHash} use cardano/address.{Address, Credential} use cardano/assets.{PolicyId, without_lovelace} use cardano/certificate.{Certificate} use cardano/transaction.{Transaction} use cocktail.{ input_inline_datum, inputs_at_with_policy, inputs_with_policy, key_signed, output_inline_datum, outputs_at_with_policy, valid_before, } pub type OracleDatum { app_owner: VerificationKeyHash, app_expiry: Int, spending_validator_address: Address, state_thread_token_policy_id: PolicyId, } pub type SpendingValidatorDatum { count: Int, } pub type MyRedeemer { ContinueCounting StopCounting } validator complex_withdrawal_contract(oracle_nft: PolicyId) { withdraw(redeemer: MyRedeemer, _credential: Credential, tx: Transaction) { let Transaction { reference_inputs, inputs, outputs, mint, extra_signatories, validity_range, .. } = tx expect [oracle_ref_input] = inputs_with_policy(reference_inputs, oracle_nft) expect OracleDatum { app_owner, app_expiry, spending_validator_address, state_thread_token_policy_id, } = input_inline_datum(oracle_ref_input) expect [state_thread_input] = inputs_at_with_policy( inputs, spending_validator_address, state_thread_token_policy_id, ) let is_app_owner_signed = key_signed(extra_signatories, app_owner) when redeemer is { ContinueCounting -> { expect [state_thread_output] = outputs_at_with_policy( outputs, spending_validator_address, state_thread_token_policy_id, ) expect input_datum: SpendingValidatorDatum = input_inline_datum(state_thread_input) expect output_datum: SpendingValidatorDatum = output_inline_datum(state_thread_output) let is_app_not_expired = valid_before(validity_range, app_expiry) let is_count_added = input_datum.count + 1 == output_datum.count let is_nothing_minted = mint == assets.zero is_app_owner_signed? && is_app_not_expired? && is_count_added && is_nothing_minted? } StopCounting -> { let state_thread_value = state_thread_input.output.value |> without_lovelace() let is_thread_token_burned = mint == assets.negate(state_thread_value) is_app_owner_signed? && is_thread_token_burned? } } } publish(_redeemer: Data, _credential: Certificate, _tx: Transaction) { True } else(_) { fail @"unsupported purpose" } } We have used some new techniques here. We have extracted the inline datum of the state thread token input and output using `input_inline_datum` and `output_inline_datum`. We have also used `inputs_at_with_policy` and `outputs_at_with_policy` to filter the inputs and outputs at a specific address with a specific policy ID. With that, we can compare the datum of input and output to ensure the count is incremented by 1. In `StopCounting` case, we ensure the state thread token is burned by checking the `mint` field of the transaction. We use `without_lovelace` to ignore the lovelace part of the value when comparing. [Build mock transaction in Aiken](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#build-mock-transaction-in-aiken) ------------------------------------------------------------------------------------------------------------------------------------------- All Aiken contracts can be interpreted as simple functions, which takes in a few parameters and returns a boolean value. This makes it easy to test the contract by providing mock data. In Aiken, we can build testing functions with `test` keyword, followed by running `aiken check` in project root to execute the tests. The vanilla example: test always_true() { True } With `aiken check`, we will see: ![Dummy Test](https://meshjs.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdummy-test.d3891d15.png&w=3840&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) ### [Testing always succeed and always fail cases](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#testing-always-succeed-and-always-fail-cases) In our complex withdrawal contract, we have a `publish` function that always returns `True`. We can write a test for it: use mocktail.{complete, mock_utxo_ref, mocktail_tx} test test_publish() { let data = Void complex_withdrawal_contract.publish( "", data, RegisterCredential(Script(#""), Never), mocktail_tx() |> complete(), ) } In this test, we call the `publish` function of our contract with mock parameters. We use `mocktail_tx()` to create a mock transaction and `complete()` to provide an empty `Transaction`. For the rest of script purposes, it will fallback to the `else` branch which always fails. We can write a test for it: test test_else() fail { complex_withdrawal_contract.else( "", ScriptContext( mocktail_tx() |> complete(), Void, Spending(mock_utxo_ref(0, 0), None), ), ) } Note that the test is not returning a `False`, but the programme breaks with `fail`. We can indicate that the test is expected to fail by adding `fail` after the test name. Running `aiken check` will show: ![Always Succeed and Always Fail Test](https://meshjs.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Falways-succeed-n-fail.bdc3d0e0.png&w=3840&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) ### [Testing `withdraw` function](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#testing-withdraw-function) You will notice the `withdraw` function is validated the `Transaction` mostly, therefore, we should craft the `Transaction` carefully. However, crafting it with mock data is a bit tricky especially when we have to deal with all the Aiken types. `vodka` library comes to rescue. In `vodka`, the `mocktail` module provides a set of functions to create mock data for testing Aiken contracts. We can use `mocktail_tx()` to create a mock `Transaction` and then use various functions to modify the transaction to fit our test case. const mock_oracle_nft = mock_policy_id(0) const mock_oracle_address = mock_script_address(0, None) const mock_oracle_value = assets.from_asset(mock_oracle_nft, "", 1) |> assets.add("", "", 2_000_000) const mock_app_owner = mock_pub_key_hash(0) const mock_spending_validator_address = mock_script_address(1, None) const mock_state_thread_token_policy_id = mock_policy_id(1) const mock_state_thread_value = assets.from_asset(mock_state_thread_token_policy_id, "", 1) |> assets.add("", "", 2_000_000) const mock_oracle_datum = OracleDatum { app_owner: mock_app_owner, app_expiry: 1000, spending_validator_address: mock_spending_validator_address, state_thread_token_policy_id: mock_state_thread_token_policy_id, } fn mock_datum(count: Int) -> SpendingValidatorDatum { SpendingValidatorDatum { count } } fn mock_continue_counting_tx() -> Transaction { mocktail_tx() |> ref_tx_in( True, mock_tx_hash(0), 0, mock_oracle_value, mock_oracle_address, ) |> ref_tx_in_inline_datum(True, mock_oracle_datum) |> tx_in( True, mock_tx_hash(1), 0, mock_state_thread_value, mock_spending_validator_address, ) |> tx_in_inline_datum(True, mock_datum(0)) |> tx_out(True, mock_spending_validator_address, mock_state_thread_value) |> tx_out_inline_datum(True, mock_datum(1)) |> required_signer_hash(True, mock_app_owner) |> invalid_hereafter(True, 999) |> complete() } We can import all the `mock_...` functions from `mocktail` module to build up the types we need. In above example, we create a mock transaction for `ContinueCounting` action. We create the oracle NFT input with inline datum, the state thread token input with inline datum, the state thread token output with inline datum, the required signer and the validity range. Now we can write a test for `ContinueCounting` action: test success_continue_counting() { complex_withdrawal_contract.withdraw( mock_oracle_nft, ContinueCounting, Credential.Script(#""), mock_continue_counting_tx(), ) } ### [Dynamically Testing Failure Cases](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#dynamically-testing-failure-cases) In the mocktail transaction building methods, we can pass a boolean parameter to indicate whether we want the field to be present or not. This allows us to dynamically create failure cases by omitting certain fields. type ContinueCountingTest { is_ref_input_presented: Bool, is_thread_input_presented: Bool, is_thread_output_presented: Bool, is_count_added: Bool, is_app_owner_signed: Bool, is_tx_not_expired: Bool, } fn mock_continue_counting_tx(test_case: ContinueCountingTest) -> Transaction { let ContinueCountingTest { is_ref_input_presented, is_thread_input_presented, is_thread_output_presented, is_count_added, is_app_owner_signed, is_tx_not_expired, } = test_case let output_datum = if is_count_added { mock_datum(1) } else { mock_datum(0) } mocktail_tx() |> ref_tx_in( is_ref_input_presented, mock_tx_hash(0), 0, mock_oracle_value, mock_oracle_address, ) |> ref_tx_in_inline_datum(is_ref_input_presented, mock_oracle_datum) |> tx_in( is_thread_input_presented, mock_tx_hash(1), 0, mock_state_thread_value, mock_spending_validator_address, ) |> tx_in_inline_datum(is_thread_input_presented, mock_datum(0)) |> tx_out( is_thread_output_presented, mock_spending_validator_address, mock_state_thread_value, ) |> tx_out_inline_datum(is_thread_output_presented, output_datum) |> required_signer_hash(is_app_owner_signed, mock_app_owner) |> invalid_hereafter(is_tx_not_expired, 999) |> complete() } And we update the successful test accordingly: test success_continue_counting() { let test_case = ContinueCountingTest { is_ref_input_presented: True, is_thread_input_presented: True, is_thread_output_presented: True, is_count_added: True, is_app_owner_signed: True, is_tx_not_expired: True, } complex_withdrawal_contract.withdraw( mock_oracle_nft, ContinueCounting, Credential.Script(#""), mock_continue_counting_tx(test_case), ) } And we can populate the failure cases at ease: test fail_continue_counting_no_ref_input() fail { let test_case = ContinueCountingTest { is_ref_input_presented: False, is_thread_input_presented: True, is_thread_output_presented: True, is_count_added: True, is_app_owner_signed: True, is_tx_not_expired: True, } complex_withdrawal_contract.withdraw( mock_oracle_nft, ContinueCounting, Credential.Script(#""), mock_continue_counting_tx(test_case), ) } test fail_continue_counting_no_thread_input() fail { let test_case = ContinueCountingTest { is_ref_input_presented: True, is_thread_input_presented: False, is_thread_output_presented: True, is_count_added: True, is_app_owner_signed: True, is_tx_not_expired: True, } complex_withdrawal_contract.withdraw( mock_oracle_nft, ContinueCounting, Credential.Script(#""), mock_continue_counting_tx(test_case), ) } test fail_continue_counting_no_thread_output() fail { let test_case = ContinueCountingTest { is_ref_input_presented: True, is_thread_input_presented: True, is_thread_output_presented: False, is_count_added: True, is_app_owner_signed: True, is_tx_not_expired: True, } complex_withdrawal_contract.withdraw( mock_oracle_nft, ContinueCounting, Credential.Script(#""), mock_continue_counting_tx(test_case), ) } test fail_continue_counting_incorrect_count() { let test_case = ContinueCountingTest { is_ref_input_presented: True, is_thread_input_presented: True, is_thread_output_presented: True, is_count_added: False, is_app_owner_signed: True, is_tx_not_expired: True, } !complex_withdrawal_contract.withdraw( mock_oracle_nft, ContinueCounting, Credential.Script(#""), mock_continue_counting_tx(test_case), ) } test fail_continue_counting_not_signed_by_owner() { let test_case = ContinueCountingTest { is_ref_input_presented: True, is_thread_input_presented: True, is_thread_output_presented: True, is_count_added: True, is_app_owner_signed: False, is_tx_not_expired: True, } !complex_withdrawal_contract.withdraw( mock_oracle_nft, ContinueCounting, Credential.Script(#""), mock_continue_counting_tx(test_case), ) } test fail_continue_counting_app_expired() { let test_case = ContinueCountingTest { is_ref_input_presented: True, is_thread_input_presented: True, is_thread_output_presented: True, is_count_added: True, is_app_owner_signed: True, is_tx_not_expired: False, } !complex_withdrawal_contract.withdraw( mock_oracle_nft, ContinueCounting, Credential.Script(#""), mock_continue_counting_tx(test_case), ) } Running `aiken check` will show: ![Continue Counting Tests](https://meshjs.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fall-tests.3e70ef29.png&w=3840&q=75&dpl=dpl_FVaK7HhRZvqiCyqJmXaCr2D3YLGt) ### [Exercise](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#exercise) Write tests for `StopCounting` action. Refer to `ContinueCounting` tests for guidance. Suggested answers are in the code example. [Aiken Contracts\ \ Building Aiken smart contracts.](https://meshjs.dev/resources/cardano-course/lessons/03-aiken-contracts) [Avoid Redundant Validation\ \ Key contract best practice - reduce redundant validation logics being run onchain.](https://meshjs.dev/resources/cardano-course/lessons/05-avoid-redundant-validation) ### On this page [Preparing a Complex Contract](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#preparing-a-complex-contract) [Contract Code](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#contract-code) [`expect`](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#expect) [`?` operator](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#-operator) [Validating Input & Output](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#validating-input--output) [Build mock transaction in Aiken](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#build-mock-transaction-in-aiken) [Testing always succeed and always fail cases](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#testing-always-succeed-and-always-fail-cases) [Testing `withdraw` function](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#testing-withdraw-function) [Dynamically Testing Failure Cases](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#dynamically-testing-failure-cases) [Exercise](https://meshjs.dev/resources/cardano-course/lessons/04-contract-testing#exercise) Ask AI --- # Plutus NFT Contract | Mesh SDK [Learn](https://meshjs.dev/resources) [Cardano Course](https://meshjs.dev/resources/cardano-course) [Lessons](https://meshjs.dev/resources/cardano-course/lessons) Plutus NFT Contract =================== Plutus NFT smart contract enforces non-fungibility and uniqueness of the NFT under the same policy. Copy MarkdownOpen After the simple vesting contract, let's level up to a more complex contract with multiple validators interacting with each other. This lesson will guide you step-by-step through the process of creating a Plutus NFT contract, ensuring clarity and simplicity. [Overview](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#overview) --------------------------------------------------------------------------------------- This lesson focuses on creating a smart contract for minting NFTs with an automatically incremented index. The contract ensures non-fungibility and uniqueness of the NFTs under the same policy. To achieve this, we will: 1. Set up a one-time minting policy to create an oracle token. 2. Use the oracle token to maintain the state and index of NFTs. 3. Increment the token index with each new NFT minted. [Step 1: Oracle NFT](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#step-1-oracle-nft) ---------------------------------------------------------------------------------------------------------- The oracle NFT acts as the single source of truth for the system. It uses a state thread token to ensure consistency. We will implement a one-time minting policy for the oracle NFT. ### [Code Explanation](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#code-explanation) The following code defines the minting policy for the oracle NFT: pub type MintPolarity { RMint RBurn } validator oracle_nft(utxo_ref: OutputReference) { mint(redeemer: MintPolarity, policy_id: PolicyId, tx: Transaction) { when redeemer is { RMint -> { let Transaction { inputs, .. } = tx let hash_equal = fn(input: Input) { let hash = input.output_reference utxo_ref == hash } let target_input_exist = list.find(inputs, hash_equal) when target_input_exist is { Some(_) -> True None -> False } } RBurn -> check_policy_only_burn(tx.mint, policy_id) } } else(_) { fail } } **Key Points:** * `RMint` ensures the token is minted only once. * `RBurn` allows the token to be burned but prevents reminting. [Step 2: Oracle Validator](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#step-2-oracle-validator) ---------------------------------------------------------------------------------------------------------------------- The oracle validator holds the current state of the NFT index. It defines the datum and redeemer types for state changes. ### [Datum Definition](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#datum-definition) pub type OracleDatum { count: Int, lovelace_price: Int, fee_address: Address, } ### [Redeemer Types](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#redeemer-types) pub type OracleRedeemer { MintPlutusNFT StopOracle } ### [Validator Logic](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#validator-logic) The validator ensures the state changes are valid: validator oracle { spend( datum_opt: Option, redeemer: OracleRedeemer, input: OutputReference, tx: Transaction, ) { let Transaction { mint, inputs, outputs, extra_signatories, .. } = tx expect Some(OracleDatum { count, lovelace_price, fee_address }) = datum_opt expect Some(own_input) = find_input(inputs, input) expect [(oracle_nft_policy, _, _)] = list.filter(flatten(own_input.output.value), fn(x) { x.1st != "" }) todo } else(_) { fail } } In this setup, we identified the own input with `find_input` function, which is a utility function that finds the input with the given output reference. We also expect the oracle NFT policy to be present in the own input's value. We know that for state change, we will have exactly one input from current address, and one output to the same address. We can then perform below pattern matching: let own_address = own_input.output.address when ( redeemer, inputs_at_with_policy(inputs, own_address, oracle_nft_policy), outputs_at_with_policy(outputs, own_address, oracle_nft_policy), ) is { (MintPlutusNFT, [_], [only_output]) -> { todo } _ -> False } Add in core checks for `MintPlutusNFT`: let is_output_value_clean = list.length(flatten(only_output.value)) == 2 let is_count_updated = only_output.datum == InlineDatum( OracleDatum { count: count + 1, lovelace_price, fee_address }, ) let is_fee_paid = get_all_value_to(outputs, fee_address) |> value_geq(from_lovelace(lovelace_price)) is_output_value_clean? && is_count_updated? && is_fee_paid? Notice there is a `is_output_value_clean` check here, which ensures the changed state UTxO only contains the state thread token and ADA, i.e. no other assets are present in the output value. This is to prevent a common vulnerability of `Unbounded Value`, where people can attach infinitely amount of assets to the output to make it unspendable by overflowing the transaction size. Complete with `StopOracle` logics: (StopOracle, [_], _) -> { let is_oracle_nft_burnt = only_minted_token(mint, oracle_nft_policy, "", -1) let owner_key = address_payment_key(fee_address) let is_owner_signed = key_signed(extra_signatories, owner_key) is_oracle_nft_burnt? && is_owner_signed? } A complete oracle validator looks like this: validator oracle { spend( datum_opt: Option, redeemer: OracleRedeemer, input: OutputReference, tx: Transaction, ) { let Transaction { mint, inputs, outputs, extra_signatories, .. } = tx expect Some(OracleDatum { count, lovelace_price, fee_address }) = datum_opt expect Some(own_input) = find_input(inputs, input) expect [(oracle_nft_policy, _, _)] = list.filter(flatten(own_input.output.value), fn(x) { x.1st != "" }) let own_address = own_input.output.address when ( redeemer, inputs_at_with_policy(inputs, own_address, oracle_nft_policy), outputs_at_with_policy(outputs, own_address, oracle_nft_policy), ) is { (MintPlutusNFT, [_], [only_output]) -> { let is_output_value_clean = list.length(flatten(only_output.value)) == 2 let is_count_updated = only_output.datum == InlineDatum( OracleDatum { count: count + 1, lovelace_price, fee_address }, ) let is_fee_paid = get_all_value_to(outputs, fee_address) |> value_geq(from_lovelace(lovelace_price)) is_output_value_clean? && is_count_updated? && is_fee_paid? } (StopOracle, [_], _) -> { let is_oracle_nft_burnt = only_minted_token(mint, oracle_nft_policy, "", -1) let owner_key = address_payment_key(fee_address) let is_owner_signed = key_signed(extra_signatories, owner_key) is_oracle_nft_burnt? && is_owner_signed? } _ -> False } } else(_) { fail } } **Key Points:** * `MintPlutusNFT` increments the NFT index and ensures fees are paid. * `StopOracle` burns the oracle NFT and requires owner authorization. [Step 3: Plutus NFT Minting Validator](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#step-3-plutus-nft-minting-validator) ---------------------------------------------------------------------------------------------------------------------------------------------- The Plutus NFT minting validator ensures the NFT is unique and non-fungible. ### [Code Explanation](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#code-explanation-1) pub type MintPolarity { RMint RBurn } validator plutus_nft(collection_name: ByteArray, oracle_nft: PolicyId) { mint(redeemer: MintPolarity, policy_id: PolicyId, tx: Transaction) { when redeemer is { RMint -> { let Transaction { inputs, mint, .. } = tx expect [auth_input] = inputs_with_policy(inputs, oracle_nft) expect InlineDatum(input_datum) = auth_input.output.datum expect OracleDatum { count, .. }: OracleDatum = input_datum let asset_name = collection_name |> concat(" (") |> concat(convert_int_to_bytes(count)) |> concat(")") only_minted_token(mint, policy_id, asset_name, 1) } RBurn -> check_policy_only_burn(tx.mint, policy_id) } } else(_) { fail } } **Key Points:** * Ensures the NFT name includes the incremented index. * Validates the minting and burning process. The code example above is presented in [Mesh repository](https://github.com/MeshJS/mesh/tree/main/packages/mesh-contract/src/plutus-nft/aiken-workspace) , you can find the equivalent tests there. ### [Compile and build script](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#compile-and-build-script) 1. Compile the script using: aiken build This command will generate a CIP-0057 Plutus blueprint, which you can find in [`plutus.json`](https://github.com/cardanobuilders/cardanobuilders.github.io/blob/main/codes/course-hello-cardano/03-vesting/src/aiken-workspace/plutus.json) . [Setup Oracle](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#setup-oracle) ----------------------------------------------------------------------------------------------- To set up the oracle, we need to mint the oracle NFT first and lock it in the oracle validator. This is a one-time operation, and we can do it with the following code: We prepare the wallet and tx-builder similar to previous lessons, and get some static information: const compiledCode = ; const utxos = await wallet?.getUtxos(); const collateral = (await wallet.getCollateral())[0]!; const walletAddress = await wallet.getChangeAddress() const paramUtxo = utxos[0]!; const param: Data = mOutputReference( paramUtxo.input.txHash, paramUtxo.input.outputIndex, ); const paramScript = applyParamsToScript(compiledCode, [param]); const policyId = resolveScriptHash(paramScript, "V3"); const tokenName = ""; const { pubKeyHash, stakeCredentialHash } = deserializeAddress(walletAddress); Then we can perform the setup: const txHex = await txBuilder .txIn( paramUtxo.input.txHash, paramUtxo.input.outputIndex, paramUtxo.output.amount, paramUtxo.output.address, ) .mintPlutusScriptV3() .mint("1", policyId, tokenName) .mintingScript(paramScript) .mintRedeemerValue(mConStr0([])) .txOut(oracleAddress, [{ unit: policyId, quantity: "1" }]) .txOutInlineDatumValue( mConStr0([\ 0,\ lovelacePrice,\ mPubKeyAddress(pubKeyHash, stakeCredentialHash),\ ]), ) .txInCollateral( collateral.input.txHash, collateral.input.outputIndex, collateral.output.amount, collateral.output.address, ) .changeAddress(walletAddress) .selectUtxosFrom(utxos) .complete(); Important, we need to save the `paramUtxo` information for later use: [Mint Plutus NFT](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#mint-plutus-nft) ----------------------------------------------------------------------------------------------------- To mint the Plutus NFT, first we need to define static info: type OracleDatum = ConStr0<[Integer, Integer, PubKeyAddress]>; const oracleCompileCode = ; const oracleNftCbor = applyParamsToScript(blueprint.validators[2]!.compiledCode, [\ mOutputReference(paramUtxo.txHash, paramUtxo.outputIndex),\ ]) const oracleNftPolicyId = resolveScriptHash(oracleNftCbor, "V3"); const oracleCbor = applyCborEncoding() const oracleAddress = serializePlutusScript( { code: oracleCbor, version: "V3", }, "", // the stake credential, we can supply if we have one "preprod", ).address const getAddressUtxosWithToken = async ( walletAddress: string, assetHex: string, ) => { let utxos = await fetcher.fetchAddressUTxOs(walletAddress); return utxos.filter((u) => { const assetAmount = u.output.amount.find( (a: any) => a.unit === assetHex, )?.quantity; return Number(assetAmount) >= 1; }); }; And a helper method to get the existing oracle information: const getOracleData = async () => { const oracleUtxo = ( await getAddressUtxosWithToken(oracleAddress, oracleNftPolicyId) )[0]!; const oracleDatum: OracleDatum = parseDatumCbor( oracleUtxo!.output.plutusData!, ); const nftIndex = oracleDatum.fields[0].int; const lovelacePrice = oracleDatum.fields[1].int; const feeCollectorAddressObj = oracleDatum.fields[2]; const feeCollectorAddress = serializeAddressObj( feeCollectorAddressObj, "preprod", ); const policyId = resolveScriptHash(oracleNftCbor, "V3"); return { nftIndex, policyId, lovelacePrice, oracleUtxo, oracleNftPolicyId, feeCollectorAddress, feeCollectorAddressObj, }; }; Then we can build the core logic to mint the Plutus NFT: const utxos = await wallet?.getUtxos(); const collateral = (await wallet.getCollateral())[0]!; const walletAddress = await wallet.getChangeAddress() const collectionName = "MyNFTCollection"; const nftCbor = applyParamsToScript(, [\ stringToHex(collectionName),\ oracleNftPolicyId,\ ]); const { nftIndex, policyId, lovelacePrice, oracleUtxo, oracleNftPolicyId, feeCollectorAddress, feeCollectorAddressObj, } = await getOracleData(); const tokenName = `${collectionName} (${nftIndex})`; const tokenNameHex = stringToHex(tokenName); const updatedOracleDatum: OracleDatum = conStr0([\ integer((nftIndex as number) + 1),\ integer(lovelacePrice),\ feeCollectorAddressObj,\ ]); const tx = txBuilder .spendingPlutusScriptV3() .txIn( oracleUtxo.input.txHash, oracleUtxo.input.outputIndex, oracleUtxo.output.amount, oracleUtxo.output.address, 0 ) .txInRedeemerValue(mConStr0([])) .txInScript(oracleCbor) .txInInlineDatumPresent() .txOut(oracleAddress, [{ unit: oracleNftPolicyId, quantity: "1" }]) .txOutInlineDatumValue(updatedOracleDatum, "JSON") .mintPlutusScriptV3() .mint("1", policyId, tokenNameHex) .mintingScript(nftCbor); const assetMetadata = { name: `MyNFTCollection (${nftIndex})`, image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "This NFT was minted by Mesh (https://meshjs.dev/).", }; const metadata = { [policyId]: { [tokenName]: { ...assetMetadata } } }; tx.metadataValue(721, metadata); tx.mintRedeemerValue(mConStr0([])) .txOut(feeCollectorAddress, [\ { unit: "lovelace", quantity: lovelacePrice.toString() },\ ]) .txInCollateral( collateral.input.txHash, collateral.input.outputIndex, collateral.output.amount, collateral.output.address, ) .changeAddress(walletAddress) .selectUtxosFrom(utxos); const txHex = await tx.complete(); [Packaged functions](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#packaged-functions) ----------------------------------------------------------------------------------------------------------- The Plutus NFT contract has been implemented in `@meshsdk/contract` package, you can find further explanation at the [Mesh documentation](https://meshjs.dev/smart-contracts/plutus-nft) and more details about entire stack source code at [Mesh repository](https://github.com/MeshJS/mesh/tree/main/packages/mesh-contract/src/plutus-nft) . [Vesting Contract\ \ Vesting smart contract that locks up funds and allows the beneficiary to withdraw the funds after the lockup period.](https://meshjs.dev/resources/cardano-course/lessons/07-vesting) [End-to-End Hydra Happy Flow\ \ Layer 2 scaling solution for Cardano, an end-to-end tutorial for state channel between two participants using the Hydra Head protocol.](https://meshjs.dev/resources/cardano-course/lessons/09-hydra) ### On this page [Overview](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#overview) [Step 1: Oracle NFT](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#step-1-oracle-nft) [Code Explanation](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#code-explanation) [Step 2: Oracle Validator](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#step-2-oracle-validator) [Datum Definition](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#datum-definition) [Redeemer Types](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#redeemer-types) [Validator Logic](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#validator-logic) [Step 3: Plutus NFT Minting Validator](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#step-3-plutus-nft-minting-validator) [Code Explanation](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#code-explanation-1) [Compile and build script](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#compile-and-build-script) [Setup Oracle](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#setup-oracle) [Mint Plutus NFT](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#mint-plutus-nft) [Packaged functions](https://meshjs.dev/resources/cardano-course/lessons/08-plutus-nft#packaged-functions) Ask AI --- # Tutorials | Mesh SDK [Learn](https://meshjs.dev/resources) Tutorials ========= Step-by-step tutorials for building Cardano applications with Mesh SDK - from beginner to advanced. Copy MarkdownOpen Learn Cardano development with Mesh through hands-on tutorials. Each tutorial includes working code examples, explanations, and best practices. [🚀 Getting Started](https://meshjs.dev/resources/tutorials#-getting-started) ------------------------------------------------------------------------------ Perfect for developers new to Mesh or Cardano. [Installation & Setup\ \ ⏱️ 10 minutes • 🎯 Beginner\ \ \ \ \ Install Mesh and set up your first Cardano project with React or Next.js.](https://meshjs.dev/guides) [Next.js Integration\ \ ⏱️ 15 minutes • 🎯 Beginner\ \ \ \ \ Integrate Mesh with Next.js App Router and Pages Router configurations.](https://meshjs.dev/guides/nextjs) [React Hooks & Components\ \ ⏱️ 20 minutes • 🎯 Beginner\ \ \ \ \ Use Mesh React hooks and components to build wallet-connected interfaces.](https://meshjs.dev/react/getting-started) [Wallet Connection\ \ ⏱️ 15 minutes • 🎯 Beginner\ \ \ \ \ Connect Cardano wallets and prove wallet ownership in your dApp.](https://meshjs.dev/guides/prove-wallet-ownership) [💰 Transactions & Payments](https://meshjs.dev/resources/tutorials#-transactions--payments) --------------------------------------------------------------------------------------------- Learn to build and submit Cardano transactions. [Send ADA & Tokens\ \ ⏱️ 20 minutes • 🎯 Beginner\ \ \ \ \ Build transactions to send ADA and native tokens to any address.](https://meshjs.dev/apis/transaction) [Transaction Builder\ \ ⏱️ 30 minutes • 🎯 Intermediate\ \ \ \ \ Master the transaction builder for complex multi-input/output transactions.](https://meshjs.dev/apis/transaction/builder) [Multi-Asset Transactions\ \ ⏱️ 25 minutes • 🎯 Intermediate\ \ \ \ \ Handle transactions with multiple native assets and tokens.](https://meshjs.dev/apis/transaction/minting) [Server-Side Transactions\ \ ⏱️ 30 minutes • 🎯 Intermediate\ \ \ \ \ Build and submit transactions from Node.js backend applications.](https://meshjs.dev/guides/minting-on-nodejs) [🎨 NFT Development](https://meshjs.dev/resources/tutorials#-nft-development) ------------------------------------------------------------------------------ Create and manage NFTs on Cardano. [Mint Your First NFT\ \ ⏱️ 30 minutes • 🎯 Beginner\ \ \ \ \ Create a complete NFT collection with proper metadata and minting policies.](https://meshjs.dev/guides/nft-collection) [Multi-Signature Minting\ \ ⏱️ 45 minutes • 🎯 Intermediate\ \ \ \ \ Implement multi-signature NFT minting for team collaborations.](https://meshjs.dev/guides/multisig-minting) [Advanced NFT Metadata\ \ ⏱️ 35 minutes • 🎯 Intermediate\ \ \ \ \ Work with CIP-25 and CIP-68 metadata standards for NFTs.](https://meshjs.dev/apis/transaction/minting) [Burning & Managing Assets\ \ ⏱️ 25 minutes • 🎯 Intermediate\ \ \ \ \ Burn tokens and NFTs, manage asset lifecycles.](https://meshjs.dev/apis/txbuilder/minting#burning-assets) [🔐 Smart Contracts](https://meshjs.dev/resources/tutorials#-smart-contracts) ------------------------------------------------------------------------------ Build with Plutus and Aiken smart contracts. [Getting Started with Aiken\ \ ⏱️ 40 minutes • 🎯 Intermediate\ \ \ \ \ Set up Aiken development environment and write your first smart contract.](https://meshjs.dev/aiken/getting-started) [Your First Aiken Script\ \ ⏱️ 50 minutes • 🎯 Intermediate\ \ \ \ \ Build a complete Aiken validator and integrate it with Mesh.](https://meshjs.dev/aiken/first-script) [Smart Contract Transactions\ \ ⏱️ 60 minutes • 🎯 Advanced\ \ \ \ \ Lock and unlock assets using smart contracts with proper datum and redeemer handling.](https://meshjs.dev/guides/smart-contract-transactions) [Advanced Smart Contract Patterns\ \ ⏱️ 90 minutes • 🎯 Advanced\ \ \ \ \ Implement complex patterns like state machines, oracles, and multi-party contracts.](https://meshjs.dev/aiken/transactions) [🛠️ Advanced Topics](https://meshjs.dev/resources/tutorials#%EF%B8%8F-advanced-topics) ---------------------------------------------------------------------------------------- For experienced developers building production applications. [Custom Providers\ \ ⏱️ 45 minutes • 🎯 Advanced\ \ \ \ \ Create custom blockchain data providers for specific use cases.](https://meshjs.dev/guides/custom-provider) [Provider Integration\ \ ⏱️ 30 minutes • 🎯 Intermediate\ \ \ \ \ Integrate with Blockfrost, Maestro, Koios, and other data providers.](https://meshjs.dev/providers) [Local Development with Yaci\ \ ⏱️ 40 minutes • 🎯 Advanced\ \ \ \ \ Set up local Cardano development network for rapid iteration and testing.](https://meshjs.dev/yaci) [Production Best Practices\ \ ⏱️ 60 minutes • 🎯 Advanced\ \ \ \ \ Security, optimization, error handling, and deployment strategies.](https://meshjs.dev/guides/aiken) [📱 Framework Integrations](https://meshjs.dev/resources/tutorials#-framework-integrations) -------------------------------------------------------------------------------------------- Use Mesh with your favorite framework. [Next.js Full Stack\ \ ⏱️ 45 minutes • 🎯 Intermediate\ \ \ \ \ Build full-stack Cardano dApps with Next.js, including API routes and server components.](https://meshjs.dev/guides/nextjs) [Svelte Integration\ \ ⏱️ 30 minutes • 🎯 Intermediate\ \ \ \ \ Use Mesh with Svelte and SvelteKit for reactive Cardano applications.](https://meshjs.dev/svelte) [Node.js Backend\ \ ⏱️ 35 minutes • 🎯 Intermediate\ \ \ \ \ Use Mesh in Node.js backends, APIs, and automation scripts.](https://meshjs.dev/guides/node-specific-imports) Vue.js Integration ⏱️ Coming Soon • 🎯 Intermediate Tutorial for using Mesh with Vue.js and Nuxt. [🎓 Learning Paths](https://meshjs.dev/resources/tutorials#-learning-paths) ---------------------------------------------------------------------------- Structured learning journeys that combine the tutorials and guides listed on this page into recommended sequences for different goals. ### [Path 1: Web Developer → Cardano dApp Developer](https://meshjs.dev/resources/tutorials#path-1-web-developer--cardano-dapp-developer) 1. Installation & Setup (10 min) 2. Wallet Connection (15 min) 3. Send ADA & Tokens (20 min) 4. React Hooks & Components (20 min) 5. Mint Your First NFT (30 min) 6. Next.js Integration (45 min) **Total Time:** ~2.5 hours • **Level:** Beginner to Intermediate ### [Path 2: Smart Contract Developer](https://meshjs.dev/resources/tutorials#path-2-smart-contract-developer) 1. Getting Started with Aiken (40 min) 2. Your First Aiken Script (50 min) 3. Smart Contract Transactions (60 min) 4. Advanced Smart Contract Patterns (90 min) 5. Local Development with Yaci (40 min) 6. Production Best Practices (60 min) **Total Time:** ~5.5 hours • **Level:** Intermediate to Advanced ### [Path 3: NFT Collection Creator](https://meshjs.dev/resources/tutorials#path-3-nft-collection-creator) 1. Installation & Setup (10 min) 2. Wallet Connection (15 min) 3. Mint Your First NFT (30 min) 4. Advanced NFT Metadata (35 min) 5. Multi-Signature Minting (45 min) 6. Server-Side Transactions (30 min) **Total Time:** ~2.5 hours • **Level:** Beginner to Intermediate [📚 Additional Resources](https://meshjs.dev/resources/tutorials#-additional-resources) ---------------------------------------------------------------------------------------- * **[API Reference](https://meshjs.dev/apis) ** - Complete API documentation * **[Code Examples](https://github.com/MeshJS/examples) ** - Working code repositories * **[FAQ](https://meshjs.dev/resources/faq) ** - Frequently asked questions * **[Use Cases](https://meshjs.dev/resources/use-cases) ** - Real-world applications * **[Developer Resources](https://meshjs.dev/resources/developer-resources) ** - Tools and communities [💬 Need Help?](https://meshjs.dev/resources/tutorials#-need-help) ------------------------------------------------------------------- Stuck on a tutorial? Here's how to get help: * **[Discord Community](https://discord.gg/dH48jH3BKa) ** - Real-time support from the community * **[GitHub Discussions](https://github.com/MeshJS/mesh/discussions) ** - Longer-form Q&A * **[Stack Overflow](https://stackoverflow.com/questions/tagged/meshsdk) ** - Tagged questions [🎯 What's Next?](https://meshjs.dev/resources/tutorials#-whats-next) ---------------------------------------------------------------------- After completing these tutorials, you'll be ready to: * Build production Cardano dApps * Create NFT collections and marketplaces * Develop DeFi applications * Integrate smart contracts * Contribute to the Cardano ecosystem Start your journey today with our [Getting Started Guide](https://meshjs.dev/guides) ! [Mint an NFT Collection\ \ Previous Page](https://meshjs.dev/guides/nft-collection) [Use Cases & Showcases\ \ Discover real-world applications and projects built with Mesh - from DeFi platforms to NFT marketplaces and enterprise solutions on Cardano.](https://meshjs.dev/resources/use-cases) ### On this page [🚀 Getting Started](https://meshjs.dev/resources/tutorials#-getting-started) [💰 Transactions & Payments](https://meshjs.dev/resources/tutorials#-transactions--payments) [🎨 NFT Development](https://meshjs.dev/resources/tutorials#-nft-development) [🔐 Smart Contracts](https://meshjs.dev/resources/tutorials#-smart-contracts) [🛠️ Advanced Topics](https://meshjs.dev/resources/tutorials#%EF%B8%8F-advanced-topics) [📱 Framework Integrations](https://meshjs.dev/resources/tutorials#-framework-integrations) [🎓 Learning Paths](https://meshjs.dev/resources/tutorials#-learning-paths) [Path 1: Web Developer → Cardano dApp Developer](https://meshjs.dev/resources/tutorials#path-1-web-developer--cardano-dapp-developer) [Path 2: Smart Contract Developer](https://meshjs.dev/resources/tutorials#path-2-smart-contract-developer) [Path 3: NFT Collection Creator](https://meshjs.dev/resources/tutorials#path-3-nft-collection-creator) [📚 Additional Resources](https://meshjs.dev/resources/tutorials#-additional-resources) [💬 Need Help?](https://meshjs.dev/resources/tutorials#-need-help) [🎯 What's Next?](https://meshjs.dev/resources/tutorials#-whats-next) Ask AI --- # Unknown \# Branding URL: /about/branding These resources exist to help you use Mesh's assets. \*\*\* title: "Branding" description: "These resources exist to help you use Mesh's assets." ------------------------------------------------------------------- import Link from "next/link"; import Image from "next/image"; ## Logo \\\[!toc\] The Mesh logo is available in two color schemes: black and white. You can use the logo in either color scheme depending on your design needs. The logo is available in various sizes to suit different use cases. ![mesh-black-512](https://meshjs.dev/logo-mesh/black/logo-mesh-black-512x512.png) Download black logo: SVG {\["16x16", "32x32", "64x64", "128x128", "256x256", "512x512"\].map((size) => ( {size} ))} ![mesh-white-512](https://meshjs.dev/logo-mesh/white/logo-mesh-white-512x512.png) Download white logo: SVG {\["16x16", "32x32", "64x64", "128x128", "256x256", "512x512"\].map((size) => ( {size} ))} ![mesh-black-title-512](https://meshjs.dev/logo-mesh/meshlogo-with-title-black.svg) Download black logo with title: SVG ![mesh-white-title-512](https://meshjs.dev/logo-mesh/meshlogo-with-title-white.svg) Download white logo with title: SVG ![mesh-background](https://meshjs.dev/logo-mesh/mesh.png) Download logo with background: PNG \# Project Catalyst URL: /about/catalyst Proposals that we have submitted to Project Catalyst and its progress. \*\*\* title: "Project Catalyst" description: "Proposals that we have submitted to Project Catalyst and its progress." ------------------------------------------------------------------------------------- import { Status } from "@/components/ui/Status"; import { TaskList } from "@/components/ui/TaskList"; import Link from "fumadocs-core/link"; import { CatalystCard } from "@/components/ui/CatalystCard"; import { fund13, fund12, fund11, fund10 } from "@/data/catalyst"; { fund13 && ( <> Fund13 ====== { fund13.map((fundItem, idx) => ( )) } )} { fund12 && ( <> Fund12 ====== { fund12.map((fundItem, idx) => ( )) } )} { fund11 && ( <> Fund11 ====== { fund11.map((fundItem, idx) => ( )) } )} { fund10 && ( <> Fund10 ====== { fund10.map((fundItem, idx) => ( )) } )} \# Feature complete Web3 SDK URL: /about Our enterprise-ready SDK is professionally designed, robust, and developer-friendly. With simple transaction builders, seamless wallet integrations, and reliable data services, building Web3 applications has never been this effortless. \*\*\* title: "Feature complete Web3 SDK" description: "Our enterprise-ready SDK is professionally designed, robust, and developer-friendly. With simple transaction builders, seamless wallet integrations, and reliable data services, building Web3 applications has never been this effortless." ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- import Image from 'next/image'; import Link from 'fumadocs-core/link'; import { SiDiscord, SiX, SiGithub } from "@icons-pack/react-simple-icons"; import { GlobeAltIcon } from '@heroicons/react/24/outline'; import {team} from "@/data/team"; Our Team ======== { team.map((member) => ( ![{member.name}](https://meshjs.dev/%7B%60/team/$%7Bmember.image%7D%60%7D) {member.name} ============= {member.twitter && } {member.linkedin && ( )} )) } What are we working on? ======================= Check out our GitHub milestones to see what we are currently working on. Incorporation ============= MeshJS Pte. Ltd. is a company registered in Singapore since 2023, with the registration number (UEN): 202344120W. Status ====== Stay up to date with our latest releases, tests and build status. ### Published on NPM ![](https://img.shields.io/npm/v/%40meshsdk%2Fcore?style=for-the-badge) ### Build status ![](https://github.com/meshjs/mesh/actions/workflows/build.yml/badge.svg) ### Publish status ![](https://github.com/meshjs/mesh/actions/workflows/publish.yml/badge.svg) \# Support Us URL: /about/support-us Thank you for your interest in Mesh, we appreciate any kind of support! Here are some ways you can support us. \*\*\* title: "Support Us" description: "Thank you for your interest in Mesh, we appreciate any kind of support! Here are some ways you can support us." ----------------------------------------------------------------------------------------------------------------------------- import Link from 'fumadocs-core/link'; import Image from 'next/image'; import { cn } from '@/lib/cn'; import { buttonVariants } from '@/components/ui/button'; import { useTheme } from 'next-themes'; \# Follow us on Twitter \\\[!toc\] Follow us on Twitter so you get updated with the latest development! Follow us on Twitter ![support-x](https://meshjs.dev/support/x-logo.svg) \# Donate to Mesh \\\[!toc\] Your support for this open-source SDK will go a long way. So thank you! Coming soon {/\* surprise svg has kinda padding which doesnt look when not able to right align \*/} \# Star Mesh GitHub Repo \\\[!toc\] Visit our GitHub and star it! Star GitHub repo ![support-github](https://meshjs.dev/support/github-mark-white.svg) \# Add Mesh Badge in your Application \\\[!toc\] Add our beautiful Mesh Badge to give your users confidence knowing that your application is running on top of a solid SDK. \`\`\`tsx import { MeshBadge } from '@meshsdk/react'; export default function Page() { return ( <> ); } \`\`\` ![support-mesh](https://meshjs.dev/support/meshbadge.png) \# Join our Discord Server \\\[!toc\] Come and talk to us in our Discord server. Join Mesh's Discord server ![support-discord](https://meshjs.dev/support/discord.png) \# Mesh AI Features URL: /ai We've built AI tools to help you work with Mesh faster \*\*\* title: "Mesh AI Features" description: "We've built AI tools to help you work with Mesh faster" --------------------------------------------------------------------- import Link from "fumadocs-core/link"; ## Ask MeshAI Ask MeshAI is the chatbot on the website which answers your queries instantly and accurately by utilizing the contextual retrieval built on top of traditional RAG. ### How it works: MeshAI searches through all the vector embeddings of Mesh documentation, code examples and starter templates to find the right answer for your question. It uses contextual retrieval technique to pull closet vectors to your query and make an LLM call to produce accurate answer without making things up. ### Example Response: In this demo, we create a transaction that transfers ADA back to the sender’s own address using MeshAI. ## LLMs.txt Mesh provides llms.txt file that is easily understood by AI tools. This file contains everything from Mesh documentation and code examples. This file can be plugged into any AI code editors and will be instantly indexed to help you code with AI using up-to-date documentation from Mesh. Because the file follows a standardized AI-friendly format, code generation stays consistent across different tools. Since it's written in markdown text, it's just as easy for humans to browse as it is for machines to process. You can find llms.txt file here. AI code editors like Cursor let you add and index documentation, so you can reference it directly in your chats. For example, you can bring Mesh docs into Cursor by typing @Docs → Add new doc. A modal will open where you can paste the link to the /llms.txt file. Once added, the doc becomes available as context, making it easier and faster to build apps with AI. ## Mesh MCP Setup Use Mesh MCP to access Mesh docs and get coding/debugging help directly in VS Code, Cursor, or Claude Desktop. ### Quick Install (Cursor) If you're using Cursor, you can install Mesh MCP with one click: [![Add mesh-mcp MCP server to Cursor](https://cursor.com/deeplink/mcp-install-light.svg)](https://cursor.com/en-US/install-mcp?name=mesh-mcp&config=eyJuYW1lIjoibWVzaC1tY3Atc2VydmVyIiwiZW52Ijp7IkFQSV9LRVkiOiJ5b3VyLWFwaS1rZXkiLCJNT0RFTCI6InlvdXItcHJlZmVycmVkLW1vZGVsIn0sImNvbW1hbmQiOiJucHggLXkgbWVzaGpzLW1jcCJ9) [![Add mesh-mcp MCP server to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=mesh-mcp&config=eyJuYW1lIjoibWVzaC1tY3Atc2VydmVyIiwiZW52Ijp7IkFQSV9LRVkiOiJ5b3VyLWFwaS1rZXkiLCJNT0RFTCI6InlvdXItcHJlZmVycmVkLW1vZGVsIn0sImNvbW1hbmQiOiJucHggLXkgbWVzaGpzLW1jcCJ9) \*\*Note:\*\* After clicking the button, you'll need to configure your \`API\_KEY\` and \`MODEL\` environment variables in Cursor's MCP settings. ### CLI Setup (Claude Desktop) If you have the \`claude\` CLI installed, you can add Mesh MCP with: \`\`\`bash claude mcp add-json mesh-mcp '{ "command": "npx", "args": \["-y", "meshjs-mcp"\], "env": { "API\_KEY": "your-api-key", "MODEL": "your-preferred-model" } }' \`\`\` ### Manual Setup Add this to your MCP server settings: \`\`\`ts { "servers": { "mesh-mcp": { "name": "mesh-mcp-server", "command": "npx", "args": \["-y", "meshjs-mcp"\], "env": { "API\_KEY": "your-api-key", "MODEL": "your-preferred-model" } } } } \`\`\` ### Setup notes 1. Replace your-api-key with your API key from the supported providers (OpenAI, Gemini, or Anthropic Claude). 2. Set MODEL to the model you want to use from respective provider. 3. Restart your editor after saving the config. 4. Start the server manually (restarting alone doesn't run it): \* VS Code: Open Command Palette (Cmd+Shift+P), search "MCP: List Servers", select "mesh-mcp", and choose "Run Server". \* Cursor: Similar to VS Code, use the MCP extension's list servers command to run it. \* Claude Desktop: The server should start automatically on launch if configured correctly in settings; check the MCP logs if issues arise. 5. Get help to code faster with Mesh MCP and AI editor ### Example ![mcp-example](https://meshjs.dev/ai/mcp-example.png) # Write a Smart Contract URL: /aiken/first-script Learn how to write your first Aiken script, with a simple redeemer \*\*\* title: "Write a Smart Contract" description: "Learn how to write your first Aiken script, with a simple redeemer" --------------------------------------------------------------------------------- import Link from "fumadocs-core/link"; ## Write your first smart contract in Aiken In this section, we will walk you through the process of writing a simple smart contract in Aiken. We will use the Visual Studio Code editor for this tutorial. You can use any other editor of your choice, but we recommend using Visual Studio Code for its rich feature set and support for Aiken. First, we create a new Aiken project within this project folder: \`\`\`bash $ aiken new meshjs/hello\_world $ cd hello\_world $ aiken check \`\`\` Remember to check your Aiken project by running \`aiken check\` after creating a new project and as you develop the contract. ### Write the smart contract \\\[!toc\] Let's create file for our validator, \`validators/hello\_world.ak\`: \`\`\`tsx use aiken/hash.{Blake2b\_224, Hash} use aiken/list use aiken/transaction.{ScriptContext} use aiken/transaction/credential.{VerificationKey} type Datum { owner: Hash, } type Redeemer { msg: ByteArray, } validator { fn hello\_world(datum: Datum, redeemer: Redeemer, context: ScriptContext) -> Bool { let must\_say\_hello = redeemer.msg == "Hello, World!" let must\_be\_signed = list.has(context.transaction.extra\_signatories, datum.owner) must\_say\_hello && must\_be\_signed } } \`\`\` The validator checks for two conditions: \* The redeemer message is \`Hello, World!\` \* The transaction is signed by the owner If both conditions are met, the validator returns \`true\`. Otherwise, it returns \`false\`. ## Compile and build Let's compile the smart contract with the Aiken CLI: \`\`\`tsx $ aiken build \`\`\` This command will compile the smart contract and generate the \`plutus.json\` file in the root folder. This file is a CIP-0057 Plutus blueprint, blueprint describes your on-chain contract and its binary interface. # Getting Started URL: /aiken/getting-started Setting up your system to compile Aiken smart contracts \*\*\* title: "Getting Started" description: "Setting up your system to compile Aiken smart contracts" ---------------------------------------------------------------------- import Link from "fumadocs-core/link"; ## Installation Instructions This section will guide you through the process of setting up your system compile Aiken smart contracts. You can skip this section if you have already set up your system or do not wish to compile the contract. ### Using aikup (on Linux & MacOS only) \\\[!toc\] If you are using Linux or MacOS, you can use the utility tool to download and manage Aiken's pre-compiled executables. You can install the Aiken CLI by running the following command in your terminal: \`\`\`bash $ curl -sSfL https://install.aiken-lang.org | bash \`\`\` After installing the Aiken CLI, you can use the following command to installs the latest version available. \`aikup\` is a cross-platform utility tool to download and manage Aiken's across multiple versions and for seamless upgrades. \`\`\`tsx $ aikup \`\`\` ### From sources (all platforms) \\\[!toc\] You will know you have successfully installed Rust and Cargo when you can run the following commands in your terminal: \`\`\`tsx $ rustc --version $ cargo --version \`\`\` Next, you will need to install the Aiken CLI. You can install the Aiken CLI by running the following command in your terminal: \`\`\`tsx $ cargo install aiken \`\`\` ### Check your installation \\\[!toc\] You will know you have successfully installed the Aiken CLI when you can run the following command in your terminal: \`\`\`tsx $ aiken -V \`\`\` If you face any issues, please check the installation instructions on the Aiken website for more information. ## Editor integrations Aiken language support for Visual Studio Code is provided by the Aiken extension. This extension provides syntax highlighting, code snippets, and error checking for Aiken smart contracts. Download the extension from the Visual Studio Code Marketplace or search \`aiken\` in the extensions tab of Visual Studio Code. ## Useful commands Here are some useful commands you can use to compile and test your scripts. \* \`aiken build\` - compiles the Aiken smart contract and generates a \`plutus.json\` file which contains type information, params, redeemer, datum, and the compiled code for each validator of your project and their corresponding hash digests to be used in addresses \* \`aiken check\` - type-check a project and run tests \* \`aiken docs\` - if you're writing a library, this generate documentation from you project \* \`aiken blueprint\` - provides utility functions to generate addresses, apply parameters and convert the build output to various formats # Aiken URL: /aiken A programming language and toolkit for developing smart contracts \*\*\* title: "Aiken" description: "A programming language and toolkit for developing smart contracts" icon: "icons/aiken.png" ----------------------- Aiken is a functional programming language created for Cardano smart contract development. It prioritizes on-chain execution and offers a user-friendly approach for building secure and efficient smart contracts, making it a valuable choice for developers aiming to create robust on-chain applications. import {linksAiken} from "@/data/links-aiken"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksAiken.map((card) => ( {card.title} {card.desc} ))} \# Build Transactions URL: /aiken/transactions Build transactions to interact with smart contracts \*\*\* title: "Build Transactions" description: "Build transactions to interact with smart contracts" ------------------------------------------------------------------ import Link from "fumadocs-core/link"; ## Create transaction to lock tokens In this section, we will create a simple UI that allows users to lock assets on the Cardano blockchain. First, we get initialze the \`PlutusScript\` and resolve the script address: \`\`\`tsx function getScript() { const scriptCbor = applyParamsToScript(compiledCode, \[\]); const script: PlutusScript = { code: scriptCbor, version: "V2", }; const scriptAddress = resolvePlutusScriptAddress(script, 0); return { script, scriptAddress }; } \`\`\` \`\`\`tsx const { scriptAddress } = await getScript(); \`\`\` We are using the \`resolvePlutusScriptAddress\` function to resolve the script address. You notice here we use the \`applyParamsToScript\`, which apply parameters to a script allows you to create a custom CIP-57 compliant script based on some inputs. For this script, we don't have any parameters to apply, but simply applied with double CBOR encoding to \`scriptCbor\`. Next, we get the wallet address hash: \`\`\`tsx async function getWalletAddress(wallet: BrowserWallet) { const addresses = await wallet.getUsedAddresses(); const address = addresses\[0\]; if (!address) { throw new Error("No address found"); } const hash = resolvePaymentKeyHash(address); return { address, hash }; } \`\`\` \`\`\`tsx const { hash } = await getWalletAddress(wallet); \`\`\` Here, we use the \`resolvePaymentKeyHash\` function to resolve the payment key hash of the wallet. Then, we create the \`Data\` (datum) object containing the address hash: \`\`\`tsx const datum: Data = { alternative: 0, fields: \[hash\], }; \`\`\` Finally, we prepare the transaction to lock the assets on the Cardano blockchain. \`\`\`tsx const tx = new Transaction({ initiator: wallet }); tx.sendLovelace( { address: scriptAddress, datum: { value: datum }, }, "5000000", ); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` ## Create transaction to redeem tokens In this section, we will walk you through the process of creating a transaction to redeem tokens. First, we need to get the script and script address. We can do this by calling the function we created in the previous section. \`\`\`tsx const { script, scriptAddress } = await getScript(); \`\`\` Next, we need to get the wallet address and its hash. We can do this by calling the function we created in the previous section. \`\`\`tsx const { address, hash } = await getWalletAddress(wallet); \`\`\` As the contracts requires the owner's address in the datum field, we are creating a new datum with the owner's address. We create the \`Data\` (datum) object containing the address hash: \`\`\`tsx const datum: Data = { alternative: 0, fields: \[hash\], }; \`\`\` After that, we get the UTXO in the script based on the datum: \`\`\`tsx async function getAssetUtxo({ scriptAddress, asset, datum, }: { scriptAddress: string; asset: string; datum: any; }) { const provider = getProvider(); const utxos = await provider.fetchAddressUTxOs( scriptAddress, asset, ); const dataHash = resolveDataHash(datum); let utxo = utxos.find((utxo: any) => { return utxo.output.dataHash == dataHash; }); return utxo; } \`\`\` \`\`\`tsx const assetUtxo = await getAssetUtxo({ scriptAddress: scriptAddress, asset: "lovelace", datum: datum, }); \`\`\` Finally, we prepare the transaction to redeem the tokens: \`\`\`tsx const redeemer = { data: { alternative: 0, fields: \["Hello, World!"\] } }; const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datum, redeemer: redeemer, }) .sendValue(address, assetUtxo) .setRequiredSigners(\[address\]); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` Here you notice that in the \`redeemer\`. As the validator requires, here we specify \`Hello, World!\`, which is the message we need to provide to unlock the tokens. For the transaction, we use the \`redeemValue\` function to redeem the locked assets, the \`sendValue\` function to send the assets to the owner's address, and the \`setRequiredSigners\` function to set the required signers. # Mesh API URL: /apis From wallet integrations to transaction builders, Mesh makes Web3 development easy with reliable, scalable, and well-engineered APIs & developer tools. \*\*\* title: "Mesh API" description: "From wallet integrations to transaction builders, Mesh makes Web3 development easy with reliable, scalable, and well-engineered APIs & developer tools." ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; import {linksApi} from "@/data/links-api"; import Link from "next/link"; {linksApi.map((card) => ( {card.title} {card.desc} ))} \# Aiken Hello World URL: /guides/aiken undefined \*\*\* title: "Aiken Hello World" icon: "guides/aiken.png" ------------------------ import Link from "fumadocs-core/link"; Aiken is a functional programming language for Cardano smart contract development. It prioritizes on-chain execution and offers a user-friendly approach for building secure and efficient smart contracts. This tutorial walks you through writing a smart contract in Aiken and creating two transactions to lock and unlock assets on the Cardano blockchain. Try the live demo. View the code on the GitHub repository. ## System setup Set up your system to compile Aiken smart contracts. Skip this section if you have already set up your system or do not wish to compile the contract. Check the installation instructions on the Aiken website for more information. ### Using aikup (on Linux & MacOS only) \\\[!toc\] Linux and MacOS users can use the utility tool to download and manage Aiken's pre-compiled executables. Install the Aiken CLI: \`\`\`tsx $ curl -sSfL https://install.aiken-lang.org | bash $ aikup \`\`\` ### From sources (all platforms) \\\[!toc\] Aiken is written in Rust. Install Rust and Cargo to compile the smart contract. Install Rust via the Rust website. Install Cargo, the Rust package manager, via the Cargo website. Verify installation: \`\`\`tsx $ rustc --version $ cargo --version \`\`\` Install the Aiken CLI: \`\`\`tsx $ cargo install aiken \`\`\` ### Check your installation \\\[!toc\] Verify the Aiken CLI installation: \`\`\`tsx $ aiken -V \`\`\` If issues arise, check the Aiken website. ## Writing a smart contract with Aiken Write a smart contract in Aiken and create two transactions to lock and unlock assets. Read more about this example on the Aiken website. ### Create a new project \\\[!toc\] Create a new project. Refer to this guide for creating a new Next.js project. Create a new Aiken project within this project folder: \`\`\`tsx $ aiken meshjs/hello\_world $ cd hello\_world $ aiken check \`\`\` Run \`aiken check\` to verify your project. ### Write the smart contract \\\[!toc\] Create \`validators/hello\_world.ak\`: \`\`\`tsx use aiken/hash.{Blake2b\_224, Hash} use aiken/list use aiken/transaction.{ScriptContext} use aiken/transaction/credential.{VerificationKey} type Datum { owner: Hash, } type Redeemer { msg: ByteArray, } validator { fn hello\_world(datum: Datum, redeemer: Redeemer, context: ScriptContext) -> Bool { let must\_say\_hello = redeemer.msg == "Hello, World!" let must\_be\_signed = list.has(context.transaction.extra\_signatories, datum.owner) must\_say\_hello && must\_be\_signed } } \`\`\` This validator checks that the redeemer message is "Hello, World!" and that the transaction is signed by the datum owner. Returns \`true\` if both conditions are met; otherwise \`false\`. Compile the smart contract: \`\`\`tsx $ aiken build \`\`\` This generates \`plutus.json\` in the root folder. This file is a CIP-0057 Plutus blueprint, describing your on-chain contract and its binary interface. ## Creating locking transaction ### Preparing the frontend \\\[!toc\] Prepare the frontend to allow users to lock and unlock assets. Install \`cbor\`: \`\`\`tsx $ npm install cbor \`\`\` Create a \`data\` folder and copy \`plutus.json\` into it. Open \`pages/index.tsx\` and import the packages: \`\`\`tsx import { resolvePlutusScriptAddress, Transaction, KoiosProvider, resolveDataHash, resolvePaymentKeyHash, } from "@meshsdk/core"; import type { PlutusScript, Data } from "@meshsdk/core"; import { CardanoWallet, useWallet } from "@meshsdk/react"; import plutusScript from "../data/plutus.json"; import cbor from "cbor"; \`\`\` ### Importing the contract \\\[!toc\] Import the contract: \`\`\`tsx const script: PlutusScript = { code: cbor .encode(Buffer.from(plutusScript.validators\[0\].compiledCode, "hex")) .toString("hex"), version: "V2", }; const scriptAddress = resolvePlutusScriptAddress(script, 0); \`\`\` Use \`plutus.json\` to create the script and \`resolvePlutusScriptAddress\` to resolve the address. We encode the compiled validator code with cbor because the validator uses a flat format, unlike the format expected by cardano-cli and the serialization library. ### Locking assets \\\[!toc\] Create the transaction to lock assets: \`\`\`tsx const hash = resolvePaymentKeyHash((await wallet.getUsedAddresses())\[0\]); const datum: Data = { alternative: 0, fields: \[hash\], }; const tx = new Transaction({ initiator: wallet }).sendLovelace( { address: scriptAddress, datum: { value: datum }, }, "5000000" ); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` This transaction locks assets. \`resolvePaymentKeyHash\` resolves the wallet's key hash. \`sendLovelace\` sends lovelace to the script address. The contract requires the owner's address in the datum. We build, sign, and submit the transaction. ## Unlocking assets Create the transaction to unlock assets. Retrieve the UTXO of the locked assets: \`\`\`tsx async function \_getAssetUtxo({ scriptAddress, asset, datum }) { const utxos = await koios.fetchAddressUTxOs(scriptAddress, asset); const dataHash = resolveDataHash(datum); let utxo = utxos.find((utxo: any) => { return utxo.output.dataHash == dataHash; }); return utxo; } \`\`\` Create the unlock transaction: \`\`\`tsx const scriptAddress = resolvePlutusScriptAddress(script, 0); const address = (await wallet.getUsedAddresses())\[0\]; const hash = resolvePaymentKeyHash(address); const datum: Data = { alternative: 0, fields: \[hash\], }; const assetUtxo = await \_getAssetUtxo({ scriptAddress: scriptAddress, asset: "lovelace", datum: datum, }); const redeemer = { data: { alternative: 0, fields: \['Hello, World!'\] } }; // create the unlock asset transaction const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datum, redeemer: redeemer, }) .sendValue(address, assetUtxo) .setRequiredSigners(\[address\]); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` This transaction unlocks assets. \`resolvePlutusScriptAddress\` resolves the script address. \`resolvePaymentKeyHash\` resolves the wallet's key hash. \`\_getAssetUtxo\` retrieves the locked asset UTXO. \`redeemValue\` redeems the assets. \`sendValue\` sends assets to the owner. \`setRequiredSigners\` sets the required signers. The validator requires "Hello, World!" as the redeemer message. We build, sign, and submit the transaction. Check the full code on GitHub. # Implement Custom Provider URL: /guides/custom-provider undefined \*\*\* title: "Implement Custom Provider" icon: "guides/implement-custom-provider.png" -------------------------------------------- import Link from "fumadocs-core/link"; Mesh offers options like Blockfrost or Koios (see Providers). These providers access the Cardano blockchain to retrieve data, such as smart contract UTXOs, or submit signed transactions. Customize a provider to utilize GraphQL, cardano-cli, or websocket with Mesh SDK. Any query method works if the output conforms to the interface. This guide demonstrates how to create a custom provider and integrate it with Mesh to work with the transaction builder. ## How it works JavaScript interfaces define the application structure and syntax for classes. Classes based on an interface must abide by its structure. Providers implement one or more interfaces. For example, the \*\*KoiosProvider\*\* Class implements \*\*IFetcher\*\* and \*\*ISubmitter\*\*. It must strictly conform to their structures. \*\*KoiosProvider\*\* implements \*\*IFetcher\*\* and \*\*ISubmitter\*\* using the \*\*implement\*\* keyword: \`\`\`tsx export class KoiosProvider implements IFetcher, ISubmitter {} \`\`\` Visit the GitHub repo at packages/module/src/common/contracts for the latest interfaces. Create a custom provider class by creating functions with the same name, input parameters, and return type as the defined methods for each interface. This ensures compatibility with Mesh functions. IFetcher has 6 functions (see packages/module/src/common/contracts/fetcher.ts): \`\`\`tsx import type { AccountInfo, AssetMetadata, Protocol, UTxO } from '@mesh/common/types'; export interface IFetcher { fetchAccountInfo(address: string): Promise; fetchAddressUTxOs(address: string, asset?: string): Promise; fetchAssetAddresses(asset: string): Promise<{ address: string; quantity: string }\[\]>; fetchAssetMetadata(asset: string): Promise; fetchHandleAddress(handle: string): Promise; fetchProtocolParameters(epoch: number): Promise; } \`\`\` \*\*KoiosProvider\*\* must implement these functions as defined in \*\*IFetcher\*\*. ## Implement your own provider Review existing providers to get started. Visit packages/module/src/providers. Use this codebase as a starting point: \`\`\`tsx import { IFetcher, ISubmitter } from "@mesh/common/contracts"; import { parseHttpError } from "@mesh/common/utils"; import type { AccountInfo, AssetMetadata, Protocol, UTxO, } from "@mesh/common/types"; export class NAMEProvider implements IFetcher, ISubmitter { constructor(network: "") { // init variables and other Javascript libraries needed } async fetchAccountInfo(address: string): Promise { try { // return { // ... // }; } catch (error) { throw parseHttpError(error); } } async fetchAddressUTxOs(address: string, asset?: string): Promise { try { // return \[ // ... // \]; } catch (error) { throw parseHttpError(error); } } async fetchAssetAddresses( asset: string ): Promise<{ address: string; quantity: string }\[\]> { try { // return AssetAddresses; } catch (error) { throw parseHttpError(error); } } async fetchAssetMetadata(asset: string): Promise { try { // return \[ // ... // \]; } catch (error) { throw parseHttpError(error); } } async fetchHandleAddress(handle: string): Promise { try { // return handleAddress; } catch (error) { throw parseHttpError(error); } } async fetchProtocolParameters(epoch = Number.NaN): Promise { try { // return { // ... // }; } catch (error) { throw parseHttpError(error); } } async submitTx(tx: string): Promise { try { // if (status === 200) // return txHash; } catch (error) { throw parseHttpError(error); } } } \`\`\` This code may change if the interface updates. Your provider may require different interfaces depending on its purpose. ## Implement constructor and functions Define the constructor. A constructor creates and initializes a class. It runs when creating an object using the \*\*new\*\* keyword. Providers usually require basic information, such as the network or API key. \*\*KoiosProvider\*\* requires \*\*network\*\* and \*\*version\*\* (optional): \`\`\`tsx private readonly \_axiosInstance: AxiosInstance; constructor(network: 'api' | 'preview' | 'preprod' | 'guild', version = 0) { this.\_axiosInstance = axios.create({ baseURL: \`https://${network}.koios.rest/api/v${version}\`, }); } \`\`\` This constructor initializes the Axios instance with user-provided parameters. Define each function required by the interface. Understand the following: \* Query method for the blockchain provider. \* Interface input parameters. \* Blockchain provider input parameters. \* Expected interface outputs. \* Blockchain provider return values. Map data correctly from the blockchain provider to the interface's required data type. For example, \*\*KoiosProvider\*\* implements \*\*fetchProtocolParameters()\*\* to map Koios responses to the Protocol data type: \`\`\`tsx async fetchProtocolParameters(epoch: number): Promise { try { const { data, status } = await this.\_axiosInstance.get( \`epoch\_params?\_epoch\_no=${epoch}\`, ); if (status === 200) return { coinsPerUTxOSize: data\[0\].coins\_per\_utxo\_size, collateralPercent: data\[0\].collateral\_percent, decentralisation: data\[0\].decentralisation, epoch: data\[0\].epoch\_no, keyDeposit: data\[0\].key\_deposit, maxBlockExMem: data\[0\].max\_block\_ex\_mem.toString(), maxBlockExSteps: data\[0\].max\_block\_ex\_steps.toString(), maxBlockHeaderSize: data\[0\].max\_bh\_size, maxBlockSize: data\[0\].max\_block\_size, maxCollateralInputs: data\[0\].max\_collateral\_inputs, maxTxExMem: data\[0\].max\_tx\_ex\_mem.toString(), maxTxExSteps: data\[0\].max\_tx\_ex\_steps.toString(), maxTxSize: data\[0\].max\_tx\_size, maxValSize: data\[0\].max\_val\_size.toString(), minFeeA: data\[0\].min\_fee\_a, minFeeB: data\[0\].min\_fee\_b, minPoolCost: data\[0\].min\_pool\_cost, poolDeposit: data\[0\].pool\_deposit, priceMem: data\[0\].price\_mem, priceStep: data\[0\].price\_step, }; throw parseHttpError(data); } catch (error) { throw parseHttpError(error); } } \`\`\` Implement every function specified by the interface and test them. Create a pull request if your provider benefits the Cardano developer community. # Guides URL: /guides Guides for web developers and blockchain full-stack developers. \*\*\* title: "Guides" description: "Guides for web developers and blockchain full-stack developers." icon: BookOpenIcon ------------------ import {linksGuides} from "@/data/links-guides"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksGuides.map((card) => { const Icon = card.icon; return ( {Icon && ( )} {card.title} {card.desc} ); })} \# Minting Application URL: /guides/minting-on-nodejs undefined \*\*\* title: "Minting Application" icon: "guides/minting-application.png" -------------------------------------- import Link from "fumadocs-core/link"; Mint assets with \*\*MeshWallet\*\* on Node.js. ## System setup ### 1. Visual Studio Code \\\[!toc\] Download and install Visual Studio Code. ### 2. Node.js \\\[!toc\] Install the Long-Term Support (LTS) version of Node.js. ## Project setup Create a new folder and initialize a Node.js project: \`\`\`tsx npm init \`\`\` Install \*\*typescript\*\* and \*\*Mesh\*\*: \`\`\`tsx npm install --dev typescript && npm install @meshsdk/core \`\`\` Initialize TypeScript: \`\`\`tsx npx tsc --init \`\`\` Open \*\*tsconfig.json\*\* and define the configurations: \`\`\`tsx { ... "target": "ESNext", "module": "ESNext", "moduleResolution": "Node", "outDir": "dist", ... } \`\`\` Open \*\*package.json\*\* and add the configurations: \`\`\`tsx { ... "type": "module", "scripts": { "start": "tsc && node ./dist/main.js" } ... } \`\`\` ## Build the minting transaction ### 1. Create list of NFT's metadata \\\[!toc\] Create \`metadata.ts\` and define the NFT metadata: \`\`\`tsx export const metadata: { \[assetName: string\]: any } = { MeshToken01: { name: "Mesh Token 1", image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "Just a purple coin.", artist: "This NFT was minted by Mesh (https://meshjs.dev/).", }, MeshToken02: { name: "Mesh Token 2", image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "This is suppose to be a gold coin.", artist: "This NFT was minted by Mesh (https://meshjs.dev/).", }, MeshToken03: { name: "Mesh Token 3", image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "A coin with a M on it.", artist: "This NFT was minted by Mesh (https://meshjs.dev/).", }, }; \`\`\` ### 2. Create a list of recipients \\\[!toc\] Create \`recipients.ts\` and specify the recipients: \`\`\`tsx export const recipients: { \[recipient: string\]: string } = { addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr: "MeshToken01", addr\_test1qqlcxawu4gxarenqvdqyw0tqyjy69mrgsmfqhm6h65jwm4vvldqg2n2p8y4kyjm8sqfyg0tpq9042atz0fr8c3grjmyscxry4r: "MeshToken02", addr\_test1qq5tay78z9l77vkxvrvtrv70nvjdk0fyvxmqzs57jg0vq6wk3w9pfppagj5rc4wsmlfyvc8xs7ytkumazu9xq49z94pqzl95zt: "MeshToken03", }; \`\`\` ### 3. Create main.ts and import the packages: \\\[!toc\] Create \`main.ts\` and import the required packages and files: \`\`\`tsx import { MeshWallet, Transaction, ForgeScript, BlockfrostProvider, resolveTxHash, } from '@meshsdk/core'; import type { Mint, AssetMetadata } from '@meshsdk/core'; import { metadata } from './metadata.js'; import { recipients } from './recipients.js'; \`\`\` ### 4. Define variables \\\[!toc\] Define minting variables. Use your own wallet to mint your own collection. This example uses: \`\`\`tsx const demoCLIKey = { paymentSkey: '5820aaca553a7b95b38b5d9b82a5daa7a27ac8e34f3cf27152a978f4576520dd6503', stakeSkey: '582097c458f19a3111c3b965220b1bef7d548fd75bc140a7f0a4f080e03cce604f0e', }; const networkId = 0; const blockfrostKey = 'BLOCKFROST\_KEY\_HERE'; \`\`\` ### 5. Build the minting transaction \\\[!toc\] This guide builds a minting transaction, but the process applies to any transaction. Learn more about Transaction. Initialize a blockchain provider. This guide uses \*\*BlockfrostProvider\*\*: \`\`\`tsx const provider = new BlockfrostProvider(blockfrostKey); \`\`\` Initialize \*\*MeshWallet\*\* and its forging script. This example uses CLI generated keys, but you can load your wallet with a private key or mnemonic phrase. Learn more about MeshWallet. \`\`\`tsx const wallet = new MeshWallet({ networkId: networkId, fetcher: provider, submitter: provider, key: { type: 'cli', payment: demoCLIKey.paymentSkey, stake: demoCLIKey.stakeSkey, }, }); const walletAddress = wallet.getPaymentAddress(); const forgingScript = ForgeScript.withOneSignature(walletAddress); \`\`\` Create a new Transaction, loop through each recipient, and mint assets with \*\*mintAsset\*\* (Learn more about minting transactions): \`\`\`tsx const tx = new Transaction({ initiator: wallet }); for (let recipient in recipients) { const recipientAddress = recipient; const assetName = recipients\[recipient\]; const assetMetadata: AssetMetadata = metadata\[assetName\]; const asset: Mint = { assetName: assetName, assetQuantity: '1', metadata: assetMetadata, label: '721', recipient: recipientAddress }; tx.mintAsset(forgingScript, asset); } \`\`\` Sign and submit the transaction: \`\`\`tsx const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, false); const txHash = await wallet.submitTx(signedTx); \`\`\` Execute the script: \`\`\`tsx npm start \`\`\` A successful transaction returns a transaction hash, mints multiple assets, and sends them to multiple recipients. # Multi-Signatures Transaction URL: /guides/multisig-minting undefined \*\*\* title: "Multi-Signatures Transaction" icon: "guides/multi-signatures-transaction.png" ----------------------------------------------- import Link from "fumadocs-core/link"; Multi-signature (multi-sig) transactions require more than one signature before broadcasting. Include two or more signers, such as wallets (Browser Wallet or Mesh Wallet) or Plutus scripts. Build a multi-sig transaction for minting. Two wallets are involved: 1. Client wallet (user buying the asset) 2. Application wallet (holds the forging script) Connect to the user's CIP30 wallet (\`BrowserWallet\`) to request a minting transaction. The backend application wallet (\`MeshWallet\`) builds the transaction, and the user signs it. Check out the code here. ## Connect wallet (client) Connect the client's wallet and obtain their address and UTXOs. Connect with \`BrowserWallet\`: \`\`\`tsx import { BrowserWallet } from '@meshsdk/core'; const wallet = await BrowserWallet.enable(walletName); \`\`\` Or use the \`CardanoWallet\` component: \`\`\`tsx import { CardanoWallet, useWallet } from "@meshsdk/react"; export default function Page() { const { wallet, connected } = useWallet(); return } \`\`\` Get the client's address and UTXOs: \`\`\`tsx const recipientAddress = await wallet.getChangeAddress(); const utxos = await wallet.getUtxos(); \`\`\` The change address receives the minted NFTs and change. The client's UTXOs are needed to build the transaction. Select required UTXOs using \`experimentalSelectUtxos\`: \`\`\`tsx const assetMap = new Map(); assetMap.set("lovelace", mintingFee); const selectedUtxos = experimentalSelectUtxos(assetMap, utxos, "5000000"); \`\`\` \`experimentalSelectUtxos\` returns required UTXOs. \`mintingFee\` is the minting cost; \`5000000\` buffers the transaction fee. Send \`selectedUtxos\` and \`recipientAddress\` to the backend. ## Build transaction (application) Build the minting transaction. This guide assumes a backend server (e.g., Vercel API, NestJS, ExpressJS). Initialize a blockchain provider and Mesh Wallet. \`\`\`tsx const provider = new BlockfrostProvider( '' ); const meshWallet = new MeshWallet({ networkId: 0, fetcher: provider, submitter: provider, key: { type: 'mnemonic', words: yourMnemonic, }, }); \`\`\` Define the forging script: \`\`\`tsx const meshWalletAddress = meshWallet.getChangeAddress(); const forgingScript = ForgeScript.withOneSignature(meshWalletAddress); \`\`\` Define \`AssetMetadata\`: \`\`\`tsx const assetName = 'MeshToken'; const assetMetadata: AssetMetadata = { name: 'Mesh Token', image: 'ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua', mediaType: 'image/jpg', description: 'This NFT was minted by Mesh (https://meshjs.dev/).', }; \`\`\` Create the \`Mint\` object: \`\`\`tsx const asset: Mint = { assetName: assetName, assetQuantity: '1', metadata: assetMetadata, label: '721', recipient: recipientAddress, }; \`\`\` Create the transaction. Set inputs, mint asset, send lovelace, set change address, and build: \`\`\`tsx const tx = new Transaction({ initiator: meshWallet }); tx.setTxInputs(userUtxos); tx.mintAsset(forgingScript, asset); tx.sendLovelace(bankWalletAddress, mintingFee); tx.setChangeAddress(recipientAddress); const unsignedTx = await tx.build(); \`\`\` Optionally, mask metadata: \`\`\`tsx originalMetadata = Transaction.readMetadata(unsignedTx); \`\`\` Store \`originalMetadata\` to merge after user signature. Send the transaction to the client. ## Sign transaction (client) Obtain the client's signature. The wallet prompts for a password. Set partial sign to \`true\`. \`\`\`tsx const signedTx = await wallet.signTx(unsignedTx, true); \`\`\` ## Sign transaction (application) The backend signs with the application wallet: \`\`\`tsx const meshWalletSignedTx = await systemWallet.signTx(unsignedTx, true); \`\`\` Merge masked metadata if applicable: \`\`\`tsx const signedOriginalTx = Transaction.writeMetadata( unsignedTx, originalMetadata, ); const meshWalletSignedTx = await systemWallet.signTx( signedOriginalTx, true, ); \`\`\` ## Submit transaction (application) Submit the transaction: \`\`\`tsx const txHash = await wallet.submitTx(signedTx); \`\`\` You can now build multi-sig transactions. Check out the code here. # Develop your first Web3 App URL: /guides/nextjs undefined \*\*\* title: "Develop your first Web3 App" icon: "guides/develop-first-web-app.png" ---------------------------------------- import Link from "fumadocs-core/link"; Set up a Next.js application and connect it to the Cardano blockchain using Mesh. Create a simple application that allows users to connect their wallets and view assets. This guide focuses on Next.js, but Mesh works with Remix, React, Vue, and Svelte. Follow this guide or use the Mesh CLI to scaffold a new project. \`\`\`tsx npx meshjs your-app-name \`\`\` ## Setup Next.js ### 1. Create project folder and open Visual Studio Code \\\[!toc\] Create a new folder. Open Visual Studio Code and drag the folder into it. ### 2. Create Next.js app \\\[!toc\] Open the \*\*Terminal\*\* and create a new Next.js application: \`\`\`tsx npx create-next-app@latest --typescript . \`\`\` \`\`\`tsx Need to install the following packages: Ok to proceed? (y) ✔ Would you like to use ESLint? … Yes ✔ Would you like to use Tailwind CSS? … Yes ✔ Would you like your code inside a \`src/\` directory? … Yes ✔ Would you like to use App Router? … No ✔ Would you like to use Turbopack for next dev? … No ✔ Would you like to customize the import alias (@/\* by default)? … No \`\`\` ### 3. Start development server \\\[!toc\] Start the development server: \`\`\`tsx npm run dev \`\`\` Visit \[http://localhost:3000\](http://localhost:3000) to view your application. \`CTRL+C\` to stop. ## Setup Mesh Install Mesh: \`\`\`tsx npm install @meshsdk/core @meshsdk/react \`\`\` Your application is ready to connect wallets and transact. ## Connect wallet and view assets ### 1. Add MeshProvider \\\[!toc\] Open \*\*pages/\\\_app.tsx\*\*, import and include MeshProvider: \`\`\`tsx import "../styles/globals.css"; import "@meshsdk/react/styles.css"; import type { AppProps } from "next/app"; import { MeshProvider } from "@meshsdk/react"; function MyApp({ Component, pageProps }: AppProps) { return ( ); } export default MyApp; \`\`\` ### 2. Add connect wallet component and check wallet's assets \\\[!toc\] Add the connect wallet component. Link components to allow users to connect and query assets. Replace \*\*pages/index.tsx\*\* with: \`\`\`tsx import { useState } from "react"; import type { NextPage } from "next"; import { useWallet } from '@meshsdk/react'; import { CardanoWallet } from '@meshsdk/react'; const Home: NextPage = () => { const { connected, wallet } = useWallet(); const \[assets, setAssets\] = useState(null); const \[loading, setLoading\] = useState(false); async function getAssets() { if (wallet) { setLoading(true); const \_assets = await wallet.getAssets(); setAssets(\_assets); setLoading(false); } } return ( Connect Wallet ============== {connected && ( <> Get Wallet Assets ================= {assets ? ( `{JSON.stringify(assets, null, 2)}` ) : ( getAssets()} disabled={loading} style={{ margin: "8px", backgroundColor: loading ? "orange" : "grey", }} > Get Wallet Assets )} )} ); }; export default Home; \`\`\` Start the development server: \`\`\`tsx npm run dev \`\`\` Visit \[http://localhost:3000\](http://localhost:3000) to connect available wallets and view assets. Receive test ADA (tADA) from the official faucet. New to Cardano? Download a wallet. Tall Nupinks' Cardano Wallets 101 guide covers the fundamentals. ### 3. Try on your own \\\[!toc\] Implement a component to display the wallet address and lovelace amount. See the wallet page. # Mint an NFT Collection URL: /guides/nft-collection undefined \*\*\* title: "Mint an NFT Collection" icon: "guides/mint-nft-collection.png" -------------------------------------- import Youtube from "@/components/ui/Youtube"; \### Course Materials: \\\[!toc\] 1. Install Bun (\[https://bun.sh/docs/installation\](https://bun.sh/docs/installation)) 2. Fund Your Preprod Wallet (\[https://docs.cardano.org/cardano-testnets/tools/faucet\](https://docs.cardano.org/cardano-testnets/tools/faucet)) 3. Create a Blockfrost Preprod Project (\[https://blockfrost.io/dashboard\](https://blockfrost.io/dashboard)) 4. CIP-20 Definition (\[https://cips.cardano.org/cip/CIP-20\](https://cips.cardano.org/cip/CIP-20)) Learn how to mint native assets on the Cardano blockchain. You will: 1. Understand tokens on Cardano. 2. Build simple minting transactions. 3. Understand community standards for NFTs. ## Project Setup Install Bun (see course material #1). Initialize a new directory and run: \`\`\`tsx bun init bun install @meshsdk/core \`\`\` Generate and fund a Cardano wallet. Create \`/scripts/brew.ts\` and use MeshSDK to generate a wallet and log information. \`\`\`tsx import { MeshWallet } from "@meshsdk/core"; const words = MeshWallet.brew() as string\[\]; const mnemonicString = words.join(" "); console.log("mnemonic:", mnemonicString); const wallet = new MeshWallet({ key: { type: "mnemonic", words }, networkId: 0, }); console.log("Public Change Address:", await wallet.getChangeAddress()); \`\`\` Run the script: \`\`\`tsx bun run scripts/brew.ts \`\`\` Copy your public address and fund the wallet (course material #2). Obtain a Blockfrost Preprod project (course material #3). Copy your mnemonic and Blockfrost key into a \`.env\` file. ## Mint Your Collection In \`index.ts\`, use Mesh building blocks to interact with the blockchain. \`\`\`tsx import { MeshTxBuilder, MeshWallet, BlockfrostProvider } from "@meshsdk/core" const provider = new BlockfrostProvider(process.env.BLOCKFROST\_KEY!); const words = process.env.MNEMONIC!.split(" "); const wallet = new MeshWallet({ key: { type: "mnemonic", words }, networkId: 0, fetcher: provider, submitter: provider, }); const txBuilder = new MeshTxBuilder({ fetcher: provider }); const address = await wallet.getChangeAddress(); const utxos = await wallet.getUtxos(); const { pubKeyHash } = deserializeAddress(address); \`\`\` Create a minting ruleset using a native script to derive the policy ID. \`\`\`tsx const nativeScript: NativeScript = { type: "all", scripts: \[ { type: "before", slot: "90000000", // Any value beyond the current preprod absolute slot. When you read this, it's possible this slot has passed. }, { type: "sig", keyHash: pubKeyHash }, \], }; const forgeScript = ForgeScript.fromNativeScript(nativeScript); const policyId = resolveScriptHash(forgeScript); \`\`\` Write a function to generate on-chain metadata for image and attributes. \`\`\`tsx type AssetMetadata = { files: { mediaType: string; name: string; src: string; }\[\]; image: string; mediaType: string; name: string; }; function get721Metadata( name: string, attributes?: Record ): AssetMetadata { return { ...attributes, files: \[ { mediaType: "image/png", name, src: "ipfs://QmPS4PBvpGc2z6Dd6JdYqfHrKnURjtRGPTJWdhnAXNA8bQ", }, \], image: "ipfs://QmPS4PBvpGc2z6Dd6JdYqfHrKnURjtRGPTJWdhnAXNA8bQ", mediaType: "image/png", name, }; } \`\`\` Loop to create 9 unique tokens using the forge script. Commit, sign, and submit the transaction. \`\`\`tsx const metadata: { \[policyId: string\]: { \[assetName: string\]: AssetMetadata; }; } = { \[policyId\]: {} }; for (let i = 1; i < 10; i++) { const tokenName = "Asset #" + i; const tokenHex = stringToHex(tokenName); txBuilder.mint("1", policyId, tokenHex).mintingScript(forgeScript); metadata\[policyId\]!\[tokenName\] = get721Metadata(tokenName, { Attribute: i }); } const unsignedTx = await txBuilder .metadataValue(721, metadata) .changeAddress(address) .invalidHereafter(90000000) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); console.log("Submitted TX Hash:", txHash); \`\`\` Read the transaction hash and view the transaction on a chain explorer. # Resolve Node-Specific Imports Errors URL: /guides/node-specific-imports undefined \*\*\* title: "Resolve Node-Specific Imports Errors" icon: "guides/node-specific-imports.png" ---------------------------------------- import Link from "fumadocs-core/link"; Resolve Node-Specific Imports Errors (e.g., Buffer, TextEncoder) in Browser-Based Projects. Web-based projects (React, Vue, Svelte, Angular) may encounter errors like: \`\`\`bash Uncaught ReferenceError: Buffer is not defined \`\`\` or \`\`\`bash Module not found: Can't resolve 'buffer' \`\`\` or \`\`\`bash ReferenceError: TextEncoder is not defined \`\`\` These errors occur when code relies on Node.js-specific modules unavailable in browsers. Common examples: \* \`Buffer\` \* \`TextEncoder\` / \`TextDecoder\` \* \`crypto\` \* \`process\` \* Node’s built-in modules (\`fs\`, \`path\`, \`stream\`) Modern bundlers (Webpack 5, Vite, Next.js) do \*\*not\*\* automatically include Node polyfills. Use these guidelines to fix errors. ## 1. General Concepts \\\[!toc\] 1. \*\*Polyfill\*\*: Implements missing functionality (e.g., \`buffer\` package). 2. \*\*Fallback configuration\*\*: Replaces Node modules with browser-friendly versions. 3. \*\*npm dependencies\*\*: Install equivalents: \`\`\`tsx npm install buffer process stream-browserify crypto-browserify --save \`\`\` 4. \*\*ES Modules vs CommonJS\*\*: Ensure imports match bundler expectations. ## 2. Webpack \\\[!toc\] ### 2.1 Webpack 5 and Above \\\[!toc\] Webpack 5 excludes Node polyfills. Two approaches exist: \*\*Approach A: Use NodePolyfillPlugin\*\* Install the plugin: \`\`\`tsx npm install node-polyfill-webpack-plugin --save-dev \`\`\` Add to \`webpack.config.js\`: \`\`\`tsx const NodePolyfillPlugin = require('node-polyfill-webpack-plugin'); module.exports = { // ...your existing config plugins: \[ new NodePolyfillPlugin(), // ...other plugins \], }; \`\`\` This plugin injects common polyfills. \*\*Approach B: Use \`resolve.fallback\`\*\* For granular control, configure fallbacks manually: Install polyfills: \`\`\`tsx npm install buffer process stream-browserify --save \`\`\` Edit \`webpack.config.js\`: \`\`\`tsx module.exports = { // ... resolve: { fallback: { buffer: require.resolve('buffer/'), // or 'buffer' process: require.resolve('process/browser'), stream: require.resolve('stream-browserify'), // ...add more if needed }, }, }; \`\`\` Import polyfills if needed: \`\`\`tsx import { Buffer } from 'buffer'; global.Buffer = global.Buffer || Buffer; \`\`\` ## 3. Vite Vite uses Rollup, which lacks automatic Node polyfills. Use a Rollup plugin. Install the plugin: \`\`\`tsx npm install rollup-plugin-polyfill-node --save-dev \`\`\` Add to \`vite.config.js\`: \`\`\`tsx import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' // or react, svelte, etc. import rollupNodePolyFill from 'rollup-plugin-polyfill-node' export default defineConfig({ plugins: \[ vue(), // any other plugins \], build: { rollupOptions: { plugins: \[ rollupNodePolyFill() \], }, }, resolve: { alias: { // Optionally, if you want the polyfill for \`buffer\` and \`process\` as top-level buffer: 'rollup-plugin-polyfill-node/polyfills/buffer-es6', process: 'rollup-plugin-polyfill-node/polyfills/process-es6', // Add more if needed }, }, }) \`\`\` Use the polyfilled global if necessary: \`\`\`tsx import { Buffer } from 'buffer'; globalThis.Buffer = globalThis.Buffer || Buffer; \`\`\` ## 4. Next.js Next.js uses Webpack. Use \`node-polyfill-webpack-plugin\` or configure \`resolve.fallback\`. Example with \`node-polyfill-webpack-plugin\`: \`\`\`tsx // next.config.js const NodePolyfillPlugin = require('node-polyfill-webpack-plugin') module.exports = { webpack: (config, { isServer }) => { if (!isServer) { config.plugins.push(new NodePolyfillPlugin()) } return config }, } \`\`\` Node modules like \`Buffer\` or \`process\` are now polyfilled. ## 5. Create React App (CRA) Create React App \*\*v5\*\* uses Webpack 5. Use \`react-app-rewired\` or \`craco\` to override config. ### 5.1 Example with craco \\\[!toc\] Install craco: \`\`\`tsx npm install @craco/craco --save-dev \`\`\` Update \`package.json\` scripts: \`\`\`tsx { "scripts": { "start": "craco start", "build": "craco build", "test": "craco test" } } \`\`\` Create \`craco.config.js\`: \`\`\`tsx const NodePolyfillPlugin = require('node-polyfill-webpack-plugin'); module.exports = { webpack: { plugins: { add: \[ new NodePolyfillPlugin() \], }, configure: (webpackConfig) => { // Optionally, if you want to set fallback manually: webpackConfig.resolve.fallback = { ...webpackConfig.resolve.fallback, buffer: require.resolve('buffer'), process: require.resolve('process/browser'), } return webpackConfig; } }, }; \`\`\` Use polyfills: \`\`\`tsx import { Buffer } from 'buffer'; global.Buffer = global.Buffer || Buffer; \`\`\` ## 6. Angular Angular CLI uses Webpack. Polyfill Node modules: Install polyfills: \`\`\`tsx npm install buffer process stream-browserify --save \`\`\` Edit \`angular.json\` or use \`ngx-build-plus\`. Example with \`ngx-build-plus\`: \`\`\`tsx npm install ngx-build-plus --save-dev \`\`\` In \`angular.json\`: \`\`\`tsx { "projects": { "my-app": { "architect": { "build": { "builder": "ngx-build-plus:browser", "options": { // ... }, "configurations": { "production": { // ... } } }, "serve": { "builder": "ngx-build-plus:dev-server", "options": { // ... } } } } } } \`\`\` Create or update \`webpack.config.js\`: \`\`\`tsx const NodePolyfillPlugin = require('node-polyfill-webpack-plugin'); module.exports = { plugins: \[ new NodePolyfillPlugin(), \], resolve: { fallback: { buffer: require.resolve('buffer'), process: require.resolve('process/browser'), // ... }, }, }; \`\`\` Run Angular commands via \`ng build --extra-webpack-config webpack.config.js --output-hashing=none\`. ## 7. Svelte SvelteKit uses Vite or Rollup. Use Vite instructions (Section 3) or add the plugin to Rollup config: \`\`\`tsx // rollup.config.js import nodePolyfills from 'rollup-plugin-polyfill-node' export default { plugins: \[ nodePolyfills(), // ... \], // ... } \`\`\` # Prove Wallet Ownership URL: /guides/prove-wallet-ownership undefined \*\*\* title: "Prove Wallet Ownership" icon: "guides/cryptographically-prove-wallet-ownership.png" ----------------------------------------------------------- import Link from "fumadocs-core/link"; Cryptographically prove account ownership by signing data with a private key. Use the public address as an identifier and build authentication based on message signing. Use JSON Web Tokens (JWT) to pass authenticated user identity. Example uses: \* \*\*Authenticate sign-in\*\*: Prove account ownership. \* \*\*Authenticate actions\*\*: Authorize off-chain actions. \* \*\*Off-chain data\*\*: Display user-specific off-chain data. ## How it works !\[cryptographically-prove-wallet-ownership-process\](/guides/cryptographically-prove-wallet-ownership-process.png) Signing a message affirms control of the wallet address. Four ingredients are required: \* User wallet address \* Private key \* Public key \* Message to sign To verify ownership, provide a message for the user to sign. Validate the signature using the public key. ## Client: Connect Wallet and Get Staking Address The backend User model requires \`public address\` and \`nonce\` fields. The address must be unique. On Cardano, use the wallet's staking address as the identifier. Retrieve it using \`wallet.getUsedAddresses()\`. Get the user's staking address and send it to the backend: \`\`\`tsx const { wallet, connected } = useWallet(); async function frontendStartLoginProcess() { if (connected) { const userAddress = (await wallet.getUsedAddresses())\[0\]; // do: send request with 'userAddress' to the backend } } \`\`\` ## Server: Generate Nonce and Store in Database Generate a random nonce in the backend to create a unique authentication message. Use \`generateNonce()\` from Mesh. Check the database for the \`userAddress\`. Create a new entry for new users. Store the new nonce for existing users. \`\`\`tsx import { generateNonce } from '@meshsdk/core'; async function backendGetNonce(userAddress) { // do: if new user, create new user model in the database const nonce = generateNonce('I agree to the term and conditions of the Mesh: '); // do: store 'nonce' in user model in the database // do: return 'nonce' } \`\`\` Return the \`nonce\` for signing. ## Client: Verify ownership by signing the nonce Sign the nonce using the wallet's private key with \`wallet.signData(nonce, userAddress)\` (CIP-8). Request authorization. The app processes the generated signature. \`\`\`tsx async function frontendSignMessage(nonce) { try { const userAddress = (await wallet.getUsedAddresses())\[0\]; const signature = await wallet.signData(nonce, userAddress); // do: send request with 'signature' and 'userAddress' to the backend } catch (error) { // catch error if user refuse to sign } } \`\`\` ## Server: Verify Signature The backend retrieves the user and nonce from the database. Verify the signature using \`checkSignature\`. If verified, issue a JWT or session identifier. Prevent replay attacks by regenerating the nonce after verification. \`\`\`tsx import { checkSignature } from '@meshsdk/core'; async function backendVerifySignature(userAddress, signature) { // do: get 'nonce' from user (database) using 'userAddress' const result = checkSignature(nonce, signature, userAddress); // do: update 'nonce' in the database with another random string // do: do whatever you need to do, once the user has proven ownership // it could be creating a valid JSON Web Token (JWT) or session // it could be doing something offchain // it could just be updating something in the database } \`\`\` ## Putting It All Together Frontend implementation: \`\`\`tsx import { CardanoWallet, useWallet } from '@meshsdk/react'; export default function Page() { const { wallet, connected } = useWallet(); async function frontendStartLoginProcess() { if (connected) { const userAddress = (await wallet.getUsedAddresses())\[0\]; const nonce = await backendGetNonce(userAddress); await frontendSignMessage(nonce); } } async function frontendSignMessage(nonce) { try { const userAddress = (await wallet.getUsedAddresses())\[0\]; const signature = await wallet.signData(nonce, userAddress); await backendVerifySignature(userAddress, signature); } catch (error) { setState(0); } } return ( <> frontendStartLoginProcess()} /> ); } \`\`\` Server-side implementation: \`\`\`tsx import { checkSignature, generateNonce } from '@meshsdk/core'; async function backendGetNonce(userAddress) { const nonce = generateNonce('I agree to the term and conditions of the Mesh: '); return nonce; } async function backendVerifySignature(userAddress, signature) { // do: get 'nonce' from database const result = checkSignature(nonce, signature, userAddress); if(result){ // create JWT or approve certain process } else{ // prompt user that signature is not correct } } \`\`\` This technique authenticates sign-ins or any user action. # Smart Contract Transactions URL: /guides/smart-contract-transactions undefined \*\*\* title: "Smart Contract Transactions" icon: "guides/smart-contract-transactions.png" ---------------------------------------------- import Link from "fumadocs-core/link"; Build a marketplace where users list assets for sale and purchase listed assets. Sellers can update or cancel listings. ## Initialize the Plutus script Initialize the Plutus script. The compiled Plutus smart contract script CBOR is: \`\`\`tsx const scriptCbor = '59079559079201000033232323232323232323232323232332232323232323232222232325335333006300800530070043333573466e1cd55cea80124000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4060064d5d0a80619a80c00c9aba1500b33501801a35742a014666aa038eb9406cd5d0a804999aa80e3ae501b35742a01066a0300466ae85401cccd54070091d69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b9d69aba15002302f357426ae8940088c98c80c8cd5ce01981901809aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a8173ad35742a004605e6ae84d5d1280111931901919ab9c033032030135573ca00226ea8004d5d09aba2500223263202e33573805e05c05826aae7940044dd50009aba1500533501875c6ae854010ccd540700808004d5d0a801999aa80e3ae200135742a00460446ae84d5d1280111931901519ab9c02b02a028135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00460246ae84d5d1280111931900e19ab9c01d01c01a101b13263201b3357389201035054350001b135573ca00226ea80054049404448c88c008dd6000990009aa80a911999aab9f0012500a233500930043574200460066ae880080548c8c8cccd5cd19b8735573aa004900011991091980080180118061aba150023005357426ae8940088c98c8054cd5ce00b00a80989aab9e5001137540024646464646666ae68cdc39aab9d5004480008cccc888848cccc00401401000c008c8c8c8cccd5cd19b8735573aa0049000119910919800801801180a9aba1500233500f014357426ae8940088c98c8068cd5ce00d80d00c09aab9e5001137540026ae854010ccd54021d728039aba150033232323333573466e1d4005200423212223002004357426aae79400c8cccd5cd19b875002480088c84888c004010dd71aba135573ca00846666ae68cdc3a801a400042444006464c6403866ae700740700680640604d55cea80089baa00135742a00466a016eb8d5d09aba2500223263201633573802e02c02826ae8940044d5d1280089aab9e500113754002266aa002eb9d6889119118011bab00132001355012223233335573e0044a010466a00e66442466002006004600c6aae754008c014d55cf280118021aba200301313574200222440042442446600200800624464646666ae68cdc3a800a40004642446004006600a6ae84d55cf280191999ab9a3370ea0049001109100091931900899ab9c01201100f00e135573aa00226ea80048c8c8cccd5cd19b875001480188c848888c010014c01cd5d09aab9e500323333573466e1d400920042321222230020053009357426aae7940108cccd5cd19b875003480088c848888c004014c01cd5d09aab9e500523333573466e1d40112000232122223003005375c6ae84d55cf280311931900899ab9c01201100f00e00d00c135573aa00226ea80048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931900699ab9c00e00d00b135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98c802ccd5ce00600580489baa001232323232323333573466e1d4005200c21222222200323333573466e1d4009200a21222222200423333573466e1d400d2008233221222222233001009008375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c4664424444444660040120106eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc8848888888cc018024020c030d5d0a8049bae357426ae8940248cccd5cd19b875006480088c848888888c01c020c034d5d09aab9e500b23333573466e1d401d2000232122222223005008300e357426aae7940308c98c8050cd5ce00a80a00900880800780700680609aab9d5004135573ca00626aae7940084d55cf280089baa0012323232323333573466e1d400520022333222122333001005004003375a6ae854010dd69aba15003375a6ae84d5d1280191999ab9a3370ea0049000119091180100198041aba135573ca00c464c6401a66ae7003803402c0284d55cea80189aba25001135573ca00226ea80048c8c8cccd5cd19b875001480088c8488c00400cdd71aba135573ca00646666ae68cdc3a8012400046424460040066eb8d5d09aab9e500423263200a33573801601401000e26aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6401666ae7003002c02402001c4d55cea80089baa0012323333573466e1d40052002212200223333573466e1d40092000212200123263200733573801000e00a00826aae74dd5000891999ab9a3370e6aae74dd5000a40004008464c6400866ae700140100092612001490103505431001123230010012233003300200200122212200201'; \`\`\` Initialize the Plutus script: \`\`\`tsx const script: PlutusScript = { code: scriptCbor, version: 'V2', }; \`\`\` Resolve the Plutus script address using \`resolvePlutusScriptAddress\`. Input the \`PlutusScript\` and \`network\` (0 for testnet): \`\`\`tsx const scriptAddress = resolvePlutusScriptAddress(script, 0); \`\`\` ## Listing Asset for Sale Get the seller's address from the connected wallet: \`\`\`tsx const addr = (await wallet.getUsedAddresses())\[0\]; \`\`\` Create the datum schema: \`\`\`tsx const datumConstr: Data = { alternative: 0, fields: \[ resolvePaymentKeyHash(addr), // seller address as pubkeyhash listPriceInLovelace, // price policyId, // policy ID of token assetId, // asset name of token in hex \], }; \`\`\` Create a transaction using \`sendAssets()\` to send the asset to the script address with the defined datum. \`policyId + assetId\` is the asset name in hex. Build, sign, and submit the transaction. \`\`\`tsx const tx = new Transaction({ initiator: wallet }) .sendAssets( { address: scriptAddress, datum: { value: datumConstr, }, }, \[ { unit: policyId + assetId, quantity: '1', }, \] ); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` Implement your own marketplace. Note: A database may be required to store listing information. Full code for listing an asset: \`\`\`tsx const addr = (await wallet.getUsedAddresses())\[0\]; const datumConstr: Data = { alternative: 0, fields: \[ resolvePaymentKeyHash(addr), listPriceInLovelace, policyId, assetId, \], }; const tx = new Transaction({ initiator: wallet }) .sendAssets( { address: scriptAddress, datum: { value: datumConstr, }, }, \[ { unit: policyId + assetId, quantity: '1', }, \] ); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` ## Cancel the Listing Cancel the listing. Only the seller can cancel. Define the datum: \`\`\`tsx const datumConstr: Data = { alternative: 0, fields: \[ resolvePaymentKeyHash(addr), // seller address as pubkeyhash listPriceInLovelace, // price policyId, // policy ID of token assetId, // asset name of token in hex \], }; \`\`\` Cancel, update, and purchase endpoints require the UTxO in the script address. Use \`fetchAddressUTxOs()\` to query UTxOs containing the asset. Filter by datum hash using \`resolveDataHash()\` (see resolvers). Implementation for \`\_getAssetUtxo()\`: \`\`\`tsx async function \_getAssetUtxo({ scriptAddress, asset, datum }) { const utxos = await blockchainFetcher.fetchAddressUTxOs( scriptAddress, asset ); if (utxos.length == 0) { throw 'No listing found.'; } const dataHash = resolveDataHash(datum); let utxo = utxos.find((utxo: any) => { return utxo.output.dataHash == dataHash; }); return utxo; } \`\`\` Define the redeemer for cancellation: \`\`\`tsx const redeemer = { data: { alternative: 1, fields: \[\] } }; \`\`\` Build the transaction. Use \`redeemValue()\` to redeem the UTxO and send the value back to the seller. Set required signers to the seller's address. \`\`\`tsx const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datumConstr, redeemer: redeemer, }) .sendValue(addr, assetUtxo) .setRequiredSigners(\[addr\]); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` Full code for cancellation: \`\`\`tsx const addr = (await wallet.getUsedAddresses())\[0\]; const datumConstr: Data = { alternative: 0, fields: \[ resolvePaymentKeyHash(addr), listPriceInLovelace, policyId, assetId, \], }; const assetUtxo = await \_getAssetUtxo({ scriptAddress: scriptAddress, asset: 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e', datum: datumConstr, }); if (assetUtxo === undefined) { throw 'No listing found.'; } const redeemer = { data: { alternative: 1, fields: \[\] } }; const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datumConstr, redeemer: redeemer, }) .sendValue(addr, assetUtxo) .setRequiredSigners(\[addr\]); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` ## Purchase the Listed Asset Purchase the listed asset. The endpoint requires the asset, price, and seller address to create the validator datum. Successful purchase transfers the asset to the buyer and price to the seller. Get the buyer's address: \`\`\`tsx const addr = (await wallet.getUsedAddresses())\[0\]; // buyer's address \`\`\` Create the validator datum using the seller's address: \`\`\`tsx const datumConstr: Data = { alternative: 0, fields: \[ resolvePaymentKeyHash(sellerAddr), // seller address as pubkeyhash listPriceInLovelace, // price policyId, // policy ID of token assetId, // asset name of token in hex \], }; \`\`\` Define the redeemer: \`\`\`tsx const redeemer = { data: { alternative: 0, fields: \[\] } }; \`\`\` Build and submit the transaction. Use \`redeemValue()\` to redeem the asset, \`sendValue()\` to transfer to the buyer, and \`sendLovelace()\` to pay the seller: \`\`\`tsx const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datumConstr, redeemer: redeemer, }) .sendValue(addr, assetUtxo) .sendLovelace(sellerAddr, listPriceInLovelace.toString()) .setRequiredSigners(\[addr\]); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` Full code for purchase: \`\`\`tsx const addr = (await wallet.getUsedAddresses())\[0\]; // buyer's address const datumConstr: Data = { alternative: 0, fields: \[ resolvePaymentKeyHash(sellerAddr), listPriceInLovelace, policyId, assetId, \], }; const assetUtxo = await \_getAssetUtxo({ scriptAddress: scriptAddress, asset: 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e', datum: datumConstr, }); const redeemer = { data: { alternative: 0, fields: \[\] } }; const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datumConstr, redeemer: redeemer, }) .sendValue(addr, assetUtxo) .sendLovelace(sellerAddr, listPriceInLovelace.toString()) .setRequiredSigners(\[addr\]); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` ## Update the Listing Update the listing. Only the seller can update. Define the original datum: \`\`\`tsx const datumConstr: Data = { alternative: 0, fields: \[ resolvePaymentKeyHash(addr), // seller address as pubkeyhash listPriceInLovelace, // listed price policyId, // policy ID of token assetId, // asset name of token in hex \], }; \`\`\` Create the updated datum with the new price: \`\`\`tsx const datumConstrNew: Data = { alternative: 0, fields: \[ resolvePaymentKeyHash(addr), // seller address as pubkeyhash updatedPriceInLovelace, // updated price policyId, // policy ID of token assetId, // asset name of token in hex \], }; \`\`\` Define the redeemer for update: \`\`\`tsx const redeemer = { data: { alternative: 1, fields: \[\] } }; \`\`\` Build the transaction. Redeem the UTxO with the original datum and send the NFT to the script address with the new datum using \`sendAssets()\`. \`\`\`tsx const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datumConstr, redeemer: redeemer, }) .setRequiredSigners(\[addr\]) .sendAssets( { address: scriptAddress, datum: { value: datumConstrNew, }, }, \[ { unit: 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e', quantity: '1', }, \] ); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` Full code for update: \`\`\`tsx const addr = (await wallet.getUsedAddresses())\[0\]; const datumConstr: Data = { alternative: 0, fields: \[ resolvePaymentKeyHash(addr), listPriceInLovelace, policyId, assetId, \], }; const datumConstrNew: Data = { alternative: 0, fields: \[ resolvePaymentKeyHash(addr), updatedPriceInLovelace, policyId, assetId, \], }; const assetUtxo = await \_getAssetUtxo({ scriptAddress: scriptAddress, asset: 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e', datum: datumConstr, }); const redeemer = { data: { alternative: 1, fields: \[\] } }; const tx = new Transaction({ initiator: wallet }) .redeemValue({ value: assetUtxo, script: script, datum: datumConstr, redeemer: redeemer, }) .setRequiredSigners(\[addr\]) .sendAssets( { address: scriptAddress, datum: { value: datumConstrNew, }, }, \[ { unit: 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e', quantity: '1', }, \] ); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` This serves as a starting point for building apps with smart contracts. # Executing a standalone script URL: /guides/standalone undefined \*\*\* title: "Executing a standalone script" icon: "guides/standalone.png" ----------------------------- import Link from "fumadocs-core/link"; Run JavaScript/TypeScript files directly to interact with the blockchain using the \`tsx\` package. Set up a simple project using MeshSDK. Create a wallet, build and sign transactions, and submit them to the blockchain. This tutorial covers: \* Creating a \`package.json\` file. \* Installing MeshSDK and dependencies. \* Writing a script to create a wallet and send a transaction. \* Running the project. ## System Setup ### Create \`package.json\` \\\[!toc\] Create \`package.json\` in the project root: \`\`\`tsx { "type": "module", "dependencies": {}, "scripts": { "dev": "tsx index.ts" } } \`\`\` ### Install Packages \\\[!toc\] Install required packages: \`\`\`tsx npm install npm install tsx @meshsdk/core \`\`\` \`package.json\` should look like this: \`\`\`tsx { "type": "module", "dependencies": { "@meshsdk/core": "^1.5.18", "tsx": "^4.9.4" }, "scripts": { "dev": "tsx index.ts" } } \`\`\` \* \`@meshsdk/core\`: Core functionality. \* \`tsx\`: Runs TypeScript files directly. ## Make a Simple Transaction ### Create \`index.ts\` \\\[!toc\] Create \`index.ts\` and add the following code: \`\`\`tsx import { BlockfrostProvider, MeshWallet, Transaction } from "@meshsdk/core"; // Set up the blockchain provider with your key const provider = new BlockfrostProvider("YOUR\_KEY\_HERE"); // Initialize the wallet with a mnemonic key const wallet = new MeshWallet({ networkId: 0, fetcher: provider, submitter: provider, key: { type: "mnemonic", words: \[ "your", "mnemonic", "...", "here", \], }, }); // Create and send a transaction const tx = new Transaction({ initiator: wallet }).sendLovelace( "addr\_test1qp2k7wnshzngpqw0xmy33hvexw4aeg60yr79x3yeeqt3s2uvldqg2n2p8y4kyjm8sqfyg0tpq9042atz0fr8c3grjmysdp6yv3", "1000000" ); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` ### Run Application \\\[!toc\] Replace \`YOUR\_KEY\_HERE\` with a valid Blockfrost key and the mnemonic words with your own. Get a key from Blockfrost and generate a mnemonic from Mesh. Start the application: \`\`\`tsx npm run dev \`\`\` The transaction hash will log to the console. View the complete code in the Mesh GitHub repo. # Vesting Script End-to-End URL: /guides/vesting undefined \*\*\* title: "Vesting Script End-to-End" icon: "guides/vesting.png" -------------------------- import Link from "fumadocs-core/link"; A vesting contract locks funds and allows beneficiary withdrawal after a lockup period. Organizations use vesting contracts to incentivize retention. Funds deposited are accessible to employees after a predetermined period. ## On-Chain Code Define the datum shape to configure vesting parameters. \`\`\`tsx pub type VestingDatum { /// POSIX time in milliseconds, e.g. 1672843961000 lock\_until: Int, /// Owner's credentials owner: ByteArray, /// Beneficiary's credentials beneficiary: ByteArray, } \`\`\` The \`VestingDatum\` contains: \* \`lock\_until\`: POSIX timestamp (ms) for lock expiration. \* \`owner\`: Owner credentials (public key hash). \* \`beneficiary\`: Beneficiary credentials (public key hash). Source: \`aiken-vesting/aiken-workspace/lib/vesting/types.ak\`. Define the spend validator: \`\`\`tsx use aiken/transaction.{ScriptContext, Spend} use vesting/types.{VestingDatum} use vodka\_extra\_signatories.{key\_signed} use vodka\_validity\_range.{valid\_after} validator { pub fn vesting(datum: VestingDatum, \_redeemer: Data, ctx: ScriptContext) { // In principle, scripts can be used for different purpose (e.g. minting // assets). Here we make sure it's only used when 'spending' from a eUTxO when ctx.purpose is { Spend(\_) -> or { key\_signed(ctx.transaction.extra\_signatories, datum.owner), and { key\_signed(ctx.transaction.extra\_signatories, datum.beneficiary), valid\_after(ctx.transaction.validity\_range, datum.lock\_until), }, } \_ -> False } } } \`\`\` The \`vesting\` validator ensures: \* The transaction is signed by the owner. \* OR: \* The transaction is signed by the beneficiary AND valid after the lockup period. Source: \`aiken-vesting/aiken-workspace/validators/vesting.ak\`. ### How It Works \\\[!toc\] The owner deposits funds, locked until the period expires. Transactions include validity intervals. The ledger verifies these bounds before script execution. This incorporates time while maintaining determinism. Since the upper bound is uncontrolled, execution can occur long after the delay. This is acceptable. The beneficiary (potentially different from the owner) withdraws funds after expiration. ## Testing Run comprehensive tests with \`aiken check\`. Test cases include: \* Success unlocking. \* Success unlocking with only owner signature. \* Success unlocking with beneficiary signature and time passed. \* Fail unlocking with only beneficiary signature. \* Fail unlocking with only time passed. See \`aiken-vesting/aiken-workspace/validators/tests/vesting.ak\`. ## Compile and Build Script Compile the script: \`\`\`tsx aiken build \`\`\` Generates a CIP-0057 Plutus blueprint in \`aiken-vesting/aiken-workspace/plutus.json\`. ## Off-Chain Code ### Deposit Funds \\\[!toc\] The owner deposits funds, specifying the lockup period and beneficiary. \`\`\`tsx const assets: Asset\[\] = \[ { unit: "lovelace", quantity: "10000000", }, \]; const lockUntilTimeStamp = new Date(); lockUntilTimeStamp.setMinutes(lockUntilTimeStamp.getMinutes() + 1); const beneficiary = "addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9"; \`\`\` Deposit 10 ADA, locked for 1 minute. Prepare transaction variables: wallet address, UTXOs, script address, and public key hashes. \`\`\`tsx const { utxos, walletAddress } = await getWalletInfoForTx(); const { scriptAddr } = getScript(); const { pubKeyHash: ownerPubKeyHash } = deserializeAddress(walletAddress); const { pubKeyHash: beneficiaryPubKeyHash } = deserializeAddress(beneficiary); \`\`\` Construct the deposit transaction. Specify script address, amount, lockup period, owner, and beneficiary. \`\`\`tsx const txBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); await txBuilder .txOut(scriptAddr, amount) .txOutInlineDatumValue( mConStr0(\[lockUntilTimeStampMs, ownerPubKeyHash, beneficiaryPubKeyHash\]) ) .changeAddress(walletAddress) .selectUtxosFrom(utxos) .complete(); const unsignedTx = txBuilder.txHex; \`\`\` Sign and submit. \`\`\`tsx const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` Ensure the Blockfrost key is in \`.env\` and mnemonic in \`aiken-vesting/src/configs.ts\`. Run the deposit code: \`\`\`tsx npm run deposit \`\`\` Save the returned transaction hash for withdrawal. See successful deposit transaction. ### Withdraw Funds \\\[!toc\] Beneficiaries (or owners) withdraw funds after expiration. Fetch UTxOs containing locked funds using the deposit transaction hash. \`\`\`tsx const txHashFromDesposit = "ede9f8176fe41f0c84cfc9802b693dedb5500c0cbe4377b7bb0d57cf0435200b"; const utxos = await provider.fetchUTxOs(txHash); const vestingUtxo = utxos\[0\]; \`\`\` Prepare transaction variables. \`\`\`tsx const { utxos, walletAddress, collateral } = await getWalletInfoForTx(); const { input: collateralInput, output: collateralOutput } = collateral; const { scriptAddr, scriptCbor } = getScript(); const { pubKeyHash } = deserializeAddress(walletAddress); \`\`\` Prepare the datum and validity interval slot. Set the valid interval to start after the lockup period. \`\`\`tsx const datum = deserializeDatum(vestingUtxo.output.plutusData!); const invalidBefore = unixTimeToEnclosingSlot( Math.min(datum.fields\[0\].int as number, Date.now() - 15000), SLOT\_CONFIG\_NETWORK.preprod ) + 1; \`\`\` Construct the withdrawal transaction. Specify the UTxO, script address, recipient address, and validity interval. \`\`\`tsx const txBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); await txBuilder .spendingPlutusScriptV2() .txIn( vestingUtxo.input.txHash, vestingUtxo.input.outputIndex, vestingUtxo.output.amount, scriptAddr ) .spendingReferenceTxInInlineDatumPresent() .spendingReferenceTxInRedeemerValue("") .txInScript(scriptCbor) .txOut(walletAddress, \[\]) .txInCollateral( collateralInput.txHash, collateralInput.outputIndex, collateralOutput.amount, collateralOutput.address ) .invalidBefore(invalidBefore) .requiredSignerHash(pubKeyHash) .changeAddress(walletAddress) .selectUtxosFrom(utxos) .complete(); const unsignedTx = txBuilder.txHex; \`\`\` Sign and submit. Enable partial signing (\`true\`) for validator unlocking. \`\`\`tsx const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` Update \`aiken-vesting/src/withdraw-fund.ts\` with the deposit transaction hash. Run: \`\`\`tsx npm run withdraw \`\`\` See successful withdraw transaction. # Layer 2 scaling solution URL: /hydra Scaling solution for Cardano that increases transaction throughput and ensures cost efficiency while maintaining rigorous security. \*\*\* title: "Layer 2 scaling solution" description: "Scaling solution for Cardano that increases transaction throughput and ensures cost efficiency while maintaining rigorous security." icon: "icons/hydra.svg" ----------------------- import {linksHydra} from "@/data/links-hydra"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksHydra.map((card) => ( {card.title} {card.desc} ))} \# Hydra Instance URL: /hydra/instance The HydraInstance is a class interface for interacting with a Hydra head after initialization. \*\*\* title: "Hydra Instance" description: "The HydraInstance is a class interface for interacting with a Hydra head after initialization." ------------------------------------------------------------------------------------------------------------- import Link from "fumadocs-core/link"; ## Overview The \`HydraInstance\` is intialized together with \`HydraProvider\`, for accessing other methods to interact with Hydra head after \`HeadIsInitializing\` phase. ## Get started: \`\`\`tsx import { HydraInstance, HydraProvider } from "@meshsdk/hydra"; const provider = new HydraProvider({ httpUrl: "", }); const instance = new HydraInstance({ provider: hydraProvider, fetcher: "", submitter: "", }); \`\`\` ### Commit Empty If you don't want to commit any funds and only want to receive on layer 2, you can request an empty commit transaction to open the head \`\`\`tsx const commit = await instance.commitEmpty(); const submitTx = await wallet.submitTx(commit); console.log("submitTx", submitTx); \`\`\` ### Commit Funds Commits funds to the Hydra head by selecting specific UTxOs to make available on layer 2. \*\*Parameters:\*\* \* \`txHash\` \* \`outputIndex\` \*\*Returns:\*\* The transaction CBOR hex ready to be partially signed \`\`\`tsx await instance.commitFunds(txHash: string, outputIndex: number) \`\`\` \`\`\`tsx const txHash = "00000000000000000000000000000000000000000000000000000000000000000"; const outputIndex = 0; const commitTx = await instance.commitFunds(txHash, outputIndex); const signedTx = await wallet.signTx(commitTx, true); const commitTxHash = await wallet.submitTx(signedTx); \`\`\` ### Commit Blueprint Commits a Cardano transaction blueprint to the Hydra head. This is useful for advanced use cases such as commiting \`scriptUTxOs\`. \*\*Parameters:\*\* \* \`txHash\` \* \`outputIndex\` \* \`hydraTransaction\` \`\`\`tsx await instance.commitBlueprint("txHash", outputIndex, { cborHex: "", description: "commit tx", type: "Tx ConwayEra", }); \`\`\` \`\`\`tsx const commitTx = await instance.commitBlueprint(txHash, outputIndex, { cborHex: "", description: "commit tx", type: "Tx ConwayEra", }); const signedTx = await wallet.signTx(commitTx, true); const commitTxHash = await wallet.submitTx(signedTx); \`\`\` ### Incremental Commit Incremental commit methods allow you commit additional UTxOs to an open hydra head after the initial commit: The time it takes for it top be added after commit depends on the \`hydra-node\` configuration parameter \`--deposit-period\` To read more on incremental commit, see \[the Hydra documentation\](https://hydra.family/head-protocol/docs/how-to/incremental-commit). ### incrementalCommitFunds \`\`\`tsx await instance.incrementalCommitFunds(txHash: string, outputIndex: number) \`\`\` ### incrementalBlueprintCommit \`\`\`tsx await instance.incrementalBlueprintCommit(txHash, outputIndex, { cborHex: "unsignedTx", description: "commit tx", type: "Tx ConwayEra", }); \`\`\` ## Basic Workflow ### commit Funds \`\`\`tsx import { HydraInstance, HydraProvider } from "@meshsdk/hydra"; import { BlockfrostProvider } from "@meshsdk/core"; const provider = new HydraProvider({ httpUrl: "http://localhost:4001", }); const instance = new HydraInstance({ provider: provider, fetcher: "blockchainProvider", submitter: "blockchainProvider", }); await provider.connect(); await provider.init(); provider.onMessage((message) => { const status = message.tag === "Greetings" ? { headStatus: message.headStatus } : { tag: message.tag }; if ( status.tag === "HeadIsInitializing" || status.headStatus === "Initializing" ) { } const commitTx = await instance.commitFunds(txHash, outputIndex); const signedTx = await wallet.signTx(commitTx, true); await wallet.submitTx(signedTx); }); \`\`\` ### Blueprint Commit \`\`\`tsx provider.onMessage((message) => { const status = message.tag === "Greetings" ? { headStatus: message.headStatus } : { tag: message.tag }; if ( status.tag === "HeadIsInitializing" || status.headStatus === "Initializing" ) { const txBuilder = new MeshTxBuilder({ submitter: "", fetcher: "", verbose: true, }); const unsignedTx = await txBuilder .txIn(txHash, outputIndex) .setFee("0") .changeAddress(address) .selectUtxosFrom(UTxOs) .complete(); const commitTx = await instance.commitBlueprint(txHash, outputIndex, { type: "Tx ConwayEra", cborHex: unsignedTx, description: "Commit Blueprint", }); const signedTx = await wallet.signTx(commitTx); const commitTxHash = await wallet.submitTx(signedTx); console.log(commitTxHash); } }); \`\`\` # End-to-end Hydra Tutorial URL: /hydra/tutorial Open a layer 2 state channel between two participants, build transactions, and close the Hydra head \*\*\* title: "End-to-end Hydra Tutorial" description: "Open a layer 2 state channel between two participants, build transactions, and close the Hydra head" ------------------------------------------------------------------------------------------------------------------ import Link from "fumadocs-core/link"; This tutorial demonstrates how to use Hydra Head protocol on Cardano's preprod testing environment to open a layer 2 state channel between two participants using Mesh. Hydra Head is a layer 2 scaling solution for Cardano that enables fast, low-cost transactions between participants. This tutorial is adapted from the Hydra documentation. ### Initialize Hydra with Mesh \\\[!toc\] To initialize Hydra with Mesh, you need to set the \`HydraProvider\` with the Hydra API URL and then use it to initialize the \`HydraInstance\`. You can use one of the cardano providers, example: \`blockfrostProvider\`, or \`maestroProvider\`, to initialize the \`HydraInstance\`. \`\`\`tsx import { HydraInstance, HydraProvider } from "@meshsdk/hydra"; const provider = new HydraProvider({ httpUrl: "", }); const hydraInstance = new HydraInstance({ provider: provider, fetcher: "", submitter: "", }); \`\`\` ## Prerequisites \* A running cardano node is required to access \`cardano-cli\` \* A \`Hydra-node\` \* Another participant following this tutorial (recommended), or \* Access to two such machines \* 100 test ada per participant in a wallet on the \`preprod\` network Hydra-node and cardano-node running, check Installation. You could also set-up a Docker container for a \`cardano-node\` and \`Hydra-node\` to quickly follow this tutorial. Check the setup example/demo for a devnet here ## Step 1. Prepare keys and funding In a Hydra head, each participant is authenticated using two sets of keys. The first set identifies a participant on the Cardano layer 1 and is used to hold ada for paying fees. Each hydra-node requires a \`cardano-signing-key\`, and you must provide the \`cardano-verification-key\` for each participant. First, generate Cardano key pairs and addresses for both participants with \`cardano-cli\` to identify the hydra-node and manage funds on layer 1. Alice's keys: \`\`\`bash mkdir -p credentials cardano-cli address key-gen \\ --verification-key-file credentials/alice-node.vk \\ --signing-key-file credentials/alice-node.sk cardano-cli address build \\ --payment-verification-key-file credentials/alice-node.vk \\ --out-file credentials/alice-node.addr \\ --testnet-magic 1 cardano-cli address key-gen \\ --verification-key-file credentials/alice-funds.vk \\ --signing-key-file credentials/alice-funds.sk cardano-cli address build \\ --payment-verification-key-file credentials/alice-funds.vk \\ --out-file credentials/alice-funds.addr \\ --testnet-magic 1 \`\`\` Bob's keys: \`\`\`bash mkdir -p credentials cardano-cli address key-gen \\ --verification-key-file credentials/bob-node.vk \\ --signing-key-file credentials/bob-node.sk cardano-cli address build \\ --payment-verification-key-file credentials/bob-node.vk \\ --out-file credentials/bob-node.addr \\ --testnet-magic 1 cardano-cli address key-gen \\ --verification-key-file credentials/bob-funds.vk \\ --signing-key-file credentials/bob-funds.sk cardano-cli address build \\ --payment-verification-key-file credentials/bob-funds.vk \\ --out-file credentials/bob-funds.addr \\ --testnet-magic 1 \`\`\` After generating the addresses, make sure to fund both Alice's and Bob's addresses with test ADA. if you don't have testAda, you can use cardano-faucet to fund the generated addresses \* Send at least \`30 tADA\` to \`alice-node.addr\` and \`bob-node.addr\` addresses. \* Send any amount of \`tADA\` to \`alice-funds.addr\` and \`bob-funds.addr\` addresses. Next, generate Hydra key pairs for use on layer 2. Use this Hydra-node command to generate the keys for alice and/or bob respectively: \`\`\`tsx hydra-node gen-hydra-key --output-file credentials/alice-hydra \`\`\` \`\`\`tsx hydra-node gen-hydra-key --output-file credentials/bob-hydra \`\`\` The next step involves configuring the protocol parameters for the ledger within our Hydra head. For the purposes of this tutorial, we'll modify the default Cardano layer 1 parameters to eliminate transaction fees, \`\`\`tsx cardano-cli query protocol-parameters --testnet-magic 1 --socket-path /"${socketPath}" --out-file protocol-parameters.json \`\`\` Simplifying Hydra fees and environments, change the following parameters: \* \`txFeeFixed\` to 0 \* \`txFeePerByte\` to 0 \* \`executionUnitPrices.priceMemory\` to 0 \* \`executionUnitPrices.priceSteps\` to 0 ## Step 2. Configure Hydra nodes Configure your Hydra nodes with the generated keys and network settings. Each participant needs to set up their hydra-node with the correct configuration. Alice: \`\`\`tsx hydra-node \\ --node-id alice-node \\ --api-host 0.0.0.0 \\ --api-port 4001 \\ --listen 172.16.239.10:5001 \\ --monitoring-port 6001 \\ --peer 172.16.239.20:5001 \\ --hydra-scripts-tx-id c9c4d820d5575173cfa81ba2d2d1096fc40f84d16d8c17284da410a4fb5e64eb,ae4443b46f550289337fc5c2c52b24f1288dab36d1a229167a6e04f056a966fe,48bd29e43dd01d12ab464f75fe40eed80e4051c8d3409e1cb20b8c01120b425e \\ --cardano-signing-key /credentials/alice-node.sk \\ --cardano-verification-key /credentials/bob-node.vk \\ --hydra-signing-key /keys/alice-hydra.sk \\ --hydra-verification-key /keys/bob-hydra.vk \\ --ledger-protocol-parameters ./testnet/protocol-parameters.json \\ --testnet-magic 1 \\ --node-socket /cardano-node/db/node.socket \\ --contestation-period 300s \`\`\` Bob: \`\`\`tsx hydra-node \\ --node-id bob-node \\ --api-host 0.0.0.0 \\ --api-port 4002 \\ --listen 172.16.239.20:5001 \\ --monitoring-port 6001 \\ --peer 172.16.239.10:5001 \\ --hydra-scripts-tx-id c9c4d820d5575173cfa81ba2d2d1096fc40f84d16d8c17284da410a4fb5e64eb,ae4443b46f550289337fc5c2c52b24f1288dab36d1a229167a6e04f056a966fe,48bd29e43dd01d12ab464f75fe40eed80e4051c8d3409e1cb20b8c01120b425e \\ --cardano-signing-key /credentials/bob-node.sk \\ --cardano-verification-key /credentials/alice-node.vk \\ --hydra-signing-key /keys/bob-hydra.sk \\ --hydra-verification-key /keys/alice-hydra.vk \\ --ledger-protocol-parameters ./testnet/protocol-parameters.json \\ --testnet-magic 1 \\ --node-socket /cardano-node/db/node.socket \\ --contestation-period 300s \`\`\` Fields in the Hydra node configuration: \* \`node-id\`: Unique identifier for each Hydra node. This distinguishes Alice's node from Bob's node. \* \`api-host\`: as the API is not authenticated by default, the node is only binding to \`0.0.0.0\`. \* \`api-port\`: The port on which the API will listen. \* \`listen\`: The IP address and port on which the Hydra node will listen for incoming connections. \* \`peer\`: The IP address of another Hydra node to connect to. This is how nodes discover and communicate with each other. \* \`monitoring-port\`: The port on which the monitoring API will listen. This is used to monitor the Hydra node's performance. \* \`cardano-signing-key\`: These keys authenticate on-chain transactions and ensure that only authorized participants can control the head's lifecycle used to hold ada for paying fees \* \`hydra-signing-key\`: Used for multi-signing snapshots within a head. Although these keys may eventually support an aggregated multi-signature scheme, they currently use the Ed25519 format. \* \`hydra-scripts-tx-id\`: The hydra-node uses reference scripts to reduce transaction sizes driving the head's lifecycle. For public (test) networks, you can use the pre-published Hydra scripts with each new release, listing transaction IDs in the release notes and networks.json. Note: The value of above \`--hydra-scripts-tx-id\` comes from the hydra-node release 0.22.2. \* \`ledger-protocol-parameters\`: This defines the updatable protocol parameters to be used on L2 such as fees or transaction sizes. These parameters follow the same format as the \`cardano-cli query protocol-parameters\` output. \* \`contestation-period\`:This is an important protocol parameter, defined in seconds The contestation period is used to set the contestation deadline. That is, after \`Close\`, all participants have at minimum \`CP\` to submit a \`Contest\` transaction More on hydra configuration. Ensure both nodes can communicate with each other and change to your correct file paths in the above configuration. This configuration sets up Alice's node to listen to API connection on port 4001 Bob's node on port 4002. ## Step 3. Open a Hydra head ### Connect to the Hydra head \\\[!toc\] Now that both Hydra nodes are running and connected, we can start using the head API url and port together with Mesh \`HydraProvider\` in connecting to the Hydra head. \`\`\`tsx await provider.connect(); \`\`\` ### Initialize the Head \\\[!toc\] Send the initialization command to start the Hydra head: \`\`\`tsx await provider.init(); \`\`\` ### Commit Funds \\\[!toc\] After initialization, both participants need to commit funds to the head. In this tutorial we use the \`commitFunds\` function on \`HydraInstance\` by selecting specific UTxOs and make them available for layer 2 transactions: \`\`\`tsx import { HydraInstance , HydraProvider} from "@meshsdk/hydra"; const provider = new HydraProvider({ httpUrl: "", }); const hInstance = new HydraInstance({ provider: provider, fetcher: "", submitter: "", }); const wallet = new MeshWallet({ networkId: 0, // 0: testnet fetcher: "", submitter: "", key: { type: 'cli', payment: 'alice-funds.sk', }, }); const outputIndex = 0; const txHash = "00000000000000000000000000000000000000000000000000000000000000000"; const commitTx = await hInstance.commitFunds(txHash, outputIndex); const signedTx = await wallet.signTx(commitTx, true); const commitTxHash = await wallet.submitTx(signedTx); console.log(commitTxHash); \`\`\` The hydra-node will create a draft commit transaction for you to sign. Once signed and submitted to the Cardano network, you'll see a \`Committed\` message in your WebSocket connection. When both parties have committed their funds, the Hydra head will open automatically. You'll see a \`HeadIsOpen\` message confirming the head is operational and ready for transactions. ### Hydra Head Status Flow \\\[!toc\] The head goes through these status changes: \* \`HeadIsInitializing\` - Head is being initialized \* \`Committed\` - Funds are committed to the head \* \`HeadIsOpen\` - Head is open and ready for transactions ## Step 4. Use the Hydra head Now that the Hydra head is open, you can perform transactions within the layer 2 state channel. Hydra Head operates as an isomorphic protocol, meaning that functionalities available on Cardano layer 1 are also available on layer 2. This allows us to use Mesh SDK for transaction creation within the head. ### Fetch UTxOs \\\[!toc\] First, let's see what UTxOs are available in the Hydra head: \`\`\`tsx const utxos = await provider.fetchUTxOs(); \`\`\` ### Fetch Address UTxOs \\\[!toc\] Alternatively, you can fetch Head UTxOs for a specific address: \`\`\`tsx const utxos = await provider.fetchAddressUTxOs("alice-funds.addr") \`\`\` ### Build and Submit Transaction \\\[!toc\] You can build transactions just like on layer 1 assuming you are sending from alice to bob: \`\`\`tsx const pp = await provider.fetchProtocolParameters(); const utxos = await provider.fetchAddressUTxOs("address"); const txBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, isHydra: true, params: pp, }); const unsignedTx = await txBuilder .txOut( "bob-funds.addr", \[{ unit: "lovelace", quantity: "3000000" }\] ) .changeAddress("alice-funds.addr") .selectUtxosFrom(utxos) .setNetwork("preprod") .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await provider.submitTx(signedTx); console.log(txHash); \`\`\` The transaction will be validated by both hydra-nodes and either result in a \`TxValid\` message or a \`TxInvalid\` message If valid, you'll see a \`SnapshotConfirmedmessage\` shortly after with the new UTxO set. ### Transaction Flow \\\[!toc\] The transaction goes through these steps: \* \`NewTx\` - Transaction submitted to head \* \`TxValid\` - Transaction validated by all nodes \* \`SnapshotConfirmed\` - New state confirmed ## Step 5. Close the Hydra head You can close the head to return head utxos to layer 1. This process involves closing the head, waiting for the contestation period, and then fan out the final state. ### Close the Head \\\[!toc\] Any participant can initiate closing the Hydra head. Once closed, no more transactions can be submitted to the head. The head enters a contestation period where participants can challenge the closing snapshot. \`\`\`tsx await provider.close() \`\`\` ### Contestation Period \\\[!toc\] After closing, there's a contestation period (configurable with \`--contestation-period\`). During this time: \* Participants can contest the closing snapshot \* If contested, a more recent snapshot can be used \* After the deadline, fanout becomes possible ### Fanout the Head \\\[!toc\] After the contestation period, the head participants can use the \`fanout\` to fully close the \`hydra-head\` and return the head utxos to layer one. \`\`\`tsx await provider.fanout() \`\`\` ### Check Final Balances \\\[!toc\] After fanout, check the final balances on layer one: \`\`\`tsx const aliceFundsBalance = await blockchainProvider.fetchAddressUTxOs("alice-funds.addr"); const bobFundsBalance = await blockchainProvider.fetchAddressUTxOs("bob-funds.addr"); \`\`\` ### Head Lifecycle \\\[!toc\] The complete head lifecycle: \* \`INITIALIZE\` - Initial state \* \`COMMIT\` - Committing to Hydra head \* \`OPEN\` - Head open for transactions \* \`NEW TX\` - New transaction submitted in Hydra head \* \`CLOSE\` - Ready to fanout \* \`CONTEST\` - Head closed, contestation period \* \`FANOUT\` - Head finalized on layer one Congratulations! You've completed the full lifecycle of a Hydra head from initialization to finalization. # Blockfrost Provider URL: /providers/blockfrost Featuring over 100 APIs tailored for easy access to Cardano blockchain \*\*\* title: "Blockfrost Provider" description: "Featuring over 100 APIs tailored for easy access to Cardano blockchain" ------------------------------------------------------------------------------------- import Link from "fumadocs-core/link"; Blockfrost provides restful APIs which allows your app to access information stored on the blockchain. Get started: \`\`\`tsx import { BlockfrostProvider } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); \`\`\` If you are using a privately hosted Blockfrost instance, you can set the URL in the parameter: \`\`\`tsx const provider = new BlockfrostProvider(''); \`\`\` ### Get data from URL You can fetch any data from the blockchain by providing the URL path. \`\`\`tsx await provider.get('/addresses/addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9/transactions') \`\`\` ## Fetch Account Info Obtain information about a specific stake account. \`\`\`tsx await provider.fetchAccountInfo('stake\_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n') \`\`\` ## Fetch Address Assets Fetch assets from an address. \`\`\`tsx await provider.fetchAddressAssets('addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') \`\`\` \### Fetch Address UTxOs \\\[!toc\] Fetch UTxOs from address \*\*Address\*\* \`\`\`bash addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9 \`\`\` \`\`\`tsx await provider.fetchAddressAssets( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); \`\`\` \### Fetch assets from address \\\[!toc\] Fetch assets given an address \*\*Address\*\* \`\`\`bash addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9 \`\`\` \`\`\`tsx await provider.fetchAddressAssets( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); \`\`\` \## Fetch Address UTxOs Fetch UTxOs controlled by an address. \`\`\`tsx await provider.fetchAddressUTxOs('addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') \`\`\` Optionally, you can filter UTXOs containing a particular \`asset\` by providing asset, where it is the concatenation of policy ID and asset. \`\`\`tsx await fetchAddressUTxOs(address: string, asset?: string) \`\`\` \### Fetch Address UTxOs \\\[!toc\] Fetch UTxOs from address \*\*Address\*\* \`\`\`bash addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9 \`\`\` \`\`\`tsx await provider.fetchAddressUTxOs( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); \`\`\` \### Fetch UTxOs with Asset \\\[!toc\] Fetch UTxOs from address with asset \*\*Address\*\* \`\`\`bash addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9 \`\`\` \*\*Asset\*\*: \`d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e\` \`\`\`tsx await provider.fetchAddressUTxOs( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); \`\`\` \## Fetch Asset Addresses Fetch a list of a addresses containing a specific \`asset\` where it is the concatenation of policy ID and asset. \`\`\`tsx await provider.fetchAssetAddresses('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') \`\`\` \### Fetch Asset Addresses \\\[!toc\] Fetch list of addresses containing a specific asset \*\*Asset Unit\*\*: \`d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e\` \`\`\`tsx await provider.fetchAssetAddresses( 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e' ); \`\`\` \## Fetch Asset Metadata Fetch the asset metadata by providing asset's \`unit\`, which is the concatenation of policy ID and asset name in hex. \`\`\`tsx // Asset Unit: \`d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e\` await provider.fetchAssetMetadata('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') \`\`\` ## Fetch Block Info Fetch block infomation. You can get the hash from \`fetchTxInfo()\`. \`\`\`tsx // Block hash: \`79f60880b097ec7dabb81f75f0b52fedf5e922d4f779a11c0c432dcf22c56089\` await provider.fetchBlockInfo('79f60880b097ec7dabb81f75f0b52fedf5e922d4f779a11c0c432dcf22c56089') \`\`\` ## Fetch Collection Assets Fetch a list of assets belonging to a collection by providing its Policy ID. \`\`\`tsx await provider.fetchCollectionAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527') \`\`\` The API will return a list of \`assets\` and a cursor \`next\`. If the cursor is not null, you can use it to fetch the next page of results. Here is an example of the response. \`\`\`tsx { "assets": \[ { "unit": "d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527", "quantity": "1" }, \], "next": 2 } \`\`\` The \`fetchCollectionAssets\` function also accepts an optional \`cursor\` parameter to fetch the next page of results. The default value is \`1\`. \`\`\`tsx await fetchCollectionAssets( policyId: string, cursor = 1 ) \`\`\` ## Fetch Handle Address ADA Handle allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. We can resolve the handle's address with \`fetchHandleAddress\`. \`\`\`tsx // Handle: \`meshsdk\` await provider.fetchHandleAddress('meshsdk') \`\`\` ## Fetch Handle ADA Handle allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. ADA Handle also released a CIP68 handle and this function will fetch the metadata of the handle. \`\`\`tsx // Handle: \`meshsdk\` await provider.fetchHandle('meshsdk') \`\`\` ## Fetch Protocol Parameters Fetch the latest protocol parameters. \`\`\`tsx await provider.fetchProtocolParameters() \`\`\` Optionally, you can provide an epoch number to fetch the protocol parameters of that epoch. ## Fetch Transaction Info Fetch transaction infomation. Only confirmed transaction can be retrieved. \`\`\`tsx // Transaction hash: \`f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159\` await provider.fetchTxInfo('f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159') \`\`\` ## Fetch UTxOs Get UTxOs for a given hash. \`\`\`tsx await provider.fetchUTxOs('dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70') \`\`\` Optionally, you can specify the index of the index output. \`\`\`tsx await provider.fetchUTxOs('hash\_here', 0) \`\`\` ## Fetch Proposal Info Get information for a given governance proposal, identified by the txHash and proposal index \`\`\`tsx await provider.fetchGovernanceProposal('372d688faa77e146798b581b322c0f2981a9023764736ade5d12e0e4e796af8c', 0) \`\`\` ## Evaluate Transaction \`evaluateTx()\` accepts an unsigned transaction (\`unsignedTx\`) and it evaluates the resources required to execute the transaction. Note that, this is only valid for transaction interacting with redeemer (smart contract). By knowing the budget required, you can use this to adjust the redeemer's budget so you don't spend more than you need to execute transactions for this smart contract. \`\`\`tsx const unsignedTx = await tx.build(); const evaluateTx = await provider.evaluateTx(unsignedTx); \`\`\` Example responses from unlocking assets from the always succeed smart contract. \`\`\`tsx \[ { "index": 0, "tag": "SPEND", "budget": { "mem": 1700, "steps": 368100 } } \] \`\`\` With the \`mem\` and \`steps\`, you can refine the budget for the redeemer. For example: \`\`\`tsx const redeemer = { data: { alternative: 0, fields: \[...\] }, budget: { mem: 1700, steps: 368100, }, }; \`\`\` ## Submit Transaction Submit a serialized transaction to the network. \`\`\`tsx await provider.submitTx(signedTx); \`\`\` ## On Transaction Confirmed Allow you to listen to a transaction confirmation. Upon confirmation, the callback will be called. \`\`\`tsx const tx = new Transaction({ initiator: wallet }); tx.sendLovelace('addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', '5000000'); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); provider.onTxConfirmed(txHash, () => { // Transaction confirmed }); \`\`\` # Hydra Provider (beta) URL: /providers/hydra Layer 2 scaling solution for Cardano that increases transaction throughput and ensures cost efficiency while maintaining security. \*\*\* title: "Hydra Provider (beta)" description: "Layer 2 scaling solution for Cardano that increases transaction throughput and ensures cost efficiency while maintaining security." ------------------------------------------------------------------------------------------------------------------------------------------------- import Link from "fumadocs-core/link"; The Hydra Head protocol is a layer 2 scaling solution for Cardano rooted in peer-reviewed research that increases transaction throughput and ensures cost efficiency while maintaining rigorous security. Get started: \`\`\`tsx import { HydraProvider } from "@meshsdk/hydra"; // Hydra Head URL and PORT: e.g. http://123.45.67.890:4001 const provider = new HydraProvider({ httpUrl: }); \`\`\` ## connect Establishes a connection to a Hydra Head. This is typically managed through the HydraProvider.. \`\`\`tsx await provider.connect(); \`\`\` ## hydra-head messages Listens to messages from hydra-head \`\`\`tsx provider.onMessage((message) => console.log("messages received from hydra", message) ); \`\`\` can be used together with connect to Receive Messages after connect \`\`\`tsx await provider.connect(); provider.onMessage((message) => console.log("messages received from hydra", message) ); \`\`\` ## disconnect Closes the active connection to a Hydra Head. This is typically managed through the HydraProvider. Parameter (Optional) \* timeout: Specifies the timeout duration in milliseconds. The default timeout is 5 minutes (300,000 ms). \`\`\`tsx // Disconnect with default timeout (5 minutes) await provider.disconnect(); // Disconnect with custom timeout (e.g., 10 minutes) await provider.disconnect(10 \* 60 \* 1000); \`\`\` ## Hydra commands APIs ### Initialize Initializes a new Head. This command is a no-op when a Head is already open and the server will output an \`CommandFailed\` message should this happen. \`\`\`tsx await provider.init(); \`\`\` ### Abort Aborts a head before it is opened. This can only be done before all participants have committed. Once opened, the head can't be aborted anymore but it can be closed using: \`Close\`. \`\`\`tsx await provider.abort(); \`\`\` ### Commit Commit a particular UTxO to the head. This will make the UTxO available on the layer 2. This is used together with the \[\`HydraInstance\`\](../hydra/instance) (see the Hydra Instance page for details). \`\`\`tsx await instance.commitFunds(txHash, outputIndex); \`\`\` ### New Transaction Submit a transaction through the head. Note that the transaction is only broadcast if well-formed and valid. The \`newTx\` method accepts the following arguments: \*\*parameters\*\* \* cborHex: This is the transaction in hex format usually the unsigned transaction. \* type: Any transaction is tried to decode as a 'ConwayEra' transaction, which mostly is backward compatible to previous eras. \* description(optional): transaction description \*\*returns\*\* \* txId(transaction Hash) \`\`\`tsx async provider.newTx({ cborHex: "", description: "commit tx", type: "Tx ConwayEra", }) \`\`\` Here is an example of how to create a transaction using the Hydra provider, Mesh wallet and Mesh transaction builder: \`\`\`tsx async function makeTx() { const walletA = { addr: "addr\_test1vpsthwvxgfkkm2lm8ggy0c5345u6vrfctmug6tdyx4rf4mqn2xcyw", key: "58201aae63d93899640e91b51c5e8bd542262df3ecf3246c3854f39c40f4eb83557d", }; const wallet = new MeshWallet({ networkId: 0, key: { type: "cli", payment: walletA.key, }, fetcher: provider, submitter: provider, }); const pp = await provider.fetchProtocolParameters(); const utxos = await wallet.getUtxos("enterprise"); const changeAddress = walletA.addr; const txBuilder = new MeshTxBuilder({ fetcher: provider, params: pp, verbose: true, }); const unsignedTx = await txBuilder .txOut("addr\_test1vpd5axpq4qsh8sxvzny49cp22gc5tqx0djf6wmjv5cx7q5qyrzuw8", \[ { unit: "lovelace", quantity: "3000000" }, \]) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); console.log("txHash", txHash); } \`\`\` ### Decommit Request to decommit a UTxO from a Head by providing a decommit tx. Upon reaching consensus, this will eventually result in corresponding transaction outputs becoming available on the layer 1. The decommit method accepts the following arguments: \`\`\`tsx async decommit({ cborHex: "", description: "commit tx", type: "Tx ConwayEra" }) \`\`\` ### Close Terminate a head with the latest known snapshot. This effectively moves the head from the Open state to the Close state where the contestation phase begin. As a result of closing a head, no more transactions can be submitted via NewTx. \`\`\`tsx await provider.close(); \`\`\` ### Contest Challenge the latest snapshot announced as a result of a head closure from another participant. Note that this necessarily contest with the latest snapshot known of your local Hydra node. Participants can only contest once. \`\`\`tsx await provider.contest(); \`\`\` ### Fanout Finalize a head UTxOs to L1 after the contestation period passed. \`\`\`tsx await provider.fanout(); \`\`\` ## Hydra Query APIs ### Fetch UTxOs Get UTxOs for a given hash. Optionally, you can specify the index of the index output. \`\`\`tsx await provider.fetchUTxOs("txHash"); \`\`\` ### Fetch Address UTxOs Fetch UTxOs controlled by an address. Optionally, you can filter UTXOs containing a particular asset by providing \`asset\`, where it is the concatenation of policy ID and assetname. \`\`\`tsx await provider.fetchAddressUTxOs(address: string, asset?: string) \`\`\` ### Fetch Asset Addresses Fetches the addresses and quantities for a given Cardano asset. \`\`\`tsx await provider.fetchAssetAddresses(asset: string): \`\`\` ### Fetch collection Assest Fetches the list of assets for a given policy ID. \`\`\`tsx await provider.fetchCollectionAssets(policyId: string) \`\`\` ### Fetch Protocol Parameters Fetch the latest protocol parameters. \`\`\`tsx await provider.fetchProtocolParameters(); \`\`\` Optionally, you can provide an epoch number to fetch the protocol parameters of that epoch.\\\` ### Listens for new messages from Hydra node Listens for new messages from Hydra node. The callback function will be called with the message as the only argument. Check all events emitted by the Hydra node. \`\`\`tsx provider.onMessage((message) => { if (message.tag === "Greetings") { console.log("message.snapshotUtxo", message.snapshotUtxo); } }); \`\`\` ### Submit Transaction Submit a serialized transaction to the network. \`\`\`tsx const txHash = await provider.submitTx(signedTx); console.log("txHash", txHash); \`\`\` # Providers URL: /providers Data providers for connecting to the blockchain \*\*\* title: "Providers" description: "Data providers for connecting to the blockchain" icon: CloudIcon --------------- import {linksProviders} from "@/data/links-providers"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksProviders.map((card) => ( {card.title} {card.desc} ))} \# Koios Provider URL: /providers/koios Distributed & open-source public API query layer for Cardano \*\*\* title: "Koios Provider" description: "Distributed & open-source public API query layer for Cardano" --------------------------------------------------------------------------- import Link from "fumadocs-core/link"; import Youtube from "@/components/ui/Youtube"; Koios provides a query layer which allows your app to access information stored on the blockchain. Get started: \`\`\`tsx import { KoiosProvider } from "@meshsdk/core"; const provider = new KoiosProvider( 'preprod', // "api" | "preview" | "preprod" | "guild" '', ); \`\`\` Get your API key from Koios User Profile page. ## Get data from URL You can fetch any data from the blockchain by providing the URL path. \`\`\`tsx await provider.get('/addresses/addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9/transactions') \`\`\` ## Fetch Account Info Obtain information about a specific stake account. \`\`\`tsx await provider.fetchAccountInfo('stake\_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n') \`\`\` ## Fetch Address Assets Fetch assets from an address. \`\`\`tsx await provider.fetchAddressAssets( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); \`\`\` \### Fetch Address UTxOs \\\[!toc\] Fetch UTxOs from address \`\`\`tsx await provider.fetchAddressAssets( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); \`\`\` \### Fetch assets from address \\\[!toc\] Fetch assets given an address \`\`\`tsx await provider.fetchAddressAssets( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', ); \`\`\` \## Fetch Address UTxOs Fetch UTxOs controlled by an address. \`\`\`tsx await provider.fetchAddressUTxOs('addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') \`\`\` Optionally, you can filter UTXOs containing a particular \`asset\` by providing asset, where it is the concatenation of policy ID and asset. \`\`\`tsx await fetchAddressUTxOs(address: string, asset?: string) \`\`\` ## Fetch Asset Addresses Fetch a list of a addresses containing a specific \`asset\` where it is the concatenation of policy ID and asset. \`\`\`tsx await provider.fetchAssetAddresses('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') \`\`\` ## Fetch Asset Metadata Fetch the asset metadata by providing asset's \`unit\`, which is the concatenation of policy ID and asset name in hex. \`\`\`tsx await provider.fetchAssetMetadata('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') \`\`\` ## Fetch Block Info Fetch block infomation. You can get the hash from \`fetchTxInfo()\`. \`\`\`tsx await provider.fetchBlockInfo('79f60880b097ec7dabb81f75f0b52fedf5e922d4f779a11c0c432dcf22c56089') \`\`\` ## Fetch Collection Assets Fetch a list of assets belonging to a collection by providing its Policy ID. \`\`\`tsx await provider.fetchCollectionAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527') \`\`\` The API will return a list of \`assets\` and a cursor \`next\`. If the cursor is not null, you can use it to fetch the next page of results. Here is an example of the response. \`\`\`tsx { "assets": \[ { "unit": "d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527", "quantity": "1" }, \], "next": 2 } \`\`\` The \`fetchCollectionAssets\` function also accepts an optional \`cursor\` parameter to fetch the next page of results. The default value is \`1\`. \`\`\`tsx await fetchCollectionAssets( policyId: string, cursor = 1 ) \`\`\` ## Fetch Handle Address ADA Handle allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. We can resolve the handle's address with \`fetchHandleAddress\`. \`\`\`tsx // Handle: \`meshsdk\` await provider.fetchHandleAddress('meshsdk') \`\`\` ## Fetch Handle ADA Handle allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. ADA Handle also released a CIP68 handle and this function will fetch the metadata of the handle. \`\`\`tsx // Handle: \`meshsdk\` await provider.fetchHandle('meshsdk') \`\`\` ## Fetch Protocol Parameters Fetch the latest protocol parameters. \`\`\`tsx await provider.fetchProtocolParameters() \`\`\` Optionally, you can provide an epoch number to fetch the protocol parameters of that epoch. ## Fetch Transaction Info Fetch transaction infomation. Only confirmed transaction can be retrieved. \`\`\`tsx await provider.fetchTxInfo('f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159') \`\`\` ## Fetch UTxOs Get UTxOs for a given hash. \`\`\`tsx await provider.fetchUTxOs('dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70') \`\`\` Optionally, you can specify the index of the index output. \`\`\`tsx await provider.fetchUTxOs('hash\_here', 0) \`\`\` ## Fetch Proposal Info Get information for a given governance proposal, identified by the txHash and proposal index \`\`\`tsx await provider.fetchGovernanceProposal('372d688faa77e146798b581b322c0f2981a9023764736ade5d12e0e4e796af8c', 0) \`\`\` ## Submit Transaction Submit a serialized transaction to the network. \`\`\`tsx await provider.submitTx(signedTx); \`\`\` ## On Transaction Confirmed Allow you to listen to a transaction confirmation. Upon confirmation, the callback will be called. \`\`\`tsx const tx = new Transaction({ initiator: wallet }); tx.sendLovelace('addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', '5000000'); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); provider.onTxConfirmed(txHash, () => { // Transaction confirmed }); \`\`\` # Maestro Provider URL: /providers/maestro Advanced UTxO-indexing data layer to supercharge Defi on Bitcoin, Cardano & Dogecoin \*\*\* title: "Maestro Provider" description: "Advanced UTxO-indexing data layer to supercharge Defi on Bitcoin, Cardano & Dogecoin" --------------------------------------------------------------------------------------------------- import Link from "fumadocs-core/link"; Maestro is the complete Web3 stack for Cardano which provides among others:- \* ⛓️ Enterprise-grade onchain data access. \* ⚡️ Transaction monitoring system with submission retires, rollback notifications and accelerated tranaction finality. \* 💰 High-fidelity smart contract data feeds from top Cardano DeFi protocols. \* 📝 Fully managed smart contract APIs and ready-to-go UI plugins. Get started: \`\`\`tsx import { MaestroProvider } from "@meshsdk/core"; const provider = new MaestroProvider({ network: 'Preprod', // Mainnet / Preprod / Preview apiKey: '', // Get key at https://docs.gomaestro.org/ turboSubmit: false // Read about paid turbo transaction submission feature at https://docs.gomaestro.org }); \`\`\` ## Get data from URL You can fetch any data from the blockchain by providing the URL path. \`\`\`tsx await provider.get('/addresses/addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9/transactions') \`\`\` ## Fetch Account Info Obtain information about a specific stake account. \`\`\`tsx await provider.fetchAccountInfo('stake\_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n') \`\`\` ## Fetch Address Assets Fetch assets from an address. \`\`\`tsx await provider.fetchAddressAssets( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); \`\`\` \## Fetch Address UTxOs Fetch UTxOs from address \`\`\`tsx await provider.fetchAddressAssets( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); \`\`\` \## Fetch assets from address Fetch assets given an address \`\`\`tsx await provider.fetchAddressAssets( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', ); \`\`\` \## Fetch Address UTxOs Fetch UTxOs controlled by an address. \`\`\`tsx await provider.fetchAddressUTxOs('addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') \`\`\` Optionally, you can filter UTXOs containing a particular asset by providing \`asset\`, where it is the concatenation of policy ID and asset. \`\`\`tsx await provider.fetchAddressUTxOs( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e' ); \`\`\` ## Fetch Asset Addresses Fetch a list of a addresses containing a specific \`asset\` where it is the concatenation of policy ID and asset. \`\`\`tsx await provider.fetchAssetAddresses('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') \`\`\` ## Fetch Asset Metadata Fetch the asset metadata by providing asset's \`unit\`, which is the concatenation of policy ID and asset name in hex. \`\`\`tsx await provider.fetchAssetMetadata('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') \`\`\` ## Fetch Block Info Fetch block infomation. You can get the hash from \`fetchTxInfo()\`. \`\`\`tsx await provider.fetchBlockInfo('79f60880b097ec7dabb81f75f0b52fedf5e922d4f779a11c0c432dcf22c56089') \`\`\` ## Fetch Collection Assets Fetch a list of assets belonging to a collection by providing its Policy ID. \`\`\`tsx await provider.fetchCollectionAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527') \`\`\` The API will return a list of \`assets\` and a cursor \`next\`. If the cursor is not null, you can use it to fetch the next page of results. Here is an example of the response. \`\`\`tsx { "assets": \[ { "unit": "d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527", "quantity": "1" }, \], "next": 2 } \`\`\` The \`fetchCollectionAssets\` function also accepts an optional \`cursor\` parameter to fetch the next page of results. The default value is \`1\`. \`\`\`tsx await fetchCollectionAssets( policyId: string, cursor = 1 ) \`\`\` ## Fetch Handle Address ADA Handle allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. We can resolve the handle's address with \`fetchHandleAddress\`. \`\`\`tsx // Handle: \`meshsdk\` await provider.fetchHandleAddress('meshsdk') \`\`\` ## Fetch Handle ADA Handle allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. ADA Handle also released a CIP68 handle and this function will fetch the metadata of the handle. \`\`\`tsx // Handle: \`meshsdk\` await provider.fetchHandle('meshsdk') \`\`\` ## Fetch Protocol Parameters Fetch the latest protocol parameters. \`\`\`tsx await provider.fetchProtocolParameters() \`\`\` Optionally, you can provide an epoch number to fetch the protocol parameters of that epoch. ## Fetch Transaction Info Fetch transaction infomation. Only confirmed transaction can be retrieved. \`\`\`tsx // Transaction hash f.e. f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159 await provider.fetchTxInfo('f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159') \`\`\` ## Fetch UTxOs Get UTxOs for a given hash. \`\`\`tsx await provider.fetchUTxOs('dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70') \`\`\` Optionally, you can specify the index of the index output. \`\`\`tsx await provider.fetchUTxOs('hash\_here', 0) \`\`\` ## Fetch Proposal Info Get information for a given governance proposal, identified by the txHash and proposal index \`\`\`tsx // Params: TxHash, CertIndex await provider.fetchGovernanceProposal('372d688faa77e146798b581b322c0f2981a9023764736ade5d12e0e4e796af8c', 0) \`\`\` ## Evaluate Transaction \`evaluateTx()\` accepts an unsigned transaction (\`unsignedTx\`) and it evaluates the resources required to execute the transaction. Note that, this is only valid for transaction interacting with redeemer (smart contract). By knowing the budget required, you can use this to adjust the redeemer's budget so you don't spend more than you need to execute transactions for this smart contract. \`\`\`tsx const unsignedTx = await tx.build(); const evaluateTx = await provider.evaluateTx(unsignedTx); \`\`\` Example responses from unlocking assets from the always succeed smart contract. \`\`\`tsx \[ { "index": 0, "tag": "SPEND", "budget": { "mem": 1700, "steps": 368100 } } \] \`\`\` With the \`mem\` and \`steps\`, you can refine the budget for the redeemer. For example: \`\`\`tsx const redeemer = { data: { alternative: 0, fields: \[...\] }, budget: { mem: 1700, steps: 368100, }, }; \`\`\` ## Submit Transaction Submit a serialized transaction to the network. \`\`\`tsx await provider.submitTx(signedTx); \`\`\` ## On Transaction Confirmed Allow you to listen to a transaction confirmation. Upon confirmation, the callback will be called. \`\`\`tsx const tx = new Transaction({ initiator: wallet }); tx.sendLovelace('addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', '5000000'); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); provider.onTxConfirmed(txHash, () => { // Transaction confirmed }); \`\`\` # Offline Evaluator URL: /providers/offline-evaluator An offline Plutus script evaluator for testing and validation. \*\*\* title: "Offline Evaluator" description: "An offline Plutus script evaluator for testing and validation." ----------------------------------------------------------------------------- import Link from "fumadocs-core/link"; The OfflineEvaluator calculates execution costs (memory and CPU steps) for Plutus scripts in transactions without requiring network connectivity. It works with an OfflineFetcher to resolve the UTXOs needed for script validation. This is also compatible with any other fetchers to provide online data fetching. Get started: \`\`\`tsx import { OfflineEvaluator } from "@meshsdk/core-csl"; import { OfflineFetcher } from "@meshsdk/core"; // Create fetcher for resolving UTXOs const fetcher = new OfflineFetcher(); // Add UTXOs required for script evaluation fetcher.addUTxOs(\[ { input: { txHash: "5de23a2...", outputIndex: 0 }, output: { address: "addr1...", amount: \[{ unit: "lovelace", quantity: "1000000" }\], scriptHash: "32b7e3d..." // For script UTXOs } } \]); // Create evaluator for the desired network const evaluator = new OfflineEvaluator(fetcher, "preprod"); \`\`\` Once initialized, you can evaluate Plutus scripts in transactions: \`\`\`tsx // Evaluate Plutus scripts in a transaction try { const actions = await evaluator.evaluateTx(transactionCbor); // Example result: // \[{ // index: 0, // tag: "MINT", // budget: { // mem: 508703, // Memory units used // steps: 164980381 // CPU steps used // } // }\] } catch (error) { console.error('Script evaluation failed:', error); } \`\`\` The evaluator is particularly useful for testing Plutus scripts, ensuring they execute within memory and CPU limits: \`\`\`tsx // In your test file describe("Plutus Script Tests", () => { let evaluator: OfflineEvaluator; let fetcher: OfflineFetcher; beforeEach(() => { fetcher = new OfflineFetcher(); evaluator = new OfflineEvaluator(fetcher, "preprod"); // Add test UTXOs fetcher.addUTxOs(\[...\]); }); it("should evaluate minting policy", async () => { const result = await evaluator.evaluateTx(txCbor); expect(result\[0\].tag).toBe("MINT"); expect(result\[0\].budget.mem).toBeLessThan(600000); }); }); \`\`\` The evaluation results include memory units and CPU steps required for each script execution, helping you optimize your scripts and ensure they meet protocol constraints. ## Evaluate Transaction \`evaluateTx()\` accepts an unsigned transaction (\`unsignedTx\`) and it evaluates the resources required to execute the transaction. Note that, this is only valid for transaction interacting with redeemer (smart contract). By knowing the budget required, you can use this to adjust the redeemer's budget so you don't spend more than you need to execute transactions for this smart contract. \`\`\`tsx const unsignedTx = await tx.build(); const evaluateTx = await provider.evaluateTx(unsignedTx); \`\`\` Example responses from unlocking assets from the always succeed smart contract. \`\`\`tsx \[ { "index": 0, "tag": "SPEND", "budget": { "mem": 1700, "steps": 368100 } } \] \`\`\` With the \`mem\` and \`steps\`, you can refine the budget for the redeemer. For example: \`\`\`tsx const redeemer = { data: { alternative: 0, fields: \[...\] }, budget: { mem: 1700, steps: 368100, }, }; \`\`\` # OfflineFetcher URL: /providers/offline-fetcher An offline blockchain data provider for testing, development and offline scenarios. \*\*\* title: "OfflineFetcher" description: "An offline blockchain data provider for testing, development and offline scenarios." -------------------------------------------------------------------------------------------------- import Link from "fumadocs-core/link"; The OfflineFetcher provides access to blockchain data without requiring network connectivity. It's ideal for testing, development, and scenarios where you need to work with pre-loaded blockchain data offline. Initialize the fetcher: \`\`\`tsx import { OfflineFetcher } from "@meshsdk/core"; // Create a new instance const fetcher = new OfflineFetcher(); // Create with specified network const fetcherWithNetwork = new OfflineFetcher("mainnet"); \`\`\` Before you can fetch data, you need to add it to the fetcher. Here are examples of adding different types of blockchain data: \`\`\`tsx // Add account information fetcher.addAccount("addr1...", { balance: "1000000", rewards: "500000", withdrawals: "100000", poolId: "pool1..." // optional }); // Add UTXOs fetcher.addUTxOs(\[ { input: { txHash: "1234...", outputIndex: 0 }, output: { address: "addr1...", amount: \[{ unit: "lovelace", quantity: "1000000" }\], // Optional fields for script UTXOs: scriptHash: "abcd...", dataHash: "ef12...", plutusData: "...", scriptRef: "..." } } \]); // Add asset addresses fetcher.addAssetAddresses("policyID.assetName", \[ { address: "addr1...", quantity: "1" } \]); // Add asset metadata fetcher.addAssetMetadata("policyID.assetName", { name: "Asset Name", image: "ipfs://...", // Any other metadata attributes }); // Add protocol parameters fetcher.addProtocolParameters({ epoch: 290, minFeeA: 44, minFeeB: 155381, maxBlockSize: 73728, maxTxSize: 16384, maxBlockHeaderSize: 1100, keyDeposit: 2000000, poolDeposit: 500000000, minPoolCost: "340000000", // Other parameters... }); // Add serilized transaction fetcher.addSerializedTransaction("txHash"); \`\`\` The fetcher's state can be saved and loaded, making it easy to persist data between sessions: \`\`\`tsx // Save state const state = fetcher.toJSON(); localStorage.setItem('fetcher-state', state); // Load state const savedState = localStorage.getItem('fetcher-state'); const fetcher = OfflineFetcher.fromJSON(savedState); \`\`\` Once data is added, you can use the fetch\\\* methods just like with other providers such as BlockfrostProvider. This makes OfflineFetcher a drop-in replacement for testing and offline scenarios. ## Get data from URL You can fetch any data from the blockchain by providing the URL path. \`\`\`tsx // Params: URL await provider.get('/addresses/addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9/transactions') \`\`\` ## Fetch Account Info Obtain information about a specific stake account. \`\`\`tsx // Params: Stake Address await provider.fetchAccountInfo('stake\_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n') \`\`\` ## Fetch Address Assets Fetch assets from an address. \`\`\`tsx // Params: Address await provider.fetchAddressAssets('addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') \`\`\` \### Fetch Address UTxOs \\\[!toc\] Fetch UTxOs from address \`\`\`tsx await provider.fetchAddressAssets( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); \`\`\` \### Fetch assets from address \\\[!toc\] Fetch assets given an address \`\`\`tsx await provider.fetchAddressAssets( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', ); \`\`\` \## Fetch Address UTxOs Fetch UTxOs controlled by an address. \`\`\`tsx // Params: Address await provider.fetchAddressUTxOs('addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') \`\`\` Optionally, you can filter UTXOs containing a particular asset by providing \`asset\`, where it is the concatenation of policy ID and asset. \`\`\`tsx await fetchAddressUTxOs(address: string, asset?: string) \`\`\` \### Fetch Address UTxOs \\\[!toc\] Fetch UTxOs from address \`\`\`tsx await provider.fetchAddressUTxOs( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); \`\`\` \### Fetch UTxOs with Asset \\\[!toc\] Fetch UTxOs from address with asset \`\`\`tsx await provider.fetchAddressUTxOs( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e' ); \`\`\` \## Fetch Asset Addresses Fetch a list of a addresses containing a specific asset where it is the concatenation of policy ID and asset. \`\`\`tsx // Params: Asset Unit await provider.fetchAssetAddresses('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') \`\`\` ## Fetch Asset Metadata Fetch the asset metadata by providing asset's \`unit\`, which is the concatenation of policy ID and asset name in hex. \`\`\`tsx // Params: Asset Unit await provider.fetchAssetMetadata('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') \`\`\` ## Fetch Block Info Fetch block infomation. You can get the hash from \`fetchTxInfo()\`. \`\`\`tsx // Params: Block hash await provider.fetchBlockInfo('79f60880b097ec7dabb81f75f0b52fedf5e922d4f779a11c0c432dcf22c56089') \`\`\` ## Fetch Collection Assets Fetch a list of assets belonging to a collection by providing its Policy ID. \`\`\`tsx await provider.fetchCollectionAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527') \`\`\` The API will return a list of \`assets\` and a cursor \`next\`. If the cursor is not null, you can use it to fetch the next page of results. Here is an example of the response. \`\`\`tsx { "assets": \[ { "unit": "d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527", "quantity": "1" }, \], "next": 2 } \`\`\` The \`fetchCollectionAssets\` function also accepts an optional \`cursor\` parameter to fetch the next page of results. The default value is \`1\`. \`\`\`tsx await fetchCollectionAssets( policyId: string, cursor = 1 ) \`\`\` ## Fetch Handle Address ADA Handle allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. We can resolve the handle's address with \`fetchHandleAddress\`. \`\`\`tsx // Params: Handle await provider.fetchHandleAddress('meshsdk') \`\`\` ## Fetch Handle ADA Handle allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. ADA Handle also released a CIP68 handle and this function will fetch the metadata of the handle. \`\`\`tsx // Params: Handle await provider.fetchHandle('meshsdk') \`\`\` ## Fetch Protocol Parameters Fetch the latest protocol parameters. \`\`\`tsx await provider.fetchProtocolParameters() \`\`\` Optionally, you can provide an epoch number to fetch the protocol parameters of that epoch. ## Fetch Transaction Info Fetch transaction infomation. Only confirmed transaction can be retrieved. \`\`\`tsx await provider.fetchTxInfo('f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159') \`\`\` ## Fetch UTxOs Get UTxOs for a given hash. \`\`\`tsx // Params: Hash await provider.fetchUTxOs('dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70') \`\`\` Optionally, you can specify the index of the index output. \`\`\`tsx await provider.fetchUTxOs('hash\_here', 0) \`\`\` ## Fetch Proposal Info Get information for a given governance proposal, identified by the txHash and proposal index \`\`\`tsx // Params: TxHash, CertIndex await provider.fetchGovernanceProposal('372d688faa77e146798b581b322c0f2981a9023764736ade5d12e0e4e796af8c', 0) \`\`\` # Ogmios Provider URL: /providers/ogmios Lightweight bridge interface for cardano-node that offers WebSockets API that enables local clients to speak Ouroboros' mini-protocols \*\*\* title: "Ogmios Provider" description: "Lightweight bridge interface for cardano-node that offers WebSockets API that enables local clients to speak Ouroboros' mini-protocols" ----------------------------------------------------------------------------------------------------------------------------------------------------- import Link from "fumadocs-core/link"; Ogmios is a lightweight bridge interface for cardano-node. It offers a WebSockets API that enables local clients to speak Ouroboros' mini-protocols via JSON/RPC. Ogmios is a fast and lightweight solution that can be deployed alongside relays to create entry points on the Cardano network for various types of applications. Get started: \`\`\`tsx import { OgmiosProvider } from "@meshsdk/core"; const provider = new OgmiosProvider(''); \`\`\` ## Evaluate Transaction \`evaluateTx()\` accepts an unsigned transaction (\`unsignedTx\`) and it evaluates the resources required to execute the transaction. Note that, this is only valid for transaction interacting with redeemer (smart contract). By knowing the budget required, you can use this to adjust the redeemer's budget so you don't spend more than you need to execute transactions for this smart contract. \`\`\`tsx const unsignedTx = await tx.build(); const evaluateTx = await provider.evaluateTx(unsignedTx); \`\`\` Example responses from unlocking assets from the always succeed smart contract. \`\`\`tsx \[ { "index": 0, "tag": "SPEND", "budget": { "mem": 1700, "steps": 368100 } } \] \`\`\` With the \`mem\` and \`steps\`, you can refine the budget for the redeemer. For example: \`\`\`tsx const redeemer = { data: { alternative: 0, fields: \[...\] }, budget: { mem: 1700, steps: 368100, }, }; \`\`\` ## Submit Transaction Submit a serialized transaction to the network. \`\`\`tsx await provider.submitTx(signedTx); \`\`\` # UTxORPC Provider URL: /providers/utxorpc Highly efficient through gRPC, using a compact and high-performance binary format \*\*\* title: "UTxORPC Provider" description: "Highly efficient through gRPC, using a compact and high-performance binary format" ------------------------------------------------------------------------------------------------ import Link from "fumadocs-core/link"; Highly efficient through gRPC, using a compact and high-performance binary format The UTxORPC (u5c) provider facilitates access to this state in a standardized and efficient manner through gRPC, using a compact and high-performance binary format. It enables seamless interaction with the Cardano blockchain, to facilitate the creation, signing, and submission of transactions. \* Standardized Interface: Implements the UTxORPC specification to ensure compatibility and interoperability across UTxO-based blockchains. \* Performance Optimized: Utilizes gRPC for efficient communication with blockchain nodes, minimizing network overhead and message size. \* Flexible Provider Options: Suitable for use with hosted services, local nodes like Dolos, or any UTxORPC-compliant service. The following code samples assume that the UTxORPC node is running locally on localhost:50051. If your node is hosted remotely or on a different server, replace "\[http://localhost:50051\](http://localhost:50051)" with the appropriate server URL and port for your environment. You can also use the UTxORPC provider with a hosted service like Demeter.run. Demeter is a PaaS (Platform-as-a-Service) that provides managed Cardano infrastructure. One of their services consists of a cloud-hosted endpoint for Cardano integration using the UTxO RPC spec. Developers can sign-up and get access to the API on a per-request basis. For more details on configuring your node, refer to the UTxORPC Ecosystem Servers Documentation. \`\`\`tsx import { U5CProvider } from "@meshsdk/core"; const provider = new U5CProvider({ url: "http://localhost:50051", headers: { "dmtr-api-key": "", }, }); \`\`\` ## Get data from URL You can fetch any data from the blockchain by providing the URL path. \`\`\`tsx await provider.get('/addresses/addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9/transactions') \`\`\` ## Fetch Account Info Obtain information about a specific stake account. \`\`\`tsx await provider.fetchAccountInfo('stake\_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n') \`\`\` ## Fetch Address Assets Fetch assets from an address. \`\`\`tsx await provider.fetchAddressAssets('addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') \`\`\` \### Fetch Address UTxOs \\\[!toc\] Fetch UTxOs from address \`\`\`tsx await provider.fetchAddressAssets( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); \`\`\` \### Fetch assets from address \\\[!toc\] Fetch assets given an address. \`\`\`tsx await provider.fetchAddressAssets( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', ); \`\`\` \## Fetch Address UTxOs Fetch UTxOs controlled by an address. \`\`\`tsx await provider.fetchAddressUTxOs('addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') \`\`\` Optionally, you can filter UTXOs containing a particular asset by providing \`asset\`, where it is the concatenation of policy ID and asset. \`\`\`tsx await fetchAddressUTxOs(address: string, asset?: string) \`\`\` ## Fetch Asset Addresses Fetch a list of a addresses containing a specific asset where it is the concatenation of policy ID and asset. \`\`\`tsx await provider.fetchAssetAddresses('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') \`\`\` ## Fetch Asset Metadata Fetch the asset metadata by providing asset's \`unit\`, which is the concatenation of policy ID and asset name in hex. \`\`\`tsx await provider.fetchAssetMetadata('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') \`\`\` ## Fetch Block Info Fetch block infomation. You can get the hash from \`fetchTxInfo()\`. \`\`\`tsx await provider.fetchBlockInfo('79f60880b097ec7dabb81f75f0b52fedf5e922d4f779a11c0c432dcf22c56089') \`\`\` ## Fetch Collection Assets Fetch a list of assets belonging to a collection by providing its Policy ID. \`\`\`tsx await provider.fetchCollectionAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527') \`\`\` The API will return a list of \`assets\` and a cursor \`next\`. If the cursor is not null, you can use it to fetch the next page of results. Here is an example of the response. \`\`\`tsx { "assets": \[ { "unit": "d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527", "quantity": "1" }, \], "next": 2 } \`\`\` The \`fetchCollectionAssets\` function also accepts an optional \`cursor\` parameter to fetch the next page of results. The default value is \`1\`. \`\`\`tsx await fetchCollectionAssets( policyId: string, cursor = 1 ) \`\`\` ## Fetch Handle Address ADA Handle allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. We can resolve the handle's address with \`fetchHandleAddress\`. \`\`\`tsx // Handle: \`meshsdk\` await provider.fetchHandleAddress('meshsdk') \`\`\` ## Fetch Handle ADA Handle allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. ADA Handle also released a CIP68 handle and this function will fetch the metadata of the handle. \`\`\`tsx // Handle: \`meshsdk\` await provider.fetchHandle('meshsdk') \`\`\` ### Fetch Protocol Parameters Fetch the latest protocol parameters. \`\`\`tsx await provider.fetchProtocolParameters() \`\`\` Optionally, you can provide an epoch number to fetch the protocol parameters of that epoch. ## Fetch Transaction Info Fetch transaction infomation. Only confirmed transaction can be retrieved. \`\`\`tsx await provider.fetchTxInfo('f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159') \`\`\` ## Fetch UTxOs Get UTxOs for a given hash. \`\`\`tsx // Hash f.e. dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70 await provider.fetchUTxOs('dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70') \`\`\` Optionally, you can specify the index of the index output. \`\`\`tsx await provider.fetchUTxOs('hash\_here', 0) \`\`\` ## Fetch Proposal Info Get information for a given governance proposal, identified by the txHash and proposal index \`\`\`tsx await provider.fetchGovernanceProposal('372d688faa77e146798b581b322c0f2981a9023764736ade5d12e0e4e796af8c', 0) \`\`\` ## Evaluate Transaction \`evaluateTx()\` accepts an unsigned transaction (\`unsignedTx\`) and it evaluates the resources required to execute the transaction. Note that, this is only valid for transaction interacting with redeemer (smart contract). By knowing the budget required, you can use this to adjust the redeemer's budget so you don't spend more than you need to execute transactions for this smart contract. \`\`\`tsx const unsignedTx = await tx.build(); const evaluateTx = await provider.evaluateTx(unsignedTx); \`\`\` Example responses from unlocking assets from the always succeed smart contract. \`\`\`tsx \[ { "index": 0, "tag": "SPEND", "budget": { "mem": 1700, "steps": 368100 } } \] \`\`\` With the \`mem\` and \`steps\`, you can refine the budget for the redeemer. For example: \`\`\`tsx const redeemer = { data: { alternative: 0, fields: \[...\] }, budget: { mem: 1700, steps: 368100, }, }; \`\`\` ## Submit Transaction Submit a serialized transaction to the network. \`\`\`tsx await provider.submitTx(signedTx); \`\`\` ## On Transaction Confirmed Allow you to listen to a transaction confirmation. Upon confirmation, the callback will be called. \`\`\`tsx const tx = new Transaction({ initiator: wallet }); tx.sendLovelace('addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', '5000000'); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); provider.onTxConfirmed(txHash, () => { // Transaction confirmed }); \`\`\` # Yaci Provider URL: /providers/yaci Custom Cardano devnet to tailor your devnet needs with a builtin indexer and custom viewer for devnet \*\*\* title: "Yaci Provider" description: "Custom Cardano devnet to tailor your devnet needs with a builtin indexer and custom viewer for devnet" -------------------------------------------------------------------------------------------------------------------- import Link from "fumadocs-core/link"; Yaci DevKit is a development tool designed for rapid and efficient Cardano blockchain development. It allows developers to create and destroy custom Cardano devnets in seconds, providing fast feedback loops and simplifying the iteration process. Get started: \`\`\`tsx import { YaciProvider } from "@meshsdk/core"; const provider = new YaciProvider('', ''); \`\`\` ## Get data from URL You can fetch any data from the blockchain by providing the URL path. \`\`\`tsx await provider.get('/addresses/addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9/transactions') \`\`\` ## Fetch Account Info Obtain information about a specific stake account. \`\`\`tsx await provider.fetchAccountInfo('stake\_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n') \`\`\` ## Fetch Address Assets Fetch assets from an address. \`\`\`tsx await provider.fetchAddressAssets('addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') \`\`\` \### Fetch Address UTxOs \\\[!toc\] Fetch UTxOs from address \`\`\`tsx await provider.fetchAddressAssets( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); \`\`\` \### Fetch assets from address \\\[!toc\] Fetch assets given an address \`\`\`tsx await provider.fetchAddressAssets( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', ); \`\`\` \## Fetch Address UTxOs Fetch UTxOs controlled by an address. \`\`\`tsx await provider.fetchAddressUTxOs('addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9') \`\`\` Optionally, you can filter UTXOs containing a particular \`asset\` by providing asset, where it is the concatenation of policy ID and asset. \`\`\`tsx await fetchAddressUTxOs(address: string, asset?: string) \`\`\` \### Fetch Address UTxOs \\\[!toc\] Fetch UTxOs from address \`\`\`tsx await provider.fetchAddressUTxOs( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9' ); \`\`\` \### Fetch UTxOs with Asset \\\[!toc\] Fetch UTxOs from address with asset \`\`\`tsx await provider.fetchAddressUTxOs( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e' ); \`\`\` \## Fetch Asset Addresses Fetch a list of a addresses containing a specific \`asset\` where it is the concatenation of policy ID and asset. \`\`\`tsx await provider.fetchAssetAddresses('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') \`\`\` ## Fetch Asset Metadata Fetch the asset metadata by providing asset's \`unit\`, which is the concatenation of policy ID and asset name in hex. \`\`\`tsx await provider.fetchAssetMetadata('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e') \`\`\` ## Fetch Block Info Fetch block infomation. You can get the hash from \`fetchTxInfo()\`. \`\`\`tsx await provider.fetchBlockInfo('79f60880b097ec7dabb81f75f0b52fedf5e922d4f779a11c0c432dcf22c56089') \`\`\` ## Fetch Collection Assets Fetch a list of assets belonging to a collection by providing its Policy ID. \`\`\`tsx await provider.fetchCollectionAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527') \`\`\` The API will return a list of \`assets\` and a cursor \`next\`. If the cursor is not null, you can use it to fetch the next page of results. Here is an example of the response. \`\`\`tsx { "assets": \[ { "unit": "d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527", "quantity": "1" }, \], "next": 2 } \`\`\` The \`fetchCollectionAssets\` function also accepts an optional \`cursor\` parameter to fetch the next page of results. The default value is \`1\`. \`\`\`tsx await fetchCollectionAssets( policyId: string, cursor = 1 ) \`\`\` ## Fetch Handle Address ADA Handle allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. We can resolve the handle's address with \`fetchHandleAddress\`. \`\`\`tsx // Handle: \`meshsdk\` await provider.fetchHandleAddress('meshsdk') \`\`\` ## Fetch Handle ADA Handle allows users to use a human-readable "Handle" to associate an address. Each Handle is a unique NFT, minted and issued on the Cardano blockchain. These NFTs act as unique identifiers for the UTXO that they reside in. ADA Handle also released a CIP68 handle and this function will fetch the metadata of the handle. \`\`\`tsx // Handle: \`meshsdk\` await provider.fetchHandle('meshsdk') \`\`\` ## Fetch Protocol Parameters Fetch the latest protocol parameters. \`\`\`tsx await provider.fetchProtocolParameters() \`\`\` Optionally, you can provide an epoch number to fetch the protocol parameters of that epoch. ## Fetch Transaction Info Fetch transaction infomation. Only confirmed transaction can be retrieved. \`\`\`tsx await provider.fetchTxInfo('f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159') \`\`\` ## Fetch UTxOs Get UTxOs for a given hash. \`\`\`tsx // Hash: \`dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70\` await provider.fetchUTxOs('dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70') \`\`\` Optionally, you can specify the index of the index output. \`\`\`tsx await provider.fetchUTxOs('hash\_here', 0) \`\`\` ## Fetch Proposal Info Get information for a given governance proposal, identified by the txHash and proposal index \`\`\`tsx await provider.fetchGovernanceProposal('372d688faa77e146798b581b322c0f2981a9023764736ade5d12e0e4e796af8c', 0) \`\`\` ## Evaluate Transaction \`evaluateTx()\` accepts an unsigned transaction (\`unsignedTx\`) and it evaluates the resources required to execute the transaction. Note that, this is only valid for transaction interacting with redeemer (smart contract). By knowing the budget required, you can use this to adjust the redeemer's budget so you don't spend more than you need to execute transactions for this smart contract. \`\`\`tsx const unsignedTx = await tx.build(); const evaluateTx = await provider.evaluateTx(unsignedTx); \`\`\` Example responses from unlocking assets from the always succeed smart contract. \`\`\`tsx \[ { "index": 0, "tag": "SPEND", "budget": { "mem": 1700, "steps": 368100 } } \] \`\`\` With the \`mem\` and \`steps\`, you can refine the budget for the redeemer. For example: \`\`\`tsx const redeemer = { data: { alternative: 0, fields: \[...\] }, budget: { mem: 1700, steps: 368100, }, }; \`\`\` ## Submit Transaction Submit a serialized transaction to the network. \`\`\`tsx await provider.submitTx(signedTx); \`\`\` ## On Transaction Confirmed Allow you to listen to a transaction confirmation. Upon confirmation, the callback will be called. \`\`\`tsx const tx = new Transaction({ initiator: wallet }); tx.sendLovelace('addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', '5000000'); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); provider.onTxConfirmed(txHash, () => { // Transaction confirmed }); \`\`\` ## Admin Get Devnet Info Get information about the devnet. \`\`\`tsx await provider.getDevnetInfo() \`\`\` Example response: \`\`\`tsx { "nodePort": 0, "submitApiPort": 0, "socketPath": "string", "protocolMagic": 0, "slotLength": 0, "blockTime": 0, "epochLength": 0, "p2pEnabled": true, "startTime": 0, "masterNode": true, "adminNodeUrl": "string", "era": "Byron", "genesisProfile": "zero\_fee", "ogmiosPort": 0, "kupoPort": 0, "yaciStorePort": 0, "socatPort": 0, "prometheusPort": 0, "blockProducer": true } \`\`\` ## Admin Get Genesis Info By Era You can topup ADA for any address. To topup ADA in your wallet, run the following command from devnet: \`\`\`tsx await provider.getGenesisByEra() \`\`\` Example response: \`\`\`tsx { "activeSlotsCoeff": 1, "epochLength": 500, "genDelegs": { "337bc5ef0f1abf205624555c13a37258c42b46b1259a6b1a6d82574e": { "delegate": "41fd6bb31f34469320aa47cf6ccc3918e58a06d60ea1f2361efe2458", "vrf": "7053e3ecd2b19db13e5338aa75fb518fc08b6c218f56ad65760d3eb074be95d4" } }, "initialFunds": { "60ba957a0fff6816021b2afa7900beea68fd10f2d78fb5b64de0d2379c": 3000000000000000, "007290ea8fa9433c1045a4c8473959ad608e6c03a58c7de33bdbd3ce6f295b987135610616f3c74e11c94d77b6ced5ccc93a7d719cfb135062": 300000000000, "605276322ac7882434173dcc6441905f6737689bd309b68ad8b3614fd8": 3000000000000000, "60a0f1aa7dca95017c11e7e373aebcf0c4568cf47ec12b94f8eb5bba8b": 3000000000000000, "005867c3b8e27840f556ac268b781578b14c5661fc63ee720dbeab663f9d4dcd7e454d2434164f4efb8edeb358d86a1dad9ec6224cfcbce3e6": 1000000000 }, "maxKESEvolutions": 60, "maxLovelaceSupply": 45000000000000000, "networkId": "Testnet", "networkMagic": 42, "protocolParams": { "a0": 0, "decentralisationParam": 0, "eMax": 18, "extraEntropy": { "tag": "NeutralNonce" }, "keyDeposit": 2000000, "maxBlockBodySize": 65536, "maxBlockHeaderSize": 1100, "maxTxSize": 16384, "minFeeA": 0, "minFeeB": 0, "minPoolCost": 340000000, "minUTxOValue": 1000000, "nOpt": 100, "poolDeposit": 500000000, "protocolVersion": { "major": 8, "minor": 0 }, "rho": 0.003, "tau": 0.2 }, "securityParam": 300, "slotLength": 1, "slotsPerKESPeriod": 129600, "staking": { "pools": { "7301761068762f5900bde9eb7c1c15b09840285130f5b0f53606cc57": { "cost": 340000000, "margin": 0, "metadata": null, "owners": \[\], "pledge": 0, "publicKey": "7301761068762f5900bde9eb7c1c15b09840285130f5b0f53606cc57", "relays": \[\], "rewardAccount": { "credential": { "keyHash": "11a14edf73b08a0a27cb98b2c57eb37c780df18fcfcf6785ed5df84a" }, "network": "Testnet" }, "vrf": "c2b62ffa92ad18ffc117ea3abeb161a68885000a466f9c71db5e4731d6630061" } }, "stake": { "9d4dcd7e454d2434164f4efb8edeb358d86a1dad9ec6224cfcbce3e6": "7301761068762f5900bde9eb7c1c15b09840285130f5b0f53606cc57" } }, "systemStart": "2024-10-30T05:11:07.442512Z", "updateQuorum": 1 } \`\`\` ## Admin Address Topup You can topup ADA for any address. To topup ADA in your wallet, run the following command from devnet: \`\`\`tsx await provider.addressTopup( , ) \`\`\` \## Topup Address \\\[!toc\] Admin function to topup address with ADA \*\*Address\*\* \`addr\_test1qpvx....9uu0nq93swx9\` \*\*Amount\*\* \`20000000\` \`\`\`tsx await provider.addressTopup('addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', '20000000'); \`\`\` \# Midnight URL: /midnight Zero-knowledge privacy network for Cardano \*\*\* title: "Midnight" description: "Zero-knowledge privacy network for Cardano" icon: "icons/midnight.svg" -------------------------- import {linksMidnight} from "@/data/links-midnight"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksMidnight.map((card) => ( {card.title} {card.desc} ))} \# Getting Started with React URL: /react/getting-started Frontend components for wallet connections, and useful React hooks to getting wallet states \*\*\* title: "Getting Started with React" description: "Frontend components for wallet connections, and useful React hooks to getting wallet states" icon: RocketLaunchIcon ---------------------- import Link from "fumadocs-core/link"; Mesh provide a collection of useful UI components, so you can easily include web3 functionality and convenient utilities for your application. ## Setup The fastest way to get started a new project with React is to use the Mesh-CLI, which will scaffold a new project for you. To do this, run the following: \`\`\`tsx npx meshjs your-app-name \`\`\` During the installation process, you will be asked to choose a template. Choose the React template. This will scaffold a new React project with Mesh pre-installed. To manually, install the Mesh React package, run the following: \`\`\`tsx npm install @meshsdk/react \`\`\` Next, add the Mesh CSS to your application, doing so will apply the default styles to the components. You can add this in \`/pages/\_app.tsx\`. \`\`\`tsx import "@meshsdk/react/styles.css"; \`\`\` ## Mesh Provider React Context allows apps to share data across the app, and \`MeshProvider\` allows your app to subscribe to context changes. If you use the CLI to initialize your project, \`MeshProvider\` has been added in the root component. Otherwise, you can wrap \`MeshProvider\` at the root of your application, for example in Next.js: \`\`\`tsx import "@meshsdk/react/styles.css"; import { MeshProvider } from "@meshsdk/react"; function MyApp({ Component, pageProps }: AppProps) { return ( ); }; \`\`\` Now your application is ready, explore the available UI components and wallet hooks and start using them in your application. ## Connect Wallet In order for pps to communicate with the user's wallet, we need a way to connect to their wallet. Add this CardanoWallet to allow the user to select a wallet to connect to your app. After the wallet is connected, see Browser Wallet for a list of CIP-30 APIs. The signature for the CardanoWallet component is as follows: \`\`\`tsx { label?: string; onConnected?: Function; isDark?: boolean; } \`\`\` ### Customization \\\[!toc\] For dark mode style, add isDark. \`\`\`tsx \`\`\` For a custom label, add the label prop. \`\`\`tsx \`\`\` The customization is limited. For more customization, you can easily build your own wallet connection component. If you are using React, the React hooks will be useful. You may also take reference from this component. ### Persist user session \\\[!toc\] If you would like to save the user last connected wallet and automatically connect to it on the next visit, you can use the persist prop. \`\`\`tsx \`\`\` ### onConnected \\\[!toc\] If you want to run a function after the wallet is connected, you can add the onConnected prop. \`\`\`tsx export default function Page() { function afterConnectedWallet() { // do something } return ( <> ); } \`\`\` The above code will log "Hello, World!" to the console when the wallet is connected. ### Mesh Web3 Services \\\[!toc\] Mesh Web3 Services streamline user onboarding and on-chain feature integration, accelerating your app's time to market. To integrate Mesh Web3 Services, use the \`web3Services\` prop. The \`networkId\` is the network ID of the wallet you are connecting to. You may use any providers for \`fetcher\` and \`submitter\`. \`\`\`tsx const provider = new BlockfrostProvider(''); \`\`\` ### Decentralized WebRTC Wallet Communication (CIP 45) \\\[!toc\] CIP-45 is a communication method between pps and wallets based on WebTorrent trackers and WebRTC. Using WebTorrent trackers for the peer discovery to remove the need of this central component. ### Burner wallet \\\[!toc\] Burner wallets are wallets that are created on the fly on the user's device. They are temporary wallets useful for testing purposes. The private keys are generated and stored on the user's device. \`\`\`tsx \`\`\` ### MetaMask Snaps \\\[!toc\] MetaMask Snaps are a new way to extend MetaMask with custom functionality and integrations. You can check the implementation to integrate NuFi from the GitHub repository. Use the \`injectFn\` prop to add custom functionality. \`\`\`tsx await checkIfMetamaskInstalled("preprod")} /> \`\`\` \### Connect Wallet Component \\\[!toc\] Connect to user's wallet to interact with app \`\`\`tsx import { CardanoWallet } from '@meshsdk/react'; export default function Page() { return ( <> {console.log('on connected')}} cardanoPeerConnect={{ dAppInfo: { name: "Mesh SDK", url: "https://meshjs.dev/", }, announce: \[ "wss://dev.btt.cf-identity-wallet.metadata.dev.cf-deployments.org", \], }} burnerWallet={{ networkId: 0, provider: provider, }} /> ); } \`\`\` \## useWallet Hook Provide information on the current wallet's state, and functions for connecting and disconnecting user wallet. \`\`\`tsx const { wallet, state, connected, name, connecting, connect, disconnect, error } = useWallet(); \`\`\` \`wallet\` is a Browser Wallet instance, which expose all CIP wallets functions from getting assets to signing tranasction. \`state\`, a enum string, the state of the wallet, can be \`NOT\_CONNECTED\`, \`CONNECTING\` or \`CONNECTED\`. \`connected\`, a boolean, \`true\` if user's wallet is connected. \`name\`, a string, the name of the connect wallet. \`connecting\`, a boolean, \`true\` if the wallet is connecting and initializing. \`connect(walletName: string)\`, a function, provide the wallet name to connect wallet. Retrive a list of available wallets with \`useWalletList()\`. \`disconnect()\`, a function, to disconnect the connected wallet. \`error\`, returns the error object if any error occurs during wallet connection, such as "account not set". \### useWallet Hook \\\[!toc\] Interact with user's wallet \`\`\`tsx import { useWallet } from '@meshsdk/react'; export default function Page() { const { wallet, state, connected, name, connecting, connect, disconnect, error } = useWallet(); return ( **State:** {state} **Connected?:** {connected ? 'Is connected' : 'Not connected'} **Connecting wallet?:** {connecting ? 'Connecting...' : 'No'} **Name of connected wallet:** {name} disconnect()}>Disconnect Wallet ); } \`\`\` \# React Components URL: /react Frontend React UI components and React hooks \*\*\* title: "React Components" description: "Frontend React UI components and React hooks" icon: ComputerDesktopIcon ------------------------- import {linksReact} from "@/data/links-react"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksReact.map((card) => ( {card.title} {card.desc} ))} \# UI Components URL: /react/ui-components UI components to speed up your app development. \*\*\* title: "UI Components" description: "UI components to speed up your app development." icon: PaintBrushIcon -------------------- import Link from "fumadocs-core/link"; Mesh provide a collection of useful UI components, so you can easily include web3 functionality and convenient utilities for your application. ## Connect Wallet In order for pps to communicate with the user's wallet, we need a way to connect to their wallet. Add this CardanoWallet to allow the user to select a wallet to connect to your app. After the wallet is connected, see Browser Wallet for a list of CIP-30 APIs. The signature for the CardanoWallet component is as follows: \`\`\`tsx { label?: string; onConnected?: Function; isDark?: boolean; } \`\`\` ### Customization \\\[!toc\] For dark mode style, add isDark. \`\`\`tsx \`\`\` For a custom label, add the label prop. \`\`\`tsx \`\`\` The customization is limited. For more customization, you can easily build your own wallet connection component. If you are using React, the React hooks will be useful. You may also take reference from this component. ### Persist user session \\\[!toc\] If you would like to save the user last connected wallet and automatically connect to it on the next visit, you can use the persist prop. \`\`\`tsx \`\`\` ### onConnected \\\[!toc\] If you want to run a function after the wallet is connected, you can add the onConnected prop. \`\`\`tsx export default function Page() { function afterConnectedWallet() { // do something } return ( <> ); } \`\`\` The above code will log "Hello, World!" to the console when the wallet is connected. ### Mesh Web3 Services \\\[!toc\] Mesh Web3 Services streamline user onboarding and on-chain feature integration, accelerating your app's time to market. To integrate Mesh Web3 Services, use the \`web3Services\` prop. The \`networkId\` is the network ID of the wallet you are connecting to. You may use any providers for \`fetcher\` and \`submitter\`. \`\`\`tsx const provider = new BlockfrostProvider(''); \`\`\` ### Decentralized WebRTC Wallet Communication (CIP 45) \\\[!toc\] CIP-45 is a communication method between pps and wallets based on WebTorrent trackers and WebRTC. Using WebTorrent trackers for the peer discovery to remove the need of this central component. ### Burner wallet \\\[!toc\] Burner wallets are wallets that are created on the fly on the user's device. They are temporary wallets useful for testing purposes. The private keys are generated and stored on the user's device. \`\`\`tsx \`\`\` ### MetaMask Snaps \\\[!toc\] MetaMask Snaps are a new way to extend MetaMask with custom functionality and integrations. You can check the implementation to integrate NuFi from the GitHub repository. Use the \`injectFn\` prop to add custom functionality. \`\`\`tsx await checkIfMetamaskInstalled("preprod")} /> \`\`\` \### Connect Wallet Component \\\[!toc\] Connect to user's wallet to interact with app \`\`\`tsx import { CardanoWallet } from '@meshsdk/react'; export default function Page() { return ( <> {console.log('on connected')}} cardanoPeerConnect={{ dAppInfo: { name: "Mesh SDK", url: "https://meshjs.dev/", }, announce: \[ "wss://dev.btt.cf-identity-wallet.metadata.dev.cf-deployments.org", \], }} burnerWallet={{ networkId: 0, provider: provider, }} /> ); } \`\`\` \## Powered by Mesh Badge If you love Mesh, here's a beautifully designed badge for you to embed in your application. \`\`\`tsx \`\`\` \### Mesh Badge Component \\\[!toc\] Show your support for Mesh \`\`\`tsx import { CardanoWallet } from '@meshsdk/react'; export default function Page() { return ( <> ); } \`\`\` \# Wallet Hooks URL: /react/wallet-hooks React hooks for interacting with connected wallets. \*\*\* title: "Wallet Hooks" description: "React hooks for interacting with connected wallets." icon: BoltIcon -------------- import Link from "fumadocs-core/link"; React Hooks allow function components to have access to state and other React features. With Mesh Hooks, you can easily interact and access wallet data. ## useWallet Hook Provide information on the current wallet's state, and functions for connecting and disconnecting user wallet. \`\`\`tsx const { wallet, state, connected, name, connecting, connect, disconnect, error } = useWallet(); \`\`\` \`wallet\` is a Browser Wallet instance, which expose all CIP wallets functions from getting assets to signing tranasction. \`state\`, a enum string, the state of the wallet, can be \`NOT\_CONNECTED\`, \`CONNECTING\` or \`CONNECTED\`. \`connected\`, a boolean, \`true\` if user's wallet is connected. \`name\`, a string, the name of the connect wallet. \`connecting\`, a boolean, \`true\` if the wallet is connecting and initializing. \`connect(walletName: string)\`, a function, provide the wallet name to connect wallet. Retrive a list of available wallets with \`useWalletList()\`. \`disconnect()\`, a function, to disconnect the connected wallet. \`error\`, returns the error object if any error occurs during wallet connection, such as "account not set". \### useWallet Hook \\\[!toc\] Interact with user's wallet \`\`\`tsx import { useWallet } from '@meshsdk/react'; export default function Page() { const { wallet, state, connected, name, connecting, connect, disconnect, error } = useWallet(); return ( **State:** {state} **Connected?:** {connected ? 'Is connected' : 'Not connected'} **Connecting wallet?:** {connecting ? 'Connecting...' : 'No'} **Name of connected wallet:** {name} disconnect()}>Disconnect Wallet ); } \`\`\` \## useWalletList Hook Returns a list of wallets installed on user's device. \`\`\`tsx const wallets = useWalletList(); \`\`\` You can define a function to be injected into the wallet provider by passing it as the \`injectFn\` prop. \`\`\`tsx const wallets = useWalletList({injectFn={async () => await checkIfMetamaskInstalled("preprod")})} \`\`\` \### useWalletList Hook \\\[!toc\] List of wallets installed on user's device \`\`\`tsx const wallets = useWalletList(); \`\`\` \`\`\`tsx \[\] \`\`\` \`\`\`tsx import { useWalletList } from '@meshsdk/react'; export default function Page() { const wallets = useWalletList(); return ( <> {wallets.map((wallet, i) => { return ( ![](https://meshjs.dev/%7Bwallet.icon%7D) **{wallet.name}** ); })} ); } \`\`\` \## useAddress Hook Return address of connected wallet. \`accountId\` is an optional parameter, that allows you to choose which address to return. \`\`\`tsx const address = useAddress(accountId = 0); \`\`\` \### useAddress Hook \\\[!toc\] List of wallets installed on user's device \`\`\`tsx import { useAddress } from '@meshsdk/react'; const address = useAddress(); Your wallet address is: `{address}` \`\`\` \## useAssets Hook Return a list of assets in connected wallet from all UTXOs. \`\`\`tsx const assets = useAssets(); \`\`\` \### useAssets Hook \\\[!toc\] List assets of connected wallet \`\`\`tsx import { useAssets } from '@meshsdk/react'; const assets = useAssets(); {JSON.stringify(assets, null, 2)} \`\`\` \## useLovelace Hook Return amount of lovelace in wallet. \`\`\`tsx const lovelace = useLovelace(); \`\`\` \### useLovelace Hook \\\[!toc\] Fetch the lovelace balance of the connected wallet \`\`\`tsx import { useLovelace } from '@meshsdk/react'; const lovelace = useLovelace(); Your lovelace balance is: `{lovelace}` \`\`\` \## useNetwork Hook Return the network of connected wallet. \`\`\`tsx const network = useNetwork(); \`\`\` \### useNetwork Hook \\\[!toc\] Fetch the network of the connected wallet \`\`\`tsx import { useNetwork } from '@meshsdk/react'; const network = useNetwork(); Connected network: `{network}`. \`\`\` \# Developer Resources URL: /resources/developer-resources Essential tools, communities, and resources for Cardano developers using Mesh SDK. \*\*\* title: "Developer Resources" description: "Essential tools, communities, and resources for Cardano developers using Mesh SDK." icon: WrenchScrewdriverIcon --------------------------- import { Card, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; import Link from 'next/link'; Your central hub for tools, communities, learning materials, and ecosystem resources to accelerate your Cardano development journey with Mesh. ## Official Mesh Resources ### Documentation & Learning \* \*\*\[Mesh Documentation\](/docs)\*\* - Comprehensive guides and API references \* \*\*\[Getting Started Guide\](/guides)\*\* - Your first steps with Mesh \* \*\*\[API Reference\](/apis)\*\* - Complete API documentation \* \*\*\[Smart Contracts\](/smart-contracts)\*\* - Build with Plutus and Aiken \* \*\*\[React Components\](/react)\*\* - UI components for your dApp ### Code & Examples \* \*\*\[GitHub Repository\](https://github.com/MeshJS/mesh)\*\* - Source code and contributions \* \*\*\[Example Projects\](https://github.com/MeshJS/examples)\*\* - Working code samples \* \*\*\[Starter Templates\](https://github.com/MeshJS/mesh-starter)\*\* - Boilerplate projects \* \*\*\[Code Playground\](https://meshjs.dev/apis)\*\* - Interactive code editor on every API page ### Stay Updated \* \*\*\[GitHub Milestones\](https://github.com/MeshJS/mesh/milestones)\*\* - Current development roadmap \* \*\*\[Release Notes\](https://github.com/MeshJS/mesh/releases)\*\* - Latest updates and changes \* \*\*\[NPM Package\](https://www.npmjs.com/package/@meshsdk/core)\*\* - Package downloads and versions ## Community & Support ### Join the Conversation Discord Community Join our active Discord server for real-time help, discussions, and updates. Join Discord → Twitter / X Follow \[@meshsdk\](https://twitter.com/meshsdk) for announcements, tips, and community highlights. Follow on Twitter → GitHub Discussions Participate in longer-form discussions, ask questions, and share ideas. Join Discussions → Stack Overflow Ask technical questions tagged with \`meshsdk\` for searchable Q\\&A. View Questions → \### Get Help \* \*\*\[FAQ\](/resources/faq)\*\* - Frequently asked questions \* \*\*\[GitHub Issues\](https://github.com/MeshJS/mesh/issues)\*\* - Report bugs or request features \* \*\*\[Community Support\](https://discord.gg/dH48jH3BKa)\*\* - Free community help via Discord ## Cardano Ecosystem ### Official Cardano Resources \* \*\*\[Cardano.org\](https://cardano.org)\*\* - Official Cardano website \* \*\*\[Cardano Documentation\](https://docs.cardano.org)\*\* - Official protocol documentation \* \*\*\[Cardano Forum\](https://forum.cardano.org)\*\* - Community discussions \* \*\*\[Cardano Stack Exchange\](https://cardano.stackexchange.com)\*\* - Technical Q\\&A ### Block Explorers \* \*\*\[CardanoScan\](https://cardanoscan.io)\*\* - Comprehensive Cardano blockchain explorer \* \*\*\[AdaStat\](https://adastat.net)\*\* - Analytics and statistics \* \*\*\[Pool.pm\](https://pool.pm)\*\* - Native assets and NFT explorer \* \*\*\[Cexplorer\](https://cexplorer.io)\*\* - Detailed blockchain data ## Learning Resources ### Courses & Bootcamps \* \*\*\[Emurgo Academy\](https://education.emurgo.io)\*\* - Professional Cardano development courses \* \*\*\[IOG Academy\](https://www.iohkacademy.io)\*\* - Official Cardano education platform \* \*\*\[Gimbalabs\](https://gimbalabs.com)\*\* - Community-driven learning platform \* \*\*\[Plutus Pioneers Program\](https://plutus-pioneer-program.readthedocs.io)\*\* - Learn Plutus smart contracts ### Books & Written Content \* \*\*\[Cardano Developer Portal\](https://developers.cardano.org)\*\* - Comprehensive development guides \* \*\*\[Essential Cardano\](https://essentialcardano.io)\*\* - Curated Cardano resources \* \*\*\[Building on Cardano\](https://builtoncardano.com)\*\* - Showcase of Cardano projects ## Mesh AI Features Mesh includes AI-powered development assistance: \* \*\*\[AI Chat Assistant\](/ai)\*\* - Ask questions and get instant answers \* \*\*AI Code Generation\*\* - Generate Mesh code from natural language \* \*\*Documentation Search\*\* - Semantic search across all docs \* \*\*Context-Aware Help\*\* - Get relevant suggestions as you code Access Mesh AI directly from our documentation using the sparkle icon ✨ or visit the \[AI page\](/ai). ## Open Source Contributions ### How to Contribute 1. \*\*Code Contributions\*\*: Fork the repo, make changes, submit PR 2. \*\*Documentation\*\*: Improve or add to our docs 3. \*\*Bug Reports\*\*: Help us identify and fix issues 4. \*\*Feature Requests\*\*: Suggest new capabilities 5. \*\*Community Help\*\*: Answer questions on Discord See our \[Contributing Guide\](https://github.com/MeshJS/mesh/blob/main/CONTRIBUTING.md) for details. ### Financial Support Support Mesh development: \* \*\*\[GitHub Sponsors\](https://github.com/sponsors/MeshJS)\*\* - Monthly sponsorships \* \*\*\[Support Page\](/about/support-us)\*\* - Various support options ## Newsletter & Updates Stay informed about Mesh and Cardano development: \* Subscribe to our newsletter (coming soon) \* Follow \[@meshsdk\](https://twitter.com/meshsdk) on Twitter \* Star our \[GitHub repo\](https://github.com/MeshJS/mesh) for updates \* Join \[Discord\](https://discord.gg/dH48jH3BKa) announcements channel ## Quick Links 📚 Guides Step-by-step tutorials ⚡ API Docs Complete API reference ❓ FAQ Common questions 💻 Examples Working code samples 💬 Discord Community chat ❤️ Support Help Mesh grow \*\*\* \*\*Ready to build?\*\* Start with our \[Getting Started Guide\](/guides) or jump into the \[API Documentation\](/apis). Need help? \[Join our Discord community\](https://discord.gg/dH48jH3BKa) - we're here to help! # Frequently Asked Questions URL: /resources/faq Common questions and answers about Mesh - the TypeScript SDK for Cardano blockchain development. \*\*\* title: "Frequently Asked Questions" description: "Common questions and answers about Mesh - the TypeScript SDK for Cardano blockchain development." icon: QuestionMarkCircleIcon ---------------------------- import { Accordion, Accordions } from 'fumadocs-ui/components/accordion'; Find answers to common questions about Mesh, the open-source TypeScript SDK for Cardano. ## Getting Started Mesh is an open-source TypeScript SDK that makes it easy to build Cardano blockchain applications. It provides a comprehensive suite of tools, React components, wallet integrations, and transaction builders to help developers ship UTXO dApps faster. Mesh offers several advantages: \* \*\*Lightweight\*\*: Less than 60kB bundle size for fast-loading applications \* \*\*Production-Ready\*\*: Battle-tested with 1M+ downloads \* \*\*Developer-Friendly\*\*: Simple, intuitive APIs with excellent TypeScript support \* \*\*Comprehensive\*\*: Everything you need - wallet integration, transaction building, smart contracts \* \*\*AI-Powered\*\*: Built-in AI features to help you develop faster \* \*\*Always Updated\*\*: Kept current with the latest Cardano network changes Yes! Mesh is completely open-source and free to use for both personal and commercial projects. You can find the source code on \[GitHub\](https://github.com/MeshJS/mesh). Mesh requires: \* Node.js 16 or higher \* npm or yarn package manager \* TypeScript 4.5+ (recommended) \* For React projects: React 18+ \## Installation & Setup Install Mesh Core using npm or yarn: \`\`\`bash npm install @meshsdk/core \`\`\` or \`\`\`bash yarn add @meshsdk/core \`\`\` If you're building a React app, you can also install the optional React bindings: \`\`\`bash npm install @meshsdk/react \`\`\` Then follow our \[Getting Started Guide\](/guides) for setup instructions. Yes! Mesh works great with Next.js. Check out our \[Next.js integration guide\](/guides/nextjs) for detailed setup instructions including App Router and Pages Router configurations. Yes! While we have official React support, Mesh Core can be used with: \* Next.js \* Vue.js \* Svelte (we have a \[Svelte package\](/svelte)) \* Angular \* Vanilla JavaScript/TypeScript \* Node.js backend applications \## Wallets & Integration Mesh supports all CIP-30 compliant Cardano wallets including: \* Nami \* Eternl \* Flint \* Typhon \* Yoroi \* Lace \* And many more! The wallet integration is universal, so any new CIP-30 wallet is automatically supported. Absolutely! Mesh provides the \`MeshWallet\` class that allows you to create wallet applications. You can: \* Generate wallets from mnemonic phrases \* Import wallets from private keys \* Work with cardano-cli wallets \* Build multi-signature applications \* Create browser extension wallets Check out the \[Wallet documentation\](/apis/wallets) for details. Use the \`CardanoWallet\` React component for the easiest integration: \`\`\`tsx import { CardanoWallet } from '@meshsdk/react'; export default function MyApp() { return ( console.log('Wallet connected!')} /> ); } \`\`\` See our \[wallet hooks documentation\](/react/wallet-hooks) for more advanced use cases. \## Smart Contracts & Transactions Yes! Mesh provides comprehensive smart contract support for both Plutus and Aiken: \* Transaction building with smart contract execution \* Datum and redeemer handling \* Script validation \* Multi-asset operations \* Complex transaction scenarios Check out our \[Smart Contracts guides\](/smart-contracts) and \[Aiken tutorials\](/aiken). Mesh provides an intuitive transaction builder API via \`MeshTxBuilder\`. Here's a simple example for sending ADA: \`\`\`typescript import { MeshTxBuilder } from '@meshsdk/core'; const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true, }); const unsignedTx = await txBuilder .txOut( 'addr1...', // recipient address \[{ unit: 'lovelace', quantity: '1000000' }\] // 1 ADA in lovelace ) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` See the \[\`MeshTxBuilder\` documentation\](/apis/txbuilder) for advanced features. Yes! Mesh makes NFT minting straightforward. We have dedicated guides for: \* \[Minting your first NFT\](/guides/nft-collection) \* \[Multi-signature minting\](/guides/multisig-minting) \* Creating NFT collections \* Metadata standards (CIP-25, CIP-68) Check out our \[NFT guides\](/guides) for step-by-step tutorials. \## Development & Debugging Mesh supports testing on: \* \*\*Cardano Testnet\*\*: Use the preprod or preview test networks \* \*\*Local DevNet\*\*: Run \[Yaci DevNet\](/yaci) for faster development \* \*\*Mainnet\*\*: Deploy when ready for production Configure the network by setting the \`networkId\` in your provider. We provide extensive examples: \* Throughout our \[documentation\](/docs) \* In our \[guides section\](/guides) \* On our \[GitHub examples repository\](https://github.com/MeshJS/examples) \* Interactive demos on each API page All examples are tested and ready to use. Several resources are available: \* \*\*Documentation\*\*: Comprehensive guides and API references \* \*\*Discord Community\*\*: Join our \[Discord server\](https://discord.gg/dH48jH3BKa) for real-time help \* \*\*GitHub Issues\*\*: Report bugs or request features on \[GitHub\](https://github.com/MeshJS/mesh/issues) \* \*\*Stack Overflow\*\*: Tag questions with \`meshsdk\` \* \*\*Twitter\*\*: Follow \[@meshsdk\](https://twitter.com/meshsdk) for updates \## Performance & Optimization Absolutely! Mesh is production-ready and used by many live Cardano applications. Key production features: \* Battle-tested code with 1M+ downloads \* Comprehensive error handling \* TypeScript for type safety \* Small bundle size (\\< 60kB) \* Regular updates aligned with Cardano network changes \* Active maintenance and support Mesh is already optimized with tree-shaking support. To minimize bundle size: \* Import only what you need \* Use code splitting in your bundler \* Enable production builds \* Leverage Next.js automatic optimization The core Mesh library is less than 60kB minified and gzipped. Yes and no: \* \*\*Offline\*\*: Transaction building, address generation, key management work offline \* \*\*Online Required\*\*: Querying blockchain data, submitting transactions, fetching UTXOs require internet connectivity For offline scenarios, consider pre-fetching required data. \## Commercial Use & Contributions Yes! Mesh is open-source (Apache 2.0 and MIT licenses) and free for commercial use. You can build and sell applications using Mesh without any licensing fees. We welcome contributions! You can: \* Submit bug reports and feature requests on \[GitHub\](https://github.com/MeshJS/mesh/issues) \* Contribute code via pull requests \* Improve documentation \* Help other developers in our Discord \* Share your projects built with Mesh \* \[Support us financially\](/about/support-us) Check our \[GitHub repository\](https://github.com/MeshJS/mesh) for contribution guidelines. \## Still Have Questions? If you can't find the answer you're looking for, please: \* Join our \[Discord community\](https://discord.gg/dH48jH3BKa) \* Ask on \[GitHub Discussions\](https://github.com/MeshJS/mesh/discussions) \* Check our comprehensive \[documentation\](/docs) \* Reach out on \[Twitter\](https://twitter.com/meshsdk) # Learn URL: /resources Comprehensive courses, tutorials, and resources for Cardano developers. \*\*\* title: "Learn" description: "Comprehensive courses, tutorials, and resources for Cardano developers." icon: AcademicCapIcon --------------------- import {linksLearn} from "@/data/links-course"; import {metaGuides} from "@/data/links-guides"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {\[...linksLearn, metaGuides\].map((card) => ( {card.title} {card.desc} ))} \# Tutorials URL: /resources/tutorials Step-by-step tutorials for building Cardano applications with Mesh SDK - from beginner to advanced. \*\*\* title: "Tutorials" description: "Step-by-step tutorials for building Cardano applications with Mesh SDK - from beginner to advanced." icon: BookOpenIcon ------------------ import Link from 'next/link'; import { Card, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; Learn Cardano development with Mesh through hands-on tutorials. Each tutorial includes working code examples, explanations, and best practices. ## 🚀 Getting Started Perfect for developers new to Mesh or Cardano. Installation & Setup ⏱️ 10 minutes • 🎯 Beginner Install Mesh and set up your first Cardano project with React or Next.js. Next.js Integration ⏱️ 15 minutes • 🎯 Beginner Integrate Mesh with Next.js App Router and Pages Router configurations. React Hooks & Components ⏱️ 20 minutes • 🎯 Beginner Use Mesh React hooks and components to build wallet-connected interfaces. Wallet Connection ⏱️ 15 minutes • 🎯 Beginner Connect Cardano wallets and prove wallet ownership in your dApp. \## 💰 Transactions & Payments Learn to build and submit Cardano transactions. Send ADA & Tokens ⏱️ 20 minutes • 🎯 Beginner Build transactions to send ADA and native tokens to any address. Transaction Builder ⏱️ 30 minutes • 🎯 Intermediate Master the transaction builder for complex multi-input/output transactions. Multi-Asset Transactions ⏱️ 25 minutes • 🎯 Intermediate Handle transactions with multiple native assets and tokens. Server-Side Transactions ⏱️ 30 minutes • 🎯 Intermediate Build and submit transactions from Node.js backend applications. \## 🎨 NFT Development Create and manage NFTs on Cardano. Mint Your First NFT ⏱️ 30 minutes • 🎯 Beginner Create a complete NFT collection with proper metadata and minting policies. Multi-Signature Minting ⏱️ 45 minutes • 🎯 Intermediate Implement multi-signature NFT minting for team collaborations. Advanced NFT Metadata ⏱️ 35 minutes • 🎯 Intermediate Work with CIP-25 and CIP-68 metadata standards for NFTs. Burning & Managing Assets ⏱️ 25 minutes • 🎯 Intermediate Burn tokens and NFTs, manage asset lifecycles. \## 🔐 Smart Contracts Build with Plutus and Aiken smart contracts. Getting Started with Aiken ⏱️ 40 minutes • 🎯 Intermediate Set up Aiken development environment and write your first smart contract. Your First Aiken Script ⏱️ 50 minutes • 🎯 Intermediate Build a complete Aiken validator and integrate it with Mesh. Smart Contract Transactions ⏱️ 60 minutes • 🎯 Advanced Lock and unlock assets using smart contracts with proper datum and redeemer handling. Advanced Smart Contract Patterns ⏱️ 90 minutes • 🎯 Advanced Implement complex patterns like state machines, oracles, and multi-party contracts. \## 🛠️ Advanced Topics For experienced developers building production applications. Custom Providers ⏱️ 45 minutes • 🎯 Advanced Create custom blockchain data providers for specific use cases. Provider Integration ⏱️ 30 minutes • 🎯 Intermediate Integrate with Blockfrost, Maestro, Koios, and other data providers. Local Development with Yaci ⏱️ 40 minutes • 🎯 Advanced Set up local Cardano development network for rapid iteration and testing. Production Best Practices ⏱️ 60 minutes • 🎯 Advanced Security, optimization, error handling, and deployment strategies. \## 📱 Framework Integrations Use Mesh with your favorite framework. Next.js Full Stack ⏱️ 45 minutes • 🎯 Intermediate Build full-stack Cardano dApps with Next.js, including API routes and server components. Svelte Integration ⏱️ 30 minutes • 🎯 Intermediate Use Mesh with Svelte and SvelteKit for reactive Cardano applications. Node.js Backend ⏱️ 35 minutes • 🎯 Intermediate Use Mesh in Node.js backends, APIs, and automation scripts. Vue.js Integration ⏱️ Coming Soon • 🎯 Intermediate Tutorial for using Mesh with Vue.js and Nuxt. \## 🎓 Learning Paths Structured learning journeys that combine the tutorials and guides listed on this page into recommended sequences for different goals. ### Path 1: Web Developer → Cardano dApp Developer 1. Installation & Setup (10 min) 2. Wallet Connection (15 min) 3. Send ADA & Tokens (20 min) 4. React Hooks & Components (20 min) 5. Mint Your First NFT (30 min) 6. Next.js Integration (45 min) \*\*Total Time:\*\* \\~2.5 hours • \*\*Level:\*\* Beginner to Intermediate ### Path 2: Smart Contract Developer 1. Getting Started with Aiken (40 min) 2. Your First Aiken Script (50 min) 3. Smart Contract Transactions (60 min) 4. Advanced Smart Contract Patterns (90 min) 5. Local Development with Yaci (40 min) 6. Production Best Practices (60 min) \*\*Total Time:\*\* \\~5.5 hours • \*\*Level:\*\* Intermediate to Advanced ### Path 3: NFT Collection Creator 1. Installation & Setup (10 min) 2. Wallet Connection (15 min) 3. Mint Your First NFT (30 min) 4. Advanced NFT Metadata (35 min) 5. Multi-Signature Minting (45 min) 6. Server-Side Transactions (30 min) \*\*Total Time:\*\* \\~2.5 hours • \*\*Level:\*\* Beginner to Intermediate ## 📚 Additional Resources \* \*\*\[API Reference\](/apis)\*\* - Complete API documentation \* \*\*\[Code Examples\](https://github.com/MeshJS/examples)\*\* - Working code repositories \* \*\*\[FAQ\](/resources/faq)\*\* - Frequently asked questions \* \*\*\[Use Cases\](/resources/use-cases)\*\* - Real-world applications \* \*\*\[Developer Resources\](/resources/developer-resources)\*\* - Tools and communities ## 💬 Need Help? Stuck on a tutorial? Here's how to get help: \* \*\*\[Discord Community\](https://discord.gg/dH48jH3BKa)\*\* - Real-time support from the community \* \*\*\[GitHub Discussions\](https://github.com/MeshJS/mesh/discussions)\*\* - Longer-form Q\\&A \* \*\*\[Stack Overflow\](https://stackoverflow.com/questions/tagged/meshsdk)\*\* - Tagged questions ## 🎯 What's Next? After completing these tutorials, you'll be ready to: \* Build production Cardano dApps \* Create NFT collections and marketplaces \* Develop DeFi applications \* Integrate smart contracts \* Contribute to the Cardano ecosystem Start your journey today with our \[Getting Started Guide\](/guides)! # Use Cases & Showcases URL: /resources/use-cases Discover real-world applications and projects built with Mesh - from DeFi platforms to NFT marketplaces and enterprise solutions on Cardano. \*\*\* title: "Use Cases & Showcases" description: "Discover real-world applications and projects built with Mesh - from DeFi platforms to NFT marketplaces and enterprise solutions on Cardano." icon: RocketLaunchIcon ---------------------- import { Card, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; Discover how developers and organizations are using Mesh to build innovative Cardano applications. From DeFi platforms to NFT marketplaces, Mesh powers a wide range of blockchain solutions. ## DeFi Applications ### Decentralized Exchanges (DEX) Mesh provides the perfect foundation for building decentralized exchanges on Cardano: \* \*\*Automated Market Makers (AMM)\*\*: Build liquidity pools and swap mechanisms with Mesh's transaction builder \* \*\*Order Book DEXs\*\*: Manage complex order matching with smart contract integration \* \*\*Multi-Asset Swaps\*\*: Handle native token exchanges with ease \*\*Key Features Used:\*\* \* Transaction building APIs \* Multi-asset handling \* Smart contract integration \* Wallet connections ### Lending Protocols Create secure lending and borrowing platforms: \* \*\*Collateral Management\*\*: Lock and release assets with smart contracts \* \*\*Interest Calculations\*\*: Automated interest accrual and distribution \* \*\*Liquidation Mechanisms\*\*: Monitor and execute collateral liquidations \*\*Real-World Example:\*\* Lending protocols use Mesh to handle complex multi-party transactions, ensuring secure collateral locks and automated interest payments through Plutus smart contracts. ### Staking Platforms Build custom staking solutions: \* \*\*Stake Pool Delegation\*\*: Simplified delegation interfaces \* \*\*Rewards Distribution\*\*: Automated reward calculations and distributions \* \*\*Multi-Pool Support\*\*: Manage delegations across multiple pools ## NFT Marketplaces ### NFT Minting Platforms Mesh simplifies NFT creation and distribution: \* \*\*Single NFT Minting\*\*: Easy one-off NFT creation \* \*\*Collection Launches\*\*: Batch minting for entire collections \* \*\*Generative Art\*\*: Create unique combinations programmatically \* \*\*Metadata Management\*\*: CIP-25 and CIP-68 compliance \*\*Implementation tip:\*\* For minting NFTs in your own project, use the modern \`MeshTxBuilder\` APIs shown in the \[Mint and Burn Assets guide\](/apis/txbuilder/minting) rather than the legacy \`Transaction\` class. ### Secondary Marketplaces Power NFT trading platforms with Mesh: \* \*\*Listing Management\*\*: List and delist NFTs for sale \* \*\*Bidding Systems\*\*: Implement auction mechanisms \* \*\*Instant Purchases\*\*: Enable direct NFT purchases \* \*\*Royalty Enforcement\*\*: Automated creator royalty distributions \*\*Key Features:\*\* \* Smart contract escrow \* Multi-signature support \* Metadata resolution \* Price oracles integration ## Wallet Applications ### Browser Extension Wallets Build feature-rich Cardano wallets: \* \*\*Key Management\*\*: Secure mnemonic and key storage \* \*\*Transaction Signing\*\*: Sign and submit transactions \* \*\*dApp Connector\*\*: CIP-30 compliance for dApp integration \* \*\*Multi-Account Support\*\*: Manage multiple addresses ### Hardware Wallet Integration Integrate with hardware wallets for enhanced security: \* \*\*Ledger Support\*\*: Connect with Ledger devices \* \*\*Trezor Integration\*\*: Support for Trezor hardware wallets \* \*\*Air-Gapped Signing\*\*: Build offline transaction signing flows ## Gaming & Metaverse ### Blockchain Games Create engaging gaming experiences on Cardano: \* \*\*In-Game Assets\*\*: Represent items as NFTs \* \*\*Play-to-Earn\*\*: Token rewards and economies \* \*\*Character NFTs\*\*: Unique, tradeable characters \* \*\*Land Ownership\*\*: Virtual real estate on-chain \*\*Use Case Example:\*\* A trading card game uses Mesh to handle card minting, trading between players, and tournament rewards distribution, all with seamless wallet integration. ### Virtual Worlds Build metaverse platforms: \* \*\*Land Parcels\*\*: NFT-based land ownership \* \*\*Avatar Systems\*\*: Customizable NFT avatars \* \*\*Virtual Economies\*\*: In-world token systems \* \*\*Social Features\*\*: Decentralized identity and messaging ## Enterprise Solutions ### Supply Chain Tracking Implement transparent supply chain management: \* \*\*Asset Tracking\*\*: Record product journey on-chain \* \*\*Authenticity Verification\*\*: Prove product origin \* \*\*Smart Contracts\*\*: Automated fulfillment conditions \* \*\*Multi-Party Workflows\*\*: Coordinate between stakeholders \*\*Real-World Application:\*\* Track luxury goods from manufacturer to customer, with each transfer recorded on Cardano using Mesh, ensuring authenticity and preventing counterfeits. ### Identity Verification Build decentralized identity solutions: \* \*\*KYC/AML\*\*: Store verified credentials on-chain \* \*\*Age Verification\*\*: Prove age without revealing birthdate \* \*\*Professional Credentials\*\*: Verifiable certifications \* \*\*Access Control\*\*: Token-gated content and services ### Voting & Governance Create transparent governance systems: \* \*\*DAO Governance\*\*: Token-weighted voting \* \*\*Proposal Systems\*\*: Submit and vote on proposals \* \*\*Quadratic Voting\*\*: Fair voting mechanisms \* \*\*Election Systems\*\*: Verifiable public elections ## Developer Tools ### Block Explorers Build custom blockchain explorers: \* \*\*Transaction Search\*\*: Query and display transaction history \* \*\*Address Monitoring\*\*: Track address activity \* \*\*Smart Contract Viewers\*\*: Inspect contract state \* \*\*Analytics Dashboards\*\*: Blockchain statistics and metrics ### API Services Create Cardano API platforms: \* \*\*Data Providers\*\*: Serve blockchain data to applications \* \*\*Webhook Services\*\*: Real-time blockchain event notifications \* \*\*Query Interfaces\*\*: GraphQL/REST APIs for Cardano data \* \*\*Historical Data\*\*: Archive and serve historical blockchain data ## Education & Research ### Learning Platforms Build educational tools for Cardano: \* \*\*Interactive Tutorials\*\*: Hands-on Cardano development lessons \* \*\*Sandbox Environments\*\*: Safe spaces to experiment \* \*\*Code Playgrounds\*\*: Browser-based Cardano coding \* \*\*Certification Systems\*\*: Issue blockchain certificates ### Research Tools Enable blockchain research: \* \*\*Data Analysis\*\*: Extract and analyze blockchain data \* \*\*Simulation Tools\*\*: Model economic scenarios \* \*\*Testing Frameworks\*\*: Automated smart contract testing \* \*\*Network Monitoring\*\*: Track network health and performance ## Social & Community ### Social Platforms Build Web3 social networks: \* \*\*Token-Gated Communities\*\*: Access based on NFT/token ownership \* \*\*Creator Platforms\*\*: Content monetization with NFTs \* \*\*Tipping Systems\*\*: Microtransactions for content creators \* \*\*Decentralized Social Graphs\*\*: On-chain social connections ### Fundraising Platforms Create transparent fundraising solutions: \* \*\*Crowdfunding\*\*: Decentralized campaign management \* \*\*Charity Platforms\*\*: Transparent donation tracking \* \*\*Investment DAOs\*\*: Collective investment vehicles \* \*\*Grant Programs\*\*: Automated grant distribution ## Real-World Success Metrics Projects built with Mesh have achieved: \* 📈 \*\*Millions in Transaction Volume\*\*: DeFi platforms processing substantial daily volumes \* 🎨 \*\*Thousands of NFTs Minted\*\*: Successful collections with sell-outs \* 👥 \*\*Large User Bases\*\*: Wallets and dApps with tens of thousands of users \* ⚡ \*\*Fast Performance\*\*: Applications maintaining sub-second response times \* 🔒 \*\*Zero Security Incidents\*\*: Secure smart contract implementations ## Building Your Own? Ready to create your own Cardano application with Mesh? \* \*\*Start with \[Guides\](/guides)\*\*: Step-by-step tutorials for common use cases \* \*\*Explore \[API Documentation\](/apis)\*\*: Complete reference for all Mesh features \* \*\*Join \[Community\](https://discord.gg/dH48jH3BKa)\*\*: Get help from other builders \* \*\*View \[Examples\](https://github.com/MeshJS/examples)\*\*: Working code samples ## Submit Your Project Built something awesome with Mesh? We'd love to feature it! Share your project: \* Discord: Join our showcase channel \* Twitter: Tag \[@meshsdk\](https://twitter.com/meshsdk) \* GitHub: Add to our \[ecosystem list\](https://github.com/MeshJS/mesh) # Content Ownership URL: /smart-contracts/content-ownership Manage ownership of digital content and assets \*\*\* title: "Content Ownership" description: "Manage ownership of digital content and assets" icon: DocumentCheckIcon ----------------------- import Link from "fumadocs-core/link"; This contract allows you to create a content registry and users can create content that is stored in the registry. It facilitates on-chain record of content (i.e. file on IPFS) ownership and transfer. While one cannot prefer others from obtaining a copy of the content, the app owner of the contract can serve the single source of truth of who owns the content. With the blockchain trace and record in place, it provides a trustless way to verify the ownership of the content and facilitates further application logics such as royalties, licensing, etc. ### Install package \\\[!toc\] First you can to install the \`@meshsdk/contracts\` package: \`\`\`tsx npm install @meshsdk/contract \`\`\` ### Initialize the contract \\\[!toc\] To initialize the contract, we need to initialize a provider, \`MeshTxBuilder\` and \`MeshContentOwnershipContract\`. \`\`\`tsx import { MeshContentOwnershipContract } from "@meshsdk/contract"; import { MeshTxBuilder, BlockfrostProvider } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshContentOwnershipContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, { operationAddress: operationAddress, // the address of the app owner, where most of the actions should be signed by the spending key of this address paramUtxo: { outputIndex: 0, txHash: "0000000000000000000000000000000000000000000000000000000000000000" }, // you can get this from the output of mintOneTimeMintingPolicy() transaction refScriptUtxos?: { // you can get these from the output of sendRefScriptOnchain() transactions contentRegistry: { outputIndex: 0, txHash: "0000000000000000000000000000000000000000000000000000000000000000" }, contentRefToken: { outputIndex: 0, txHash: "0000000000000000000000000000000000000000000000000000000000000000" }, ownershipRegistry: { outputIndex: 0, txHash: "0000000000000000000000000000000000000000000000000000000000000000" }, ownershipRefToken: { outputIndex: 0, txHash: "0000000000000000000000000000000000000000000000000000000000000000" }, }, }, ); \`\`\` Both on-chain and off-chain codes are open-source and available on Mesh Github Repository. ## Mint One Time Minting Policy This is the first transaction you need to setup the contract. This transaction mints the one-time minting policy (a NFT) for the contract. It will be attached with the datum which serves as the single source of truth for the contract oracle. Note: You must save the \`paramUtxo\` for future transactions. \### Mint One Time Minting Policy \\\[!toc\] This transaction mints the one-time minting policy (a NFT) for the contract. \*\*Operation address\*\* \`addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr\` \`\`\`tsx const { tx, paramUtxo } = await contract.mintOneTimeMintingPolicy(); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Setup Oracle Utxo This transaction send the NFT to a oracle contract locking the datum, which serves as the single source of truth for the contract oracle with data integrity. This is the second transaction you need to setup the contract. Note: You must provide the \`paramUtxo\` from the \`mintOneTimeMintingPolicy\` transaction. \### Setup Oracle Utxo \\\[!toc\] This transaction send the NFT to a oracle contract locking the datum. \*\*Operation address\*\* \`addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr\` \*\*Param UTxO\*\* \`{"outputIndex":0,"txHash":"2aba4d6705cfe6405cf02...f3f8bded3df2359"}\` \`\`\`tsx const tx = await contract.setupOracleUtxo(); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Send Ref-Script Onchain This are the next transactions you need to setup the contract. You need to run once for each script, and you would likely have to run one after the previous one is confirmed. This transaction sends the reference scripts to the blockchain for later transactions, boosting efficiency and avoid exceeding 16kb of transaction size limits enforced by protocol parameter. Note: You must provide the \`paramUtxo\` from the \`mintOneTimeMintingPolicy\` transaction. Note: You must save txHash (after signed and submitted) for \`ContentRegistry\`, \`ContentRefToken\`, \`OwnershipRegistry\`,\`OwnershipRefToken\` transactions for future transactions. \### Send Ref-Script Onchain \\\[!toc\] This transaction sends the reference scripts to the blockchain for later transactions. \*\*Operation address\*\* \`addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr\` \*\*Param UTxO\*\* \`{"outputIndex":0,"txHash":"2aba4d6705cfe6405cf02...f3f8bded3df2359"}\` \*\*Select script index\*\* \`OracleNFT\` \`\`\`tsx const tx = await contract.sendRefScriptOnchain('OracleNFT'); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Create Content Registry This is the next transaction you need to setup the contract after completing all the \`sendRefScriptOnchain\` transactions. This transaction creates one content registry. Each registry should comes in pair with one ownership registry and each pair of registry serves around 50 records of content ownership. The application can be scaled indefinitely according to the number of parallelization needed and volumes of content expected to be managed. Note: You must provide the \`paramUtxo\` from the \`mintOneTimeMintingPolicy\` transaction. Note: You must provide the txHash \`forContentRegistry\`, \`ContentRefToken\`, \`OwnershipRegistry\`, \`OwnershipRefToken\` transactions. \### Create Ownership Registry \\\[!toc\] This transaction creates one content registry \*\*Operation address\*\* \`addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr\` \*\*Param UTxO\*\* \`{"outputIndex":0,"txHash":"2aba4d6705cfe6405cf02...f3f8bded3df2359"}\` \*\*Content Registry Tx Hash\*\* \`dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70\` \*\*Content Ref Token Tx Hash\*\* \`8f731be135171df172c07578a5d74589ec8fb30b37c12fdbe2639d69b7587f5e\` \*\*Ownership Registry Tx Hash\*\* \`ec874b61eec4e5e8e395dead6c9bb18690e6d6ea64d773760c5e654ec9ff5f97\` \*\*Ownership Ref Token Tx Hash\*\* \`e1bdfc7ae6929f934cf9d418273dde143cbb65ec0eec23bdb6c342e4cd91dbd0\` \`\`\`tsx const tx = await contract.createContentRegistry(); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Create Ownership Registry This is the last transaction you need to setup the contract after completing all the \`sendRefScriptOnchain\` transactions. This transaction creates one content registry. Each registry should comes in pair with one content registry and each pair of registry serves around 50 records of content ownership. The application can be scaled indefinitely according to the number of parallelization needed and volumes of content expected to be managed. \*\*Note\*\*: You must provide the \`paramUtxo\` from the \`mintOneTimeMintingPolicy\` transaction. \*\*Note\*\*: You must provide the txHash for \`ContentRegistry\`, \`ContentRefToken\`, \`OwnershipRegistry\`,\`OwnershipRefToken\` transactions. \### Create Ownership Registry \\\[!toc\] This transaction creates one content registry \*\*Operation address\*\* \`addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr\` \*\*Param UTxO\*\* \`{"outputIndex":0,"txHash":"2aba4d6705cfe6405cf02e4e2c8b7...ed3df2359"}\` \*\*Content Registry Tx Hash\*\* \`dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70\` \*\*Content Ref Token Tx Hash\*\* \`8f731be135171df172c07578a5d74589ec8fb30b37c12fdbe2639d69b7587f5e \` \*\*Ownership Registry Tx Hash\*\* \`ec874b61eec4e5e8e395dead6c9bb18690e6d6ea64d773760c5e654ec9ff5f97\` \*\*Ownership Ref Token Tx Hash\*\* \`e1bdfc7ae6929f934cf9d418273dde143cbb65ec0eec23bdb6c342e4cd91dbd0\` \`\`\`tsx const tx = await contract.createOwnershipRegistry(); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Get Oracle Data Getting the oracle data is essential to fetch the current state of the registry. To facilitate this process, you must provide the \`paramUtxo\` that contains the output index and transaction hash of the NFT minting policy. The \`getOracleData()\` function will return the current oracle data. \`\`\`tsx const oracleData = await contract.getOracleData(); \`\`\` For example: \`\`\`tsx { "contentNumber": 2, "ownershipNumber": 2 } \`\`\` ## Mint User Token This transaction mints a token that users can use to create content. Note that you can actually use any tokens for \`createContent()\`, this \`mintUserToken()\` function is just helpful if you want to mint a token specifically for this purpose. Note that you signTx with \`true\` to mint the token to enable partial signing. \### Mint User Token \\\[!toc\] Mint a token that users can use to create content \*\*Operation address\*\* \`addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr\` \*\*Param UTxO\*\* \`{"outputIndex":0,"txHash":"2aba4d6705cfe6405cf02e4e2c8b7...ed3df2359"}\` \`\`\`tsx const tx = await contract.mintUserToken("MeshContentOwnership", { name: "Mesh Content Ownership", description: "Demo at https://meshjs.dev/smart-contracts/content-ownership", }); const signedTx = await wallet.signTx(tx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Create Content This transaction creates a content attached to the registry reference by a token. You can use any token for \`ownerAssetHex\` and the \`contentHashHex\` is a string to identify the content. \*\*Note\*\*: You must provide the \`paramUtxo\` from the \`mintOneTimeMintingPolicy\` transaction. \*\*Note\*\*: You must provide the txHash for \`ContentRegistry\`, \`ContentRefToken\`, \`OwnershipRegistry\`,\`OwnershipRefToken\` transactions. \### Create Content \\\[!toc\] For users to create a content attached to the registry reference by a token \*\*Operation address\*\* \`addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr\` \*\*Param UTxO\*\* \`{"outputIndex":0,"txHash":"2aba4d6705cfe6405cf02e4e2c8b7...ed3df2359"}\` \*\*Content Registry Tx Hash\*\* \`dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70\` \*\*Content Ref Token Tx Hash\*\* \`8f731be135171df172c07578a5d74589ec8fb30b37c12fdbe2639d69b7587f5e \` \*\*Ownership Registry Tx Hash\*\* \`ec874b61eec4e5e8e395dead6c9bb18690e6d6ea64d773760c5e654ec9ff5f97\` \*\*Ownership Ref Token Tx Hash\*\* \`e1bdfc7ae6929f934cf9d418273dde143cbb65ec0eec23bdb6c342e4cd91dbd0\` \`\`\`tsx const asset = demoAsset; const contentHashHex = "ipfs://contentHashHex"; const registryNumber = 0; const tx = await contract.createContent( asset, contentHashHex, registryNumber, ); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Get Content This transaction fetches the content data from the registry. \### Get Oracle Data \\\[!toc\] Fetch the current oracle data \*\*Operation address\*\* \`addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr\` \*\*Param UTxO\*\* \`{"outputIndex":0,"txHash":"2aba4d6705cfe6405cf02e4e2c8b7...ed3df2359"}\` \*\*Content Registry Tx Hash\*\* \`dfd2a2616e6154a092807b1ceebb9ddcadc0f22cf5c8e0e6b0757815083ccb70\` \*\*Content Ref Token Tx Hash\*\* \`8f731be135171df172c07578a5d74589ec8fb30b37c12fdbe2639d69b7587f5e \` \*\*Ownership Registry Tx Hash\*\* \`ec874b61eec4e5e8e395dead6c9bb18690e6d6ea64d773760c5e654ec9ff5f97\` \*\*Ownership Ref Token Tx Hash\*\* \`e1bdfc7ae6929f934cf9d418273dde143cbb65ec0eec23bdb6c342e4cd91dbd0\` \`\`\`tsx const content = await contract.getContent(0, 0); \`\`\` \# Escrow URL: /smart-contracts/escrow Secure exchange of assets between two parties \*\*\* title: "Escrow" description: "Secure exchange of assets between two parties" icon: ArrowsRightLeftIcon ------------------------- import Link from "fumadocs-core/link"; The escrow smart contract allows two parties to exchange assets securely. The contract holds the assets until both parties agree and sign off on the transaction. There are 4 actions available to interact with this smart contract: \* initiate escrow and deposit assets \* deposit assets \* complete escrow \* cancel escrow ### Install package \\\[!toc\] First you can to install the \`@meshsdk/contracts\` package: \`\`\`tsx npm install @meshsdk/contract \`\`\` ### Initialize the contract \\\[!toc\] To initialize the escrow, we need to initialize a provider, \`MeshTxBuilder\` and \`MeshEscrowContract\`. \`\`\`tsx import { MeshEscrowContract } from "@meshsdk/contract"; import { MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshEscrowContract({ mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }); \`\`\` Both on-chain and off-chain codes are open-source and available on Mesh Github Repository. ## Initiate Escrow An escrow is initiated by one of the party, user A, by locking assets to the escrow contract. \`initiateEscrow()\` initiate an escrow. The function accepts the following parameters: \* escrowAmount (Asset\\\[\]) - a list of assets user A is trading The function returns a transaction hex if the escrow is successfully initiated. \### Initiate Escrow \\\[!toc\] Initiate an escrow, in this demo, person A is initiating the escrow and deposit ADA. \*\*Listing price in Lovelace\*\* \`10000000\` \`\`\`tsx const escrowAmount: Asset\[\] = \[ { unit: "lovelace", quantity: '10000000', }, \]; const tx = await contract.initiateEscrow(escrowAmount); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Recipient Deposit User B can deposit assets into the escrow after initiation step (\`initiateEscrow()\`). \`recipientDeposit()\` deposit assets into the escrow. The function accepts the following parameters: \* escrowUtxo (UTxO) - the utxo of the transaction on the contract \* depositAmount (Asset\\\[\]) - a list of assets user B is trading We have provided a very handle function, \`getUtxoByTxHash\`, which will return the UTxO object for a given transaction hash. \### Recipient Deposit \\\[!toc\] Deposit funds into the escrow for trade. In this demo, person B is depositing an asset into the escrow. \*\*Tx hash:\*\* \`Tx hash\` \*\*Asset unit\*\* \`d9312da562da182b02322fd8acb536f37eb9d29fba7...68546f6b656e\` \`\`\`tsx const utxo = await contract.getUtxoByTxHash('');const escrowAmount: Asset\[\] = \[ { unit: 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e', quantity: '1', }, \]; const tx = await contract.initiateEscrow(escrowAmount); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Complete Escrow A user can complete an escrow if the terms of the agreement are met. The completion can be initiated by any recipient of the escrow. \`completeEscrow()\` complete an escrow. The function accepts the following parameters: \* escrowUtxo (UTxO) - the utxo of the transaction in the script to be completed \*\*Important\*\*: This is a multi-signature transaction. Both users must sign the transaction to complete the escrow. A successful completion of the escrow will result in the assets being swapped between the two parties. \### Person A signs the transaction \\\[!toc\] User A completes the escrow by calling the \`completeEscrow()\` function and partial sign the transaction. \*\*Tx hash:\*\* \`Tx hash\` \`\`\`tsx const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.completeEscrow(utxo); const signedTxUserA = await wallet.signTx(tx, true); \`\`\` \### Person B signs and submits the transaction \\\[!toc\] The signed transaction will be handled to User B to sign the transaction and submits it to the blockchain to complete the escrow. \*\*Tx hash:\*\* \`Tx hash\` \*\*Transaction CBOR\*\* \`Transaction CBOR\` \`\`\`tsx const signedTxUserB = await wallet.signTx(signedTxUserA, true); const txHash = await wallet.submitTx(signedTxUserB); \`\`\` \## Cancel Escrow A user can cancel an escrow if the other party fails to fulfill the terms of the agreement. Cancel can be initiated by any users who have partcipated in the escrow and can be done at any time before complete. Canceling the escrow will return the assets to the respective users. \`cancelEscrow()\` cancel an escrow. The function accepts the following parameters: \* escrowUtxo (UTxO) - the utxo of the transaction to be canceled We have provided a very handle function, \`getUtxoByTxHash\`, which will return the UTxO object for a given transaction hash. \### Cancel Escrow \\\[!toc\] Any users who have partcipated in the escrow and can cancel the trade at any time before complete. \*\*Tx hash:\*\* \`Tx hash\` \`\`\`tsx const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.cancelEscrow(utxo); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \# GiftCard URL: /smart-contracts/giftcard Create a giftcard with native tokens \*\*\* title: "GiftCard" description: "Create a giftcard with native tokens" icon: GiftIcon -------------- import Link from "fumadocs-core/link"; Giftcard contract allows users to create a transactions to lock assets into the smart contract, which can be redeemed by any user. Creating a giftcard will mint a token and send the assets to the contract. While redeeming will burn the token and send the assets to the redeemer. There are 2 actions (or endpoints) available to interact with this smart contract: \* create giftcard \* redeem giftcard ### Install package \\\[!toc\] First you can to install the \`@meshsdk/contracts\` package: \`\`\`tsx npm install @meshsdk/contract \`\`\` ### Initialize the contract \\\[!toc\] To initialize the contract, we need to initialize a provider, \`MeshTxBuilder\` and \`MeshGiftCardContract\`. \`\`\`tsx import { MeshGiftCardContract } from "@meshsdk/contract"; import { MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshGiftCardContract({ mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }); \`\`\` Both on-chain and off-chain codes are open-source and available on Mesh Github Repository. ## Create Giftcard \`createGiftCard()\` create a gift card. The function accepts the following parameters: \* tokenName (string) - name of the token \* giftValue (Asset\\\[\]) - a list of assets The function returns a transaction hash if the gift card is successfully created. The function returns a transaction hex if giftcard has been created successfully. \### Create Giftcard \\\[!toc\] Create a gift card with a given amount of lovelace \*\*Gitfcard amount\*\* \`10000000\` \*\*Giftcard name\*\* \`Mesh\_Gift\_Card\` \`\`\`tsx const giftValue: Asset\[\] = \[ { unit: "lovelace", quantity: '10000000', }, \]; const tx = await contract.createGiftCard('Mesh\_Gift\_Card', giftValue); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Redeem Giftcard \`redeemGiftCard()\` redeem a gift card. The function accepts the following parameters: \* giftCardUtxo (UTxO) - unspent transaction output in the script The function returns a transaction hash if the gift card is successfully redeemed. It will burn the gift card and transfer the value to the wallet signing this transaction. The function returns a transaction hex if the gift card has been redeemed successfully. We have provided a very handle function, \`getUtxoByTxHash\`, which will return the UTxO object for a given transaction hash. You can always create another function that searches by token name. A successful redemption will send the value to the wallet that signed the transaction to redeem the gift card. \### Redeem Giftcard \\\[!toc\] Redeem a gift card given the gift card UTxO \*\*Tx hash\*\* \`Tx hash\` \`\`\`tsx const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.redeemGiftCard(utxo); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \# Hello World URL: /smart-contracts/hello-world Simple lock and unlock assets contract \*\*\* title: "Hello World" description: "Simple lock and unlock assets contract" icon: PlayIcon -------------- import Link from "fumadocs-core/link"; The Hello World smart contract is a simple lock-and-unlock assets contract, providing a hands-on introduction to end-to-end smart contract validation and transaction building. There are 2 conditions to unlock the assets: \* Signer must be the same as the one who locked the assets \* Signer must provide the message \`Hello, World!\` There are 2 actions (or endpoints) available to interact with this smart contract: \* Lock assets \* Redeem assets ### Install package \\\[!toc\] First you can to install the \`@meshsdk/contracts\` package: \`\`\`tsx npm install @meshsdk/contract \`\`\` ### Initialize the contract \\\[!toc\] To initialize the contract, we need to initialize a provider, \`MeshTxBuilder\` and \`MeshGiftCardContract\`. \`\`\`tsx import { MeshHelloWorldContract } from "@meshsdk/contract"; import { MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshHelloWorldContract({ mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }); \`\`\` Both on-chain and off-chain codes are open-source and available on Mesh Github Repository. ## Lock Assets This transaction locks funds into the contract. The datum must match the representation expected by the validator (and as specified in the blueprint), so this is a constructor with a single field that is a byte array. \`\`\`tsx pub type Datum { owner: VerificationKeyHash, } \`\`\` Thus, we provide a hash digest of our public key, which will be needed to unlock the funds. \`\`\`tsx await txBuilder .txOut(scriptAddress, assets) .txOutDatumHashValue(mConStr0(\[signerHash\])) .changeAddress(walletAddress) .selectUtxosFrom(utxos) .complete(); \`\`\` \### Lock Asset \\\[!toc\] Lock asset in the contract \*\*Lovelace amount\*\* \`5000000\` \`\`\`tsx const assets: Asset\[\] = \[ { unit: "lovelace", quantity: '5000000', }, \]; const tx = await contract.lockAsset(assets); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Unlock Assets There are 2 conditions to unlock the assets: \* Signer must be the same as the one who locked the assets \* Signer must provide the message \`Hello, World!\` The validator script for the contract checks that the redeemer is the same as the owner of the datum and that the message is \`Hello, World!\`: \`\`\`tsx validator hello\_world { spend( datum\_opt: Option, redeemer: Redeemer, \_input: OutputReference, tx: Transaction, ) { expect Some(datum) = datum\_opt let must\_say\_hello = redeemer.msg == "Hello, World!" let must\_be\_signed = list.has(tx.extra\_signatories, datum.owner) must\_say\_hello && must\_be\_signed } else(\_) { fail } } \`\`\` \### Redeem Giftcard \\\[!toc\] Redeem a gift card given the gift card UTxO \*\*Tx hash\*\* \`Tx hash\` \*\*Message\*\* \`Hello, World!\` \`\`\`tsx const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.unlockAsset(utxo, 'Hello, World!'); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \# Smart Contracts URL: /smart-contracts Open-source smart contracts, complete with documentation, and live demos \*\*\* title: "Smart Contracts" description: "Open-source smart contracts, complete with documentation, and live demos" icon: DocumentCheckIcon ----------------------- import {linksSmartContracts} from "@/data/links-smart-contracts"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksSmartContracts.map((card) => ( {card.title} {card.desc} ))} \# Marketplace URL: /smart-contracts/marketplace Build a NFT marketplace to buy and sell NFTs \*\*\* title: "Marketplace" description: "Build a NFT marketplace to buy and sell NFTs" icon: ShoppingCartIcon ---------------------- import Link from "fumadocs-core/link"; The marketplace smart contract allows users to buy and sell NFTs. A seller list an NFT for sales by specifying a certain price, and anyone can buy it by paying the demanded price. There are 4 actions (or endpoints) available to interact with this smart contract: \* list asset \* buy asset \* updating listing \* cancel listing ### Install package \\\[!toc\] First you can to install the \`@meshsdk/contracts\` package: \`\`\`tsx npm install @meshsdk/contract \`\`\` ### Initialize the Marketplace \\\[!toc\] Utilizing the Marketplace contract requires a blockchain provider and a connected browser wallet. Here is an example how we can initialize the Marketplace. \`\`\`tsx import { MeshMarketplaceContract } from "@meshsdk/contract"; import { MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshMarketplaceContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, 'addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', 200, // 2% fee ); \`\`\` To initialize the Marketplace, we import the \`MeshMarketplaceContract\`. The first JSON object is the \`inputs\` for the \`MeshTxInitiatorInput\`, this requires a \`MeshTxBuilder\`, a \`Provider\`, a \`Wallet\`, and define the network ID. Second and third parameters are the \`ownerAddress\` and \`feePercentageBasisPoint\`. The \`ownerAddress\` is the address of the marketplace owner which will receive the marketplace fee. The \`feePercentageBasisPoint\` is the percentage of the sale price that the marketplace \`owner\` will take. The fee numerator is in the order of hundreds, for example \`200\` implies a fee of \`2%\`. Both on-chain and off-chain codes are open-source and available on Mesh Github Repository. ## List Asset List an asset on the marketplace. This will allow other users to buy the asset. The seller will receive the listing price in ADA. The seller can cancel the listing at any time. The seller can also update the listing price at any time. \`listAsset()\` list an asset for sale. The function accepts the following parameters: \* asset (string) - the asset's unit to be listed \* price (number) - the listing price in Lovelace \### List Asset \\\[!toc\] List an asset for sale \*\*Listing price in Lovelace\*\* \`10000000\` \*\*Asset unit\*\* \`d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e\` \`\`\`tsx const tx = await contract.listAsset('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e', 10000000); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Buy Asset Purchase a listed asset from the marketplace. The seller will receive the listed price in ADA and the buyer will receive the asset. The marketplace owner will receive a fee if it is specified. \`purchaseAsset()\` purchase a listed asset. The function accepts the following parameters: \* utxo (UTxO) - unspent transaction output in the script We have provided a very handle function, \`getUtxoByTxHash\`, which will return the UTxO object for a given transaction hash. A successful purchase will send the asset to the wallet that signed the transaction to purchase the asset. \### Buy Asset \\\[!toc\] Purchase a listed asset from the marketplace \*\*Tx hash\*\* \`Tx hash\` \`\`\`tsx const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.purchaseAsset(utxo); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Update Listing Update a listing on the marketplace. For the contract, the seller can update the listing price. \`relistAsset()\` update a listing on the marketplace. The function accepts the following parameters: \* utxo (UTxO) - unspent transaction output in the script \* newListPrice (number) - the new listing price in Lovelace We have provided a very handle function, \`getUtxoByTxHash\`, which will return the UTxO object for a given transaction hash. \### Update Listing \\\[!toc\] Update the listing price of an asset on the marketplace \*\*Tx hash\*\* \`Tx hash\` \*\*New listing price in Lovelace\*\* \`20000000\` \`\`\`tsx const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.relistAsset(utxo, 20000000); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Cancel Listing Cancel a listing on the marketplace. The seller can cancel the listing at any time. The seller will receive the listed asset back. \`delistAsset()\` cancel a listing on the marketplace. The function accepts the following parameters: \* utxo (UTxO) - unspent transaction output in the script We have provided a very handle function, \`getUtxoByTxHash\`, which will return the UTxO object for a given transaction hash. \### Cancel Listing \\\[!toc\] Cancel a listing on the marketplace \*\*Tx hash\*\* \`Tx hash\` \`\`\`tsx const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.delistAsset(utxo); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \# Payment Splitter URL: /smart-contracts/payment-splitter Split payouts equally among a list of specified payees \*\*\* title: "Payment Splitter" description: "Split payouts equally among a list of specified payees" icon: ArrowsPointingOutIcon --------------------------- import Link from "fumadocs-core/link"; A payment splitter can be used for example to create a shared project donation address, ensuring that all payees receive the same amount Sending lovelace to the contract works similarly to sending lovelace to any other address. The payout transaction can only be submitted by one of the payees, and the output addresses are restricted to the payees. The output sum must be equally divided to ensure the transaction is successful. There are 2 actions (or endpoints) available to interact with this smart contract: \* Send Lovelace to Payment Splitter \* Trigger Payout ### Install package \\\[!toc\] First you can to install the \`@meshsdk/contracts\` package: \`\`\`tsx npm install @meshsdk/contract \`\`\` ### Initialize the contract \\\[!toc\] To initialize the payment splitter, we need to initialize a provider, a \`MeshTxBuilder\`, and a \`MeshPaymentSplitterContract\`. Additionally, a list of payees is required to define the allowed payout addresses for the contract. \`\`\`tsx import { MeshPaymentSplitterContract } from "@meshsdk/contract"; import { MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshPaymentSplitterContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, \[ 'addr\_test1vpg334d6skwu6xxq0r4lqrnsjd5293n8s3d80em60kf6guc7afx8k', 'addr\_test1vp4l2kk0encl7t7972ngepgm0044fu8695prkgh5vjj5l6sxu0l3p', 'addr\_test1vqqnfs2vt42nq4htq460wd6gjxaj05jg9vzg76ur6ws4sngs55pwr', 'addr\_test1vqv2qhqddxmf87pzky2nkd9wm4y5599mhp62mu4atuss5dgdja5pw', \] ); \`\`\` Both on-chain and off-chain codes are open-source and available on Mesh Github Repository. ## Send Lovelace to Payment Splitter \`sendLovelaceToSplitter()\` will lock Lovelace in the contract. The function accepts the following parameters: \* lovelaceAmount (number) - the amount of Lovelace you want to send to the contract The function returns a transaction hash. \### Send Lovelace to Payment Splitter \\\[!toc\] Send Lovelace to the Payment Splitter contract to be distributed to the beneficiaries. \*\*Listing price in Lovelace\*\* \`15000000\` \`\`\`tsx const tx = await contract.sendLovelaceToSplitter(15000000); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Trigger Payout \`triggerPayout()\` will split the locked amount equally among the list of payees. The function doesn't need any parameters. The function returns a transaction hash if the payout has been done successfully. \### Trigger Payout \\\[!toc\] After the amount has been locked in the contract, you can trigger the payout to the payees. \`\`\`tsx const tx = await contract.triggerPayout(); const signedTx = await wallet.signTx(tx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` \# NFT Minting Machine URL: /smart-contracts/plutus-nft Mint NFT that ensure the token name is incremented by a counter \*\*\* title: "NFT Minting Machine" description: "Mint NFT that ensure the token name is incremented by a counter" icon: PhotoIcon --------------- import Link from "fumadocs-core/link"; This NFT minting script enables users to mint NFTs with an automatically incremented index, which increases by one for each newly minted NFT. To facilitate this process, the first step is to set up a one-time minting policy by minting an oracle token. This oracle token is essential as it holds the current state and index of the NFTs, acting as a reference for the minting sequence. With each new NFT minted, the token index within the oracle is incremented by one, ensuring a consistent and orderly progression in the numbering of the NFTs. There are 3 actions available to interact with this smart contract: \* \*\*Setup Oracle:\*\* Mint one-time minting policy to set up the oracle \* \*\*Mint Token:\*\* Mint NFT that ensures the token name is incremented by a counter \* \*\*Get Oracle Data:\*\* Fetch the current oracle data to get the current NFT index and other information ### Install package \\\[!toc\] First you can to install the \`@meshsdk/contracts\` package: \`\`\`tsx npm install @meshsdk/contract \`\`\` Both on-chain and off-chain codes are open-source and available on Mesh Github Repository. ## Setup Oracle First, we need to set up a one-time minting policy by minting an oracle token. This oracle token is essential as it holds the current state and index of the NFTs, acting as a reference for the minting sequence. We need to provide 2 parameters to setup the oracle, the price of the NFT in lovelace and the collection name. The collection name is used when initializing \`MeshPlutusNFTContract\` which is used to derive the script CBOR. The price of the NFT in lovelace is used in \`setupOracle()\` function which will be added into the oracle token. \`\`\`tsx const contract = new MeshPlutusNFTContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, { collectionName: 'collectionName', // your nft collection name }, ); const { tx, paramUtxo } = await contract.setupOracle(15000000); // price in lovelace \`\`\` The \`setupOracle()\` function will return a transaction CBOR and a \`paramUtxo\`. The \`paramUtxo\` will be used in the minting transaction of the NFT, so it is important to store it. Here is an example of the \`paramUtxo\`: \`\`\`tsx { "outputIndex": 0, "txHash": "63dbd563ee9979574401599a42841e0d5b63a691af95df863cbf37d5cb44a558" } \`\`\` The transaction CBOR can be signed and submitted using the following code: \`\`\`tsx const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \### Setup Oracle \\\[!toc\] Mint one time minting policy to set up the oracle \*\*NFT Price in Lovelace\*\* \`10000000\` \*\*Collection Name\*\* \`mesh\` \`\`\`tsx const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, verbose: true, }); const contract = new MeshPlutusNFTContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, { collectionName: 'mesh', }, ); const { tx, paramUtxo } = await contract.setupOracle(10000000); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Mint Token This NFT minting script enables users to mint NFTs with an automatically incremented index, which increases by one for each newly minted NFT. To facilitate this process, you must provide the \`paramUtxo\` that contains the output index and transaction hash of the NFT minting policy. \`\`\`tsx const contract = new MeshPlutusNFTContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, { collectionName: 'collectionName', paramUtxo: {"outputIndex":0,"txHash":"63dbd563ee9979574401599a42841e0d5b63a691af95df863cbf37d5cb44a558"}, }, ); \`\`\` The \`mintPlutusNFT()\` function mints an NFT with asset metadata, which is a JSON object containing the NFT metadata. You can use the \`getOracleData()\` function to fetch the oracle data, which includes the current NFT index. This index will be helpful if you need to define the NFT name and its metadata. Here is an example of the how we can define the asset metadata: \`\`\`tsx const oracleData = await contract.getOracleData(); const assetMetadata = { ...demoAssetMetadata, name: \`Mesh Token ${oracleData.nftIndex}\`, }; \`\`\` The \`mintPlutusNFT()\` function will return a transaction object that can be signed and submitted using the following code: \`\`\`tsx const tx = await contract.mintPlutusNFT(assetMetadata); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \### Mint Token \\\[!toc\] Mint an NFT with asset metadata \*\*Collection Name\*\* \`mesh\` \*\*Param UTxO\*\* \`{"outputIndex":0,"txHash":"63dbd563ee9979574401599a...37d5cb44a558"}\` \`\`\`tsx const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, verbose: true, }); const contract = new MeshPlutusNFTContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, { collectionName: 'mesh', paramUtxo: {"outputIndex":0,"txHash":"63dbd563ee9979574401599a42841e0d5b63a691af95df863cbf37d5cb44a558"}, }, ); // Get Oracle Data const oracleData = await contract.getOracleData(); // see getOracleData() // define your NFT metadata here const assetMetadata = { ...demoAssetMetadata, name: \`Mesh Token ${oracleData.nftIndex}\`, }; const tx = await contract.mintPlutusNFT(assetMetadata); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Get Oracle Data Getting the oracle data is essential to fetch the current NFT index. To facilitate this process, you must provide the \`paramUtxo\` that contains the output index and transaction hash of the NFT minting policy. \`\`\`tsx const contract = new MeshPlutusNFTContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, { collectionName: 'collectionName', paramUtxo: {"outputIndex":0,"txHash":"63dbd563ee9979574401599a42841e0d5b63a691af95df863cbf37d5cb44a558"}, }, ); \`\`\` The \`getOracleData()\` function will return the current oracle data. \`\`\`tsx const oracleData = await contract.getOracleData(); \`\`\` \### Get Oracle Data \\\[!toc\] Fetch the current oracle data to get the current NFT index and other information \*\*Collection Name\*\* \`mesh\` \*\*Param UTxO\*\* \`{"outputIndex":0,"txHash":"63dbd563ee9979574401599a...37d5cb44a558"}\` \`\`\`tsx const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, verbose: true, }); const contract = new MeshPlutusNFTContract( { mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }, { collectionName: 'mesh', paramUtxo: {"outputIndex":0,"txHash":"63dbd563ee9979574401599a42841e0d5b63a691af95df863cbf37d5cb44a558"}, }, ); // Get Oracle Data const oracleData = await contract.getOracleData(); \`\`\` \# Swap URL: /smart-contracts/swap Swap contract facilitates the exchange of assets between two parties \*\*\* title: "Swap" description: "Swap contract facilitates the exchange of assets between two parties" icon: ArrowsRightLeftIcon ------------------------- import Link from "fumadocs-core/link"; Swap contract facilitates the exchange of assets between two parties. This contract is designed to be used in a peer-to-peer exchange scenario where two parties agree to exchange assets. The contract ensures that the assets are locked up until it is accepted by the other party. At any point before it is accepted, one can cancel the swap to retrieve the assets. There are 2 actions (or endpoints) available to interact with this smart contract: \* initiate swap \* accept asset \* cancel swap ### Install package \\\[!toc\] First you can to install the \`@meshsdk/contracts\` package: \`\`\`tsx npm install @meshsdk/contract \`\`\` ### Initialize the contract \\\[!toc\] To initialize the payment splitter, we need to initialize a provider, \`MeshTxBuilder\` and \`MeshSwapContract\`. \`\`\`tsx import { MeshSwapContract } from "@meshsdk/contract"; import { MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshSwapContract({ mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }); \`\`\` Both on-chain and off-chain codes are open-source and available on Mesh Github Repository. ## Initiate Swap User A can initiate a swap by providing assets to the swap contract. \`initiateSwap()\` initiate a swap. The function accepts the following parameters: \* toProvide (Asset\\\[\]) - a list of assets user A is trading \* toReceive (Asset\\\[\]) - a list of assets user A is expecting to receive from another user Note that the parameters are arrays, so you can provide multiple assets to the swap, and these assets can be tokens and lovelace. \### Initiate Swap \\\[!toc\] Initiate a swap by defining the assets for the swap contract \*\*Amount lovelace to give\*\* \`10000000\` \*\*Asset to receive\*\* \`d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e\` \`\`\`tsx const assetToProvide: Asset = { unit: "lovelace", quantity: '10000000', }; const assetToReceive: Asset = { unit: 'd9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e', quantity: "1", }; const tx = await contract.initiateSwap(\[assetToProvide\], \[assetToReceive\]); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Accept Swap User B can accept a swap by providing the swap transaction hash to the contract. \`acceptSwap()\` accept a swap. The function accepts the following parameters: \* swapUtxo (UTxO) - the utxo of the transaction in the script for the swap The function accepts a swap transaction hash and returns a transaction hash if the swap is successfully accepted. A successful transaction will send the assets to the wallet that signed the transaction to accept the swap. \### Accept Swap \\\[!toc\] Accept a swap by providing the assets to the swap contract \*\*Tx hash\*\* \`Tx hash\` \`\`\`tsx const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.acceptSwap(utxo); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Cancel Swap Any any time before swap is accepted, user A can cancel the swap. \`cancelSwap()\` cancel a swap. The function accepts the following parameters: \* swapUtxo (UTxO) - the utxo of the transaction in the script for the swap The function accepts a swap transaction hash and returns a transaction hash if the swap is successfully canceled. \### Cancel Swap \\\[!toc\] Cancel a swap to get your funds back \*\*Tx hash\*\* \`Tx hash\` \`\`\`tsx const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.cancelSwap(utxo); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \# Vesting URL: /smart-contracts/vesting Locks up funds and allows the beneficiary to withdraw the funds after the lockup period \*\*\* title: "Vesting" description: "Locks up funds and allows the beneficiary to withdraw the funds after the lockup period" icon: LockClosedIcon -------------------- import Link from "fumadocs-core/link"; When a new employee joins an organization, they typically receive a promise of compensation to be disbursed after a specified duration of employment. This arrangement often involves the organization depositing the funds into a vesting contract, with the employee gaining access to the funds upon the completion of a predetermined lockup period. Through the utilization of vesting contracts, organizations establish a mechanism to encourage employee retention by linking financial rewards to tenure. There are 2 actions (or endpoints) available to interact with this smart contract: \* deposit asset \* withdraw asset ### Install package \\\[!toc\] First you can to install the \`@meshsdk/contracts\` package: \`\`\`tsx npm install @meshsdk/contract \`\`\` ### Initialize the contract \\\[!toc\] To initialize the contract, we need to initialize a provider, \`MeshTxBuilder\` and \`MeshVestingContract\`. \`\`\`tsx import { MeshVestingContract } from "@meshsdk/contract"; import { MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const meshTxBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); const contract = new MeshVestingContract({ mesh: meshTxBuilder, fetcher: provider, wallet: wallet, networkId: 0, }); \`\`\` Both on-chain and off-chain codes are open-source and available on Mesh Github Repository. ## Deposit Fund After the lockup period has expired, the beneficiary can withdraw the funds from the vesting contract. \`withdrawFund()\` withdraw funds from a vesting contract. The function accepts the following parameters: \* vestingUtxo (UTxO) - unspent transaction output in the script \### Deposit Fund \\\[!toc\] Deposit funds into a vesting contract with a locking period for a beneficiary \*\*Amount in lovelace\*\* \`5000000\` \*\*Beneficiary address\*\* \`addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr\` \`\`\`tsx const assets: Asset\[\] = \[ { unit: "lovelace", quantity: '5000000', }, \]; const lockUntilTimeStamp = new Date(); lockUntilTimeStamp.setMinutes(lockUntilTimeStamp.getMinutes() + 1); const beneficiary = 'addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr'; const tx = await contract.depositFund( assets, lockUntilTimeStamp.getTime(), beneficiary, ); const signedTx = await wallet.signTx(tx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Withdraw Fund After the lockup period has expired, the beneficiary can withdraw the funds from the vesting contract. \`withdrawFund()\` withdraw funds from a vesting contract. The function accepts the following parameters: \* vestingUtxo (UTxO) - unspent transaction output in the script A successful withdrawal will send the funds to the wallet that signed the transaction to withdraw the funds. \### Withdraw Fund \\\[!toc\] Withdraw funds from a vesting contract \*\*Tx hash\*\* \`Tx hash\` \`\`\`tsx const utxo = await contract.getUtxoByTxHash(''); const tx = await contract.withdrawFund(utxo); const signedTx = await wallet.signTx(tx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Full Tutorial Vesting contract is a smart contract that locks up funds for a period of time and allows the beneficiary to withdraw the funds after the lockup period. Usually, vesting contract defines a beneficiary who can be different from the original owner. When a new employee joins an organization, they typically receive a promise of compensation to be disbursed after a specified duration of employment. This arrangement often involves the organization depositing the funds into a vesting contract, with the employee gaining access to the funds upon the completion of a predetermined lockup period. Through the utilization of vesting contracts, organizations establish a mechanism to encourage employee retention by linking financial rewards to tenure. ### On-Chain code \\\[!toc\] First, we define the datum's shape, as this datum serves as configuration and contains the different parameters of our vesting operation. \`\`\`tsx pub type VestingDatum { /// POSIX time in milliseconds, e.g. 1672843961000 lock\_until: Int, /// Owner's credentials owner: ByteArray, /// Beneficiary's credentials beneficiary: ByteArray, } \`\`\` In this example, we define a \`VestingDatum\` that contains the following fields: \* \`lock\_until\`: The POSIX timestamp in milliseconds until which the funds are locked. \* \`owner\`: The credentials (public key hash) of the owner of the funds. \* \`beneficiary\`: The credentials (public key hash) of the beneficiary of the funds. This datum can be found in \`aiken-vesting/aiken-workspace/lib/vesting/types.ak\`. Next, we define the spend validator. \`\`\`tsx use aiken/transaction.{ScriptContext, Spend} use vesting/types.{VestingDatum} use vodka\_extra\_signatories.{key\_signed} use vodka\_validity\_range.{valid\_after} validator { pub fn vesting(datum: VestingDatum, \_redeemer: Data, ctx: ScriptContext) { // In principle, scripts can be used for different purpose (e.g. minting // assets). Here we make sure it's only used when 'spending' from a eUTxO when ctx.purpose is { Spend(\_) -> or { key\_signed(ctx.transaction.extra\_signatories, datum.owner), and { key\_signed(ctx.transaction.extra\_signatories, datum.beneficiary), valid\_after(ctx.transaction.validity\_range, datum.lock\_until), }, } \_ -> False } } } \`\`\` In this example, we define a \`vesting\` validator that ensures the following conditions are met: \* The transaction must be signed by owner Or: \* The transaction must be signed by beneficiary \* The transaction must be valid after the lockup period This validator can be found in \`aiken-vesting/aiken-workspace/validators/vesting.ak\`. ### How it works \\\[!toc\] The owner of the funds deposits the funds into the vesting contract. The funds are locked up until the lockup period expires. Transactions can include validity intervals that specify when the transaction is valid, both from and until a certain time. The ledger verifies these validity bounds before executing a script and will only proceed if they are legitimate. This approach allows scripts to incorporate a sense of time while maintaining determinism within the script's context. For instance, if a transaction has a lower bound \`A\`, we can infer that the current time is at least \`A\`. It's important to note that since we don't control the upper bound, a transaction might be executed even 30 years after the vesting delay. However, from the script's perspective, this is entirely acceptable. The beneficiary can withdraw the funds after the lockup period expires. The beneficiary can also be different from the owner of the funds. ### Testing \\\[!toc\] To test the vesting contract, we have provided the a comphrehensive test script,you can run tests with \`aiken check\`. The test script includes the following test cases: \* success unlocking \* success unlocking with only owner signature \* success unlocking with beneficiary signature and time passed \* fail unlocking with only beneficiary signature \* fail unlocking with only time passed We recommend you to check out \`aiken-vesting/aiken-workspace/validators/tests/vesting.ak\` to learn more. ### Compile and build script \\\[!toc\] To compile the script, run the following command: \`\`\`tsx aiken build \`\`\` This command will generate a CIP-0057 Plutus blueprint, which you can find in \`aiken-vesting/aiken-workspace/plutus.json\`. ## Off-Chain code \\\[!toc\] ### Deposit funds \\\[!toc\] First, the owner can deposit funds into the vesting contract. The owner can specify the lockup period and the beneficiary of the funds. \`\`\`tsx const assets: Asset\[\] = \[ { unit: "lovelace", quantity: "10000000", }, \]; const lockUntilTimeStamp = new Date(); lockUntilTimeStamp.setMinutes(lockUntilTimeStamp.getMinutes() + 1); const beneficiary = "addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9"; \`\`\` In this example, we deposit 10 ADA into the vesting contract. The funds are locked up for 1 minute, and the beneficiary is specified. Then, we prepare a few variables to be used in the transaction. We get the wallet address and the UTXOs of the wallet. We also get the script address of the vesting contract, to send the funds to the script address. We also get the owner and beneficiary public key hashes. \`\`\`tsx const { utxos, walletAddress } = await getWalletInfoForTx(); const { scriptAddr } = getScript(); const { pubKeyHash: ownerPubKeyHash } = deserializeAddress(walletAddress); const { pubKeyHash: beneficiaryPubKeyHash } = deserializeAddress(beneficiary); \`\`\` Next, we construct the transaction to deposit the funds into the vesting contract. \`\`\`tsx const txBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); await txBuilder .txOut(scriptAddr, amount) .txOutInlineDatumValue( mConStr0(\[lockUntilTimeStampMs, ownerPubKeyHash, beneficiaryPubKeyHash\]) ) .changeAddress(walletAddress) .selectUtxosFrom(utxos) .complete(); const unsignedTx = txBuilder.txHex; \`\`\` In this example, we construct the transaction to deposit the funds into the vesting contract. We specify the script address of the vesting contract, the amount to deposit, and the lockup period, owner, and beneficiary of the funds. Finally, we sign and submit the transaction. \`\`\`tsx const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` To execute this code, ensure you have defined blockfrost key in the \`.env\` file. You can also define your wallet mnemonic in \`aiken-vesting/src/configs.ts\` file. You can run the following command execute the deposit funds code: \`\`\`tsx npm run deposit \`\`\` Upon successful execution, you will receive a transaction hash. Save this transaction hash for withdrawing the funds. Example of a successful deposit transaction. ### Withdraw funds \\\[!toc\] After the lockup period expires, the beneficiary can withdraw the funds from the vesting contract. The owner can also withdraw the funds from the vesting contract. First, let's look for the UTxOs containing the funds locked in the vesting contract. \`\`\`tsx const txHashFromDesposit = "ede9f8176fe41f0c84cfc9802b693dedb5500c0cbe4377b7bb0d57cf0435200b"; const utxos = await provider.fetchUTxOs(txHash); const vestingUtxo = utxos\[0\]; \`\`\` In this example, we fetch the UTxOs containing the funds locked in the vesting contract. We specify the transaction hash of the deposit transaction. Like before, we prepare a few variables to be used in the transaction. We get the wallet address and the UTXOs of the wallet. We also get the script address of the vesting contract, to send the funds to the script address. We also get the owner and beneficiary public key hashes. \`\`\`tsx const { utxos, walletAddress, collateral } = await getWalletInfoForTx(); const { input: collateralInput, output: collateralOutput } = collateral; const { scriptAddr, scriptCbor } = getScript(); const { pubKeyHash } = deserializeAddress(walletAddress); \`\`\` Next, we prepare the datum and the slot number to set the transaction valid interval to be valid only after the slot. \`\`\`tsx const datum = deserializeDatum(vestingUtxo.output.plutusData!); const invalidBefore = unixTimeToEnclosingSlot( Math.min(datum.fields\[0\].int as number, Date.now() - 15000), SLOT\_CONFIG\_NETWORK.preprod ) + 1; \`\`\` In this example, we prepare the datum and the slot number to set the transaction valid interval to be valid only after the slot. We get the lockup period from the datum and set the transaction valid interval to be valid only after the lockup period. Next, we construct the transaction to withdraw the funds from the vesting contract. \`\`\`tsx const txBuilder = new MeshTxBuilder({ fetcher: provider, submitter: provider, }); await txBuilder .spendingPlutusScriptV2() .txIn( vestingUtxo.input.txHash, vestingUtxo.input.outputIndex, vestingUtxo.output.amount, scriptAddr ) .spendingReferenceTxInInlineDatumPresent() .spendingReferenceTxInRedeemerValue("") .txInScript(scriptCbor) .txOut(walletAddress, \[\]) .txInCollateral( collateralInput.txHash, collateralInput.outputIndex, collateralOutput.amount, collateralOutput.address ) .invalidBefore(invalidBefore) .requiredSignerHash(pubKeyHash) .changeAddress(walletAddress) .selectUtxosFrom(utxos) .complete(); const unsignedTx = txBuilder.txHex; \`\`\` In this example, we construct the transaction to withdraw the funds from the vesting contract. We specify the UTxO containing the funds locked in the vesting contract, the script address of the vesting contract, the wallet address to send the funds to, and the transaction valid interval. Finally, we sign and submit the transaction. Notice that since we are unlocking fund from validator, partial sign has to be specified by passing a \`true\` parameter into \`wallet.signTx\`. \`\`\`tsx const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` To execute this code, update \`aiken-vesting/src/withdraw-fund.ts\` with the transaction hash from the deposit transaction. Ensure you have defined blockfrost key in the \`.env\` file. You can also define your wallet mnemonic in \`aiken-vesting/src/configs.ts\` file. Run the following command: \`\`\`tsx npm run withdraw \`\`\` Example of a successful withdraw transaction. # Solutions URL: /solutions Mesh provides a set of solutions to help you build blockchain applications \*\*\* title: "Solutions" description: "Mesh provides a set of solutions to help you build blockchain applications" ----------------------------------------------------------------------------------------- import {metaSolutions} from "@/data/links-solutions"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {metaSolutions.items.map((card) => ( {card.title} {card.desc} ))} \# Getting Started with Svelte URL: /svelte/getting-started Svelte frontend components for wallet connections. \*\*\* title: "Getting Started with Svelte" description: "Svelte frontend components for wallet connections." icon: RocketLaunchIcon ---------------------- import Link from "fumadocs-core/link"; ## Setup The fastest way to get started a new project with Svelte is to use the Mesh-CLI, which will scaffold a new project for you. To do this, run the following: \`\`\`tsx npx meshjs your-app-name \`\`\` During the installation process, you will be asked to choose a template. Choose the Svelte template. This will scaffold a new Svelte project with Mesh pre-installed. To manually, install the Mesh Svelte package, run the following: \`\`\`tsx npm install @meshsdk/svelte \`\`\` Next, add the Mesh CSS to your application, doing so will apply the default styles to the components. You can add this in \`+layout.svelte\`. \`\`\`tsx {@render children()} \`\`\` ## Connect Wallet In order for apps to communicate with the user's wallet, we need a way to connect to their wallet. Add \`CardanoWallet\` to allow the user to select a wallet to connect to your app. After the wallet is connected, see Browser Wallet for a list of CIP-30 APIs. The signature for the \`CardanoWallet\` component is as follows: \`\`\`tsx { label?: string; onConnected?: Function; isDark?: boolean; } \`\`\` ### Customization \\\[!toc\] For dark mode style, add isDark. \`\`\`tsx \`\`\` For a custom label, add the label prop. \`\`\`tsx \`\`\` The customization is limited. For more customization, you can easily build your own wallet connection component. You may also take reference from this component. ### onConnected \\\[!toc\] If you want to run a function after the wallet is connected, you can add the onConnected prop. \`\`\`tsx export default function Page() { function afterConnectedWallet() { // do something } return ( <> ); } \`\`\` The above code will log "Hello, World!" to the console when the wallet is connected. \### Connect Wallet Component \\\[!toc\] Connect to user's wallet to interact with app \`\`\`tsx \`\`\` \## Get Wallet State Obtain information on the current wallet's state, all fields on the \`BrowserWalletState\` JavaScript object are Svelte 5 runes, meaning when using the accessor, these values are reactive. \`\`\`tsx \`\`\` \`wallet\` is a Browser Wallet instance, which expose all CIP wallets functions from getting assets to signing tranasction. \`connected\`, a boolean, \`true\` if user's wallet is connected. \`name\`, a string, the name of the connect wallet. \`connecting\`, a boolean, \`true\` if the wallet is connecting and initializing. \### Wallet State \\\[!toc\] Get the current wallet's state \`\`\`tsx \`\`\` \# Svelte Components URL: /svelte Svelte UI components for wallet connections \*\*\* title: "Svelte Components" description: "Svelte UI components for wallet connections" icon: ComputerDesktopIcon ------------------------- import {linksSvelte} from "@/data/links-svelte"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksSvelte.map((card) => ( {card.title} {card.desc} ))} \# UI Components URL: /svelte/ui-components UI components to speed up your app development. \*\*\* title: "UI Components" description: "UI components to speed up your app development." icon: PaintBrushIcon -------------------- import Link from "fumadocs-core/link"; Mesh provide a collection of useful UI components, so you can easily include web3 functionality and convenient utilities for your application. ## Connect Wallet In order for apps to communicate with the user's wallet, we need a way to connect to their wallet. Add \`CardanoWallet\` to allow the user to select a wallet to connect to your app. After the wallet is connected, see Browser Wallet for a list of CIP-30 APIs. The signature for the \`CardanoWallet\` component is as follows: \`\`\`tsx { label?: string; onConnected?: Function; isDark?: boolean; } \`\`\` ### Customization \\\[!toc\] For dark mode style, add isDark. \`\`\`tsx \`\`\` For a custom label, add the label prop. \`\`\`tsx \`\`\` The customization is limited. For more customization, you can easily build your own wallet connection component. You may also take reference from this component. ### onConnected \\\[!toc\] If you want to run a function after the wallet is connected, you can add the onConnected prop. \`\`\`tsx export default function Page() { function afterConnectedWallet() { // do something } return ( <> ); } \`\`\` The above code will log "Hello, World!" to the console when the wallet is connected. \### Connect Wallet Component \\\[!toc\] Connect to user's wallet to interact with app \`\`\`tsx \`\`\` \# Getting Started URL: /yaci/getting-started Set up Yaci Dev Kit and start the devnet \*\*\* title: "Getting Started" description: "Set up Yaci Dev Kit and start the devnet" ------------------------------------------------------- import Link from "fumadocs-core/link"; ## Mesh Hosted Yaci Devnet ### Connect right away with Yaci Provider \\\[!toc\] Mesh has a hosted Yaci Devnet that you can connect to right away. You can use the following URL to connect to the hosted Yaci Devnet: \`\`\`bash https://yaci-node.meshjs.dev/api/v1/ \`\`\` ### Import Yaci Provider \\\[!toc\] Import \`YaciProvider\` and start using it to interact with the Yaci Devnet. \`\`\`tsx import { YaciProvider } from "@meshsdk/core"; const provider = new YaciProvider(); const params = await provider.fetchProtocolParameters(); console.log(params); \`\`\` Learn more about Yaci Provider and learn more about hosted Yaci Devnet ## Set up your system to run Yaci Devkit ### Download and install Docker \\\[!toc\] You can download Docker from the official website. Docker is a platform for developers and sysadmins to develop, deploy, and run applications with containers. Go to the Docker website and download the latest version, then follow the instructions to install it. After installing, open the Docker Desktop app and make sure it's running in the background. ### Download the latest Yaci DevKit release \\\[!toc\] Go to Yaci releases on Github and download the latest release. Under \`Assets\`, you will find the \`yaci-devkit-version.zip\` file. Extract the zip file to a folder on your system. This folder will be your Yaci DevKit root directory. ## Start a Yaci Devnet Open a terminal and navigate to the Yaci DevKit root directory. Run the following command to start the DevKit containers and yaci-cli: \`\`\`bash $ ./bin/devkit.sh start \`\`\` ### Start node \\\[!toc\] To create a new devnet, run the following command from yaci-cli: \`\`\`bash yaci-cli:>create-node -o --start \`\`\` To create a new devnet with Babbage era, run the following command from yaci-cli: \`\`\`bash yaci-cli:>create-node -o --era babbage --start \`\`\` To start a devnet with zero fees, run the following command from yaci-cli: \`\`\`bash yaci-cli:>create-node -o --genesis-profile zero\_fee --start \`\`\` To start a devnet with 30 slots per epoch, run the following command from yaci-cli: \`\`\`bash yaci-cli:>create-node -o -e 30 --start \`\`\` After you have started your devnet, you can open Yaci Viewer from \[http://localhost:5173\](http://localhost:5173). Here you can view the blocks, transactions, and other details of the devnet. If you want to configure the devnet, go to \`config/node.properties\`. And if you want to change settings and change default topup addreses, go to \`config/env\`. You can use \`YaciProvider\` with the Yaci Store Api URL (\[http://localhost:8080/api/v1\](http://localhost:8080/api/v1)), to interact with the Yaci Devnet. \`\`\`tsx import { YaciProvider } from "@meshsdk/core"; const provider = new YaciProvider('http://localhost:8080/api/v1/'); const params = await provider.fetchProtocolParameters(); console.log(params); \`\`\` ### Support external PostgreSQL database for indexer \\\[!toc\] By default, Yaci DevKit's indexer uses an embedded H2 database. With this update, you can also configure an external PostgreSQL database. For Non-Docker distribution, edit config/application.properties and uncomment the following properties to set PostgreSQL database details: \`\`\`bash yaci.store.db.url=jdbc:postgresql://:/?currentSchema= yaci.store.db.username=user yaci.store.db.password=password \`\`\` For Docker distribution, edit config/env and uncomment the following properties: \`\`\`bash yaci\_store\_db\_url=jdbc:postgresql://:/?currentSchema= yaci\_store\_db\_username=user yaci\_store\_db\_password=password \`\`\` ## Useful commands Here are some useful commands to interact with the Yaci DevKit. ### Topup ADA \\\[!toc\] After you have started your devnet, you can topup ADA in your wallet. To topup ADA in your wallet, run the following command from devnet: \`\`\`bash devnet:default>topup \`\`\` For example: \`\`\`bash devnet:default>topup addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9 1000 \`\`\` ### Check UTXO \\\[!toc\] To check the UTXO of an address, run the following command from devnet: \`\`\`bash devnet:default>utxos \`\`\` For example: \`\`\`bash devnet:default>utxos addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9 \`\`\` ### Default address info \\\[!toc\] You can get the default addresses of the devnet by running: \`\`\`bash devnet:default> default-addresses \`\`\` By default, wallet mnemonic is \`\`\`bash test test test test test test test test test test test test test test test test test test test test test test test sauce \`\`\` And it's address is \`\`\`bash addr\_test1qryvgass5dsrf2kxl3vgfz76uhp83kv5lagzcp29tcana68ca5aqa6swlq6llfamln09tal7n5kvt4275ckwedpt4v7q48uhex \`\`\` ### Stop Devnet and yaci-cli \\\[!toc\] To stop the devnet, run the following command from devnet: \`\`\`bash devnet:default>exit \`\`\` To stop yaci-cli, run the following command: \`\`\`bash yaci-cli:>exit \`\`\` To stop the DevKit containers, run the following command from the Yaci DevKit root directory: \`\`\`bash ./bin/devkit.sh stop \`\`\` Sometimes you just want to reset the devnet and start from scratch. To do that, run: \`\`\`bash devnet:default>reset \`\`\` # Yaci URL: /yaci Customizable Cardano devnet for enabling faster iterations \*\*\* title: "Yaci" description: "Customizable Cardano devnet for enabling faster iterations" icon: "icons/yaci.png" ---------------------- Custom Cardano devnet that can be created and reset in seconds using the user-friendly Yaci CLI. This allows for rapid iteration and experimentation, tailored to specific needs through flexible configuration options. The default devnet is optimized for speed, with customizable parameters for various testing scenarios. Integrated tools like the lightweight chain indexer Yaci Store and the browser-based Yaci Viewer enhance transaction building and submission. Yaci DevKit's compatibility with Blockfrost API endpoints ensures seamless integration with client SDKs. import {linksYaci} from "@/data/links-yaci"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksYaci.map((card) => ( {card.title} {card.desc} ))} \# Build Transactions URL: /yaci/transactions Building and submitting transactions on Yaci \*\*\* title: "Build Transactions" description: "Building and submitting transactions on Yaci" ----------------------------------------------------------- ## Import Yaci Provider First, We import \`YaciProvider\` \`\`\`tsx import { YaciProvider } from "@meshsdk/core"; const provider = new YaciProvider('', ''); \`\`\` By default, the \`YaciProvider\` will use the default URL, \`https://yaci-node.meshjs.dev/api/v1/\`. If you want to use a custom URL, you can pass it as a parameter. In this example, we initialize the \`YaciProvider\` and fetch the UTxOs of an address. You can topup ADA in your wallet by running the following command from devne in order to fetch the UTxOs of an address. \`\`\`bash devnet:default>topup addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9 1000 \`\`\` \### Get UTxOs \\\[!toc\] Fetch UTxOs of an address. Note: your Yaci devnet must be running. \*\*Address\*\* \`addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337...pmtv7cc3yel9uu0nq93swx9\` \*\*Yaci URL\*\* \`https://yaci-node.meshjs.dev/api/v1/\` \`\`\`tsx import { YaciProvider } from "@meshsdk/core"; const provider = new YaciProvider('https://yaci-node.meshjs.dev/api/v1/'); const utxos = await provider.fetchAddressUTxOs('addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9'); \`\`\` \## Basic Transaction We import a wallet, for example \`MeshWallet\` with \`YaciProvider\` as the \`fetcher\` and \`submitter\`: \`\`\`tsx const provider = new YaciProvider(); const wallet = new MeshWallet({ networkId: 0, fetcher: provider, submitter: provider, key: { type: "mnemonic", words: demoMnemonic, }, }); \`\`\` Next, we create a transaction and send 1 ADA to the recipient address. \`\`\`tsx const tx = new Transaction({ initiator: wallet }); tx.sendLovelace('', "1000000"); const unsignedTx = await tx.build(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` Note: for this transaction to work, you must have a Yaci devnet running and the wallet is funded. You can topup ADA in your wallet by running the following command from devnet: \`\`\`bash devnet:default>topup addr\_test1qryvgass5dsrf2kxl3vgfz76uhp83kv5lagzcp29tcana68ca5aqa6swlq6llfamln09tal7n5kvt4275ckwedpt4v7q48uhex 1000 \`\`\` \### Get UTxOs \\\[!toc\] Fetch UTxOs of an address. Note: your Yaci devnet must be running. \*\*Recipient Address\*\* \`addr\_test1qryvgass5dsrf2kxl3vgfz76uhp83kv5lag...tal7n5kvt4275ckwedpt4v7q48uhex\` \*\*Yaci URL\*\* \`https://yaci-node.meshjs.dev/api/v1/\` \`\`\`tsx import { YaciProvider } from "@meshsdk/core"; const provider = new YaciProvider('https://yaci-node.meshjs.dev/api/v1/'); const utxos = await provider.fetchAddressUTxOs('addr\_test1qryvgass5dsrf2kxl3vgfz76uhp83kv5lagzcp29tcana68ca5aqa6swlq6llfamln09tal7n5kvt4275ckwedpt4v7q48uhex'); \`\`\` \# Data URL: /apis/data Useful utilities to parse and manipulate data \*\*\* title: "Data" icon: CircleStackIcon description: "Useful utilities to parse and manipulate data" ------------------------------------------------------------ import {linksData} from "@/data/links-data"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksData.map((card) => ( {card.title} {card.desc} ))} \# JSON Data URL: /apis/data/json Parse and manipulate data with JSON \*\*\* title: "JSON Data" description: "Parse and manipulate data with JSON" icon: Bars3Icon --------------- Mesh offers a full set of utility functions to help constructing the JSON data you need for your Web3 app, with the naming philosophy similar to Mesh \`Data\` type, with extra utilities mimicing the data type names in PlutusTx and Aiken. \*\*Types Support\*\* All the utilities are designed to return a type with the same naming as the utilities function, with capitalizing first letter, you can build your data in JSON with robust type supports, some examples: \* \`constr\` returns \`Constr\` type \* \`integer\` returns \`Integer\` type \* \`byteString\` returns \`ByteString\` type ## Utilities in Building Constructor Data in JSON \`conStr\` build the constructor object, with parameters: \* constructor (number) - the constructor index \* fields (any\\\[\]) - the constructor fields in array There are also some quick utilities only taking in \*\*fields\*\* as parameters for 0 - 2 indices: \* \`conStr0\` - building index 0 constructor \* \`conStr1\` - building index 1 constructor \* \`conStr2\` - building index 2 constructor \### Constructor \\\[!toc\] Building JSON constructor object \`\`\`tsx import { conStr } from "@meshsdk/core"; conStr(0, \[\]); \`\`\` \## Utilities in Building Integer Data in JSON \`integer\` build the integer object, with parameters: \* int (number | bigint) - the integer to be built This utility is compatible for both number and bigint type, which allow big integer exceeding the JS precision limit. \*\*Aliases\*\* \* \`posixTime\` - for the same functionality. \### Constructor \\\[!toc\] Building JSON integer object \*\*int\*\* \`1000000\` \`\`\`tsx import { integer } from "@meshsdk/core"; integer(1000000); \`\`\` \## Utilities in Building ByteString Data in JSON \`byteString\` build the byte string object, with parameters: \* bytes (string) - the byte string in hex to be built, validation would be performed on whether the bytes is a valid hex string \*\*Aliases\*\* \* \`builtinByteString\` - for the same functionality, for developers more familiar to the PlutusTx naming convention. \* \`scriptHash\` / \`pubKeyHash\` / \`policyId\` / \`currencySymbol\` / \`assetName\` / token\\\`Name - same building the byte string JSON but with further input validation. \### Constructor \\\[!toc\] Building JSON byteString object \*\*byteString\*\* \`a0bd47e8938e7c41d4c1d7c22033892319d28f86fdace791d45c51946553791b\` \`\`\`tsx import { byteString } from "@meshsdk/core"; byteString("a0bd47e8938e7c41d4c1d7c22033892319d28f86fdace791d45c51946553791b"); \`\`\` \## Utilities in Building Boolean Data in JSON \`bool\` build the boolean object, with parameters: \* b (boolean | boolean) - the boolean to be built \### Constructor \\\[!toc\] Building JSON bool object \`\`\`tsx import { bool } from "@meshsdk/core"; bool(true); \`\`\` \## Utilities in Building List Data in JSON \`list\` build the list object, with parameters: \* pList (T\\\[\]) - the list with items to be built. The items in the \* optional - validation (boolean) - indicate if the current data construction should perform basic validation of whether it is of typeobject (where all JSON data is in type of object) \### Constructor \\\[!toc\] Building JSON list object \`\`\`tsx import { bool, byteString, integer, list } from "@meshsdk/core"; list(\[ byteString( "a0bd47e8938e7c41d4c1d7c22033892319d28f86fdace791d45c51946553791b" ), integer(1000000), bool(false), \]); \`\`\` \## Utilities in Building Map Data in JSON \`assocMap\` build the (associative) map object, with parameters: \* mapItems - (\\\[KeyType, ValueType\]\\\[\]) - the array of map item in JS tuple format (array of array). \* optional - validation (boolean) - indicate if the current data construction should perform basic validation of whether it is of typeobject (where all JSON data is in type of object) \### Constructor \\\[!toc\] Building JSON list object \`\`\`tsx import { assocMap, byteString, integer } from "@meshsdk/core"; assocMap(\[ \[byteString("aa"), integer(1000000)\], \[byteString("bb"), integer(2000000)\], \]); \`\`\` \## Other Utilities The code example showing above does not cover all utilities, please checkout the hosted documentation for more details. The not covered utilities are as below: \* \`assetClass\` \* \`outputReference\` \* \`txOutRef\` \* \`dict\` \* \`tuple\` \* \`maybeStakingHash\` \* \`pubKeyAddress\` \* \`scriptAddress\` # Mesh Data URL: /apis/data/mesh Parse and manipulate data with Mesh Data type \*\*\* title: "Mesh Data" description: "Parse and manipulate data with Mesh Data type" icon: Bars2Icon --------------- Mesh provides a full set of utility functions to help constructing the Mesh \`Data\` type you need for your Web3 app. \*\*Types Support\*\* All utility functions start with the prefix of m and all types All the utility functions start with the prefix of m, and are designed to return a type with the same naming as the utilities function, with capitalizing first letter, you can build your data with type supports in complex types, some examples: \* \`mConstr\` returns \`MConstr\` type \* \`mBool\` returns \`MBool\` type ## Utilities in Building Constructor Mesh Data \`mConStr\` build the constructor object in Mesh \`Data\` type, with parameters: \* alternative (number) - the constructor index \* fields (any\\\[\]) - the constructor fields in array There are also some quick utilities only taking in \*\*fields\*\* as parameters for 0 - 2 indices: \* \`mConStr0\` - building index 0 constructor \* \`mConStr1\` - building index 1 constructor \* \`mConStr2\` - building index 2 constructor \### Constructor \\\[!toc\] Building Mesh constructor object \`\`\`tsx import { mConStr } from "@meshsdk/core"; mConStr(0, \[\]); \`\`\` \## Utilities in Building Primitives Mesh Data \`mBool\` build the boolean object in , with parameters: \* b (boolean | boolean) - the boolean to be built For the rest of data primitives, they are represented by JS primitives: \* Integer - \`number\` and \`bigint\` \* Byte string - \`string\` \* List - JS \`Array\` \* Map - JS \`Map\` \### Constructor \\\[!toc\] Building Mesh bool object \`\`\`tsx import { mBool } from "@meshsdk/core"; mBool(true); \`\`\` \## Other Utilities The code example showing above does not cover all utilities, please checkout the hosted documentation for more details. The not covered utilities are as below: \* \`mAssetClass\` \* \`mOutputReference\` \* \`mTxOutRef\` \* \`mTuple\` \* \`mMaybeStakingHash\` \* \`mPubKeyAddress\` \* \`mScriptAddress\` # Data Overview URL: /apis/data/overview Learn about the basics, and how Mesh handles Cardano data \*\*\* title: "Data Overview" description: "Learn about the basics, and how Mesh handles Cardano data" icon: CircleStackIcon --------------------- import Link from "fumadocs-core/link"; Parsing and converting data in Plutus is a common task when working with transactions. This page will show you how to do that. ## Use of Data in Cardano Cardano data and information is usually communicated in \`CBOR\` encoding format, which can be decoded into \`JSON\` representation. On top of the 2, Mesh also provides the \`Data\` type which get rids of unnecessary wrappers. Mesh supports building data for your app in all 3 different formats. \* \`Mesh\` - the \`Data\` type \* \`JSON\` \* \`CBOR\` ## Mesh Data Type Mesh \`Data\` type is best used when you want to quickly and easily compose your data types. Learn more ## JSON Data Type All Cardano data has the JSON representation, which is suitable for building Web3 app which needs frequent back and forth conversion between on-chain and off-chain code. Mesh also supports building data in JSON format with strong input validation support. Learn more ## CBOR CBOR is the lowest level representation of data in Cardano. Mesh provides endpoints to allow users to provide CBOR in providing data, which is the case for developers utilizing other serialization package other than mesh in part the application. # Value URL: /apis/data/value Manipulate Value Easily \*\*\* title: "Value" description: "Manipulate Value Easily" icon: Bars3Icon --------------- We all know the pain of conducting \`Value\` operation in Cardano. Mesh provides a full set of value methods to help converting, operating, accessing and comparing Cardano data. ### Value Types Support \*\*Convertors\*\* Convertor functions provide utilities around round trip among Cardano onchain data and off chain \`JSON\` and \`Data\` type. \*\*Operators\*\* Operator functions provide utilities into performing value manipulation. They are useful in apps which check against value payment involving calculation in value. \*\*Accessor\*\* Accessor functions provide utilities in obtaining keys or values of the \`Value\` type. \*\*Comparator\*\* Comparator functions provide utilities in comparing different \`Value\`. It helps with offchain validation before using for transaction building. ## Convertor - converts assets into Cardano data Value in JSON \`value\` converts assets into Cardano data Value in JSON with parameters: \* assets - Asset\\\[\] to convert \### value \\\[!toc\] Converts assets into MeshValue with parameters - asset\\\[\] e.g. ada value, simple token token, complex value. \`\`\`tsx const val: Asset\[\] = \[{ unit: "lovelace", quantity: "1000000" }\]; const datum: Value = value(val); const nameMap = dict(\[\[byteString(""), integer(1000000)\]\]); const valMap = dict\>(\[\[byteString(""), nameMap\]\]); if (JSON.stringify(datum) === JSON.stringify(valMap)) { return true; \`\`\` \## Convertor - converts assets into Cardano data Value in Mesh Data type \`mValue\` converts assets into Cardano data value in Mesh Data type with parameters: \* assets - Asset\\\[\] to convert \### mValue \\\[!toc\] Converts assets into MeshValue with parameters - asset\\\[\] e.g. ada value, simple token token, complex value. \`\`\`tsx const val: Asset\[\] = \[{ unit: "lovelace", quantity: "1000000" }\]; const datum: MValue = mValue(val); const nameMap = new Map().set("", 1000000); const valMap = new Map().set("", nameMap); if (JSON.stringify(datum) === JSON.stringify(valMap)) { return true; \`\`\` \## Convertor - converts assets into MeshValue with parameters - asset\\\[\] \`fromAssets\` converts assets into MeshValue with parameters: \* assets - the assets to convert \### fromAssets \\\[!toc\] Converts assets into MeshValue with parameters - asset\\\[\] e.g. ada value, simple token token, complex value. \`\`\`tsx import { MeshValue } from "@meshsdk/common"; const assets: Asset\[\] = \[ { unit: "c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64", quantity: "100" }, { unit: "lovelace", quantity: "10" }, \]; const value = MeshValue.fromAssets(assets); return value; \`\`\` \## Convertor - converts the MeshValue object into an array of Asset \`toAssets\` Convert the MeshValue object into an array of Asset \### toAssets \\\[!toc\] Converts the MeshValue object into an array of Asset \`\`\`tsx import { MeshValue } from "@meshsdk/common"; const val: Asset\[\] = \[{ unit: "lovelace", quantity: "1000000" }\]; const plutusValue: Value = value(val); const assets: Asset\[\] = MeshValue.fromValue(plutusValue).toAssets(); return assets; \`\`\` \## Convertor - converts Value (the JSON representation of Cardano data Value) into MeshValue \`fromValue\` Convert Value (the JSON representation of Cardano data Value) into MeshValue with parameters: \* plutusValue - the value to convert \### fromValue \\\[!toc\] Convert Value (the JSON representation of Cardano data Value) into MeshValue. \`\`\`tsx import { MeshValue } from "@meshsdk/common"; const val: Asset\[\] = \[{ unit: "lovelace", quantity: "1000000" }\]; const plutusValue: Value = value(val); const assets: Asset\[\] = MeshValue.fromValue(plutusValue).toAssets(); return assets; \`\`\` \## Convertor - converts the MeshValue object into Cardano data Value in Mesh Data type \`toData\` Convert the MashValue object into Cardano data Value in Mesh Data type \### toData \\\[!toc\] Converts the MeshValue object into Cardano data Value in Mesh Data type \`\`\`tsx import { MeshValue } from "@meshsdk/common"; const val: Asset\[\] = \[ { unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234", quantity: "100", }, { unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234", quantity: "200", }, \]; const plutusValue: Value = value(val); const data = MeshValue.fromValue(plutusValue).toData(); const expected: MValue = mValue(val); if (JSON.stringify(expected) === JSON.stringify(data)) { return true; \`\`\` \## Convertor - converts the MeshValue object into a JSON representation of Cardano data Value \`toJSON\` Converts the MeshValue object into a JSON representation of Cardano data Value \### toJSON \\\[!toc\] Converts the MeshValue object into a JSON representation of Cardano data Value \`\`\`tsx import { MeshValue } from "@meshsdk/common"; const assets: Asset\[\] = \[ { unit: "lovelace", quantity: "1000000" }, { unit: "c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64", quantity: "500", }, \]; const expectedValue = assocMap(\[ \[currencySymbol(""), assocMap(\[\[tokenName(""), integer(1000000)\]\])\], \[ currencySymbol( "c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c", ), assocMap(\[\[tokenName("000643b04d65736820676f6f64"), integer(500)\]\]), \], \]); const meshValue = new MeshValue(); meshValue.toAssets = () => assets; const jsonValue = meshValue.toJSON(); if (JSON.stringify(jsonValue) === JSON.stringify(expectedValue)) { return true; } \`\`\` \## Operator - add an asset to the Value class's value record with parameters - asset \`addAsset\` Add an asset to the Value class's value record with parameters: \* asset - Asset to add \### addAsset \\\[!toc\] Add an asset to the Value class's value record with parameters - asset \`\`\`tsx import { MeshValue } from "@meshsdk/common"; const value = new MeshValue(); const singleAsset: Asset = { unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234", quantity: "100" }; value.addAsset(singleAsset); return value.value; \`\`\` \## Operator - add an array of assets to the Value class's value record with parameters - assets \`addAssets\` Add an array of assets to the Value class's value record with parameters: \* assets - Asset\\\[\] to add \### addAssets \\\[!toc\] Add an array of assets to the Value class's value record with parameters - assets \`\`\`tsx import { MeshValue } from "@meshsdk/common"; const value = new MeshValue(); const assets: Asset\[\] = \[ { unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234", quantity: "100" }, { unit: "lovelace", quantity: "10" }, { unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234", quantity: "100" }, { unit: "lovelace", quantity: "10" }, \]; value.addAssets(assets); return value.value; \`\`\` \## Operator - substract an asset from the Value class's value record with parameters - asset \`negateAsset\` Substract an asset from the Value class's value record with parameters: \* asset - Asset to substract \### negateAsset \\\[!toc\] Substract an asset from the Value class's value record with parameters - asset \`\`\`tsx import { MeshValue } from "@meshsdk/common"; const value = new MeshValue(); value.value = { lovelace: 10n }; value.negateAsset({ unit: "lovelace", quantity: "5" }); return value.value; \`\`\` \## Operator - substract an array of assets from the Value class's value record with parameters - assets \`negateAssets\` Substract an array of assets from the Value class's value record with parameters: \* assets - Asset\\\[\] to substract \### negateAssets \\\[!toc\] Substract an array of assets from the Value class's value record with parameters - assets \`\`\`tsx const value = new MeshValue(); value.value = { lovelace: 20n, "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234": 10n }; value.negateAssets(\[ { unit: "lovelace", quantity: "5" }, { unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234", quantity: "3" }, \]); return value.value; \`\`\` \## Operator - merge the given values with parameters - values \`merge\` Merge the given values \* values - The other values to merge \## merge \\\[!toc\] Merge the given values with parameters - values \`\`\`tsx const value1 = new MeshValue(); value1.value = { lovelace: 20n, "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234": 10n }; const value2 = new MeshValue(); value2.value = { lovelace: 10n, "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234": 5n }; return value1.merge(value2).value; \`\`\` \## Accessor - get the quantity of asset object per lovelace unit \`get\` get the quantity of asset object per unit, with parameters \* unit - the unit to get the quantity of the assets e.g. lovelace \### get \\\[!toc\] Get the quantity of asset object per unit \`\`\`tsx import { MeshValue } from "@meshsdk/common"; const value = new MeshValue({ lovelace: 20n }); value.get("lovelace"); return value; \`\`\` \## Accessor - get all asset units with no parameters needed \`units\` get all asset units with no parameters (e.g. unit) needed \### units \\\[!toc\] Get all asset units with no parameters needed \`\`\`tsx import { MeshValue } from "@meshsdk/common"; const value = new MeshValue({ lovelace: 20n, "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234": 10n, }); return value.units(); \`\`\` \## Comparator - check if the value is greater than or equal to another value with parameters - other \`geq\` Check if the value is greater than or equal to another value with parameters: \* other - The MeshValue to compare against \### geq \\\[!toc\] Check if the value is greater than or equal to another value with parameters - other \`\`\`tsx import { MeshValue } from "@meshsdk/common"; const value = new MeshValue({ lovelace: 20n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 10n, }); const target = new MeshValue({ lovelace: 10n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 5n, }); return value.geq(target); \`\`\` \## Comparator - check if the value is greater than or equal to another value with parameters - unit, other \`geqUnit\` Check if the value is greater than or equal to another value with parameters: \* unit - The unit to compare \* other - The MeshValue to compare against \### geqUnit \\\[!toc\] Check if the value is greater than or equal to another value with parameters - unit, other \`\`\`tsx import { MeshValue } from "@meshsdk/common"; const value = new MeshValue({ lovelace: 20n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 10n, }); const target = new MeshValue({ lovelace: 10n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 5n, }); const resultLovelace = value.geqUnit("lovelace", target); const resultmockvalue = value.geqUnit( "c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64", target, ); return { resultLovelace, resultmockvalue }; } \`\`\` \## Comparator - check if the value is less than or equal to another value with parameters - other \`leq\` Check if the value is less than or equal to another value with parameters: \* other - The MeshValue to compare against \### leq \\\[!toc\] Check if the value is less than or equal to another value with parameters - other \`\`\`tsx import { MeshValue } from "@meshsdk/common"; const value = new MeshValue({ lovelace: 20n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 10n, }); const target = new MeshValue({ lovelace: 30n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 15n, }); return value.leq(target); \`\`\` \## Comparator - check if the specific unit of value is less than or equal to that unit of another value with parameters - unit, other \`leqUnit\` Check if the specific unit of value is less than or equal to that unit of another value with parameters: \* unit - The unit to compare \* other - The MeshValue to compare against \### lequnit \\\[!toc\] Check if the specific unit of value is less than or equal to that unit of another value with parameters - unit, other \`\`\`tsx import { MeshValue } from "@meshsdk/common"; const value = new MeshValue({ lovelace: 20n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 10n, }); const target = new MeshValue({ lovelace: 30n, c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64: 15n, }); const resultLovelace = value.leqUnit("lovelace", target); const resultmockvalue = value.leqUnit( "c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c000643b04d65736820676f6f64", target, ); return { resultLovelace, resultmockvalue }; \`\`\` \## Comparator - check if the value is empty \`isEmpty\` Check if the value is empty \### isEmpty \\\[!toc\] Check if the value is empty \`\`\`tsx import { MeshValue } from "@meshsdk/common"; const value = new MeshValue(); return value.isEmpty(); \`\`\` \# Transaction Basics URL: /apis/txbuilder/basics Working with transactions and its various options \*\*\* title: "Transaction Basics" description: "Working with transactions and its various options" icon: PaperAirplaneIcon ----------------------- import Link from 'fumadocs-core/link'; In the code snippet, you will find \`txBuilder\`, which is an instance of \`MeshTxBuilder\`, with powerful low-level APIs that allow you to build transactions. Here's how to initialize \*\*MeshTxBuilder\*\*. \`\`\`tsx const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); \`\`\` The \`MeshTxBuilder\` is a powerful interface where the higher level \`Transaction\` class is indeed a pre-built combination of the \`MeshTxBuilder\` APIs. With these lower level APIs, it builds the object to be passing to the serialization libraries like \`cardano-sdk\` and \`Whisky SDK\` to construct transactions. In this page, we will cover how to initialize the \`MeshTxBuilder\` and the basic operations of building a transaction. ## Initialize Tx Builder To start building a customized transaction, you need to first initialize \`MeshTxBuilder\`: \`\`\`tsx import { BlockfrostProvider, MeshTxBuilder } from "@meshsdk/core"; const provider = new BlockfrostProvider(''); const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true, }); \`\`\` The \`MeshTxBuilder\` instance has the following signature: \`\`\`tsx { fetcher?: IFetcher; submitter?: ISubmitter; evaluator?: IEvaluator; serializer?: IMeshTxSerializer; isHydra?: boolean; params?: Partial; verbose?: boolean; } \`\`\` There are 6 optional fields to pass in when initializing a new instance: \* \`serializer\`: The default serializer is \`CSLSerializer\`. You can pass in your own serializer instance. \* \`fetcher\`: When you build the transaction without sufficient fields as required by the serialization library, we would index the blockchain to fill the information for you. Affected APIs are \`txIn\`, \`txInCollateral\`, \`spendingTxInReference\`. \* \`submitter\`: It is used if you would like to use the \`submitter\` submitTx API directly from the instance. \* \`evaluator\`: It would perform redeemer execution unit optimization, returning error message in case of invalid transaction. \* \`isHydra\`: Use another set of default protocol parameters for building transactions. \* \`params\`: You can pass in the protocol parameters directly. \* \`verbose\`: Set to \`true\` to enable verbose logging. ## Send Value Sending value with \`MeshTxBuilder\` is done using the \`.txOut()\` endpoint: \`\`\`tsx .txOut(address: string, amount: Asset\[\]) \`\`\` To send value in a transaction, you must first fund it. There are 2 ways: \* Specifying which input to spend \`\`\`tsx .txIn(txHash: string, txIndex: number, amount?: Asset\[\], address?: string) \`\`\` \* Providing an array of UTxOs, and perform auto UTxO selection: \`\`\`tsx .selectUtxosFrom(extraInputs: UTxO\[\]) \`\`\` Since the input and output values might not be the same, we have to specify the address (usually the wallet's own address) to receive the change: \`\`\`tsx .changeAddress(addr: string) \`\`\` The following shows a simple example of building a transaction to send values with UTxO selection: \`\`\`tsx txBuilder .txOut(address, \[{ unit: "lovelace", quantity: amount }\]) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); \`\`\` \### Send Value \\\[!toc\] Send assests to a recipient \*\*Address\*\*: \`addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr\` \*\*Amount\*\*: \`1000000\` \`\`\`tsx const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .txOut('addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', \[{ unit: "lovelace", quantity: '1000000' }\]) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Multi-signature Transaction The main idea of a multi-signature (multisig) transaction is to have multiple signatures to authorize a transaction. \`\`\`tsx const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mint("1", policyId, stringToHex("MeshToken")) .mintingScript(forgingScript) .metadataValue(721, { \[policyId\]: { \[assetName\]: demoAssetMetadata } }) .changeAddress(address) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet1.signTx(unsignedTx, true); const signedTx2 = await mintingWallet.signTx(signedTx, true); const txHash = await wallet.submitTx(signedTx2); \`\`\` In the above code snippet, we are signing the transaction with the user wallet and then signing the transaction with the minting wallet. The \`signTx\` function is used to sign the transaction. The second argument is a boolean value that indicates whether the transaction is a multi-signature transaction. \`\`\`tsx await wallet.signTx(unsignedTx, true); \`\`\` \### Multi-signature Transaction \\\[!toc\] Create a multi-signature transaction. In this demo, we will create a transaction with two signatures, where one signature is from the user's wallet and the other is from a minting wallet. \`\`\`tsx const mintingWallet = new MeshWallet({ networkId: 0, fetcher: provider, submitter: provider, key: { type: "mnemonic", words: \['your','mnemonic','here'\], }, }); const forgingScript = ForgeScript.withOneSignature( await mintingWallet.getChangeAddress(), ); const assetName = "MeshToken"; const policyId = resolveScriptHash(forgingScript); const usedAddress = await wallet.getUsedAddresses(); const utxos = await wallet.getUtxos(); const address = usedAddress\[0\]!; const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mint("1", policyId, stringToHex("MeshToken")) .mintingScript(forgingScript) .metadataValue(721, { \[policyId\]: { \[assetName\]: demoAssetMetadata } }) .changeAddress(address) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx, true); const signedTx2 = await mintingWallet.signTx(signedTx, true); const txHash = await wallet.submitTx(signedTx2); \`\`\` \## Multi-signature Transaction with Native Script Here is an example of creating a multi-signature (multisig) transaction with a native script, where you need to spend from a script address. \*\*Create native script\*\* First, we need to create a native script. In this example, we will create a native script with two signatures. That means we need to get the key hashes of the two wallets. \`\`\`tsx const { pubKeyHash: keyHash1 } = deserializeAddress(walletAddress1); const { pubKeyHash: keyHash2 } = deserializeAddress(walletAddress2); \`\`\` Next, we will create a native script object with the two key hashes. The native script object will be used to create a multi-signature transaction. \`\`\`tsx const nativeScript: NativeScript = { type: "all", scripts: \[ { type: "sig", keyHash: keyHash1, }, { type: "sig", keyHash: keyHash2, }, \], }; \`\`\` The native script object is then serialized into a CBOR object and an address. \`\`\`tsx const { address: scriptAddress, scriptCbor } = serializeNativeScript(nativeScript); \`\`\` \*\*Create transaction\*\* Now that we have the native script, we can create a transaction with the script. We first need to get the UTXO from the script address. \`\`\`tsx // get utxo from script const utxos = await provider.fetchAddressUTxOs(scriptAddress); const utxo = utxos\[0\]; // create tx const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .txIn( utxo.input.txHash, utxo.input.outputIndex, utxo.output.amount, utxo.output.address, ) .txInScript(scriptCbor) .txOut( "addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr", \[{ unit: "lovelace", quantity: "2000000" }\], ) .changeAddress(scriptAddress) .selectUtxosFrom(utxos) .complete(); \`\`\` Finally, we sign the transaction with the two wallets and submit the transaction. \`\`\`tsx const signedTx1 = await wallet1.signTx(unsignedTx, true); const signedTx2 = await wallet2.signTx(signedTx1, true); const txHash = await wallet.submitTx(signedTx2); \`\`\` ## Build with Object One alternative to use the lower level APIs is to build the transaction with JSON. The following shows a simple example of building a transaction to send values to a recipient: \`\`\`tsx const meshTxBody: Partial = { outputs: \[ { address: address, amount: \[{ unit: "lovelace", quantity: amount }\], }, \], changeAddress: changeAddress, extraInputs: utxos, selectionConfig: { threshold: "5000000", strategy: "largestFirst", includeTxFees: true, }, }; const unsignedTx = await txBuilder.complete(meshTxBody); \`\`\` ## Coin selection You can select UTxOs from a list of UTxOs using the \`selectUtxosFrom\` method. This method allows you to specify the conditions for selecting UTxOs. The method signature is as follows: \`\`\`tsx selectUtxosFrom( extraInputs: UTxO\[\] strategy?: UtxoSelectionStrategy threshold?: string includeTxFees?: boolean ) \`\`\` The second parameter of \`selectUtxosFrom\` is the strategy to be used for selecting UTxOs. There are 4 strategies (\`UtxoSelectionStrategy\`) available for selecting UTxOs: \* experimental \* keepRelevant \* largestFirst \* largestFirstMultiAsset We may introduce more strategies in the future. Check the Mesh Docs for more details. The \`threshold\` parameter is used to specify the minimum amount of lovelace to be selected. You may specify a larger amount too if the transactions requires it. The last parameter is \`includeTxFees\` which is a boolean value to include transaction fees in the selection. ## Set Metadata - Transaction message Add messages / comments / memos as transaction metadata. This is useful for attaching additional information to a transaction. This is an example of setting a metadata with transaction message. \`\`\`tsx txBuilder .metadataValue(label, metadata) \`\`\` The specification for individual strings follows the general JSON metadata design, which is currently used on the Cardano blockchain. The used metadatum label is \`674\`: this number was chosen because it is the T9 encoding of the string \`msg\`. The message content has the key \`msg\`: and consists of an array of individual message-strings. The number of theses message-strings must be at least one for a single message, more for multiple messages/lines. Each of theses individual message-strings array entries must be at most 64 bytes when UTF-8 encoded. \### Transaction message \\\[!toc\] Add messages/comments/memos as transaction metadata \*\*Message (breakline for new line)\*\* \`\`\` Invoice-No: 1234567890 Customer-No: 555-1234 \`\`\` \`\`\`tsx const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const label = 674; const metadata = { msg: \[ 'Invoice-No: 1234567890', 'Customer-No: 555-1234', \], }); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .changeAddress(changeAddress) .metadataValue(label, metadata) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Set Required Signers Sets the required signers for the transaction. This is useful when you want to include multiple signers, such as in a multi-signature transaction or smart contracts. \`\`\`tsx txBuilder .requiredSignerHash(pubKeyHash) \`\`\` ## Set Start and Expire Time We can define the time-to-live (TTL) for the transaction. TTL is the time limit for our transaction to be included in a blockchain, if it is not in a blockchain by then the transaction will be cancelled. This time limit is defined as \`slot\`. In order to get the \`slot\` of the time you wish the transaction would expire, you can use \`resolveSlotNo\`. For example, if you would like the transaction to expire in 5 minutes, you can get the \`slot\` in the following way: \`\`\`tsx import { resolveSlotNo } from '@meshsdk/core'; let minutes = 5; // add 5 minutes let nowDateTime = new Date(); let dateTimeAdd5Min = new Date(nowDateTime.getTime() + minutes\*60000); const slot = resolveSlotNo('mainnet', dateTimeAdd5Min.getTime()); \`\`\` Next, we set the TTL by calling \`invalidHereafter(slot)\`. A transaction submitted after this value is invalid: \`\`\`tsx txBuilder .invalidHereafter(Number(slot)); \`\`\` Likewise, we can call \`invalidBefore(slot)\` to specify the validity start interval. A transaction submitted before this value is invalid: \`\`\`tsx txBuilder .invalidBefore(Number(slot)); \`\`\` ## Set Network Sets the network to use, this is mainly to know the cost models to be used to calculate script integrity hash. You can set the network for the transaction with \`setNetwork\`. \`\`\`tsx txBuilder.setNetwork(network: Network) \`\`\` The network parameter is a string that can be one of the following: \`\`\`tsx "testnet" | "preview" | "preprod" | "mainnet" \`\`\` ## Set Fee Set the fee for the transaction in lovelace. \`\`\`tsx .setFee(fee: string) \`\`\` The following shows a simple example of building a transaction to send values with UTxO selection: \`\`\`tsx const unsignedTx = await txBuilder .txOut(...) .changeAddress(...) .setFee("0") .complete(); \`\`\` ## Custom Protocol Parameter Custom protocol parameters can be fetched from the provider and passed to the transaction builder. This is useful when the provider does not provide the protocol parameters, or when the user wants to use a custom set of parameters. \`\`\`tsx const pp = await provider.fetchProtocolParameters(); const txBuilder = new MeshTxBuilder({ fetcher: provider, params: pp, }); \`\`\` # Governance Transactions URL: /apis/txbuilder/governance Transactions for participating in Cardano's on-chain governance \*\*\* title: "Governance Transactions" description: "Transactions for participating in Cardano's on-chain governance" icon: ScaleIcon --------------- import Link from 'fumadocs-core/link'; In \*\*CIP-1694\*\*, Cardano's on-chain governance system was proposed to allow the community to vote on proposals and protocol updates. This system is designed to be decentralized and transparent, allowing the community to have a say in the future of the network. In the code snippet, you will find \`txBuilder\`, which is an instance of \`MeshTxBuilder\`, a powerful low-level APIs that allows you to build transactions. Learn how to initialize MeshTxBuilder \`\`\`tsx const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); \`\`\` This page list the governance transactions that can be created using the Mesh SDK. ## Vote Delegation Any wallet can delegate its voting power to another DRep. This is done by creating a vote delegation certificate and submitting it to the blockchain. First we need to get the wallet information. This includes the UTXOs, the reward address, and the change address. \`\`\`tsx const utxos = await wallet.getUtxos(); const rewardAddresses = await wallet.getRewardAddresses(); const rewardAddress = rewardAddresses\[0\]; const changeAddress = await wallet.getChangeAddress(); \`\`\` Next we need to select the UTXOs to use to pay for the transaction. We will select the UTXOs that have at least 5 ADA. Though the fee is less than 1 ADA. We can now start building the transaction. We will add the selected UTXOs as inputs to the transaction. We will also add the vote delegation certificate to the transaction. The vote delegation certificate requires the DRep ID of the DRep to delegate to and the reward address of the delegator. Note that we would need to have at least 5 ADA for the certificate delegation, in the \`selectUtxosFrom\` we will configure 10 ADA as threshold buffer. \`\`\`tsx txBuilder .voteDelegationCertificate( { dRepId: dRepId, }, rewardAddress, ) .changeAddress(changeAddress) .selectUtxosFrom(utxos) \`\`\` Finally we can build, sign the transaction and submit it to the blockchain. \`\`\`tsx const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` The transaction will be submitted to the blockchain and the DRep will be registered. The deposit will be taken from the DRep owner and the DRep will be added to the list of registered DReps. \## DRep Vote Delegation \\\[!toc\] Delegate your voting power to another DRep \*\*DRep ID\*\* \`drep1yv4uesaj92wk8ljlsh4p7jzndnzrflchaz5fzug3zxg4naqkpeas3\` \`\`\`tsx const utxos = await wallet.getUtxos(); const rewardAddresses = await wallet.getRewardAddresses(); const rewardAddress = rewardAddresses\[0\]; const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .voteDelegationCertificate( { dRepId: 'drep1yv4uesaj92wk8ljlsh4p7jzndnzrflchaz5fzug3zxg4naqkpeas3', }, rewardAddress, ) .changeAddress(changeAddress) .selectUtxosFrom(utxos) const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## DRep Registration In Voltaire, stake credentials can delegate their stake to Decentralized Representatives (DReps) for voting, in addition to the current delegation to stake pools for block production. This DRep delegation will work similarly to the current stake delegation process, using on-chain certificates. Registering as a DRep will also follow the same process as stake registration. However, registered DReps need to vote regularly to remain active. If a DRep does not vote for a set number of epochs (defined by the new protocol parameter, drepActivity), they are considered inactive and will not count towards the active voting stake. To become active again, DReps need to vote on governance actions or submit a DRep update certificate within the drepActivity period. A DRep registration certificates include: \* a DRep ID \* a deposit \* an optional anchor An anchor is a pair of: \* a URL to a JSON payload of metadata \* a hash of the contents of the metadata URL First we need to get the DRep ID of the DRep we want to register. We can do this by calling \`getDRep\` method on the wallet. This will return the DRep object which contains the DRep ID. \`\`\`tsx const dRep = await wallet.getDRep(); const dRepId = dRep.dRepIDCip105; \`\`\` Next we need to get the hash of the anchor. We can do this by calling the \`getMeshJsonHash\` function. This function fetches the anchor from the given URL and returns the hash of the anchor. \`\`\`tsx async function getMeshJsonHash(url: string) { var drepAnchor = getFile(url); const anchorObj = JSON.parse(drepAnchor); return hashDrepAnchor(anchorObj); } const anchorUrl = "https://meshjs.dev/governance/meshjs.jsonld"; const anchorHash = await getMeshJsonHash(anchorUrl); \`\`\` We can now build the transaction by adding the DRep registration certificate to the transaction. We also need to add the change address and the selected UTxOs to the transaction. Note that the deposit for registering a DRep is 500 ADA, we would set 505 ADA as UTxO selection threshold. \`\`\`tsx const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .drepRegistrationCertificate(dRepId, { anchorUrl: anchorUrl, anchorDataHash: anchorHash, }) .changeAddress(changeAddress) .selectUtxosFrom(selectedUtxos); \`\`\` Finally we can sign the transaction and submit it to the blockchain. \`\`\`tsx const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` The transaction will be submitted to the blockchain and the DRep will be registered. The deposit will be taken from the DRep owner and the DRep will be added to the list of registered DReps. \### DRep Registration \\\[!toc\] Register a DRep certificate and pay the deposit \*\*Anchor Url:\*\* \`eg: https://path.to/file-name.jsonld\` \`\`\`tsx const dRep = await wallet.getDRep(); const dRepId = dRep.dRepIDCip105; const anchorUrl = ''; const anchorHash = await getMeshJsonHash(anchorUrl); // get utxo to pay for the registration const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .drepRegistrationCertificate(dRepId, { anchorUrl: anchorUrl, anchorDataHash: anchorHash, }) .changeAddress(changeAddress) .selectUtxosFrom(utxos); const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## DRep Update Updating a DRep is similar to registering. We build the transaction by adding the DRep update certificate to the transaction, providing the change address and the UTxOs needed for the transaction's fees. \`\`\`tsx const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .drepUpdateCertificate(dRepId, { anchorUrl: anchorUrl, anchorDataHash: anchorHash, }) .changeAddress(utxos) .selectUtxosFrom(selectedUtxos); \`\`\` This transaction is an example of a successful DRep update for DRep ID. \### DRep Update \\\[!toc\] Update DRep metadata \*\*Anchor Url:\*\* \`eg: https://path.to/file-name.jsonld\` \`\`\`tsx const dRep = await wallet.getDRep(); const dRepId = dRep.dRepIDCip105; const anchorUrl = ''; const anchorHash = await getMeshJsonHash(anchorUrl); const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .drepUpdateCertificate(dRepId, { anchorUrl: anchorUrl, anchorDataHash: anchorHash, }) .changeAddress(changeAddress) .selectUtxosFrom(utxos); const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## DRep Retirement A DRep is retired right away when the blockchain accepts a retirement certificate. The deposit is refunded immediately as part of the transaction that submits the retirement certificate, just like how deposits are returned when a stake credential is unregistered. First we need to get the DRep ID of the DRep we want to retire. We can do this by calling \`getDRep\` method on the wallet. This will return the DRep object which contains the DRep ID. \`\`\`tsx const dRep = await wallet.getDRep(); const dRepId = dRep.dRepIDCip105; \`\`\` We then need to initialize the transaction builder by creating a new instance of \`MeshTxBuilder\`. We need to pass the blockchain provider to the constructor. \`\`\`tsx const changeAddress = await wallet.getChangeAddress(); const utxos = await wallet.getUtxos(); const provider = new BlockfrostProvider(''); \`\`\` We can now build the transaction by adding the UTxOs as inputs to the transaction and adding the DRep deregistration certificate to the transaction. \`\`\`tsx const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .drepDeregistrationCertificate(dRepId) .selectUtxosFrom(selectedUtxos) .changeAddress(changeAddress); const unsignedTx = await txBuilder.complete(); \`\`\` Finally we can sign the transaction and submit it to the blockchain. \`\`\`tsx const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` The transaction will be submitted to the blockchain and the DRep will be retired. The deposit will be refunded to the DRep owner. \### DRep Retirement \\\[!toc\] Retire a DRep certificate and return the deposit \`\`\`tsx const dRep = await wallet.getDRep(); const dRepId = dRep.dRepIDCip105; const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .drepDeregistrationCertificate(dRepId) .selectUtxosFrom(utxos) .changeAddress(changeAddress); const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Vote Each vote transaction consists of the following: \* a governance action ID \* a role - constitutional committee member, DRep, or SPO \* a governance credential witness for the role \* an optional anchor (as defined above) for information that is relevant to the vote \* a 'Yes'/'No'/'Abstain' vote First, we get the DRep ID from the wallet, the DRep ID voting for this governance action. \`\`\`tsx const dRep = await wallet.getDRep(); const dRepId = dRep.dRepIDCip105; \`\`\` Then we get the utxos and the change address from the wallet. \`\`\`tsx const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); \`\`\` We then create the vote transaction using the \`vote()\` function. \`\`\`tsx txBuilder .vote( { type: "DRep", drepId: dRepId, }, { txHash: 'aff2909f8175ee02a8c1bf96ff516685d25bf0c6b95aac91f4dfd53a5c0867cc', txIndex: 0, }, { voteKind: "Yes", }, ) .selectUtxosFrom(utxos) .changeAddress(changeAddress); \`\`\` The \`vote()\` takes 3 parameters: \* \`voter\` - The voter, can be a Constitutional Commitee, a DRep or a StakePool \* \`govActionId\` - The transaction hash and transaction id of the governance action \* \`votingProcedure\` - The voting kind (Yes, No, Abstain) with an optional anchor Check the full documentation or the source code for more details. Finally, we sign the transaction and submit it to the blockchain. \`\`\`tsx const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` You can check here a successful vote transaction for this governance action. Here is another example of a vote transaction: \`\`\`tsx txBuilder .changeAddress( "addr\_test1qpsmz8q2xj43wg597pnpp0ffnlvr8fpfydff0wcsyzqyrxguk5v6wzdvfjyy8q5ysrh8wdxg9h0u4ncse4cxhd7qhqjqk8pse6", ) .txIn( "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85", 3, \[ { unit: "lovelace", quantity: "9891607895", }, \], "addr\_test1vru4e2un2tq50q4rv6qzk7t8w34gjdtw3y2uzuqxzj0ldrqqactxh", ) .vote( { type: "DRep", drepId: "drep1j6257gz2swty9ut46lspyvujkt02pd82am2zq97p7p9pv2euzs7", }, { txHash: "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85", txIndex: 3, }, { voteKind: "Yes", anchor: { anchorUrl: "https://path-to.jsonld", anchorDataHash: "2aef51273a566e529a2d5958d981d7f0b3c7224fc2853b6c4922e019657b5060", }, }, ) \`\`\` And another example of a vote transaction with a Plutus script and a redeemer: \`\`\`tsx txBuilder .changeAddress( "addr\_test1qpsmz8q2xj43wg597pnpp0ffnlvr8fpfydff0wcsyzqyrxguk5v6wzdvfjyy8q5ysrh8wdxg9h0u4ncse4cxhd7qhqjqk8pse6", ) .txIn( "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85", 3, \[ { unit: "lovelace", quantity: "9891607895", }, \], "addr\_test1vru4e2un2tq50q4rv6qzk7t8w34gjdtw3y2uzuqxzj0ldrqqactxh", ) .txInCollateral( "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85", 3, \[ { unit: "lovelace", quantity: "9891607895", }, \], "addr\_test1vru4e2un2tq50q4rv6qzk7t8w34gjdtw3y2uzuqxzj0ldrqqactxh", ) .votePlutusScriptV3() .vote( { type: "DRep", drepId: resolveScriptHashDRepId( resolveScriptHash( applyCborEncoding( "5834010100323232322533300232323232324a260106012004600e002600e004600a00260066ea8004526136565734aae795d0aba201", ), "V3", ), ), }, { txHash: "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85", txIndex: 3, }, { voteKind: "Yes", anchor: { anchorUrl: "https://path-to.jsonld", anchorDataHash: "2aef51273a566e529a2d5958d981d7f0b3c7224fc2853b6c4922e019657b5060", }, }, ) .voteScript( applyCborEncoding( "5834010100323232322533300232323232324a260106012004600e002600e004600a00260066ea8004526136565734aae795d0aba201", ), ) .voteRedeemerValue("") \`\`\` \### Vote \\\[!toc\] Vote on a governance action \`\`\`tsx const dRep = await wallet.getDRep(); const dRepId = dRep.dRepIDCip105; const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .vote( { type: "DRep", drepId: dRepId, }, { txHash: 'aff2909f8175ee02a8c1bf96ff516685d25bf0c6b95aac91f4dfd53a5c0867cc', txIndex: 0, }, { voteKind: "Yes", }, ) .selectUtxosFrom(utxos) .changeAddress(changeAddress); const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \# Transaction Builder URL: /apis/txbuilder Build transactions with Cardano-CLI like APIs \*\*\* title: "Transaction Builder" description: "Build transactions with Cardano-CLI like APIs" icon: BanknotesIcon ------------------- import {linksTxbuilder} from "@/data/links-txbuilders"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksTxbuilder.map((card) => ( {card.title} {card.desc} ))} \# Mint and Burn Assets URL: /apis/txbuilder/minting Minting and burning assets with Native Script and Plutus Script \*\*\* title: "Mint and Burn Assets" description: "Minting and burning assets with Native Script and Plutus Script" icon: FireIcon -------------- import Link from "fumadocs-core/link"; Minting and burning assets with Native Script and Plutus Script Minting and burning assets is a common operation in blockchain applications. In the Cardano ecosystem, minting and burning are achieved through Native Scripts and Plutus Scripts. To view a video demonstration of this feature of the MeshSDK, navigate to the video guide Mint an NFT Collection. In the code snippet, you will find \`txBuilder\`, which is an instance of \`MeshTxBuilder\`, with powerful low-level APIs that allow you to build transactions. Here's how to initialize \*\*MeshTxBuilder\*\*. \`\`\`tsx const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); \`\`\` In this page, you will find the APIs to create transactions for minting and burning assets. ## Minting with One Signature In this section, we will see how to mint native assets with a \`MeshTxBuilder\`. For minting assets with a smart contract visit \[this documentation\](/apis/txbuilder/smart-contracts#minting-assets-with-plutus-script). Firstly, we need to define the \`forgingScript\` with \`ForgeScript\`. We use the first wallet address as the "minting address" (you can use other addresses). \`\`\`tsx const changeAddress = await wallet.getChangeAddress(); const forgingScript = ForgeScript.withOneSignature(changeAddress); \`\`\` Then, we define the metadata. \`\`\`tsx const demoAssetMetadata = { name: "Mesh Token", image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "This NFT was minted by Mesh (https://meshjs.dev/).", }; const policyId = resolveScriptHash(forgingScript); const tokenName = "MeshToken"; const tokenNameHex = stringToHex(tokenName); const metadata = { \[policyId\]: { \[tokenName\]: { ...demoAssetMetadata } } }; \`\`\` Finally, we create a transaction and mint the asset with the \`MeshTxBuilder\` lower level APIs. \`\`\`tsx const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .txIn(utxo.input.txHash, utxo.input.outputIndex) .mint("1", policyId, tokenName) .mintingScript(forgingScript) .changeAddress(changeAddress) .complete(); \`\`\` \### Mint Asset Mint an asset with a native script \`\`\`tsx import { MeshTxBuilder, ForgeScript, resolveScriptHash, stringToHex } from '@meshsdk/core'; import type { Asset } from '@meshsdk/core'; // See https://meshjs.dev/apis/wallets/meshwallet for how to create a new wallet instance const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const forgingScript = ForgeScript.withOneSignature(changeAddress); const demoAssetMetadata = { name: "Mesh Token", image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "This NFT was minted by Mesh (https://meshjs.dev/).", }; const policyId = resolveScriptHash(forgingScript); const tokenName = "MeshToken"; const tokenNameHex = stringToHex(tokenName); const metadata = { \[policyId\]: { \[tokenName\]: { ...demoAssetMetadata } } }; const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mint("1", policyId, tokenNameHex) .mintingScript(forgingScript) .metadataValue(721, metadata) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Minting Multiple Assets Minting multiple assets with a single transaction is a common operation in blockchain applications. Like minting single assets, you can mint multiple assets by calling \`mint()\` and \`mintingScript\` multiple times. \`\`\`tsx const metadata = {}; metadata\[policyId\] = {}; for (let i = 1; i < 3; i++) { const tokenName = \`MeshToken${i}\`; const tokenNameHex = stringToHex(tokenName); metadata\[policyId\]\[tokenName\] = { ...demoAssetMetadata, name: tokenName, }; txBuilder.mint("1", policyId, tokenNameHex); txBuilder.mintingScript(forgingScript); } \`\`\` You add the metadata object by calling the \`metadataValue()\` method. \`\`\`tsx const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .metadataValue(721, metadata) .changeAddress(changeAddress) .selectUtxosFrom(utxos); const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \### Mint Multiple Assets \\\[!toc\] Mint multiple assets with a single transaction \`\`\`tsx import { MeshTxBuilder, ForgeScript, resolveScriptHash, stringToHex } from '@meshsdk/core'; import type { Asset } from '@meshsdk/core'; import { useWallet } from "@meshsdk/react"; const { wallet, connected } = useWallet(); const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const forgingScript = ForgeScript.withOneSignature(changeAddress); const policyId = resolveScriptHash(forgingScript); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const metadata = {}; metadata\[policyId\] = {}; for (let i = 1; i < 3; i++) { const tokenName = \`MeshToken${i}\`; const tokenNameHex = stringToHex(tokenName); metadata\[policyId\]\[tokenName\] = { ...demoAssetMetadata, name: tokenName, }; txBuilder.mint("1", policyId, tokenNameHex); txBuilder.mintingScript(forgingScript); } txBuilder .metadataValue(721, metadata) .changeAddress(changeAddress) .selectUtxosFrom(utxos); const unsignedTx = await txBuilder.complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Burning assets Like minting assets, we need to define the \`forgingScript\` with \`ForgeScript\`. We use the first wallet address as the "minting address". Note that, assets can only be burned by its minting address. \`\`\`tsx const usedAddress = await wallet.getUsedAddresses(); const address = usedAddress\[0\]; const forgingScript = ForgeScript.withOneSignature(address); \`\`\` Then, we resolve the policy ID and hex of the token name by calling \`txBuilder.mint("-1", policyId, tokenNameHex)\` \`\`\`tsx const policyId = resolveScriptHash(forgingScript); const tokenNameHex = stringToHex("MeshToken"); \`\`\` Finally, we create a transaction and burn the asset with the lower level APIs. \`\`\`tsx const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mint("-1", policyId, tokenNameHex) .mintingScript(forgingScript) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); \`\`\` \### Burn Native Assets \\\[!toc\] Burn native assets \*\*Asset Unit\*\* \`d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e\` \`\`\`tsx import { ForgeScript, resolveScriptHash, stringToHex } from "@meshsdk/core"; import { useWallet } from "@meshsdk/react"; const { wallet, connected } = useWallet(); const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const forgingScript = ForgeScript.withOneSignature(changeAddress); const policyId = resolveScriptHash(forgingScript); const tokenNameHex = stringToHex("MeshToken"); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mint("-1", policyId, tokenNameHex) .mintingScript(forgingScript) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Minting Assets with Native Script The minting and burning examples above demonstrate using a one-signature native script. Here we explain the underlying logic for native script minting. With \`MeshTxBuilder\`, you just need to call \`.mint()\` and provide a script to mint or burn native script tokens: \`\`\`tsx txBuilder .mint("1", policyId, tokenNameHex) .mintingScript(forgingScript) \`\`\` On top of these two core steps, you can attach metadata with .metadataValue() and then construct the transaction as needed. \### Mint Assets with Native Script \\\[!toc\] Mint native assets with Native Script \`\`\`tsx const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const { pubKeyHash: keyHash } = deserializeAddress(changeAddress); const nativeScript: NativeScript = { type: "all", scripts: \[ { type: "before", slot: "99999999", }, { type: "sig", keyHash: keyHash, }, \], }; const forgingScript = ForgeScript.fromNativeScript(nativeScript); const policyId = resolveScriptHash(forgingScript); const tokenName = "MeshToken"; const tokenNameHex = stringToHex(tokenName); const metadata = { \[policyId\]: { \[tokenName\]: { ...demoAssetMetadata } } }; const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mint("1", policyId, tokenNameHex) .mintingScript(forgingScript) .metadataValue(721, metadata) .changeAddress(changeAddress) .invalidHereafter(99999999) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Minting Assets with Plutus Script Plutus script minting with \`MeshTxBuilder\` starts with any of the below script version indicators: \`\`\`tsx .mintPlutusScriptV1() .mintPlutusScriptV2() .mintPlutusScriptV3() \`\`\` Followed by specifying the minting information: \`\`\`tsx .mint(quantity: string, policy: string, name: string) \`\`\` Similar to unlocking, minting or burning tokens, the Plutus script requires providing a redeemer and the script itself. However, no datum information is needed in minting or burning. \*\*Providing a Script\*\* The actual script can be either provided through \`mintTxInReference\` method by attaching an on-chain UTxO reference, or by providing a Cbor encoded script. \* (i) Reference script \`\`\`tsx .mintTxInReference(txHash: string, txIndex: number) \`\`\` \* (ii) Supplying script \`\`\`tsx .mintingScript(scriptCbor: string) \`\`\` \*\*Minting Redeemer\*\* Redeemer can be provided in different \*\*data types\*\*. If your MeshTxBuilder does not include an \`evaluator\` instance, you can also provide your budget for the unlock with this redeemer endpoint \`\`\`tsx .mintRedeemerValue(redeemer: Data | object | string, type: "Mesh" | "CBOR" | "JSON", exUnits?: Budget) \`\`\` \### Mint Assets with Plutus Script \\\[!toc\] Mint native assets with Plutus Script. For this example, the Plutus script expects a data field of 'mesh'. \*\*Redeemer value:\*\* \`mesh\` \`\`\`tsx const utxos = await wallet.getUtxos(); const collateral: UTxO = (await wallet.getCollateral())\[0\]!; const changeAddress = await wallet.getChangeAddress(); const policyId = resolveScriptHash(demoPlutusMintingScript, "V2"); const tokenName = 'mesh'; const tokenNameHex = stringToHex(tokenName); const metadata = { \[policyId\]: { \[tokenName\]: { ...demoAssetMetadata } } }; const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mintPlutusScriptV2() .mint("1", policyId, tokenNameHex) .mintingScript(demoPlutusMintingScript) .mintRedeemerValue(mConStr0(\['mesh'\])) .metadataValue(721, metadata) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .txInCollateral( collateral.input.txHash, collateral.input.outputIndex, collateral.output.amount, collateral.output.address, ) .complete(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Minting Assets with CIP-68 Metadata standard Minting CIP-68 tokens with \`MeshTxBuilder\` means 2 consecutive sets of minting APIs. The first is to mint the token with the \`100\` label, and the second is to mint the token with the \`222\` label: \`\`\`tsx txBuilder .mintPlutusScriptV2() .mint("1", policyId, CIP68\_100(tokenNameHex)) .mintingScript(scriptCode) .mintRedeemerValue(mConStr0(\[\])) .mintPlutusScriptV2() .mint("1", policyId, CIP68\_222(tokenNameHex)) .mintingScript(scriptCode) .mintRedeemerValue(mConStr0(\[\])) \`\`\` A side note, Mesh also provides the utility function of \`CIP68\_100(tokenNameHex: string)\` and \`CIP68\_222(tokenNameHex: string)\` to help easily construct the token names as needed. So you dont have to memorize the prefix bytes to correctly mint the CIP68-compliant tokens. \### Mint Assets with CIP68 metadata standard \\\[!toc\] Mint assets with CIP68 metadata standard where two assets are issued, one referencing the other user token. \*\*Token Name:\*\* \`Test1\` \`\`\`tsx const usedAddress = await wallet.getUsedAddresses(); const address = usedAddress\[0\]; if (address === undefined) { throw "Address not found"; } const userTokenMetadata = { name: userInput, image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "Hello world - CIP68", }; const alawysSucceedPlutusScript: PlutusScript = { code: demoPlutusAlwaysSucceedScript, version: "V1", }; const { address: scriptAddress } = serializePlutusScript( alawysSucceedPlutusScript, ); const utxos = await wallet.getUtxos(); if (!utxos || utxos.length <= 0) { throw "No UTxOs found in wallet"; } const scriptCode = applyParamsToScript(oneTimeMintingPolicy, \[ mTxOutRef(utxos\[0\]?.input.txHash!, utxos\[0\]?.input.outputIndex!), \]); const collateral: UTxO = (await wallet.getCollateral())\[0\]!; const changeAddress = await wallet.getChangeAddress(); const policyId = resolveScriptHash(scriptCode, "V2"); const tokenName = 'Test1'; const tokenNameHex = stringToHex(tokenName); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .txIn( utxos\[0\]?.input.txHash!, utxos\[0\]?.input.outputIndex!, utxos\[0\]?.output.amount!, utxos\[0\]?.output.address!, ) .mintPlutusScriptV2() .mint("1", policyId, CIP68\_100(tokenNameHex)) .mintingScript(scriptCode) .mintRedeemerValue(mConStr0(\[\])) .mintPlutusScriptV2() .mint("1", policyId, CIP68\_222(tokenNameHex)) .mintingScript(scriptCode) .mintRedeemerValue(mConStr0(\[\])) .txOut(scriptAddress, \[ { unit: policyId + CIP68\_100(tokenNameHex), quantity: "1" }, \]) .txOutInlineDatumValue(metadataToCip68(userTokenMetadata)) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .txInCollateral( collateral.input.txHash, collateral.input.outputIndex, collateral.output.amount, collateral.output.address, ) .complete(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Minting Royalty Token Royalty tokens are a special type of token that allow the creator to collect a royalty fee. This proposed standard will allow for uniform royalty distributions across the secondary market space. Read CIP-27 for more information. The implementation of royalty tokens is very simple – minting a token with the \`777\` label, with "rate", and "addr" in the metadata. Here is the example of the metadata: \`\`\`tsx const assetMetadata = { rate: '0.2', addr: 'addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr' }; \`\`\` \### Mint Native Assets \\\[!toc\] Mint native assets with ForgeScript \*\*Rate:\*\* \`0.2\` \*\*Address:\*\* \`addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr\` \`\`\`tsx const utxos = await wallet.getUtxos(); const usedAddress = await wallet.getUsedAddresses(); const address = usedAddress\[0\]; if (address === undefined) { throw "No address found"; } const forgingScript = ForgeScript.withOneSignature(address); const policyId = resolveScriptHash(forgingScript); const assetMetadata: RoyaltiesStandard = { rate: '0.2', address: 'addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', }; const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mint("1", policyId, "") .mintingScript(forgingScript) .metadataValue(777, assetMetadata) .changeAddress(address) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \# Smart Contracts URL: /apis/txbuilder/smart-contracts Transactions to work with smart contracts \*\*\* title: "Smart Contracts" description: "Transactions to work with smart contracts" icon: NewspaperIcon ------------------- import Link from "fumadocs-core/link"; In this guide, you will understand how to interact with smart contracts through \`MeshTxBuilder\`. In the code snippet, you will find \`txBuilder\`, which is an instance of \`MeshTxBuilder\`, with powerful low-level APIs that allow you to build transactions. Here's how to initialize \*\*MeshTxBuilder\*\*. \`\`\`tsx const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); \`\`\` In Cardano, whenever you need the nodes' computing power to execute a smart contract, you need to provide collateral to prevent spamming. You will see this is everywhere when script execution is needed in examples below, and here's how you can do so: \`\`\`tsx txBuilder .txInCollateral(txHash: string, txIndex: number, amount?: Asset\[\], address?: string) \`\`\` ## Lock Assets Locking assets meaning sending value to a script address with datum. Same as the \`Transaction\` demo, we will lock selected assets from your wallet in an always-succeed smart contract. We use one API to represent sending value, another API to represent attaching datum to complete the locking assets process: \`\`\`tsx // For inline datumtxBuilder .txOut(address, assets) .txOutInlineDatumValue(data) \`\`\` \`\`\`tsx // For datum hashtxBuilder .txOut(address, assets) .txOutDatumHashValue(data) \`\`\` The lower level APIs support providing your datum in all Mesh \`Data\` (default), JSON and CBOR representations. For details and helper utilities, please check Data section. \`\`\`tsx // For inline datum provided in JSONtxBuilder .txOut(address, assets) .txOutInlineDatumValue(jsonData, "JSON") \`\`\` \### Lock Assets \\\[!toc\] Lock assets in a Plutus script \*\*Asset unit\*\* \`d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e\` \*\*Datum:\*\* \`meshsecretcode\` \`\`\`tsx const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const script: PlutusScript = { code: demoPlutusAlwaysSucceedScript, version: "V2", }; const { address: scriptAddress } = serializePlutusScript(script); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .txOut(scriptAddress, \[{ unit: "d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e", quantity: "1" }\]) .txOutInlineDatumValue("meshsecretcode") .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Unlock Assets Unlocking assets from a Plutus script, with \`MeshTxBuilder\`, starts with any of the following script version indicators: \`\`\`tsx .spendingPlutusScriptV1() .spendingPlutusScriptV2() .spendingPlutusScriptV3() \`\`\` Followed by specifying the exact script input to spend with: \`\`\`tsx .txIn(txHash: string, txIndex: number, amount?: Asset\[\], address?: string) \`\`\` In Cardano, if you want to unlock assets from a script address, you have to provide 3 other necessary information apart from \`.txIn()\` itself. They are: \* Actual script \* Datum of the input \* Redeemer of the unlock \*\*Actual script\*\* The actual script can be either provided by transaction builder or referenced from an UTxO onchain. \* (i) Reference script \`\`\`tsx .spendingTxInReference() \`\`\` \* (ii) Supplying script \`\`\`tsx .txInScript(scriptCbor: string) \`\`\` \*\*Datum of the input\*\* Similar to script, datum can also either be provided by transaction builder or as inline datum. \* (i) Referencing inline datum \`\`\`tsx .txInInlineDatumPresent() \`\`\` \* (ii) Supplying datum \`\`\`tsx .txInDatumValue(datum: Data | object | string, type?: "Mesh" | "CBOR" | "JSON") \`\`\` \*\*Redeemer of the unlock\*\* Redeemer can be provided in different data types. If your MeshTxBuilder does not include an \`evaluator\` instance, you can also provide your budget for the unlock with this redeemer endpoint \`\`\`tsx .txInRedeemerValue(redeemer: Data | object | string, type: "Mesh" | "CBOR" | "JSON", exUnits?: Budget) \`\`\` An example of complete set of endpoints to unlock assets from a script address: \`\`\`tsx const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); txBuilder .spendingPlutusScriptV2() .txIn(txHash: string, txIndex: number, amount?: Asset\[\], address?: string) .txInInlineDatumPresent() // or .txInDatumValue(datum: Data | string | object) .txInRedeemerValue(redeemer: Data | object | string, type?: string, exUnits?: Budget) .spendingTxInReference(txHash: string, txIndex: number, spendingScriptHash?: string) // or supplying script \`\`\` \### Unlock Assets \\\[!toc\] Unlock assets in a Plutus script \*\*Asset unit\*\* \`d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e\` \*\*Datum:\*\* \`meshsecretcode\` \`\`\`tsx const utxos = await wallet.getUtxos(); const collateral = await wallet.getCollateral(); const changeAddress = await wallet.getChangeAddress(); const script: PlutusScript = { code: demoPlutusAlwaysSucceedScript, version: "V2", }; const { address: scriptAddress } = serializePlutusScript(script); const assetUtxo = await fetchAssetUtxo({ address: scriptAddress, asset: userInput, datum: userInput2, }); if (assetUtxo === undefined) { throw "Asset UTXO not found"; } const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .spendingPlutusScriptV2() .txIn(assetUtxo.input.txHash, assetUtxo.input.outputIndex) .txInInlineDatumPresent() .txInRedeemerValue(mConStr0(\[\])) .txInScript(demoPlutusAlwaysSucceedScript) .changeAddress(changeAddress) .txInCollateral( collateral\[0\]?.input.txHash!, collateral\[0\]?.input.outputIndex!, collateral\[0\]?.output.amount!, collateral\[0\]?.output.address!, ) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Minting Assets with Plutus Script Minting Plutus tokens with \`MeshTxBuilder\` starts with any of the following script version indicators: \`\`\`tsx .mintPlutusScriptV1() .mintPlutusScriptV2() .mintPlutusScriptV3() \`\`\` Followed by specifying the minting information: \`\`\`tsx .mint(quantity: string, policy: string, name: string) \`\`\` Similar to unlocking assets, minting or burning Plutus tokens require providing redeemer and scripts. However, no datum information is needed in minting or burning. \*\*Script of the token\*\* The actual script can be either provided by transaction builder or referenced from an UTxO onchain. \* (i) Reference script \`\`\`tsx .mintTxInReference(txHash: string, txIndex: number) \`\`\` \* (ii) Supplying script \`\`\`tsx .mintingScript(scriptCbor: string) \`\`\` \*\*Redeemer of the mint\*\* Redeemer can be provided in different data types. If your MeshTxBuilder does not include an \`evaluator\` instance, you can also provide your budget for the unlock with this redeemer endpoint \`\`\`tsx .mintRedeemerValue(redeemer: Data | object | string, type: "Mesh" | "CBOR" | "JSON", exUnits?: Budget) \`\`\` \### Mint Assets with Plutus Script \\\[!toc\] Mint native assets with Plutus Script. For this example, the Plutus script expects a data field of 'mesh'. \*\*Redeemer value:\*\* \`mesh\` \`\`\`tsx const utxos = await wallet.getUtxos(); const collateral: UTxO = (await wallet.getCollateral())\[0\]!; const changeAddress = await wallet.getChangeAddress(); const policyId = resolveScriptHash(demoPlutusMintingScript, "V2"); const tokenName = 'mesh'; const tokenNameHex = stringToHex(tokenName); const metadata = { \[policyId\]: { \[tokenName\]: { ...demoAssetMetadata } } }; const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .mintPlutusScriptV2() .mint("1", policyId, tokenNameHex) .mintingScript(demoPlutusMintingScript) .mintRedeemerValue(mConStr0(\['mesh'\])) .metadataValue(721, metadata) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .txInCollateral( collateral.input.txHash, collateral.input.outputIndex, collateral.output.amount, collateral.output.address, ) .complete(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Send Reference Scripts Onchain For all smart contract executions, you have option to provide script as referencing onchain. To do so, you must send the script onchain first. You can attach the script like attaching datum to a output with this: \`\`\`tsx .txOutReferenceScript(scriptCbor: string, version?: LanguageVersion) \`\`\` \### Send Reference Script \\\[!toc\] Provide script as referencing onchain \`\`\`tsx const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .txOut("addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr", \[\]) .txOutReferenceScript("4e4d01000033222220051200120011", "V2") .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \# Staking Transactions URL: /apis/txbuilder/staking Transactions for delegating ADA and managing stakepools \*\*\* title: "Staking Transactions" description: "Transactions for delegating ADA and managing stakepools" icon: ArrowsPointingInIcon -------------------------- In the code snippet, you will find \`txBuilder\`, which is an instance of \`MeshTxBuilder\`, with powerful low-level APIs that allow you to build transactions. Here's how to initialize \*\*MeshTxBuilder\*\*. \`\`\`tsx const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); \`\`\` ## Register Stake Address Same as Transaction, with \`MeshTxBuilder\`, you have to register a stake address before delegating to stakepools. Here are the 2 APIs you need: \`\`\`tsx txBuilder .registerStakeCertificate(rewardAddress) .delegateStakeCertificate(rewardAddress, poolIdHash) \`\`\` Since we need to provide the deserialize hash of pool ID, we can use the following util to get it: \`\`\`tsx const poolIdHash = deserializePoolId( "pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx", ); \`\`\` \### Register Stake Address \\\[!toc\] Register a stake address before delegating to a stakepool. \*\*Pool ID\*\* \`pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx\` \`\`\`tsx const utxos = await wallet.getUtxos(); const address = await wallet.getChangeAddress(); const addresses = await wallet.getRewardAddresses(); const rewardAddress = addresses\[0\]!; const poolIdHash = deserializePoolId("pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx"); if (rewardAddress === undefined) { throw "No address found"; } const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .registerStakeCertificate(rewardAddress) .delegateStakeCertificate(rewardAddress, poolIdHash) .selectUtxosFrom(utxos) .changeAddress(address) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Delegate Stake Stake delegation with \`MeshTxBuilder\` is the same as the first delegate, but without registering the stake key, so only one API call is needed: \`\`\`tsx txBuilder .delegateStakeCertificate(rewardAddress, poolIdHash) \`\`\` \### Delegate Stake \\\[!toc\] Delegate stake to a stake pool \*\*Pool ID\*\* \`pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx\` \`\`\`tsx const utxos = await wallet.getUtxos(); const address = await wallet.getChangeAddress(); const addresses = await wallet.getRewardAddresses(); const rewardAddress = addresses\[0\]!; const poolIdHash = deserializePoolId("pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx"); if (rewardAddress === undefined) { throw "No address found"; } const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .delegateStakeCertificate(rewardAddress, poolIdHash) .selectUtxosFrom(utxos) .changeAddress(address) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Withdraw Rewards Use MeshTxBuilder’s withdrawal method to specify the reward address and amount. \* rewardAddress (string) - the reward address to withdraw from \* lovelace (number) - the amount to withdraw in Lovelace \`\`\`tsx txBuilder .withdrawal(rewardAddress, lovelace) \`\`\` \### Withdraw Rewards \\\[!toc\] Withdraw staking rewards. \*\*Amount in lovelace:\*\* \`1000000\` \`\`\`tsx const utxos = await wallet.getUtxos(); const address = await wallet.getChangeAddress(); const addresses = await wallet.getRewardAddresses(); const rewardAddress = addresses\[0\]!; if (rewardAddress === undefined) { throw "No address found"; } const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .withdrawal(rewardAddress, "1000000") .selectUtxosFrom(utxos) .changeAddress(address) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Deregister Stake To deregister a stake address with MeshTxBuilder, use the following method: \* rewardAddress (string) - the bech32 reward address to deregister \`\`\`tsx txBuilder .deregisterStakeCertificate(rewardAddress: string) \`\`\` \### Deregister Stake \\\[!toc\] Deregister a stake address. \`\`\`tsx const utxos = await wallet.getUtxos(); const address = await wallet.getChangeAddress(); const addresses = await wallet.getRewardAddresses(); const rewardAddress = addresses\[0\]!; if (rewardAddress === undefined) { throw "No address found"; } const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .deregisterStakeCertificate(rewardAddress) .selectUtxosFrom(utxos) .changeAddress(address) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` \## Script Withdrawal - Supporting Withdraw Zero Withdrawal from a script is supported by \`MeshTxBuilder\` with this set of APIs: \`\`\`tsx txBuilder .withdrawalPlutusScriptV2() .withdrawal(rewardAddress, withdrawalAmount) .withdrawalScript(stakeScriptCbor) .withdrawalRedeemerValue(redeemer) \`\`\` \*\*Withdraw Zero\*\* This is a technique commonly used on Cardano to prove control of a stake key without actually withdrawing any rewards from its withdrawal account. To perform a "withdraw zero", you have to follow these steps: \* Register script stake key \`\`\`tsx txBuilder .registerStakeCertificate(stakeScriptHash) \`\`\` \* Withdraw Zero \`\`\`tsx txBuilder .withdrawalPlutusScriptV2() .withdrawal(rewardAddress, "0") .withdrawalScript(stakeScriptCbor) .withdrawalRedeemerValue(redeemer) \`\`\` \### Register Script Stake Key \\\[!toc\] One off setup before triggering withdraw zero \`\`\`tsx const utxos = await wallet.getUtxos(); const address = await wallet.getChangeAddress(); const txBuilder = getTxBuilder(); const stakeScriptCbor = alwaysSucceedMintingStakingScriptCbor( deserializeAddress(address).pubKeyHash, ); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .registerStakeCertificate(resolveScriptHash(stakeScriptCbor, "V2")) .selectUtxosFrom(utxos) .changeAddress(address) .complete(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` \### Withdraw Zero \\\[!toc\] Actual withdrawal of zero to trigger script validation \`\`\`tsx const utxos = await wallet.getUtxos(); const collateral = await wallet.getCollateral(); const address = await wallet.getChangeAddress(); const stakeScriptCbor = alwaysSucceedMintingStakingScriptCbor( deserializeAddress(address).pubKeyHash, ); const rewardAddress = serializeRewardAddress( resolveScriptHash(stakeScriptCbor, "V2"), true, 0, ); const txBuilder = new MeshTxBuilder({ fetcher: provider, // get a provider https://meshjs.dev/providers verbose: true, }); const unsignedTx = await txBuilder .withdrawalPlutusScriptV2() .withdrawal(rewardAddress, "0") .withdrawalScript(stakeScriptCbor) .withdrawalRedeemerValue("") .selectUtxosFrom(utxos) .changeAddress(address) .txInCollateral(...utxoToTxIn(collateral\[0\]!)) .complete(); const signedTx = await wallet.signTx(unsignedTx, true); const txHash = await wallet.submitTx(signedTx); \`\`\` \# Parser Basics URL: /apis/txparser/basics Parse transactions and rebuild \*\*\* title: "Parser Basics" description: "Parse transactions and rebuild" icon: PaperAirplaneIcon ----------------------- import Link from "fumadocs-core/link"; The \`TxParser\` is a tool where you can parse the typical transaction CBOR hex back into the \`MeshTxBuilderBody\`. With such capability, you can proceed with rebuilding a transaction or examing the with unit testing frameworks. In this page, we will cover how to initialize the \`TxParser\`. ## Initialize Tx Parser To start parsing transaction, you need to first initialize \`TxParser\`: \`\`\`tsx import { BlockfrostProvider, TxParser } from "@meshsdk/core"; import { CSLSerializer } from "@meshsdk/core-csl"; const fetcher = new BlockfrostProvider(''); const serializer = new CSLSerializer(); const txParser = new TxParser(serializer, fetcher); \`\`\` There are 2 fields to pass in to initialized \`TxParser\`: 1. \`serializer\`: The serializer instance that will be used for parsing transaction 2. \`fetcher\` (optional): \`TxParser\` requires all input \`UTxO\` information provided since the transaction CBOR hex only preserves transaction hash and output index. When you are not providing all input \`UTxO\` information, the \`fetcher\` instance is used to fetch the missing \`UTxO\` ## Rebuild Transaction To parse a transaction, you only need: \`\`\`tsx const txBuilderBody = await txParser.parse(txHex, utxos); \`\`\` With the parsed \`txBuilderBody\` in type \`MeshTxBuilderBody\`, you can proceed with adding / removing elements and rebuilding the transaction. There are 2 necessary fields to pass in: 1. \`txHex\`: The transaction CBOR to be parsed 2. \`providedUtxos\`: The input information, for all inputs, reference inputs, and collateral. You can either construct it manually or obtain it from \`fetcher\`. ## Unit Testing Transaction To unit test a transaction, you can parse the transaction and then convert the instance to \`TxTester\`: \`\`\`tsx await txParser.parse(txHex, utxos); const txTester = txParser.toTester(); \`\`\` The detailed testing APIs can be found in the documentation. # Transaction Parser URL: /apis/txparser Parse transactions for testing and rebuilding \*\*\* title: "Transaction Parser" description: "Parse transactions for testing and rebuilding" icon: MagnifyingGlassIcon ------------------------- import {linksTxParser} from "@/data/links-txparser"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksTxParser.map((card) => ( {card.title} {card.desc} ))} \# Unit Testing Transaction URL: /apis/txparser/txtester Parse and test transactions with various options \*\*\* title: "Unit Testing Transaction" description: "Parse and test transactions with various options" icon: ShieldCheckIcon --------------------- The \`TxParser\` is a tool where you can parse the typical transaction CBOR hex back into the \`MeshTxBuilderBody\`. With such capability, you can proceed with rebuilding a transaction or examing the with unit testing frameworks. In this page, we will cover how to initialize the \`TxParser\`. ## Initialize Tx Parser To start parsing transaction, you need to first initialize \`TxParser\`: \`\`\`tsx import { BlockfrostProvider, TxParser } from "@meshsdk/core"; import { CSLSerializer } from "@meshsdk/core-csl"; const fetcher = new BlockfrostProvider(''); const serializer = new CSLSerializer(); const txParser = new TxParser(serializer, fetcher); \`\`\` There are 2 fields to pass in to initialized \`TxParser\`: 1. \`serializer\`: The serializer instance that will be used for parsing transaction 2. \`fetcher\` (optional): \`TxParser\` requires all input \`UTxO\` information provided since the transaction CBOR hex only preserves transaction hash and output index. When you are not providing all input \`UTxO\` information, the \`fetcher\` instance is used to fetch the missing \`UTxO\` ## Interpret Result After performing the tests, you can interpret the results of the tests using the \`success\` and \`errors\` methods. \`\`\`tsx const result = txTester.success(); console.log("Errors:", txTester.errors()); \`\`\` 1. \`success\`: Return a boolean indicating if all tests are passed 2. \`errors\`: Show all the errors that occurred during the tests . If there are no errors, it will return an empty string. ## Testing Inputs Testing inputs starts with locating the inputs you want to test. The filtering will not reset until the filtering methods are called again. \`\`\`tsx txTester .inputsAt( "addr\_test1qrs3jlcsapdufgagzt35ug3nncwl26mlkcux49gs673sflmrjfm6y2eu7del3pprckzt4jaal9s7w9gq5kguqs5pf6fq542mmq", ) .inputsValue( MeshValue.fromAssets(\[{ unit: "lovelace", quantity: "10000000000" }\]), ) \`\`\` There are multiple methods available to filter the inputs: 1. \`allInputs\`: not apply filters 2. \`inputsAt\`: filtering inputs with address 3. \`inputsWith\`: filtering inputs with token 4. \`inputsWithPolicy\`: filtering inputs with policy id 5. \`inputsAtWith\`: filtering inputs with address and token 6. \`inputsAtWithPolicy\`: filtering inputs with address and policy id After applying filters, you can proceed with checking value: 1. \`inputsValue\`: Check the total value of the filtered inputs ## Testing Outputs Testing outputs starts with locating the outputs you want to test. The filtering will not reset until the filtering methods are called again. \`\`\`tsx txTester .outputsAt( "addr\_test1qrs3jlcsapdufgagzt35ug3nncwl26mlkcux49gs673sflmrjfm6y2eu7del3pprckzt4jaal9s7w9gq5kguqs5pf6fq542mmq", ) .outputsValue( MeshValue.fromAssets(\[{ unit: "lovelace", quantity: "10000000000" }\]), ) .outputsInlineDatumExist(datumCbor); \`\`\` There are multiple methods available to filter the outputs: 1. \`allOutputs\`: not apply filters 2. \`outputsAt\`: filtering outputs with address 3. \`outputsWith\`: filtering outputs with token 4. \`outputsWithPolicy\`: filtering outputs with policy id 5. \`outputsAtWith\`: filtering outputs with address and token 6. \`outputsAtWithPolicy\`: filtering outputs with address and policy id After applying filters, you can proceed with checking value: 1. \`outputsValue\`: Check the total value of the filtered outputs 2. \`outputsInlineDatumExist\`: Check whether any one of the outputs contains inline datum (provided as CBOR) ## Testing Mints Testing mints with below APIs: \`\`\`tsx txTester .tokenMinted( "eab3a1d125a3bf4cd941a6a0b5d7752af96fae7f5bcc641e8a0b6762", "", 1, ); \`\`\` 1. \`tokenMinted\`: Checks if a specific token is minted in the transaction. 2. \`onlyTokenMinted\`: Checks if a specific token is minted in the transaction and that it is the only mint. 3. \`policyOnlyMintedToken\`: Checks if a specific token is minted in the transaction, ensuring that it is the only mint for the given policy ID. 4. \`checkPolicyOnlyBurn\`: Checks if a specific policy ID is burned in the transaction, ensuring that it is the only minting (i.e. burning item). ## Testing Time Testing time with below APIs: \`\`\`tsx txTester .validBefore(beforeTimestamp) .validAfter(afterTimestamp); \`\`\` 1. \`validAfter\`: Checks if the transaction is valid after a specified timestamp. 2. \`validBefore\`: Checks if the transaction is valid before a specified timestamp. ## Testing Signature Testing time with below APIs: \`\`\`tsx txTester .keySigned("fa5136e9e9ecbc9071da73eeb6c9a4ff73cbf436105cf8380d1c525c"); \`\`\` 1. \`keySigned\`: Checks if a specific key is signed in the transaction. 2. \`oneOfKeysSigned\`: Checks if any one of the specified keys is signed in the transaction. 3. \`allKeysSigned\`: Checks if all specified keys are signed in the transaction. # Blueprints URL: /apis/utilities/blueprints Blueprints for script with either apply parameters or no parameters \*\*\* title: "Blueprints" description: "Blueprints for script with either apply parameters or no parameters" icon: DocumentTextIcon ---------------------- import Link from "fumadocs-core/link"; In Mesh, we have in built \`Blueprint\` utility classes to help manipulating serialization and deserialization logic around Cardano smart contracts / validators. Now it is supporting the basic use case around 3 purposes - \`Spending\`,\`Minting\` and \`Withdrawal\`. You can either directly use the \`Blueprint\` utility classes imported from Mesh, or use the Cardano Bar from SIDAN Lab, which perform a comprehensive parsing of the CIP57 blueprint object into Mesh's type. ## Spending Script Blueprint \`SpendingBlueprint\` is a class for handling spending blueprint particularly. You can provide \`plutusVersion\`, \`networkId\` and the potential \`stakeKeyHash\` for the spending validator address to initialized the class. After that, providing the \`compiledCode\` and parameters to finish the setup. The class then provide easy access to common script information: \* Script Hash \* Script Cbor \* Script Address A Spending validator with no parameter, allows to provides only the \`compiledCode\` instead. \### Spending Script Blueprint - Apply parameter to script \\\[!toc\] Creates a spending script blueprint with apply parameter to script. \`\`\`tsx import { SpendingBlueprint } from "@meshsdk/core"; const demoCompiledCode = "5906f401010032323232323232223225333005323232323253323300b3001300c37540042646464646464a66602260060022a66602860266ea8024540085854ccc044c01c00454ccc050c04cdd50048a8010b0b18089baa0081533300f30013010375400426464a64666024600860266ea80284c94ccc04cc014c050dd50008991919191919191919299980e1929998100008a5015333020302300114a22940cc88c8cc00400400c894ccc08c00452f5c026464a66604466ebcc048c090dd5180718121baa002005133026002330040040011330040040013027002302500137586018603c6ea8058c030c078dd51804180f1baa0091533301c001100214a02940cc00ccc008dd61802180e9baa01501a30063370666e08dd69803980e9baa00c018482827004cc008cc004dd61801980e1baa014300a301c3754016600a66e00dd69803180e1baa00b3330043756600c60386ea8c018c070dd5003a450048810022323300100100322533302000114bd6f7b63009991299980f99baf300f3021375400400a2646660020020046eacc030c088dd50019112999812801080089919980200218148019991191980080080291299981500089981599bb037520086e9800d2f5bded8c0264646464a66605666e400200084cc0bccdd81ba9008374c00e00a2a66605666e3c0200084c94ccc0b0c078c0b4dd500089981819bb037520126062605c6ea80040104010c94ccc0b14ccc0bc0045288a5014c0103d87a80001301b33030374c00297ae03233300100100800222253330310021001132333004004303500333223233001001005225333036001133037337606ea4010dd4001a5eb7bdb1804c8c8c8c94ccc0dccdc800400109981d99bb037520106ea001c01454ccc0dccdc7804001099299981c1815181c9baa00113303c337606ea4024c0f4c0e8dd5000802080219299981c18150008a60103d87a8000130273303c375000297ae03370000e00226607666ec0dd48011ba800133006006003375a60700066eb8c0d8008c0e8008c0e0004dd718180009bad3031001303300213302f337606ea4008dd3000998030030019bab302c003375c6054004605c00460580026eb8c090004dd5981280098138010800981100099801001181180091191980080099198008008019129998100008a5eb804c8ccc888c8cc00400400c894ccc098004400c4c8cc0a0dd3998141ba90063302830250013302830260014bd7019801801981500118140009bae301f00137566040002660060066048004604400244a66603e00229444c94ccc074c8cdc49bad3007001333008006375c601c0026eb8c028004dd618110010998018018008a5030220012301d301e301e00122232533301a3010301b37540022900009bad301f301c375400264a666034602060366ea8004530103d87a80001323300100137566040603a6ea8008894ccc07c004530103d87a80001323232325333020337220100042a66604066e3c0200084c03ccc090dd4000a5eb80530103d87a8000133006006003375a60420066eb8c07c008c08c008c084004c8cc004004010894ccc0780045300103d87a8000132323232533301f337220100042a66603e66e3c0200084c038cc08cdd3000a5eb80530103d87a8000133006006003375660400066eb8c078008c088008c08000494ccc058c02000452f5bded8c0264646600200297adef6c6022533301c00113301d337609801014000374c00697adef6c60132323232533301d33720910100002133021337609801014000374c00e00a2a66603a66e3d22100002133021337609801014000374c00e00626604266ec0dd48011ba6001330060060033756603c0066eb8c070008c080008c078004c8cc0040052f5bded8c044a66603600226603866ec13001014000375000697adef6c60132323232533301c33720910100002133020337609801014000375000e00a2a66603866e3d22100002133020337609801014000375000e00626604066ec0dd48011ba800133006006003375a603a0066eb8c06c008c07c008c0740048c068c06c004c060c054dd50008b19198008009bac30033015375401a44a66602e002298103d87a80001323253330163375e600c60306ea80080284c014cc0680092f5c026600800800260360046032002264a666026600a60286ea80044cc88c8cc00400400c894ccc068004528099299980c19b8f375c603a00400829444cc00c00c004c074004dd6180c180c980c980c980c980c980c980c980c980a9baa00d375c6030602a6ea800458c94ccc04cc014c050dd5000898011980b980c180a9baa0014bd700a60103d87a8000300230143754600460286ea800cdd2a40004602c002602860226ea800858dc3a4000602460260046022002601a6ea8008dc3a40042c601c601e004601a002601a0046016002600e6ea800452613656375a002ae6955ceaab9e5573eae815d0aba201"; // provide your staking part for the compiled address const stakeHash = "9e8a6e5fcbbb5b84deefc71d7cb6319a3da9cc3d19765efb303647ef"; const blueprint = new SpendingBlueprint("V2", 0, stakeHash); blueprint.paramScript( demoCompiledCode, mPubKeyAddress("aa048e4cc8a1e67e1d97ffbd4be614388014cbc2b2451527202943b6", "9d4dcd7e454d2434164f4efb8edeb358d86a1dad9ec6224cfcbce3e6")\], "Mesh" // Mesh data type ); const scriptHash = blueprint.hash; const scriptCbor = blueprint.cbor; const scriptAddress = blueprint.address; \`\`\` \### Spending Script blueprint - no parameter to script \\\[!toc\] Creates a spending script blueprint with no parameter to script. \`\`\`tsx const blueprint = new SpendingBlueprint("V2", 0 , stakeHash); blueprint.noParamScript(demoCompiledCode); const scriptHash = blueprint.hash; const scriptCbor = blueprint.cbor; const scriptAddress = bluePrint.address; ; \`\`\` \## Minting Script Blueprint \`MintingBlueprint\` is a class for handling minting blueprint particularly. You can provide \`plutusVersion\`, for the minting validator to initialize the class. After that, providing the \`compiledCode\` and parameters to finish the setup. The class then provide easy access to common script information: \* Policy ID (i.e Script Hash) \* Script Cbor A Minting validator with no parameter, allows to provides only the \`compiledCode\` instead. \### Minting Script Blueprint - Apply parameter to script \\\[!toc\] Creates a Minting script blueprint with apply parameter to script. \`\`\`tsx const demoCompiledCode = "5906f401010032323232323232223225333005323232323253323300b3001300c37540042646464646464a66602260060022a66602860266ea8024540085854ccc044c01c00454ccc050c04cdd50048a8010b0b18089baa0081533300f30013010375400426464a64666024600860266ea80284c94ccc04cc014c050dd50008991919191919191919299980e1929998100008a5015333020302300114a22940cc88c8cc00400400c894ccc08c00452f5c026464a66604466ebcc048c090dd5180718121baa002005133026002330040040011330040040013027002302500137586018603c6ea8058c030c078dd51804180f1baa0091533301c001100214a02940cc00ccc008dd61802180e9baa01501a30063370666e08dd69803980e9baa00c018482827004cc008cc004dd61801980e1baa014300a301c3754016600a66e00dd69803180e1baa00b3330043756600c60386ea8c018c070dd5003a450048810022323300100100322533302000114bd6f7b63009991299980f99baf300f3021375400400a2646660020020046eacc030c088dd50019112999812801080089919980200218148019991191980080080291299981500089981599bb037520086e9800d2f5bded8c0264646464a66605666e400200084cc0bccdd81ba9008374c00e00a2a66605666e3c0200084c94ccc0b0c078c0b4dd500089981819bb037520126062605c6ea80040104010c94ccc0b14ccc0bc0045288a5014c0103d87a80001301b33030374c00297ae03233300100100800222253330310021001132333004004303500333223233001001005225333036001133037337606ea4010dd4001a5eb7bdb1804c8c8c8c94ccc0dccdc800400109981d99bb037520106ea001c01454ccc0dccdc7804001099299981c1815181c9baa00113303c337606ea4024c0f4c0e8dd5000802080219299981c18150008a60103d87a8000130273303c375000297ae03370000e00226607666ec0dd48011ba800133006006003375a60700066eb8c0d8008c0e8008c0e0004dd718180009bad3031001303300213302f337606ea4008dd3000998030030019bab302c003375c6054004605c00460580026eb8c090004dd5981280098138010800981100099801001181180091191980080099198008008019129998100008a5eb804c8ccc888c8cc00400400c894ccc098004400c4c8cc0a0dd3998141ba90063302830250013302830260014bd7019801801981500118140009bae301f00137566040002660060066048004604400244a66603e00229444c94ccc074c8cdc49bad3007001333008006375c601c0026eb8c028004dd618110010998018018008a5030220012301d301e301e00122232533301a3010301b37540022900009bad301f301c375400264a666034602060366ea8004530103d87a80001323300100137566040603a6ea8008894ccc07c004530103d87a80001323232325333020337220100042a66604066e3c0200084c03ccc090dd4000a5eb80530103d87a8000133006006003375a60420066eb8c07c008c08c008c084004c8cc004004010894ccc0780045300103d87a8000132323232533301f337220100042a66603e66e3c0200084c038cc08cdd3000a5eb80530103d87a8000133006006003375660400066eb8c078008c088008c08000494ccc058c02000452f5bded8c0264646600200297adef6c6022533301c00113301d337609801014000374c00697adef6c60132323232533301d33720910100002133021337609801014000374c00e00a2a66603a66e3d22100002133021337609801014000374c00e00626604266ec0dd48011ba6001330060060033756603c0066eb8c070008c080008c078004c8cc0040052f5bded8c044a66603600226603866ec13001014000375000697adef6c60132323232533301c33720910100002133020337609801014000375000e00a2a66603866e3d22100002133020337609801014000375000e00626604066ec0dd48011ba800133006006003375a603a0066eb8c06c008c07c008c0740048c068c06c004c060c054dd50008b19198008009bac30033015375401a44a66602e002298103d87a80001323253330163375e600c60306ea80080284c014cc0680092f5c026600800800260360046032002264a666026600a60286ea80044cc88c8cc00400400c894ccc068004528099299980c19b8f375c603a00400829444cc00c00c004c074004dd6180c180c980c980c980c980c980c980c980c980a9baa00d375c6030602a6ea800458c94ccc04cc014c050dd5000898011980b980c180a9baa0014bd700a60103d87a8000300230143754600460286ea800cdd2a40004602c002602860226ea800858dc3a4000602460260046022002601a6ea8008dc3a40042c601c601e004601a002601a0046016002600e6ea800452613656375a002ae6955ceaab9e5573eae815d0aba201"; const blueprint = new MintingBlueprint("V2"); blueprint.paramScript( demoCompiledCode, \[mPubKeyAddress('aa048e4cc8a1e67e1d97ffbd4be614388014cbc2b2451527202943b6' , '9d4dcd7e454d2434164f4efb8edeb358d86a1dad9ec6224cfcbce3e6'), 100\], "Mesh"// Mesh data type ); const policyId = blueprint.hash; const scriptCbor = blueprint.cbor \`\`\` \### Minting Script blueprint - no parameter to script \\\[!toc\] Creates a Minting script blueprint with no parameter to script. \`\`\`tsx const blueprint = new MintingBlueprint("V2"); blueprint.noParamScript(demoCompiledCode); const policyId = bluePrint.hash const scriptCbor = bluePrint.cbor \`\`\` \## Withdrawal Script Blueprint \`WithdrawalBlueprint\` is a class for handling withdrawal blueprint particularly. You can provide \`plutusVersion\`, and \`networkId\` for the withdrawal validator to initialize the class. After that, providing the \`compiledCode\` and parameters to finish the setup. The class then provide easy access to common script information: \* Script Hash \* Script Cbor \* Reward Address A withdrawal validator with no parameter, allows to provides only the \`compiledCode\` instead. \### Withdrawal Script Blueprint - Apply parameter to script \\\[!toc\] Creates a withdrawal script blueprint with apply parameter to script. \`\`\`tsx import { WithdrawalBlueprint } from "@meshsdk/core"; const blueprint = new WithdrawalBlueprint("V2", 0); blueprint.paramScript( demoCompiledCode, mPubKeyAddress('aa048e4cc8a1e67e1d97ffbd4be614388014cbc2b2451527202943b6', '9d4dcd7e454d2434164f4efb8edeb358d86a1dad9ec6224cfcbce3e6'), 100\], "Mesh", // Mesh Data type ) const scripthash = blueprint.hash; const scriptCbor = blueprint.cbor; const rewardAddress = blueprint.address; \`\`\` \### Withdrawal Script blueprint - No parameter to script \\\[!toc\] Creates a withdrawal script blueprint with no parameter to script \`\`\`tsx const blueprint = new WithdrawalBlueprint("V2" ,0); blueprint.noParamScript(demoCompiledCode); const scriptHash = bluerint.hash const scriptCbor = bluerint.cbor const rewardAddress = blueprint.address; \`\`\` \# Deserializers URL: /apis/utilities/deserializers Parse CBOR or bech32 into objects \*\*\* title: "Deserializers" description: "Parse CBOR or bech32 into objects" icon: ArrowTurnRightUpIcon -------------------------- ## Deserialize Address Deserialize bech32 address into payment and staking parts, with visibility of whether they are script or key hash. \### Deserialize Address \\\[!toc\] Convert bech32 address to The deserialized address object \*\*Address:\*\* \`addr\_test1qpvx0...93swx9\` \`\`\`tsx deserializeAddress('addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9'); \`\`\` \## Deserialize Datum Deserialize a datum from a CBOR string to JSON object. \### Deserialize Datum \\\[!toc\] Deserialize a datum from a CBOR string to JSON object \*\*Datum\*\* \`167a4a048d87fcee0425ed200615ff2356f472c6413472c6106b8c5da52e3fd0\` \`\`\`tsx deserializeDatum('167a4a048d87fcee0425ed200615ff2356f472c6413472c6106b8c5da52e3fd0'); \`\`\` \## Deserialize Pool Id Deserialize a script from a pool id to Ed25519 key hash. \### Deserialize Pool Id \\\[!toc\] Deserialize a script from a pool id to Ed25519 key hash \*\*Pool Id\*\* \`pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx\` \`\`\`tsx deserializePoolId('pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx'); \`\`\` \# Utilities URL: /apis/utilities Serializers, resolvers and data types for converting between different formats. \*\*\* title: "Utilities" description: "Serializers, resolvers and data types for converting between different formats." icon: WrenchScrewdriverIcon --------------------------- import {linksUtilities} from "@/data/links-utilities"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksUtilities.map((card) => ( {card.title} {card.desc} ))} \# Resolvers URL: /apis/utilities/resolvers Converts between different formats. \*\*\* title: "Resolvers" description: "Converts between different formats." icon: ArrowRightIcon -------------------- import Link from "fumadocs-core/link"; ## Resolve Private Key Provide the mnemonic phrases and \`resolvePrivateKey\` will return a private key. \### Resolve Private Key \\\[!toc\] Convert mnemonic to private key \*\*Mnemonic\*\* \`\`\` \[ "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution", "solution" \] \`\`\` \`\`\`tsx resolvePrivateKey(\["solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution"\]); \`\`\` \## Resolve Transaction Hash Provide a \`cborTx\`, \`resolveTxHash\` will return the transaction hash. This hash is useful for creating chain transactions. \### Resolve Transaction Hash \\\[!toc\] Convert transaction cborTx to transaction hash \`\`\`tsx const tx = new Transaction({ initiator: wallet }); tx.sendLovelace('addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr', '1500000'); const unsignedTx = await tx.build(); const hash1 = resolveTxHash(unsignedTx); const signedTx = await wallet.signTx(unsignedTx, false); const hash2 = resolveTxHash(signedTx); const txHash = await wallet.submitTx(signedTx); // txHash == hash1 == hash2 \`\`\` \## Resolve Data Hash Converts datum into hash. Getting the hash is useful when you need to query for the UTXO that contain the assets you need for your transaction's input. Explore Transaction to learn more about designing Datum, and learn how to query for UTXOs containing the datum hash. \### Resolve Data Hash \\\[!toc\] Convert datum into hash \*\*Datum:\*\* \`supersecretdatum\` \`\`\`tsx resolveDataHash('supersecretdatum'); \`\`\` \## Resolve Native Script Hash Converts NativeScript into hash. \### Resolve Native Script Hash \\\[!toc\] Convert NativeScript to hash \*\*Address\*\* \`addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr\` \`\`\`tsx const keyHash = resolvePaymentKeyHash('addr\_test1vpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0c7e4cxr'); const nativeScript: NativeScript = { type: "all", scripts: \[ { type: "sig", keyHash: keyHash, }, \], }; resolveNativeScriptHash(nativeScript); \`\`\` \## Resolve Script Hash \`resolveScriptHash\` will return a script hash. For example, this is useful when you want to convert a script to a policy ID. \### Resolve Script Hash \\\[!toc\] Convert script to hash (like policy ID) \*\*script address\*\* \`8200581c5867c3b8e27840f556ac268b781578b14c5661fc63ee720dbeab663f\` \`\`\`tsx resolveScriptHash('8200581c5867c3b8e27840f556ac268b781578b14c5661fc63ee720dbeab663f') \`\`\` \## Resolve Stake Address Provide a wallet address, and \`resolveRewardAddress\` will return a staking address in bech32 format. \### Resolve Stake Address \\\[!toc\] Convert wallet address to staking address \*\*Address\*\* \`addr\_test1qpvx0sacuf...swx9\` \`\`\`tsx resolveRewardAddress('addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9'); \`\`\` \## Resolve Fingerprint Takes policy ID and asset name, and return asset fingerprint based on CIP-14. \## Resolve Asset Fingerprint \\\[!toc\] Convert asset policy ID and asset name to asset fingerprint. \*\*Policy ID\*\* \`426117329844ccb3b0ba877220ff06a5bdf21eab3fb33e2f3a3f8e69\` \*\*Asset Name\*\* \`4d657368546f6b656e\` \`\`\`tsx resolveFingerprint( '426117329844ccb3b0ba877220ff06a5bdf21eab3fb33e2f3a3f8e69', '4d657368546f6b656e' ) \`\`\` \## Resolve Stake Key Hash Provide a stake address, and \`resolveStakeKeyHash\` will return the pub key hash of the stake address. This key hash is useful for building the NativeScript. \## Resolve Stake Key Hash \\\[!toc\] Convert stake address to pub key hash \*\*Address\*\* \`stake\_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n\` \`\`\`tsx resolveStakeKeyHash('stake\_test1uzw5mnt7g4xjgdqkfa80hrk7kdvds6sa4k0vvgjvlj7w8eskffj2n'); \`\`\` \## Resolve Rep Id Resolve Rep Id from scrip hash. \### Resolve Rep Id \\\[!toc\] Resolve rep id from scrip hash \`\`\`tsx let script: NativeScript = { type: "all", scripts: \[ { type: "sig", keyHash: 'aa048e4cc8a1e67e1d97ffbd4be614388014cbc2b2451527202943b6' }, \], }; resolveScriptHashDRepId(resolveNativeScriptHash(script)); \`\`\` \## Resolve Epoch Number With \`resolveEpochNo\`, you can get the current epoch with: \`\`\`tsx import { resolveEpochNo } from '@meshsdk/core'; const epoch = resolveEpochNo('preprod'); \`\`\` You can also provide date in \`milliseconds\` to get epoch in the past or the future. For example, get the epoch 1 year from now: \`\`\`tsx import { resolveEpochNo } from '@meshsdk/core'; let oneYearFromNow = new Date(); oneYearFromNow.setFullYear(oneYearFromNow.getFullYear() + 1); const epoch = resolveEpochNo('preprod', oneYearFromNow.getTime()); \`\`\` \### Resolve Epoch number \\\[!toc\] Get the epoch number for the network \*\*Select network\*\* \`preprod\` \`\`\`tsx resolveEpochNo('preprod'); \`\`\` \### Resolve Epoch number 1 year from now \\\[!toc\] Get the epoch number for the network 1 year from now \*\*Select network\*\* \`preprod\` \`\`\`tsx let oneYearFromNow = new Date() oneYearFromNow.setFullYear(oneYearFromNow.getFullYear() + 1); resolveEpochNo(userInput, oneYearFromNow.getTime()); \`\`\` \## Resolve Slot Number With \`resolveSlotNo\`, you can get the current slot number with: \`\`\`tsx import { resolveSlotNo } from '@meshsdk/core'; const slot = resolveSlotNo('preprod'); \`\`\` You can also provide date in \`milliseconds\` to get slots in the past or the future. For example, get the slot number 1 year from now: \`\`\`tsx import { resolveSlotNo } from '@meshsdk/core'; let oneYearFromNow = new Date(); oneYearFromNow.setFullYear(oneYearFromNow.getFullYear() + 1); const slot = resolveSlotNo('preprod', oneYearFromNow.getTime()); \`\`\` \### Resolve Slot number \\\[!toc\] Get the Slot number for the network \*\*Select network\*\* \`preprod\` \`\`\`tsx resolveSlotNo('preprod'); \`\`\` \### Resolve Slot number 1 year from now \\\[!toc\] Get the Slot number for the network 1 year from now \*\*Select network\*\* \`preprod\` \`\`\`tsx let oneYearFromNow = new Date() oneYearFromNow.setFullYear(oneYearFromNow.getFullYear() + 1); resolveSlotNo(userInput, oneYearFromNow.getTime()); \`\`\` \# Serializers URL: /apis/utilities/serializers Encode objects into CBOR or bech32 format. \*\*\* title: "Serializers" description: "Encode objects into CBOR or bech32 format." icon: ArrowTurnRightDownIcon ---------------------------- import Link from "fumadocs-core/link"; In smart contract manipulations, serialization is a crucial process that encode data structures or objects into a format that can be easily stored or transmitted and later reconstructed. Below are utilities to help serialize various Cardano smart contracts components. ## Serialize Native Script The function \`serializeNativeScript\` allows you to provide the \`nativeScript\` with an option of \`networkId\` and \`stakeCredentialHash\`, returns: \* Bech32 address \* Script Cbor This example demonstrates how to derive the native script from the \`pubKeyHash\` with the \`deserializeAddress\` then serialize the native script to a bech32 address and script Cbor. To read more on deserializeAddress. \### Serialize Native Script \\\[!toc\] Serialize Native script into bech32 address \`\`\`tsx import { serializeNativeScript, NativeScript, deserializeAddress } from "@meshsdk/core"; const { pubKeyHash: keyHash } = deserializeAddress( 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', ); const nativeScript: NativeScript = { type: "all", scripts: \[ { type: "before", slot: "99999999", }, { type: "sig", keyHash: keyHash, }, \], }; serializeNativeScript(nativeScript); \`\`\` \## Serialize Plutus Script The function \`serializePlutusScript\` allows you to provide the \`plutusScript\` with an option of \`networkId\` and \`stakeCredentialHash\`, returns: \* Bech32 address This example demonstrates how to derive and serialize a plutus script into a bech32 address. \### Serialize Plutus Script \\\[!toc\] Serialize Plutus script into bech32 address \`\`\`tsx import { PlutusScript, serializePlutusScript } from "@meshsdk/core"; const plutusScript: PlutusScript = { code: demoPlutusAlwaysSucceedScript, version: "V2", }; serializePlutusScript(plutusScript); \`\`\` \## Serialize Address Object Serialize address in Cardano data JSON format into bech32 address with \`serializeAddressObj()\`. First you need to create an address object with \`pubKeyAddress()\` or \`scriptAddress()\`. \`pubKeyAddress()\` accepts the following parameters: \`\`\`tsx pubKeyAddress( bytes: string, stakeCredential?: string, isStakeScriptCredential?: boolean ): PubKeyAddress \`\`\` \`scriptAddress()\` accepts the following parameters: \`\`\`tsx scriptAddress( bytes: string, stakeCredential?: string, isStakeScriptCredential?: boolean ): ScriptAddress \`\`\` \`serializeAddressObj()\` accepts the following parameters: \`\`\`tsx serializeAddressObj( address: PubKeyAddress | ScriptAddress, networkId?: number ): string \`\`\` \### Serialize Address Object \\\[!toc\] Serialize address in Cardano data JSON format into bech32 address \`\`\`tsx import { pubKeyAddress, serializeAddressObj } from "@meshsdk/core"; const address = pubKeyAddress( 'aa048e4cc8a1e67e1d97ffbd4be614388014cbc2b2451527202943b6', '9d4dcd7e454d2434164f4efb8edeb358d86a1dad9ec6224cfcbce3e6' ); serializeAddressObj(address, 1); \`\`\` \# Browser Wallet URL: /apis/wallets/browserwallet For connecting, querying and performing wallet functions in accordance to CIP-30. \*\*\* title: "Browser Wallet" description: "For connecting, querying and performing wallet functions in accordance to CIP-30." icon: BanknotesIcon ------------------- \`BrowserWallet\` provides APIs for interacting with browser-based wallets in accordance with CIP-30. This standard defines the communication protocol between applications and user wallets, ensuring compatibility and security. In addition to the CIP-30 APIs, \`BrowserWallet\` includes utility functions that simplify common tasks such as retrieving wallet balances, signing transactions, and managing UTXOs. This section allows you to explore and test the available APIs for browser wallets, enabling seamless integration into your applications. ## Get Available Wallets Returns a list of wallets available on user's device. Each wallet is an object with the following properties: \* A name is provided to display wallet's name on the user interface. \* A version is provided to display wallet's version on the user interface. \* An icon is provided to display wallet's icon on the user interface. \#### Get Available Wallets \\\[!toc\] Get a list of wallets on user's device \`\`\`tsx import { BrowserWallet } from 'meshsdk/core'; await BrowserWallet.getAvailableWallets() \`\`\` Example response: \`\`\`tsx \[ { "name": "eternl", "icon": "data:image/png;base64,ICONBASE64HERE", "version": "0.1.0" } \] \`\`\` ## Connect Wallet This is the entry point to start communication with the user's wallet. The wallet should request the user's permission to connect the web page to the user's wallet, and if permission has been granted, the wallet will be returned, exposing the full API for the app to use. Query \`BrowserWallet.getAvailableWallets()\` to get a list of available wallets, then provide the wallet \`name\` for which wallet the user would like to connect with. You can also provide an \`extensions\` object to enable specific CIPs. For example, to enable CIP95, you would pass: \`\`\`tsx await BrowserWallet.enable('eternl', \[95\]); \`\`\` \#### Connect Wallet \\\[!toc\] Connect to a CIP30 compatible wallet \`\`\`tsx import { BrowserWallet } from '@meshsdk/core'; const wallet = await BrowserWallet.enable('eternl'); \`\`\` \## Get Balance This API retrieves a list of all assets in the connected wallet. Each asset is represented as an object containing the following properties: \* Unit: A unique identifier for the asset, which can be used to display its name in the user interface. \* Quantity: The amount of the asset held in the wallet. This information is useful for applications that need to display wallet balances or perform operations involving specific assets. \#### Get Balance \\\[!toc\] Get all assets in the connected wallet \`\`\`tsx await wallet.getBalance(); \`\`\` Example response: \`\`\`tsx \[ { "unit": "lovelace", "quantity": "796105407" }, { "unit": "0f5560dbc05282e05507aedb02d823d9d9f0e583cce579b81f9d1cd8", "quantity": "1" }, { "unit": "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d4d657368546f6b656e", "quantity": "2" }, \] \`\`\` ## Get Change Address This API returns an address owned by the wallet that should be used as a change address. A change address is where leftover assets from a transaction are returned during its creation. This ensures that any unspent assets are sent back to the connected wallet. Applications can use this API to manage transaction outputs effectively, ensuring proper handling of change during transactions. \#### Get Change Address \\\[!toc\] Get address that should be used for transaction's change \`\`\`tsx await wallet.getChangeAddress(); \`\`\` \## Get Collateral This API retrieves a list of UTXOs (unspent transaction outputs), controlled by the wallet, that can be used as collateral inputs for transactions involving Plutus scripts. The returned UTXOs must meet or exceed the specified ADA value target. If the target cannot be met, an error message will be returned explaining the issue. Wallets may return UTXOs with a greater total ADA value than requested, but must never return UTXOs with a smaller total value. This functionality is essential for applications that need to create transactions requiring collateral inputs. \#### Get Collateral \\\[!toc\] Get list of UTXOs that used as collateral inputs for transactions with plutus script inputs \`\`\`tsx await wallet.getCollateral(); \`\`\` Example response: \`\`\`tsx \[ { "input": { "outputIndex": 1, "txHash": "ff8d1e97c60989b4f...02ee937595ad741ff597af1" }, "output": { "address": "addr\_test1qzm...z0fr8c3grjmysm5e6yx", "amount": \[ { "unit": "lovelace", "quantity": "5000000" } \] } } \] \`\`\` ## Get Network ID This API retrieves the network ID of the currently connected account. The network ID indicates the blockchain network the wallet is connected to. For example: \* 0: Testnet \* 1: Mainnet Other network IDs may be returned by wallets, but these are not governed by CIP-30. The network ID remains consistent unless the connected account changes. Applications can use this information to ensure compatibility with the connected network. \#### Get Network ID \\\[!toc\] Get currently connected network \`\`\`tsx await wallet.getNetworkId(); \`\`\` \## Get Reward Addresses Returns a list of reward addresses owned by the wallet. A reward address is a stake address that is used to receive rewards from staking, generally starts from \`stake\` prefix. \#### Get Reward Addresses \\\[!toc\] Get stake addresses \`\`\`tsx await wallet.getRewardAddresses(); \`\`\` Example response: \`\`\`tsx \[ "stake\_test1uzx0ksy9f4qnj2mzfdncqyjy84sszh64w43853nug5pedjgytgke9" \] \`\`\` ## Get Unused Addresses Returns a list of unused addresses controlled by the wallet. \#### Get Unused Addresses \\\[!toc\] Get addresses that are unused \`\`\`tsx await wallet.getUnusedAddresses(); \`\`\` Example response: \`\`\`tsx \[ "addr\_test1qzk9x08mtre4jp8f7j8zu8802...r8c3grjmys7fl22c", "addr\_test1qrmf35xyw2petfr0e0p4at0r7...8sc3grjmysm73dk8", "addr\_test1qq6ts58hdaasd2q78fdjj0arm...i8c3grjmys85k8mf", \] \`\`\` ## Get Used Addresses Returns a list of used addresses controlled by the wallet. \#### Get Used Addresses \\\[!toc\] Get addresses that are used \`\`\`tsx await wallet.getUsedAddresses(); \`\`\` Example response: \`\`\`tsx \[ "addr\_test1qzk9x08mtre4jp8f7j8zu8802...r8c3grjmys7fl88a", "addr\_test1qrmf35xyw2petfr0e0p4at0r7...8sc3grjmysm76gt3", "addr\_test1qq6ts58hdaasd2q78fdjj0arm...i8c3grjmys85dn39", \] \`\`\` ## Get UTXOs Return a list of all UTXOs (unspent transaction outputs) controlled by the wallet. \#### Get UTXOs \\\[!toc\] Get UTXOs of the connected wallet \`\`\`tsx const utxos = await wallet.getUtxos(); \`\`\` Example response: \`\`\`tsx \[ { "input": { "outputIndex": 0, "txHash": "16dcbb1f93b4f9d5e...9106c7b121463c210ba" }, "output": { "address": "addr\_test1qzag7whju08xwrq...z0fr8c3grjmysgaw9y8", "amount": \[ { "unit": "lovelace", "quantity": "1314550" }, { "unit": "f05c91a850...3d824d657368546f6b656e3032", "quantity": "1" } \] } } \] \`\`\` ## Sign Data This endpoint uses CIP-8 message signing to sign arbitrary data and verify that the signature comes from the holder of the corresponding private key. \`signData\` takes two arguments, the first one is the payload to sign and the second one is the address (optional). By default, we get the first wallet's address with \`wallet.getRewardAddresses()\`, alternativelly you can specify the address to use. \#### Sign Data \\\[!toc\] Define a payload and sign it with wallet. \`Payload: mesh\` \`\`\`tsx const signature = await wallet.signData(mesh); \`\`\` Example response: \`\`\`tsx { "signature": "845846a2012...f9119a18e8977d436385cecb08", "key": "a4010103272006215...b81a7f6ed4fa29cc7b33186c" } \`\`\` Check out \[this guide\](https://meshjs.dev/guides/prove-wallet-ownership#server-verify-signature) to learn how to verify the signature. ## Sign Transaction Requests user to sign the provided transaction (\`tx\`). The wallet should ask the user for permission, and if given, try to sign the supplied body and return a signed transaction. \`partialSign\` should be \`true\` if the transaction provided requires multiple signatures. \#### Sign Transaction \\\[!toc\] Create a transaction and sign it \`\`\`tsx const signedTx = await wallet.signTx(tx, partialSign?); \`\`\` Check out \[Transaction\](https://docs.meshjs.dev/transactions) to learn more on how to use this API. \## Submit Transaction This API lets applications ask a wallet to submit signed transactions. On success, the wallet returns a transaction ID for tracking. On failure, it returns error details. \#### Submit Transaction \\\[!toc\] Submit a signed transaction with wallet \`\`\`tsx const txHash = await wallet.submitTx(signedTx); \`\`\` Check out \[Transaction\](https://docs.meshjs.dev/transactions) to learn more on how to use this API. \## Get Assests Returns a list of assets in the wallet, excluding lovelace. \#### Get Assets \\\[!toc\] Get assets in the connected wallet \`\`\`tsx const assets = await wallet.getAssets(); \`\`\` Example response: \`\`\`tsx \[ { "unit": "1207329a668cf5c42b80a220a8c85d5e82ac0b6f5ecedda4c07a8acc4d657368486f6e6f72546f6b656e2d3530343935", "policyId": "1207329a668cf5c42b80a220a8c85d5e82ac0b6f5ecedda4c07a8acc", "assetName": "Mesh Token Of Appreciation", "fingerprint": "asset1dw74h0w0meqg9cxkc9sezp8zqcxu8nl93fzfpz", "quantity": "1" } { "unit": "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d4d657368546f6b656e", "policyId": "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d", "assetName": "MeshToken", "fingerprint": "asset177e7535dclmkkph8ewt9fsghllkwmpspa3n98p", "quantity": "10" } \] \`\`\` ## Get Lovelace This API retrieves the Lovelace balance in the connected wallet. Lovelace is the smallest denomination of ADA, where 1 ADA equals 1,000,000 Lovelace. Applications can use this information to display the wallet's balance or perform operations involving ADA. \#### Get Lovelace \\\[!toc\] Get amount of ADA in the connected wallet \`\`\`tsx await wallet.getLovelace(); \`\`\` \## Get Policy IDs This API retrieves a list of policy IDs for all assets in the connected wallet. A policy ID is a unique identifier for a group of assets, often used to manage collections or verify asset ownership. Applications can use this information to query assets belonging to specific policy IDs or display asset details to the user. \#### Get Policy IDs \\\[!toc\] Get a list of policy IDs from all assets in wallet \`\`\`tsx await wallet.getPolicyIds(); \`\`\` Example response: \`\`\`tsx \[ "0f5560dbc05282e05507aedb02d823d9d9f0e583cce579b81f9d1cd8", "5bed9e89299c69d9a54bbc82d88aa5a86698b2b7b9d0ed030fc4b0ff", "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d", \] \`\`\` ## Get a Collection of Assets This API retrieves a list of assets associated with a specific policy ID. If no assets in the wallet belong to the specified policy ID, an empty list is returned. Applications can use this API to query assets belonging to a particular policy ID, which is useful for managing collections of assets or verifying ownership. To obtain a list of all policy IDs in the wallet, use \`wallet.getPolicyIds()\`. \#### Get a Collection of Assets \\\[!toc\] Get a list of assets belonging to the policy ID \`Policy ID: d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527\` \`\`\`tsx await wallet.getPolicyIdAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527'); \`\`\` \## Get Supported Extensions \`getSupportedExtensions\` is a static function that returns a list of CIPs that are supported by a wallet. You can query this function without connecting to a wallet, by providing the wallet name. You can get the list of wallet on user's device with \`await BrowserWallet.getAvailableWallets()\`. \#### Get Supported Extensions \\\[!toc\] Get a list of CIPs that are supported by a wallet \`Wallet Name: eternl\` \`\`\`tsx await wallet.getSupportedExtensions('eternl'); \`\`\` \## Get Extensions This API retrieves a list of CIP-30 extensions enabled by the connected wallet. CIP-30 extensions define additional capabilities that wallets can support, enhancing their functionality. Applications can use this information to determine the features supported by the wallet and adapt their behavior accordingly. \#### Get Extensions \\\[!toc\] Get a list of CIPs that are supported by the connected wallet \`\`\`tsx await wallet.getExtensions(); \`\`\` Example response: \`\`\`tsx \[ { "cip": 30 } \] \`\`\` ## Get DRep This API retrieves the key, hash, and bech32 encoding of the DRep ID associated with the wallet. The DRep ID is a unique identifier used for delegation representation in the Cardano blockchain. Applications can use this information to interact with delegation-related features or display the DRep ID details to the user. \#### Get DRep ID Key \\\[!toc\] Get the key, hash, and bech32 address of the DRep ID \`\`\`tsx await wallet.getDRep(); \`\`\` Example response: \`\`\`tsx { "publicKey": "6984e406dd81...39e43d798fe1a89ab", "publicKeyHash": "9f7f4b78...df83bd227e943e9808450", "dRepIDCip105": "drep1vz0h7jmc...0axqgg5q4dls5u" } \`\`\` ## Get Registered Pub Stake Keys Get a list of registered public stake keys. \#### Get Registered Pub Stake Keys \\\[!toc\] Get a list of registered public stake keys \`\`\`tsx await wallet.getRegisteredPubStakeKeys(); \`\`\` Example response: \`\`\`tsx { "pubStakeKeys": \[ "d7eb3004c14647646...40f89c1a4b8a2eb0a3" \], "pubStakeKeyHashes": \[ "8cfb40854d41392b..5575627a467c450396c9" \] } \`\`\` ## Get Unregistered Pub Stake Keys Get a list of unregistered public stake keys. \#### Get Unregistered Pub Stake Keys \\\[!toc\] Get a list of unregistered public stake keys \`\`\`tsx await wallet.getUnregisteredPubStakeKeys(); \`\`\` \# Wallets URL: /apis/wallets Wallets APIs for interacting with the blockchain. \*\*\* title: "Wallets" description: "Wallets APIs for interacting with the blockchain." icon: WalletIcon full: true ---------- import {linksWallets} from "@/data/links-wallets"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksWallets.map((card) => ( {card.title} {card.desc} ))} \# Mesh Wallet URL: /apis/wallets/meshwallet Mesh Wallet provides a set of APIs to interact with the blockchain. This wallet is compatible with Mesh transaction builders. \*\*\* title: "Mesh Wallet" description: "Mesh Wallet provides a set of APIs to interact with the blockchain. This wallet is compatible with Mesh transaction builders." icon: WalletIcon ---------------- Whether you are building a minting script, or an application that requires multi-signature, \`MeshWallet\` is all you need to get started. ## Initialize Wallet This API enables applications to load and initialize a wallet connection. It provides access to the wallet's capabilities, such as signing transactions, submitting transactions, and querying blockchain data. The wallet connection is established securely, ensuring that sensitive operations are handled by the wallet and not exposed to the application directly. This is crucial for maintaining security and user trust. Applications can use this functionality to integrate wallet features seamlessly, enabling blockchain interactions without requiring users to manage private keys manually. You can initialize Mesh Wallet with: \* Mnemonic Phrases \* Private Keys \* Cardano CLI Generated Keys \* Address (Read Only Wallet) First, we initialize a new Provider. \`\`\`tsx import { MaestroProvider } from '@meshsdk/core'; const provider = new MaestroProvider({ network: 'Preprod', apiKey: '', // Get yours by visiting https://docs.gomaestro.org/. turboSubmit: false }); \`\`\` \`\`\`tsx import { BlockfrostProvider } from '@meshsdk/core'; const provider = new BlockfrostProvider(''); \`\`\` \`\`\`tsx import { KoiosProvider } from '@meshsdk/core'; const provider = new KoiosProvider('', ''); \`\`\` \`\`\`tsx import { U5CProvider } from "@meshsdk/core"; const provider = new U5CProvider({ url: "http://localhost:5005U5c", headers: { "dmtr-api-key": "", }, }); \`\`\` \### Mnemonic Phrases We can load a wallet with mnemonic phrases, and assign our provider to the \`fetcher\` and \`submitter\`: \`\`\`tsx import { MeshWallet } from '@meshsdk/core'; const wallet = new MeshWallet({ networkId: 0, // 0: testnet, 1: mainnet fetcher: provider, submitter: provider, key: { type: 'mnemonic', words: \["solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution"\], }, }); \`\`\` With the \`wallet\` loaded, you can sign transactions, we will see how to do this in the next section, for now lets get the wallet's address: \`\`\`tsx const address = wallet.getChangeAddress(); \`\`\` ### Private Keys We can load a wallet with private keys: \`\`\`tsx import { MeshWallet } from '@meshsdk/core'; const wallet = new MeshWallet({ networkId: 0, // 0: testnet, 1: mainnet fetcher: provider, submitter: provider, key: { type: 'root', bech32: 'xprv1cqa46gk29plgkg98upclnjv5t425fcpl4rgf9mq2txdxuga7jfq5shk7np6l55nj00sl3m4syzna3uwgrwppdm0azgy9d8zahyf32s62klfyhe0ayyxkc7x92nv4s77fa0v25tufk9tnv7x6dgexe9kdz5gpeqgu', }, }); \`\`\` ### Cardano CLI generated skeys We can load a wallet with CLI-generated keys by providing the \`skey\` generated by Cardano CLI. There are two files generated by Cardano CLI, by default, it is named \`signing.skey\` and \`stake.skey\`. Opening the \`signing.skey\` file should show: \`\`\`tsx { "type": "PaymentSigningKeyShelley\_ed25519", "description": "Payment Signing Key", "cborHex": "5820aaca553a7b95b38b5d9b82a5daa7a27ac8e34f3cf27152a978f4576520dd6503" } \`\`\` We can get the \`cborHex\` from the \`signing.skey\` file, and load wallet with Cardano CLI generated skeys. Stake key is optional, but without it, you cannot sign staking transactions. \`\`\`tsx import { MeshWallet } from '@meshsdk/core'; const wallet = new MeshWallet({ networkId: 0, // 0: testnet, 1: mainnet fetcher: provider, submitter: provider, key: { type: 'cli', payment: '5820aaca553a7b95b38b5d9b82a5daa7a27ac8e34f3cf27152a978f4576520dd6503', stake: '582097c458f19a3111c3b965220b1bef7d548fd75bc140a7f0a4f080e03cce604f0e', }, }); \`\`\` ### Address We can load a wallet with address, this is useful for read-only wallets. A read-only wallet can only query the blockchain, it cannot sign transactions. This is useful for monitoring wallets. We can load wallet with the \`address\` type: \`\`\`tsx import { MeshWallet } from '@meshsdk/core'; const wallet = new MeshWallet({ networkId: 0, // 0: testnet, 1: mainnet fetcher: provider, key: { type: 'address', address: 'addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9', }, }); \`\`\` ### Initialize Wallet After creating the wallet, we need to initialize it. This will initialize the cryptography library. \`\`\`tsx await wallet.init() \`\`\` With the \`wallet\` loaded, you can sign transactions, we will see how to do this in the \[Sign Transaction\](https://meshjs.dev/apis/wallets/meshwallet#sign-transaction) section, for now lets get the wallet's address: \`\`\`tsx const address = wallet.getChangeAddress(); \`\`\` ## Generate Wallet You can generate deterministic keys based on the \`Bitcoin BIP39\`. These mnemonic phrases are essential for recovering your wallet and ensuring secure access to your funds. \`\`\`tsx const mnemonic = MeshWallet.brew(); \`\`\` Once you have your mnemonic phrase, you can use it to generate deterministic keys. These keys include a series of private and public keys, which are crucial for managing your cryptocurrencies securely. Alternatively, you can generate private keys directly by passing \`true\` to the \`brew\` function. This approach is useful for scenarios where you need immediate access to private keys without mnemonic phrases. \`\`\`tsx const privatekey = MeshWallet.brew(true); \`\`\` ## Get Balance This API returns a comprehensive list of all assets in the wallet, including lovelace. Each asset is represented as an object with the following properties: \* \`unit\`: A unique identifier for the asset, often used for display purposes. \* \`quantity\`: The amount of the asset held in the wallet. \### Get Balance \\\[!toc\] Get all assets in the connected wallet \`\`\`tsx const balance = await wallet.getBalance(); \`\`\` Example response: \`\`\`tsx \[ { "unit": "lovelace", "quantity": "796105407" }, { "unit": "0f5560dbc05282e05507aedb02d823d9d9f0e583cce579b81f9d1cd8", "quantity": "1" }, { "unit": "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d4d657368546f6b656e", "quantity": "2" }, \] \`\`\` ## Get Change Address This API returns an address owned by the wallet which is essential during transaction creation to ensure leftover assets are securely returned to the connected wallet. The change address helps maintain the integrity of transactions by preventing asset loss and ensuring proper allocation of funds. \### Get Change Address \\\[!toc\] Get address that should be used for transaction's change \`\`\`tsx const changeAddress = await wallet.getChangeAddress(); \`\`\` \## Get Collateral This API retrieves a list of UTXOs (unspent transaction outputs) controlled by the wallet that are suitable for use as collateral inputs in transactions involving Plutus script inputs. Collateral UTXOs are pure ADA-only UTXOs required to meet the specified ADA value target. If the target cannot be met, an error message explaining the issue will be returned. Wallets may return UTXOs exceeding the target value but must never return UTXOs below the specified value. This API accepts the \`addressType\` parameter, where you can specify the type of address you want to get. The available options are: \* payment (default) \* enterprise \### Get Collateral \\\[!toc\] Get list of UTXOs that used as collateral inputs for transactions with plutus script inputs \`\`\`tsx const collateralUtxos = await wallet.getCollateral(); \`\`\` Example response: \`\`\`tsx \[ { "input": { "outputIndex": 1, "txHash": "ff8d1e97c60989b4f...02ee937595ad741ff597af1" }, "output": { "address": "addr\_test1qzm...z0fr8c3grjmysm5e6yx", "amount": \[ { "unit": "lovelace", "quantity": "5000000" } \] } } \] \`\`\` ## Get Network ID This API returns the network ID of the currently connected account. The network ID indicates the environment in which the wallet is operating: \* \`0\`: Testnet \* \`1\`: Mainnet Other network IDs may be returned by wallets, but these are not governed by CIP-30. The network ID remains consistent unless the connected account changes. \### Get Network ID \\\[!toc\] Get currently connected network \`\`\`tsx const networkId = wallet.getNetworkId(); \`\`\` \## Get Reward Addresses This API retrieves a list of reward addresses owned by the wallet. Reward addresses are stake addresses used to receive rewards from staking activities. Reward addresses typically start with the \`stake\` prefix, making them easily identifiable. These addresses are essential for tracking staking rewards and managing staking operations. \### Get Reward Addresses \\\[!toc\] Get stake addresses \`\`\`tsx const rewardAddresses = wallet.getRewardAddresses(); \`\`\` Example response: \`\`\`tsx \[ "stake\_test1uzx0ksy9f4qnj2mzfdncqyjy84sszh64w43853nug5pedjgytgke9" \] \`\`\` ## Get Unused Addresses This API retrieves a list of unused addresses controlled by the wallet. Unused addresses are wallet-controlled addresses that have not been involved in any transactions. Unused addresses are important for maintaining privacy and security in transactions. They can be used for new transactions without revealing previous activity. \### Get Unused Addresses \\\[!toc\] Get addresses that are unused \`\`\`tsx const unusedAddresses = wallet.getUnusedAddresses(); \`\`\` Example response: \`\`\`tsx \[ "addr\_test1qzk9x08mtre4jp8f7j8zu8802...r8c3grjmys7fl22c", "addr\_test1qrmf35xyw2petfr0e0p4at0r7...8sc3grjmysm73dk8", "addr\_test1qq6ts58hdaasd2q78fdjj0arm...i8c3grjmys85k8mf", \] \`\`\` ## Get Used Addresses This API retrieves a list of used addresses controlled by the wallet. Used addresses are wallet-controlled addresses that have been involved in transactions. Tracking used addresses is essential for analyzing transaction history and managing wallet activity. These addresses provide insights into past transactions. \### Get Used Addresses \\\[!toc\] Get addresses that are used \`\`\`tsx const usedAddresses = wallet.getUsedAddresses(); \`\`\` Example response: \`\`\`tsx \[ "addr\_test1qzk9x08mtre4jp8f7j8zu8802...r8c3grjmys7fl88a", "addr\_test1qrmf35xyw2petfr0e0p4at0r7...8sc3grjmysm76gt3", "addr\_test1qq6ts58hdaasd2q78fdjj0arm...i8c3grjmys85dn39", \] \`\`\` ## Get UTXOs This API retrieves a list of all UTXOs (unspent transaction outputs) controlled by the wallet. UTXOs are essential for constructing transactions and managing wallet balances. Each UTXO includes details such as the transaction hash, output index, address, and amount. These details are crucial for identifying and utilizing unspent outputs. This API accepts the addressType parameter, where you can specify the type of address you want to get. The available options are: \* payment (default) \* enterprise \### Get UTXOs \\\[!toc\] Get UTXOs of the connected wallet \`\`\`tsx const utxos = await wallet.getUtxos(); \`\`\` Example response: \`\`\`tsx \[ { "input": { "outputIndex": 0, "txHash": "16dcbb1f93b4f9d5e...9106c7b121463c210ba" }, "output": { "address": "addr\_test1qzag7whju08xwrq...z0fr8c3grjmysgaw9y8", "amount": \[ { "unit": "lovelace", "quantity": "1314550" }, { "unit": "f05c91a850...3d824d657368546f6b656e3032", "quantity": "1" } \] } } \] \`\`\` ## Sign Data This API allows applications to request the signing of arbitrary data using the private keys managed by the connected wallet. This is useful for verifying the authenticity of data or creating cryptographic proofs. The wallet ensures that the signing process is secure and that private keys are not exposed during the operation. The signed data can be used for various purposes, such as authentication, data integrity checks, or blockchain interactions. This functionality is essential for applications that require secure and verifiable data signing capabilities. \### Sign Data \\\[!toc\] Define a payload and sign it with wallet. \`Payload: mesh\` \`\`\`tsx const signature = await wallet.signData('mesh'); \`\`\` Check out \[this guide\](https://meshjs.dev/guides/prove-wallet-ownership#server-verify-signature) to learn how to verify the signature. Example response: \`\`\`tsx { "signature": "845846a2012...f9119a18e8977d436385cecb08", "key": "a4010103272006215...b81a7f6ed4fa29cc7b33186c" } \`\`\` ## Sign Transaction This API enables applications to request the signing of a transaction using the private keys managed by the connected wallet. Signing a transaction is a critical step in ensuring its authenticity and authorization. The wallet ensures that the transaction is signed securely, preventing unauthorized access to private keys. Once signed, the transaction can be submitted to the blockchain network for processing. This functionality is vital for applications that need to interact with the blockchain securely, as it delegates sensitive operations to the wallet. \### Sign Transaction \\\[!toc\] Create a transaction and sign it Check out \[MeshWallet\](https://docs.meshjs.dev/wallets/classes/MeshWallet#signTx) documentation to learn more on how to use this API. \`\`\`tsx const signedTx = await wallet.signTx(tx, partialSign?); \`\`\` \## Submit Transaction This API allows applications to request the submission of a signed transaction through the connected wallet. The wallet will attempt to send the transaction to the blockchain network. If the transaction is successfully submitted, the wallet returns the transaction ID, which can be used by the application to track its status on the blockchain. In case of an error during submission, the wallet provides error messages or failure details. This functionality is essential for applications that rely on wallet integration to handle transaction submission securely and efficiently. \### Submit Transaction \\\[!toc\] Submit a signed transaction with wallet Check out \[MeshWallet\](https://docs.meshjs.dev/wallets/classes/MeshWallet#submitTx) documentation to learn more on how to use this API. \`\`\`tsx const txHash = await wallet.submitTx(signedTx); \`\`\` \## Create Collateral UTXO Collateral is a monetary guarantee provided by the user to ensure the integrity of smart contracts and compensate nodes in case phase-2 validation fails. It is specified during transaction construction by adding collateral inputs to the transaction. The total balance in the UTXOs corresponding to these inputs represents the transaction's collateral amount. If the contract executes successfully, the collateral remains safe. This mechanism ensures that contracts are carefully designed and thoroughly tested. \`\`\`tsx const txhash = await wallet.createCollateral(); \`\`\` ## Get Assets This API retrieves a list of assets in the wallet, excluding lovelace. Each asset is represented as an object with the following properties: \* \`unit\`: A unique identifier for the asset. \* \`policyId\`: The policy ID associated with the asset. \* \`assetName\`: The name of the asset. \* \`fingerprint\`: A unique fingerprint for the asset. \* \`quantity\`: The amount of the asset held in the wallet. \### Get Assets \\\[!toc\] Get all assets in the connected wallet \`\`\`tsx const assets = await wallet.getAssets(); \`\`\` Example response: \`\`\`tsx \[ { "unit": "1207329a668cf5c42b80a220a8c85d5e82ac0b6f5ecedda4c07a8acc4d657368486f6e6f72546f6b656e2d3530343935", "policyId": "1207329a668cf5c42b80a220a8c85d5e82ac0b6f5ecedda4c07a8acc", "assetName": "Mesh Token Of Appreciation", "fingerprint": "asset1dw74h0w0meqg9cxkc9sezp8zqcxu8nl93fzfpz", "quantity": "1" } { "unit": "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d4d657368546f6b656e", "policyId": "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d", "assetName": "MeshToken", "fingerprint": "asset177e7535dclmkkph8ewt9fsghllkwmpspa3n98p", "quantity": "10" } \] \`\`\` ## Get Lovelace This API retrieves the lovelace balance in the wallet. Lovelace is the smallest unit of ADA, where 1 ADA equals 1,000,000 lovelace. Knowing the lovelace balance is essential for managing wallet funds and performing transactions. \### Get Lovelace \\\[!toc\] Get lovelace balance in the connected wallet \`\`\`tsx const lovelace = await wallet.getLovelace(); \`\`\` \## Get Policy IDs This API retrieves a list of policy IDs from all assets in the wallet. A policy ID is a unique identifier that groups assets under a common policy. Policy IDs are useful for querying assets associated with specific policies. For example, you can use a policy ID to retrieve all assets belonging to that policy. \### Get Policy IDs \\\[!toc\] Get a list of policy IDs from all assets in wallet \`\`\`tsx const policyIds = await wallet.getPolicyIds(); \`\`\` Example response: \`\`\`tsx \[ "0f5560dbc05282e05507aedb02d823d9d9f0e583cce579b81f9d1cd8", "5bed9e89299c69d9a54bbc82d88aa5a86698b2b7b9d0ed030fc4b0ff", "9c8e9da7f81e3ca90485f32ebefc98137c8ac260a072a00c4aaf142d", \] \`\`\` ## Get a Collection of Assets This API retrieves a list of assets associated with a specific policy ID. A policy ID is a unique identifier that groups assets under a common policy. If no assets in the wallet belong to the specified policy ID, an empty list is returned. To query for available policy IDs, use \`wallet.getPolicyIds()\`. \### Get a Collection of Assets \\\[!toc\] Get a list of assets belonging to the policy ID \`Policy ID: d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527\` \`\`\`tsx const assets = await wallet.getPolicyIdAssets('d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc17255527'); \`\`\` \## Get DRep The DRep ID is a unique identifier for the user's wallet. It consists of three components: \* \`publicKey\`: The public key associated with the wallet. \* \`publicKeyHash\`: A hash of the public key for verification purposes. \* \`dRepIDCip105\`: The bech32 encoding of the DRep ID. \### Get DRep \\\[!toc\] Get the key, hash, and bech32 address of the DRep ID \`\`\`tsx await wallet.getDRep(); \`\`\` Example response: \`\`\`tsx { "publicKey": "6984e406dd81...39e43d798fe1a89ab", "publicKeyHash": "9f7f4b78...df83bd227e943e9808450", "dRepIDCip105": "drep1vz0h7jmc...0axqgg5q4dls5u" } \`\`\` # Core API Methods URL: /midnight/midnight-setup/api Complete reference for MidnightSetupAPI methods and provider setup \*\*\* title: "Core API Methods" description: "Complete reference for MidnightSetupAPI methods and provider setup" icon: CodeBracketIcon --------------------- import Link from "fumadocs-core/link"; ## MidnightSetupAPI The \`MidnightSetupAPI\` is the main class for interacting with Midnight Network contracts. It provides methods for deploying, joining, and managing smart contracts. ### Core Methods | Method | Description | Usage | | ---------------------------------------------------- | ---------------------- | ----------------------------- | | \`deployContract(providers, contractInstance)\` | Deploy a new contract | Creates new contract instance | | \`joinContract(providers, contractInstance, address)\` | Join existing contract | Connect to deployed contract | | \`getContractState()\` | Read contract state | Get current contract data | | \`getLedgerState()\` | Read ledger state | Get blockchain data | ### Deploy Contract Deploy a new smart contract to the Midnight Network: \`\`\`typescript import { MidnightSetupAPI } from '@meshsdk/midnight-setup'; const api = await MidnightSetupAPI.deployContract(providers, contractInstance); console.log('Contract deployed:', api.deployedContractAddress); \`\`\` ### Join Contract Connect to an existing deployed contract: \`\`\`typescript import { MidnightSetupAPI } from '@meshsdk/midnight-setup'; const contractAddress = "contract\_address\_here"; const api = await MidnightSetupAPI.joinContract(providers, contractInstance, contractAddress); console.log('Connected to contract:', contractAddress); \`\`\` ### Get Contract State Retrieve the current state of a contract: \`\`\`typescript const state = await api.getContractState(); console.log('Contract state:', state); \`\`\` ### Get Ledger State Access the current ledger state: \`\`\`typescript const ledgerState = await api.getLedgerState(); console.log('Ledger state:', ledgerState); \`\`\` ## Provider Setup Set up providers for Midnight Network: \`\`\`typescript import { setupProviders } from './lib/providers'; const providers = await setupProviders(); // Returns: MidnightSetupContractProviders \`\`\` ### Provider Configuration \`\`\`typescript const providers = { fetcher: blockfrostProvider, submitter: blockfrostProvider, wallet: laceWallet, // Additional provider configurations }; \`\`\` ## Error Handling Always wrap API calls in try-catch blocks for proper error handling: \`\`\`typescript try { const api = await MidnightSetupAPI.deployContract(providers, contractInstance); const state = await api.getContractState(); console.log('Success:', state); } catch (error) { console.error('Error:', error.message); } \`\`\` ## TypeScript Support The package includes full TypeScript definitions: \`\`\`typescript import { MidnightSetupAPI, MidnightSetupContractProviders, ContractInstance } from '@meshsdk/midnight-setup'; // Type-safe provider setup const providers: MidnightSetupContractProviders = await setupProviders(); // Type-safe contract instance const contractInstance: ContractInstance = { // Contract configuration }; \`\`\` ## Best Practices 1. \*\*Always handle errors\*\* - Wrap API calls in try-catch blocks 2. \*\*Use TypeScript\*\* - Leverage type safety for better development experience 3. \*\*Validate inputs\*\* - Ensure contract instances and addresses are valid 4. \*\*Monitor state changes\*\* - Listen for contract state updates 5. \*\*Test thoroughly\*\* - Use testnet before deploying to mainnet # Integration Examples URL: /midnight/midnight-setup/examples The fastest way to build on Midnight Network with pre-built smart contracts, complete API, and ready-to-use code snippets \*\*\* title: "Integration Examples" description: "The fastest way to build on Midnight Network with pre-built smart contracts, complete API, and ready-to-use code snippets" icon: BeakerIcon ---------------- import Link from "fumadocs-core/link"; The fastest way to build on Midnight Network with pre-built smart contract, complete API, and ready-to-use code snippets. Full React integration example and a Compact contract: \[midnight-setup\](https://github.com/MeshJS/midnight-setup) ## Installation \`\`\`bash npm install @meshsdk/midnight-setup \\ @midnight-ntwrk/dapp-connector-api@3.0.0 \\ @midnight-ntwrk/midnight-js-fetch-zk-config-provider@2.0.2 \\ @midnight-ntwrk/midnight-js-http-client-proof-provider@2.0.2 \\ @midnight-ntwrk/midnight-js-indexer-public-data-provider@2.0.2 \\ @midnight-ntwrk/midnight-js-level-private-state-provider@2.0.2 \\ @midnight-ntwrk/midnight-js-network-id@2.0.2 \`\`\` ## Features \* \*\*Type-safe SDK\*\* - Full TypeScript support \* \*\*Provider abstraction\*\* - Easy wallet and network integration \* \*\*Contract state management\*\* - Query contract and ledger states \* \*\*Flexible contract support\*\* - Works with any Midnight smart contract \* \*\*Lightweight\*\* - Only 10.4 KB package size \* \*\*ESM & CJS\*\* - Supports both module systems ## Quick Start ### 1. Setup Providers \`\`\`typescript import { FetchZkConfigProvider } from "@midnight-ntwrk/midnight-js-fetch-zk-config-provider"; import { httpClientProofProvider } from "@midnight-ntwrk/midnight-js-http-client-proof-provider"; import { indexerPublicDataProvider } from "@midnight-ntwrk/midnight-js-indexer-public-data-provider"; import { levelPrivateStateProvider } from "@midnight-ntwrk/midnight-js-level-private-state-provider"; import type { MidnightSetupContractProviders } from "@meshsdk/midnight-setup"; export async function setupProviders(): Promise { const wallet = window.midnight?.mnLace; if (!wallet) { throw new Error("Please install Lace Beta Wallet for Midnight Network"); } const walletAPI = await wallet.enable(); const walletState = await walletAPI.state(); const uris = await wallet.serviceUriConfig(); return { privateStateProvider: levelPrivateStateProvider({ privateStateStoreName: "my-dapp-state", }), zkConfigProvider: new FetchZkConfigProvider( window.location.origin, fetch.bind(window), ), proofProvider: httpClientProofProvider(uris.proverServerUri), publicDataProvider: indexerPublicDataProvider( uris.indexerUri, uris.indexerWsUri, ), walletProvider: { coinPublicKey: walletState.coinPublicKey, encryptionPublicKey: walletState.encryptionPublicKey, balanceTx: (tx, newCoins) => { return walletAPI.balanceAndProveTransaction(tx, newCoins); }, }, midnightProvider: { submitTx: (tx) => { return walletAPI.submitTransaction(tx); }, }, }; } \`\`\` ### 2. Deploy a Contract \`\`\`typescript import { MidnightSetupAPI } from "@meshsdk/midnight-setup"; import { setupProviders } from "./providers"; async function deployContract() { const providers = await setupProviders(); const contractInstance = new MyContract({}); const api = await MidnightSetupAPI.deployContract( providers, contractInstance, ); console.log("Contract deployed at:", api.deployedContractAddress); return api; } \`\`\` ### 3. Join Existing Contract \`\`\`typescript async function joinContract(contractAddress: string) { const providers = await setupProviders(); const contractInstance = new MyContract({}); const api = await MidnightSetupAPI.joinContract( providers, contractInstance, contractAddress, ); return api; } \`\`\` ### 4. Read Contract State \`\`\`typescript // Get contract state const contractState = await api.getContractState(); console.log("Contract data:", contractState.data); // Get ledger state const ledgerState = await api.getLedgerState(); console.log("Message:", ledgerState.ledgerState?.message); \`\`\` ## API Reference ### MidnightSetupAPI #### Static Methods ##### \`deployContract(providers, contractInstance, logger?)\` Deploys a new smart contract to Midnight Network. \*\*Parameters:\*\* \* \`providers\`: \`MidnightSetupContractProviders\` - Network and wallet providers \* \`contractInstance\`: \`ContractInstance\` - Your compiled contract instance \* \`logger?\`: \`Logger\` - Optional Pino logger \*\*Returns:\*\* \`Promise\` ##### \`joinContract(providers, contractInstance, contractAddress, logger?)\` Connects to an existing deployed contract. \*\*Parameters:\*\* \* \`providers\`: \`MidnightSetupContractProviders\` - Network and wallet providers \* \`contractInstance\`: \`ContractInstance\` - Your compiled contract instance \* \`contractAddress\`: \`string\` - Address of the deployed contract \* \`logger?\`: \`Logger\` - Optional Pino logger \*\*Returns:\*\* \`Promise\` #### Instance Methods \* \*\*\`getContractState()\`\*\* - Gets the current state of the contract \* \*\*Returns:\*\* \`Promise\` \* \*\*\`getLedgerState()\`\*\* - Gets and parses the ledger state \* \*\*Returns:\*\* \`Promise\` ## TypeScript Types \`\`\`typescript import type { ContractInstance, ContractStateData, DeployedContract, DeployedMidnightSetupAPI, LedgerStateData, MidnightSetupContractProviders, } from "@meshsdk/midnight-setup"; \`\`\` ## Requirements \* \*\*Node.js\*\* v18 or higher \* \*\*Midnight Lace Wallet\*\* browser extension \* \*\*TypeScript\*\* (recommended) ## React Integration Example ### Complete React Hook \`\`\`typescript import { useState, useCallback } from 'react'; import { MidnightSetupAPI } from '@meshsdk/midnight-setup'; import { setupProviders } from './providers'; export const useMidnightContract = () => { const \[api, setApi\] = useState(null); const \[isLoading, setIsLoading\] = useState(false); const \[error, setError\] = useState(null); const deployContract = useCallback(async (contractInstance) => { setIsLoading(true); setError(null); try { const providers = await setupProviders(); const newApi = await MidnightSetupAPI.deployContract(providers, contractInstance); setApi(newApi); return newApi; } catch (err) { setError(err.message); throw err; } finally { setIsLoading(false); } }, \[\]); const joinContract = useCallback(async (contractInstance, address) => { setIsLoading(true); setError(null); try { const providers = await setupProviders(); const newApi = await MidnightSetupAPI.joinContract(providers, contractInstance, address); setApi(newApi); return newApi; } catch (err) { setError(err.message); throw err; } finally { setIsLoading(false); } }, \[\]); const getContractState = useCallback(async () => { if (!api) throw new Error('No contract API available'); return await api.getContractState(); }, \[api\]); const getLedgerState = useCallback(async () => { if (!api) throw new Error('No contract API available'); return await api.getLedgerState(); }, \[api\]); return { api, deployContract, joinContract, getContractState, getLedgerState, isLoading, error }; }; \`\`\` ### React Component Example \`\`\`typescript import React, { useState } from 'react'; import { useMidnightContract } from './hooks/useMidnightContract'; function ContractManager() { const { api, deployContract, joinContract, getContractState, getLedgerState, isLoading, error } = useMidnightContract(); const \[contractAddress, setContractAddress\] = useState(''); const \[contractState, setContractState\] = useState(null); const handleDeploy = async () => { try { const contractInstance = new MyContract({}); const newApi = await deployContract(contractInstance); console.log('Deployed:', newApi.deployedContractAddress); } catch (err) { console.error('Deploy failed:', err); } }; const handleJoin = async () => { try { const contractInstance = new MyContract({}); await joinContract(contractInstance, contractAddress); console.log('Joined contract:', contractAddress); } catch (err) { console.error('Join failed:', err); } }; const handleGetState = async () => { try { const state = await getContractState(); setContractState(state); } catch (err) { console.error('Get state failed:', err); } }; return ( Contract Manager ---------------- {error && ( Error: {error} )} {isLoading ? 'Deploying...' : 'Deploy Contract'} setContractAddress(e.target.value)} /> Join Contract {api && ( Get Contract State )} {contractState && ( ### Contract State {JSON.stringify(contractState, null, 2)} )} ); } \`\`\` ## Error Handling ### Common Error Patterns \`\`\`typescript const handleMidnightError = (error: Error) => { if (error.message.includes('Please install Lace Beta Wallet')) { return 'Please install Lace Beta Wallet for Midnight Network'; } if (error.message.includes('Insufficient funds')) { return 'Insufficient funds for transaction'; } if (error.message.includes('Contract not found')) { return 'Contract address not found or invalid'; } return 'An unexpected error occurred'; }; \`\`\` ### Error Boundary Component \`\`\`typescript import React from 'react'; interface ErrorBoundaryState { hasError: boolean; error?: Error; } interface ErrorBoundaryProps { children: React.ReactNode; fallback?: React.ComponentType<{ error: Error }>; } export class MidnightErrorBoundary extends React.Component< ErrorBoundaryProps, ErrorBoundaryState > { constructor(props: ErrorBoundaryProps) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error: Error): ErrorBoundaryState { return { hasError: true, error }; } componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { console.error('Midnight Error Boundary caught an error:', error, errorInfo); } render() { if (this.state.hasError) { const FallbackComponent = this.props.fallback || DefaultErrorFallback; return ; } return this.props.children; } } const DefaultErrorFallback: React.FC<{ error: Error }> = ({ error }) => ( Something went wrong with Midnight Network ------------------------------------------ {error.message} window.location.reload()}> Reload Page ); \`\`\` ## Best Practices 1. \*\*Always handle errors\*\* - Wrap API calls in try-catch blocks 2. \*\*Use TypeScript\*\* - Leverage type safety for better development experience 3. \*\*Validate inputs\*\* - Ensure contract instances and addresses are valid 4. \*\*Monitor state changes\*\* - Listen for contract state updates 5. \*\*Test thoroughly\*\* - Use testnet before deploying to mainnet 6. \*\*Implement retry logic\*\* - Allow users to retry failed operations 7. \*\*Secure key handling\*\* - Never store private keys in localStorage # Getting Started URL: /midnight/midnight-setup/getting-started Install and set up @meshsdk/midnight-setup for building zero-knowledge privacy dApps on Midnight Network \*\*\* title: "Getting Started" description: "Install and set up @meshsdk/midnight-setup for building zero-knowledge privacy dApps on Midnight Network" icon: RocketLaunchIcon ---------------------- import Link from "fumadocs-core/link"; This guide will help you get started with building dApps on Midnight Network using the \`@meshsdk/midnight-setup\` package. Midnight Network is a zero-knowledge privacy network that enables confidential smart contracts and transactions. ## Installation Install the Midnight setup package using your preferred package manager: \`\`\`bash # Using npm npm install @meshsdk/midnight-setup # Using yarn yarn add @meshsdk/midnight-setup \`\`\` ## Quick Start ### Basic Usage \`\`\`typescript import { MidnightSetupAPI } from '@meshsdk/midnight-setup'; // Deploy a new contract const api = await MidnightSetupAPI.deployContract(providers, contractInstance); // Join an existing contract const api = await MidnightSetupAPI.joinContract(providers, contractInstance, contractAddress); // Get contract state const state = await api.getContractState(); // Get ledger state const ledgerState = await api.getLedgerState(); \`\`\` ## What's Included This monorepo contains everything you need to build Midnight Network dApps: Example repository: \[midnight-setup\](https://github.com/MeshJS/midnight-setup) \* \*\*@meshsdk/midnight-setup\*\* - Main npm package with API and types \* \*\*packages/ui\*\* - Example React application \* \*\*packages/cli\*\* - Command-line tools \* \*\*packages/api\*\* - Core API implementation \* \\\*\\\*packages/contract/ - Compact contracts ## Project Structure \`\`\` ├── packages/ │ ├── api/ # Core API implementation │ ├── ui/ # React example app │ └── cli/ # Command-line tools │ └── contract/ # Compact contracts ├── compact/ # Smart contract source └── README.md \`\`\` ## Key Features \* \*\*Zero-knowledge privacy\*\* - Built for Midnight Network \* \*\*TypeScript support\*\* - Full type safety \* \*\*React hooks\*\* - Easy integration \* \*\*Wallet integration\*\* - Lace Beta Wallet support \* \*\*CLI tools\*\* - Development utilities \* \*\*Compact contract\*\* - Compact contract integration ## Next Steps \* Learn about the \[Core API Methods\](/midnight/api) \* Set up \[Lace Wallet Integration\](/midnight/wallet) \* Explore \[Integration Examples\](/midnight/examples) ## Resources \* \[Midnight Network Documentation\](https://docs.midnight.network/) \* \[Mesh SDK Documentation\](https://midnight.meshjs.dev/en) \* \[Lace Beta Wallet\](https://chromewebstore.google.com/detail/lace-midnight-preview/hgeekaiplokcnmakghbdfbgnlfheichg) # Overview URL: /midnight/midnight-setup Complete development setup for building Midnight Network dApps \*\*\* title: "Overview" description: "Complete development setup for building Midnight Network dApps" icon: Cog6ToothIcon ------------------- import {linksMidnightSetup} from "@/data/links-midnight"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksMidnightSetup.map((card) => ( {card.title} {card.desc} ))} \# Lace Wallet Integration URL: /midnight/midnight-setup/wallet Complete Lace Beta Wallet integration for Midnight Network dApps \*\*\* title: "Lace Wallet Integration" description: "Complete Lace Beta Wallet integration for Midnight Network dApps" icon: WalletIcon ---------------- import Link from "fumadocs-core/link"; This project includes a complete Lace Beta Wallet integration for Midnight Network, enabling seamless wallet connectivity and transaction management. ## Wallet Features | Feature | Description | Implementation | | -------------------- | -------------------------------- | ------------------------------------- | | Connect Wallet | Connect to Lace Beta Wallet | \`wallet.enable()\` | | Disconnect Wallet | Disconnect from wallet | \`wallet.disconnect()\` | | Get Wallet State | Retrieve wallet address and keys | \`wallet.state()\` | | Deploy Contract | Deploy contracts through wallet | \`wallet.submitTransaction()\` | | Join Contract | Join existing contracts | \`wallet.balanceAndProveTransaction()\` | | Balance Transactions | Balance and prove transactions | Wallet API integration | ## Wallet Provider Setup ### Basic Connection Connect to Lace Wallet and get wallet state: \`\`\`typescript // Check if Lace wallet is available const wallet = window.midnight?.mnLace; if (!wallet) { throw new Error('Please install Lace Beta Wallet for Midnight Network'); } // Enable wallet and get state const walletAPI = await wallet.enable(); const walletState = await walletAPI.state(); const uris = await wallet.serviceUriConfig(); \`\`\` ### When to Use Each Method \* \*\*\`wallet.enable()\`\*\* - Use when you need to connect to the wallet for the first time \* \*\*\`wallet.state()\`\*\* - Use to get current wallet information (address, keys, etc.) \* \*\*\`wallet.serviceUriConfig()\`\*\* - Use to get network service URLs (indexer, prover, etc.) \* \*\*\`wallet.disconnect()\`\*\* - Use when user wants to disconnect from the wallet ## React Wallet Hook ### Hook Implementation Complete implementation of the \`useMidnightWallet\` hook: \`\`\`typescript import { useState, useCallback } from 'react'; export const useMidnightWallet = () => { const \[walletState, setWalletState\] = useState(null); const \[isConnected, setIsConnected\] = useState(false); const \[isLoading, setIsLoading\] = useState(false); const \[error, setError\] = useState(null); const connectWallet = useCallback(async () => { setIsLoading(true); setError(null); try { const wallet = window.midnight?.mnLace; if (!wallet) { throw new Error('Please install Lace Beta Wallet for Midnight Network'); } const walletAPI = await wallet.enable(); const state = await walletAPI.state(); const uris = await wallet.serviceUriConfig(); setWalletState({ state, uris, walletAPI }); setIsConnected(true); } catch (err) { setError(err.message); throw err; } finally { setIsLoading(false); } }, \[\]); const disconnectWallet = useCallback(async () => { try { const wallet = window.midnight?.mnLace; if (wallet) { await wallet.disconnect(); setWalletState(null); setIsConnected(false); setError(null); } } catch (err) { setError(err.message); } }, \[\]); return { connectWallet, disconnectWallet, walletState, isConnected, isLoading, error }; }; \`\`\` ### Using the Hook \`\`\`typescript import { useMidnightWallet } from './hooks/useMidnightWallet'; function App() { const { connectWallet, disconnectWallet, walletState, isConnected, isLoading, error } = useMidnightWallet(); return ( {error && Error: {error} } {isConnected ? ( Connected: {walletState?.state?.address} Disconnect ) : ( {isLoading ? 'Connecting...' : 'Connect Wallet'} )} ); } \`\`\` ## Provider Setup ### Complete Provider Configuration Set up all necessary providers for Midnight Network integration: \`\`\`typescript import { FetchZkConfigProvider } from "@midnight-ntwrk/midnight-js-fetch-zk-config-provider"; import { httpClientProofProvider } from "@midnight-ntwrk/midnight-js-http-client-proof-provider"; import { indexerPublicDataProvider } from "@midnight-ntwrk/midnight-js-indexer-public-data-provider"; import { levelPrivateStateProvider } from "@midnight-ntwrk/midnight-js-level-private-state-provider"; import type { MidnightSetupContractProviders } from "@meshsdk/midnight-setup"; export async function setupProviders(): Promise { const wallet = window.midnight?.mnLace; if (!wallet) { throw new Error("Please install Lace Beta Wallet for Midnight Network"); } const walletAPI = await wallet.enable(); const walletState = await walletAPI.state(); const uris = await wallet.serviceUriConfig(); return { privateStateProvider: levelPrivateStateProvider({ privateStateStoreName: "my-dapp-state", }), zkConfigProvider: new FetchZkConfigProvider( window.location.origin, fetch.bind(window), ), proofProvider: httpClientProofProvider(uris.proverServerUri), publicDataProvider: indexerPublicDataProvider( uris.indexerUri, uris.indexerWsUri, ), walletProvider: { coinPublicKey: walletState.coinPublicKey, encryptionPublicKey: walletState.encryptionPublicKey, balanceTx: (tx, newCoins) => { return walletAPI.balanceAndProveTransaction(tx, newCoins); }, }, midnightProvider: { submitTx: (tx) => { return walletAPI.submitTransaction(tx); }, }, }; } \`\`\` ### Provider Explanation \* \*\*\`privateStateProvider\`\*\* - Manages private state storage \* \*\*\`zkConfigProvider\`\*\* - Handles zero-knowledge proof configuration \* \*\*\`proofProvider\`\*\* - Manages proof generation and verification \* \*\*\`publicDataProvider\`\*\* - Fetches public blockchain data from indexer \* \*\*\`walletProvider\`\*\* - Integrates with Lace wallet for transactions \* \*\*\`midnightProvider\`\*\* - Handles transaction submission to Midnight Network ## Basic Usage Example ### Complete Workflow Here's a complete example showing the full workflow from wallet connection to contract interaction: \`\`\`typescript import { useMidnightWallet } from './hooks/useMidnightWallet'; import { setupProviders } from './lib/providers'; import { MidnightSetupAPI } from '@meshsdk/midnight-setup'; function CompleteExample() { const { connectWallet, disconnectWallet, walletState, isConnected, isLoading, error } = useMidnightWallet(); const \[contractApi, setContractApi\] = useState(null); const \[contractState, setContractState\] = useState(null); // Step 1: Connect wallet const handleConnectWallet = async () => { try { await connectWallet(); console.log('✅ Wallet connected successfully'); } catch (error) { console.error('❌ Wallet connection failed:', error.message); } }; // Step 2: Setup providers and deploy contract const handleDeployContract = async () => { if (!isConnected) { alert('Please connect wallet first'); return; } try { console.log('🔄 Setting up providers...'); const providers = await setupProviders(); console.log('🔄 Deploying contract...'); const contractInstance = new MyContract({}); const api = await MidnightSetupAPI.deployContract(providers, contractInstance); setContractApi(api); console.log('✅ Contract deployed at:', api.deployedContractAddress); } catch (error) { console.error('❌ Contract deployment failed:', error.message); } }; // Step 3: Get contract state const handleGetContractState = async () => { if (!contractApi) { alert('Please deploy or join a contract first'); return; } try { console.log('🔄 Getting contract state...'); const state = await contractApi.getContractState(); setContractState(state); console.log('✅ Contract state:', state); } catch (error) { console.error('❌ Failed to get contract state:', error.message); } }; // Step 4: Join existing contract const handleJoinContract = async (contractAddress) => { if (!isConnected) { alert('Please connect wallet first'); return; } try { console.log('🔄 Setting up providers...'); const providers = await setupProviders(); console.log('🔄 Joining contract...'); const contractInstance = new MyContract({}); const api = await MidnightSetupAPI.joinContract(providers, contractInstance, contractAddress); setContractApi(api); console.log('✅ Joined contract:', contractAddress); } catch (error) { console.error('❌ Failed to join contract:', error.message); } }; return ( Complete Midnight Network Example --------------------------------- {error && ( **Error:** {error} )} ### Step 1: Connect Wallet {!isConnected ? ( {isLoading ? 'Connecting...' : 'Connect Wallet'} ) : ( ✅ Wallet connected: {walletState?.state?.address} Disconnect )} ### Step 2: Deploy Contract Deploy New Contract ### Step 3: Join Contract { const address = document.getElementById('contractAddress').value; if (address) handleJoinContract(address); }} disabled={!isConnected || isLoading} > Join Contract ### Step 4: Get Contract State Get Contract State {contractState && ( #### Contract State: {JSON.stringify(contractState, null, 2)} )} ); } export default CompleteExample; \`\`\` ### Step-by-Step Breakdown 1. \*\*Connect Wallet\*\* - Use \`useMidnightWallet\` hook to connect to Lace Beta Wallet 2. \*\*Setup Providers\*\* - Call \`setupProviders()\` to configure all necessary providers 3. \*\*Deploy Contract\*\* - Use \`MidnightSetupAPI.deployContract()\` to deploy a new contract 4. \*\*Join Contract\*\* - Use \`MidnightSetupAPI.joinContract()\` to connect to existing contract 5. \*\*Get State\*\* - Use \`api.getContractState()\` to retrieve contract information 6. \*\*Handle Errors\*\* - Implement proper error handling throughout the workflow ## Error Handling ### Common Wallet Errors \`\`\`typescript const handleWalletError = (error) => { switch (error.message) { case 'Please install Lace Beta Wallet for Midnight Network': return 'Please install Lace Beta Wallet'; case 'User rejected': return 'Transaction was rejected by user'; case 'Insufficient funds': return 'Insufficient funds for transaction'; case 'Wallet is disconnected': return 'Wallet is disconnected. Please reconnect.'; default: return 'An unexpected error occurred'; } }; \`\`\` ### Error Handling in Components \`\`\`typescript const handleConnect = async () => { try { await connectWallet(); console.log('Wallet connected successfully'); } catch (error) { const errorMessage = handleWalletError(error); console.error('Connection failed:', errorMessage); // Show error to user } }; \`\`\` # Available Contracts URL: /midnight/midnight-contracts-wizard/contracts Explore the smart contract templates available in the Midnight Contracts Wizard \*\*\* title: Available Contracts description: Explore the smart contract templates available in the Midnight Contracts Wizard icon: DocumentTextIcon ---------------------- The Midnight Contracts Wizard includes several production-ready smart contract templates. Each contract is designed with privacy and zero-knowledge proofs in mind. ## Tokenization Contract \*\*7 ZK Circuits\*\* A complete project tokenization system with zero-knowledge privacy for investments. ### Features \* Private token minting and burning \* Confidential balance management \* Investment tracking with ZK proofs \* Transfer with privacy guarantees ### Use Cases \* Real estate tokenization \* Asset-backed securities \* Private equity tracking \* Confidential fundraising \*\*\* ## Staking Contract \*\*8 ZK Circuits\*\* A privacy-focused staking system with rewards and configurable lock periods. ### Features \* Private stake amounts \* Confidential reward distribution \* Flexible lock periods \* Slashing mechanisms ### Use Cases \* Network validation \* Governance participation \* Yield generation \* Long-term holding incentives \*\*\* ## Identity Contracts \*\*1 ZK Circuit\*\* Complete identity management system with cryptographic libraries for privacy-preserving verification. ### Features \* Zero-knowledge identity proofs \* Selective disclosure \* Credential verification \* Privacy-preserving authentication ### Use Cases \* KYC compliance \* Age verification \* Credential validation \* Access control \*\*\* ## Oracle Contract \*\*7 ZK Circuits\*\* Decentralized oracle system with privacy-preserving data feeds. ### Features \* Confidential data ingestion \* Multi-source aggregation \* Tamper-proof feeds \* Privacy-preserving validation ### Use Cases \* Price feeds \* Weather data \* Sports results \* IoT data streams \*\*\* ## Lending & Borrowing Contract \*\*7 ZK Circuits\*\* Privacy-preserving decentralized lending protocol. ### Features \* Confidential collateral management \* Private loan amounts \* Interest rate privacy \* Liquidation with ZK proofs ### Use Cases \* DeFi lending platforms \* Peer-to-peer lending \* Collateralized loans \* Credit lines \*\*\* ## Contract Selection Tips ### Single Contract Projects Perfect for focused applications or proof-of-concepts. Select one contract type and build a specialized solution. ### Multi-Contract Projects Combine multiple contracts for complex dApps. For example: \* \*\*Tokenization + Oracle\*\* - Real-world asset pricing \* \*\*Staking + Identity\*\* - Governance with verified participants \* \*\*Lending + Oracle\*\* - Price-aware DeFi protocols ### All Contracts Select all contracts to explore the full ecosystem or build a comprehensive platform. ## Technical Details Each contract includes: \* Complete \`.compact\` source files \* Compiled TypeScript interfaces \* ZK circuit configurations \* Build and deployment scripts \* Example usage documentation ## Next Steps Learn about the \[Project Structure\](/midnight/midnight-contracts-wizard/project-structure) that gets generated for your selected contracts. # Overview URL: /midnight/midnight-contracts-wizard A CLI tool to create new Midnight contracts projects with selected smart contracts \*\*\* title: Overview description: A CLI tool to create new Midnight contracts projects with selected smart contracts icon: SparklesIcon ------------------ import {linksMidnightContractsWizard} from "@/data/links-midnight"; import Link from "next/link"; import { Card, CardDescription, CardTitle, } from "@/components/ui/card"; {linksMidnightContractsWizard.map((card) => ( {card.title} {card.desc} ))} \# Installation URL: /midnight/midnight-contracts-wizard/installation How to use the Midnight Contracts Wizard CLI tool \*\*\* title: Installation description: How to use the Midnight Contracts Wizard CLI tool icon: ArrowDownTrayIcon ----------------------- The Midnight Contracts Wizard is a CLI tool that you can run directly using \`npx\`. No installation required! ## Using npx (Recommended) Run the wizard directly without installing: \`\`\`bash npx @meshsdk/midnight-contracts-wizard \`\`\` This command will: \* Download the latest version automatically \* Run the interactive wizard \* Create your project with selected contracts ## Check Version You can check the latest version available: \`\`\`bash npx @meshsdk/midnight-contracts-wizard --version \`\`\` ## Requirements \* \*\*Node.js\*\*: Version 18 or higher \* \*\*npm\*\*: Version 8 or higher (includes npx) ## Next Steps Once you're ready, proceed to the \[Usage\](/midnight/midnight-contracts-wizard/usage) section to learn how to create your first project. # Project Structure URL: /midnight/midnight-contracts-wizard/project-structure Understanding the generated project structure \*\*\* title: Project Structure description: Understanding the generated project structure icon: FolderIcon ---------------- # Generated Structure When you create a project using the Midnight Contracts Wizard, it generates a complete directory structure with all necessary files. ## Directory Layout \`\`\` my-project/ ├── src/ │ ├── \[selected-contracts\]/ │ │ └── \*.compact │ └── managed/ # Compiled contracts ├── dist/ # Distribution files ├── package.json ├── tsconfig.json ├── tsconfig.build.json └── README.md \`\`\` ## Directory Breakdown ### \`/src\` Contains all your contract source files. \`\`\` src/ ├── tokenization/ # If selected │ └── token.compact ├── staking/ # If selected │ └── staking.compact ├── identity/ # If selected │ └── identity.compact ├── oracle/ # If selected │ └── oracle.compact ├── lending/ # If selected │ └── lending.compact └── managed/ # Auto-generated └── \*.ts # Compiled TypeScript \`\`\` ### \`/src/managed\` Automatically generated directory containing compiled TypeScript files from your \`.compact\` contracts. \*\*Do not edit manually\*\* - these files are regenerated on each build. ### \`/dist\` Output directory for the final compiled JavaScript and type definitions, ready for distribution or deployment. ## Configuration Files ### \`package.json\` Contains project metadata, dependencies, and build scripts: \`\`\`json { "name": "my-project", "version": "1.0.0", "scripts": { "build": "tsc -p tsconfig.build.json", "compile": "compact-cli compile src/\*\*/\*.compact", "clean": "rm -rf dist src/managed" }, "dependencies": { "@midnight-ntwrk/compact-runtime": "^0.8.1", "@midnight-ntwrk/midnight-js-types": "^2.0.2" } } \`\`\` ### \`tsconfig.json\` Main TypeScript configuration for development: \`\`\`json { "compilerOptions": { "target": "ES2020", "module": "commonjs", "lib": \["ES2020"\], "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "outDir": "./dist", "rootDir": "./src" }, "include": \["src/\*\*/\*"\], "exclude": \["node\_modules", "dist"\] } \`\`\` ### \`tsconfig.build.json\` Extends main config for production builds: \`\`\`json { "extends": "./tsconfig.json", "compilerOptions": { "declaration": true, "declarationMap": true, "sourceMap": true }, "exclude": \["\*\*/\*.test.ts", "\*\*/\*.spec.ts"\] } \`\`\` ## Contract Files Each selected contract includes its \`.compact\` source file: ### Example: \`src/tokenization/token.compact\` \`\`\`text contract Token { // ZK circuit implementations circuit mint(amount: Secret) -> Public { // Minting logic } circuit transfer(to: Address, amount: Secret) -> Public { // Transfer logic } // Additional circuits... } \`\`\` ## README.md Each generated project includes a comprehensive README with: \* Project overview \* Installation instructions \* Build commands \* Contract descriptions \* Usage examples \* Deployment guide ## Next Steps Now that you understand the project structure: \* Start modifying contracts in \`src/\` \* Run builds with \`npm run build\` \* Integrate with your dApp \* Deploy to Midnight Network # Usage URL: /midnight/midnight-contracts-wizard/usage Learn how to use the Midnight Contracts Wizard CLI tool \*\*\* title: Usage description: Learn how to use the Midnight Contracts Wizard CLI tool icon: CommandLineIcon --------------------- ## Basic Usage Run the wizard using npx (no installation required): \`\`\`bash npx @meshsdk/midnight-contracts-wizard \`\`\` ## Interactive Mode When you run the wizard, it will guide you through an interactive setup: 1. \*\*Project Name\*\* - Enter a name for your new project 2. \*\*Select Contracts\*\* - Choose which contract templates to include: \* Tokenization Contract \* Staking Contract \* Identity Contracts \* Oracle Contract \* Lending & Borrowing Contract 3. \*\*Confirmation\*\* - Review your selections and confirm ## Example Session \`\`\`bash $ npx @meshsdk/midnight-contracts-wizard Welcome to Midnight Contracts Wizard! ? Enter your project name: my-midnight-contracts ? Select contracts to include: (Use arrow keys and space to select) ◉ Tokenization Contract (7 ZK circuits) ◯ Staking Contract (8 ZK circuits) ◉ Identity Contracts (1 ZK circuit) ◯ Oracle Contract (7 ZK circuits) ◯ Lending & Borrowing Contract (7 ZK circuits) ✓ Project created successfully! ✓ Tokenization contract added ✓ Identity contracts added 📋 Next steps: 1) Navigate to the project folder: cd ./my-midnight-contracts 2) Compile your smart contracts: compact compile contracts/tokenization/tokenization.compact ./src/managed/tokenization compact compile contracts/identity/identity.compact ./src/managed/identity 💡 Your contracts will be compiled to \`src/managed/\` 💡 Check the \`README.md\` for detailed instructions \`\`\` ## Command Options ### Help Display help information: \`\`\`bash npx @meshsdk/midnight-contracts-wizard --help \`\`\` ### Version Check the installed version: \`\`\`bash npx @meshsdk/midnight-contracts-wizard --version \`\`\` ## Next Steps \* Explore \[Available Contracts\](/midnight/midnight-contracts-wizard/contracts) to understand each contract type \* Review \[Project Structure\](/midnight/midnight-contracts-wizard/project-structure) to learn about generated files # Cardano Course URL: /resources/cardano-course A comprehensive course for building Cardano applications with Mesh SDK and Aiken smart contracts. \*\*\* title: "Cardano Course" description: "A comprehensive course for building Cardano applications with Mesh SDK and Aiken smart contracts." icon: AcademicCapIcon --------------------- import Link from "fumadocs-core/link"; Welcome to the Cardano Course! This comprehensive course will guide you through building Cardano applications, from basic wallet interactions to advanced smart contract development with Aiken. ## Course Structure This course is divided into lessons covering everything you need to become a proficient Cardano developer. ### Lessons The course includes 10 detailed lessons covering: 1. \*\*Hello World\*\* - Install Mesh SDK and learn wallet basics 2. \*\*Multi-signature Transactions\*\* - Build multi-sig transactions 3. \*\*Aiken Contracts\*\* - Introduction to Aiken smart contracts 4. \*\*Contract Testing\*\* - Testing strategies for smart contracts 5. \*\*Avoid Redundant Validation\*\* - Smart contract optimization patterns 6. \*\*Interpreting Blueprint\*\* - Understanding Aiken blueprints 7. \*\*Vesting Contract\*\* - Build a token vesting contract 8. \*\*Plutus NFT Contract\*\* - Create NFT minting contracts 9. \*\*Hydra End-to-End\*\* - Layer 2 scaling with Hydra 10. \*\*Web3 Services\*\* - Wallet-as-a-service and transaction sponsorship ## Getting Started Begin with Lesson 1: Hello World to set up your development environment and create your first Cardano transaction. ## Prerequisites \* Basic understanding of TypeScript/JavaScript \* Node.js v20+ installed \* Familiarity with blockchain concepts (helpful but not required) ## What You'll Learn \* Building Cardano dApps with Mesh SDK \* Creating and deploying Aiken smart contracts \* Transaction building and wallet integration \* Smart contract testing and optimization \* NFT minting and token management \* Layer 2 scaling solutions Start your journey into Cardano development today! # Hello World URL: /resources/cardano-course/lessons/01-wallet-send-lovelace Install Mesh SDK and learn how to send assets using the Mesh wallet. \*\*\* title: "Hello World" description: "Install Mesh SDK and learn how to send assets using the Mesh wallet." ----------------------------------------------------------------------------------- import Link from "fumadocs-core/link"; Welcome to the first lesson of the Cardano Application Development Course! In this session, you'll set up the Mesh SDK and learn how to create a wallet using \`MeshWallet\` and send assets using \`MeshTxBuilder\`. ## System setup Before we begin, let's prepare our system for development. We will be using Node.js v24+ in this course. We recommend nvm to manage your node versions. ### Create a package.json file First, create a new \`package.json\` file in the root of your project with the following content: \`\`\`json { "type": "module", "dependencies": {}, "scripts": {} } \`\`\` ### Install the necessary packages Open your terminal and run these commands to install the MeshSDK: \`\`\`bash npm install npm install @meshsdk/core \`\`\` Here's how your \`package.json\` file should look after installing the package: \`\`\`json { "type": "module", "dependencies": { "@meshsdk/core": "^1.9.0", }, "scripts": {} } \`\`\` \* \`@meshsdk/core\`: Core functionality for network interactions, wallets, and transactions. ## Create a wallet We will use \`MeshWallet\`. This class provides methods to create a new wallet, generate mnemonic phrases, and get the wallet address. ### Generate mnemonic phrases To create a new wallet, we need to generate a mnemonic phrase. A mnemonic phrase is a set of words that can be used to recover your wallet. It is important to keep your mnemonic phrase safe and secure, as it can be used to access your funds. To create a new wallet mnemonic, do the following: \`\`\`ts import { MeshWallet } from "@meshsdk/core"; // Generate new mnemonic phrases for your wallet const mnemonic = MeshWallet.brew(); console.log("Your mnemonic phrases are:", mnemonic); \`\`\` \* Use the \`brew\` method to generate a new mnemonic phrase. ### Initialize the wallet and get the wallet address Now that we have generated a mnemonic phrase, we can initialize the wallet with it. The \`MeshWallet\` class provides a method to create a new wallet using the mnemonic phrase. \`\`\`ts // Initialize the wallet with a mnemonic key const wallet = new MeshWallet({ networkId: 0, // preprod testnet key: { type: "mnemonic", words: mnemonic as string\[\], }, }); // Get the wallet address const address = await wallet.getChangeAddress(); console.log("Your wallet address is:", address); \`\`\` \* \`networkId\`: Specify the network, 0 for preprod testnet. \* \`key\`: Specify the key type and mnemonic phrases. \* \`getChangeAddress\`: Method to get the wallet address. ### Run the code Here is the source code. Create a new file \`mnemonic.ts\` and copy the code into it: \`\`\`ts import { MeshWallet } from "@meshsdk/core"; // Generate new mnemonic phrases for your wallet const mnemonic = MeshWallet.brew(); console.log("Your mnemonic phrases are:", mnemonic); // Initialize the wallet with a mnemonic key const wallet = new MeshWallet({ networkId: 0, // preprod testnet key: { type: "mnemonic", words: mnemonic as string\[\], }, }); // Get the wallet address const address = await wallet.getChangeAddress(); console.log("Your wallet address is:", address); \`\`\` Update the \`package.json\` file to add a script to run the code: \`\`\`json { "type": "module", "dependencies": { "@meshsdk/core": "^1.9.0", }, "scripts": { "mnemonic": "node mnemonic.ts" } } \`\`\` Run the script: \`\`\`bash npm run mnemonic \`\`\` This will generate a new mnemonic phrase and wallet address for you. The output will look something like this: \`\`\`bash > mnemonic > node mnemonic.ts Your mnemonic phrases are: \[ 'access', 'spawn', 'taxi', 'prefer', 'fortune', 'sword', 'nerve', 'price', 'valid', 'panther', 'sure', 'hello', 'layer', 'try', 'grace', 'seven', 'fossil', 'voice', 'tobacco', 'circle', 'measure', 'solar', 'pride', 'together' \] Your wallet address is: addr\_test1qptwuv6dl863u3k93mjrg0hgs0ahl08lfhsudxrwshcsx59cjxatme29s6cl7drjceknunry049shu9eudnsjvwqq9qsuem66d \`\`\` ## Send lovelace Now that we have a wallet and some lovelace, let's learn how to send lovelace using the Mesh SDK. We will use the \`MeshTxBuilder\` class to create a transaction and send it to the network. ### Get lovelace from faucet To get some lovelace for testing, you can use the Cardano Preprod Testnet Faucet. Paste your wallet address and click on the "Request funds" button. You should receive some lovelace in your wallet shortly. ### Get Blockfrost API key In order to create transactions, we need to use APIs to get UTXOs from the network. For this, we will use Blockfrost to get UTXOs and submit transactions. Sign up for a free account and get your API key here. You should get the preprod API key, which starts with \`preprod\`. You can find the API key in the "Projects" section of your Blockfrost account. ### Get wallet information Now, let's get the wallet information using the \`MeshWallet\` class. \`\`\`ts // Get wallet data needed for the transaction const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); \`\`\` \* \`getUtxos\`: Method to get the UTXOs from the wallet. \* \`getChangeAddress\`: Method to get the change address. ### Create a transaction to send lovelace Now, we will create a transaction to send lovelace using the \`MeshTxBuilder\` class. \`\`\`ts // Create the transaction const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true, // optional, prints the transaction body }); const unsignedTx = await txBuilder .txOut( "addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9", \[{ unit: "lovelace", quantity: "1500000" }\] ) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); \`\`\` \* \`txOut\`: Add the recipient address and amount. \* \`changeAddress\`: Set the change address. \* \`selectUtxosFrom\`: Provide wallet UTXOs into the transaction as inputs. \* \`complete\`: Create the transaction. ### Sign and submit the transaction Now that we have created the transaction, we need to sign it and submit it to the network. \`\`\`ts const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); console.log("Transaction hash:", txHash); \`\`\` \* \`signTx\`: Method to sign the transaction, which will return the signed transaction. \* \`submitTx\`: Method to submit the transaction to the network. ### Run the code Here is the source code. Create a new file \`send-lovelace.ts\` and copy the code into it: \`\`\`ts import { BlockfrostProvider, MeshTxBuilder, MeshWallet } from "@meshsdk/core"; // Set up the blockchain provider with your key const provider = new BlockfrostProvider("YOUR\_KEY\_HERE"); // Initialize the wallet with a mnemonic key const wallet = new MeshWallet({ networkId: 0, fetcher: provider, submitter: provider, key: { type: "mnemonic", words: \["your", "mnemonic", "...", "here"\], }, }); // Get wallet data needed for the transaction const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); // Create the transaction const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true, // optional, prints the transaction body }); const unsignedTx = await txBuilder .txOut( "addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9", \[{ unit: "lovelace", quantity: "1500000" }\] ) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); console.log("Transaction hash:", txHash); \`\`\` Update the \`package.json\` file to add a script to run the code: \`\`\`json { "type": "module", "dependencies": { "@meshsdk/core": "^1.9.0", }, "scripts": { "mnemonic": "node mnemonic.ts", "send-lovelace": "node send-lovelace.ts" } } \`\`\` Run the script: \`\`\`bash npm run send-lovelace \`\`\` This will create a transaction to send lovelace to the recipient address and submit it to the network. The output will look something like this: \`\`\`bash > send-lovelace > node send-lovelace.ts txBodyJson - before coin selection {"inputs":\[\],"outputs":\[{"address":"addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9","amount":\[{"unit":"lovelace","quantity":"1500000"}\]}\],"fee":"0","collaterals":\[\],"requiredSignatures":\[\],"referenceInputs":\[\],"mints":\[\],"changeAddress":"addr\_test1qp2k7wnshzngpqw0xmy33hvexw4aeg60yr79x3yeeqt3s2uvldqg2n2p8y4kyjm8sqfyg0tpq9042atz0fr8c3grjmysdp6yv3","metadata":{},"validityRange":{},"certificates":\[\],"withdrawals":\[\],"votes":\[\],"signingKey":\[\],"chainedTxs":\[\],"inputsForEvaluation":{},"network":"mainnet","expectedNumberKeyWitnesses":0,"expectedByronAddressWitnesses":\[\]} txBodyJson - after coin selection {"inputs":\[{"type":"PubKey","txIn":{"txHash":"99d859b305ab8021e497fad0dc55373e50fffd3e7026142fa3cf5accfe0d3aab","txIndex":1,"amount":\[{"unit":"lovelace","quantity":"9823719"}\],"address":"addr\_test1qp2k7wnshzngpqw0xmy33hvexw4aeg60yr79x3yeeqt3s2uvldqg2n2p8y4kyjm8sqfyg0tpq9042atz0fr8c3grjmysdp6yv3"}}\],"outputs":\[{"address":"addr\_test1qpvx0sacufuypa2k4sngk7q40zc5c4npl337uusdh64kv0uafhxhu32dys6pvn6wlw8dav6cmp4pmtv7cc3yel9uu0nq93swx9","amount":\[{"unit":"lovelace","quantity":"1500000"}\]},{"address":"addr\_test1qp2k7wnshzngpqw0xmy33hvexw4aeg60yr79x3yeeqt3s2uvldqg2n2p8y4kyjm8sqfyg0tpq9042atz0fr8c3grjmysdp6yv3","amount":\[{"unit":"lovelace","quantity":"8153730"}\]}\],"fee":"169989","collaterals":\[\],"requiredSignatures":\[\],"referenceInputs":\[\],"mints":\[\],"changeAddress":"addr\_test1qp2k7wnshzngpqw0xmy33hvexw4aeg60yr79x3yeeqt3s2uvldqg2n2p8y4kyjm8sqfyg0tpq9042atz0fr8c3grjmysdp6yv3","metadata":{},"validityRange":{},"certificates":\[\],"withdrawals":\[\],"votes":\[\],"signingKey":\[\],"chainedTxs":\[\],"inputsForEvaluation":{"99d859b305ab8021e497fad0dc55373e50fffd3e7026142fa3cf5accfe0d3aab1":{"input":{"outputIndex":1,"txHash":"99d859b305ab8021e497fad0dc55373e50fffd3e7026142fa3cf5accfe0d3aab"},"output":{"address":"addr\_test1qp2k7wnshzngpqw0xmy33hvexw4aeg60yr79x3yeeqt3s2uvldqg2n2p8y4kyjm8sqfyg0tpq9042atz0fr8c3grjmysdp6yv3","amount":\[{"unit":"lovelace","quantity":"9823719"}\]}}},"network":"mainnet","expectedNumberKeyWitnesses":0,"expectedByronAddressWitnesses":\[\]} Transaction hash: 62a825c607e4ca5766325c2fccd7ee98313ff81b7e8a4af67eac421b0f0866ff \`\`\` You should see the transaction hash in the output. Note, in the \`MeshTxBuilder\` class, we have set \`verbose: true\`, which will print the transaction body before and after coin selection. This is useful for debugging and understanding how the transaction is built. ## Source code The source code for this lesson is available on GitHub. ## Challenge Create a transaction that sends multiple assets to multiple addresses. Explore the Mesh SDK docs for more! # Multi-signature Transactions URL: /resources/cardano-course/lessons/02-multisig Learn to build multi-signature transactions on Cardano. \*\*\* title: "Multi-signature Transactions" description: "Learn to build multi-signature transactions on Cardano." ---------------------------------------------------------------------- import Link from "fumadocs-core/link"; A multi-signature (multi-sig) transaction requires more than one user to sign a transaction before it is broadcast on the blockchain. Think of it like a joint savings account where both parties must approve spending. Multi-sig transactions can include two or more required signers, which can be wallets or scripts. In this lesson, you'll learn how to: \* Build multi-signature transactions to mint a token. \* Set up a NextJS app with a simple web interface to interact with the Cardano blockchain. ## System setup ### Download CIP30 Wallet Extension To interact with the blockchain, you'll need a wallet extension that supports the CIP30 standard. Choose and download one here. After downloading the wallet, restore it using the seed phrase you created in the previous lesson. ### Set Up NextJS and Mesh Open your terminal and run the following command to create a new NextJS application: \`\`\`bash npx create-next-app@latest --typescript mesh-multisig \`\`\` Follow the prompts: \`\`\`bash Need to install the following packages: Ok to proceed? (y) ✔ Would you like to use ESLint? … Yes ✔ Would you like to use Tailwind CSS? … Yes ✔ Would you like your code inside a \`src/\` directory? … Yes ✔ Would you like to use App Router? … No ✔ Would you like to use Turbopack for next dev? … No ✔ Would you like to customize the import alias (@/\* by default)? … No \`\`\` Navigate to the newly created folder: \`\`\`bash cd mesh-multisig \`\`\` Install the latest version of Mesh: \`\`\`bash npm install @meshsdk/core @meshsdk/react \`\`\` ### Add MeshProvider To use Mesh React, wrap your application with the \`MeshProvider\` component. Open the \`src/app/layout.tsx\` file and add: \`\`\`ts import "@/styles/globals.css"; import type { AppProps } from "next/app"; import "@meshsdk/react/styles.css"; import { MeshProvider } from "@meshsdk/react"; export default function App({ Component, pageProps }: AppProps) { return ( ); } \`\`\` ### Add CardanoWallet Component Add a wallet React component to connect to the wallet and interact with the blockchain. Open the \`src/pages/index.tsx\` file, delete the existing code, and replace it with: \`\`\`ts import { CardanoWallet, useWallet } from "@meshsdk/react"; export default function Home() { const { wallet, connected } = useWallet(); return ( ); } \`\`\` Start the development server: \`\`\`bash npm run dev \`\`\` Visit \[http://localhost:3000\](http://localhost:3000) to view your application. Press \*\*CTRL+C\*\* to stop the server. You should see a "Connect Wallet" component. Try connecting to your wallet. ## Minting Script In this section, you'll create a minting script to mint a token using a multi-signature transaction. ### Define the Minting Script Set up constants for the minting script: \`\`\`ts const provider = new BlockfrostProvider("YOUR\_KEY\_HERE"); const demoAssetMetadata = { name: "Mesh Token", image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "This NFT was minted by Mesh (https://meshjs.dev/).", }; const mintingWallet = \["your", "mnemonic", "...", "here"\]; \`\`\` \* Replace \`YOUR\_KEY\_HERE\` with your Blockfrost API key. \* Define asset metadata in \`demoAssetMetadata\`. \* Use a mnemonic for the minting wallet. ### Create Minting Application Wallet Create a function to build the minting transaction: \`\`\`ts async function buildMintTx(inputs: UTxO\[\], changeAddress: string) { const wallet = new MeshWallet({ networkId: 0, key: { type: "mnemonic", words: mintingWallet, }, }); const { pubKeyHash: keyHash } = deserializeAddress( await wallet.getChangeAddress() ); } \`\`\` \* \`inputs\`: UTxOs from your wallet to pay minting fees. \* Initialize the wallet with the mnemonic. \* Derive the \`pubKeyHash\` for the minting script. ### Create Native Script Define the native script: \`\`\`ts const nativeScript: NativeScript = { type: "all", scripts: \[ { type: "before", slot: "99999999", }, { type: "sig", keyHash: keyHash, }, \], }; const forgingScript = ForgeScript.fromNativeScript(nativeScript); \`\`\` \* \`nativeScript\`: Parameters for the script. \* \`ForgeScript.fromNativeScript\`: Create the forging script. ### Define Asset Metadata Set up asset metadata: \`\`\`ts const policyId = resolveScriptHash(forgingScript); const tokenName = "MeshToken"; const tokenNameHex = stringToHex(tokenName); const metadata = { \[policyId\]: { \[tokenName\]: { ...demoAssetMetadata } } }; \`\`\` \* \`policyId\`: Derived from the forging script. \* \`tokenName\`: Name of the token. \* \`metadata\`: Asset metadata. ### Create Transaction Build the minting transaction: \`\`\`ts const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true, }); const unsignedTx = await txBuilder .mint("1", policyId, tokenNameHex) .mintingScript(forgingScript) .metadataValue(721, metadata) .changeAddress(changeAddress) .invalidHereafter(99999999) .requiredSignerHash(keyHash) .selectUtxosFrom(inputs) .complete(); \`\`\` \* \`mint\`: Add token details. \* \`mintingScript\`: Attach the minting script. \* \`metadataValue\`: Add asset metadata. \* \`changeAddress\`: Specify the change address. \* \`invalidHereafter\`: Set transaction expiry. \* \`selectUtxosFrom\`: Use UTxOs for fees. \* \`requiredSignerHash\` to declare that the minter wallet pub key hash is required. \* \`complete\`: Finalize the transaction. ### Sign the Transaction Sign the transaction with the minting wallet: \`\`\`ts const signedTx = await wallet.signTx(unsignedTx, true); \`\`\` ### Source code Here is the complete code for building the minting transaction: \`\`\`ts async function buildMintTx(inputs: UTxO\[\], changeAddress: string) { // minting wallet const wallet = new MeshWallet({ networkId: 0, key: { type: "mnemonic", words: mintingWallet, }, }); const { pubKeyHash: keyHash } = deserializeAddress( await wallet.getChangeAddress() ); // create minting script const nativeScript: NativeScript = { type: "all", scripts: \[ { type: "before", slot: "99999999", }, { type: "sig", keyHash: keyHash, }, \], }; const forgingScript = ForgeScript.fromNativeScript(nativeScript); // create metadata const policyId = resolveScriptHash(forgingScript); const tokenName = "MeshToken"; const tokenNameHex = stringToHex(tokenName); const metadata = { \[policyId\]: { \[tokenName\]: { ...demoAssetMetadata } } }; // create transaction const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true, }); const unsignedTx = await txBuilder .mint("1", policyId, tokenNameHex) .mintingScript(forgingScript) .metadataValue(721, metadata) .changeAddress(changeAddress) .invalidHereafter(99999999) .requiredSignerHash(keyHash) .selectUtxosFrom(inputs) .complete(); const signedTx = await wallet.signTx(unsignedTx, true); return signedTx; } \`\`\` ## Execute the transaction Now that we have the minting transaction, we can execute it. \`\`\`ts async function mint() { if (connected) { const inputs = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const tx = await buildMintTx(inputs, changeAddress); const signedTx = await wallet.signTx(tx, true); const txHash = await wallet.submitTx(signedTx); console.log("Transaction hash:", txHash); } } \`\`\` \* Check wallet connection. \* Get UTxOs and change address. \* Build, sign, and submit the transaction. ## Source code The source code for this lesson is available on GitHub. ## Challenge Create a multi-signature wallet requiring 2 out of 3 signers to approve a transaction. Build and sign a transaction with two signers, submit it, and verify success. # Aiken Contracts URL: /resources/cardano-course/lessons/03-aiken-contracts Building Aiken smart contracts. \*\*\* title: "Aiken Contracts" description: "Building Aiken smart contracts." ---------------------------------------------- import Link from "fumadocs-core/link"; From lesson 3 to lesson 6, we will explore the core concepts of building Aiken smart contracts. Some materials are abstracted from Andamio's AikenPBL. ### Overview \* \*\*Hello Cardano Course\*\*: Explains selected vital concepts of Aiken smart contract development. \* \*\*AikenPBL\*\*: A complete end-to-end project-based learning course covering essential and basic concepts. Aiken smart contract development is a specialized field. To dive deeper and start a career as a Cardano on-chain developer, we recommend completing both courses. ## System Setup Before we begin, let's prepare our system for development. We will use Aiken for this course. Follow one of these guides to set up your system: 1. Aiken Official Installation Guide 2. Andamio's AikenPBL Setup Guide ### Set Up an Empty Aiken Project Run the following command to create a new Aiken project using Mesh's template: \`\`\`bash npx meshjs 03-aiken-contracts \`\`\` Select the \`Aiken\` template when prompted. !\[Select at CLI\](../../../../../public/lessons/03-aiken-contracts/mesh-aiken-template.png) After installation, a new folder \`03-aiken-contracts\` will be created with the following structure: \`\`\` 03-aiken-contracts ├── aiken-workspace // Main Aiken project folder used in lessons └── mesh // Folder for equivalent Mesh off-chain code (not used in lessons) \`\`\` ### Optional: Install Cardano-Bar If you use VSCode as your IDE, install the Cardano-Bar extension for code snippets to follow the course more easily. !\[Aiken script info\](../../../../../public/lessons/03-aiken-contracts/cardano-bar.png) ## Understanding Transaction Context Cardano contracts are not like traditional smart contracts on other blockchains. They are more like a set of rules governing how transactions are validated. \*\*Validator\*\* is a better term to describe Cardano contracts. To build Cardano validators, we need to understand how transactions work. Refer to the Aiken documentation for details on the \`Transaction\` structure. !\[Aiken Tx\](../../../../../public/lessons/03-aiken-contracts/aiken-tx.png) ### Inputs & Outputs All Cardano transactions must have inputs and outputs: \* \*\*Inputs\*\*: UTXOs being spent in the transaction. \* \*\*Outputs\*\*: UTXOs being created in the transaction. Refer to Aiken documentation for types: !\[Input\](../../../../../public/lessons/03-aiken-contracts/input.png) !\[Output\](../../../../../public/lessons/03-aiken-contracts/output.png) Key concepts: \* An input references an output of a previous transaction, identified by \`output\_reference\`. \* Validators can check: \* If an input spends from a specific address. \* If an input spends a specific asset. \* If an output sends to a specific address. \* If an output sends a specific asset. \* If input/output datum contains specific information. ### Reference Inputs \`reference\_inputs\` in \`Transaction\` are inputs not spent but referenced in the validator. Useful for reading datum from a UTXO without spending it. ### Mint \`mint\` in \`Transaction\` lists assets being minted or burned. Useful for creating or burning tokens. ### Signatures \`extra\_signatories\` in \`Transaction\` lists public key hashes required to sign the transaction. Useful for enforcing specific users to sign. ### Time \`validity\_range\` in \`Transaction\` specifies the range of slots the transaction is valid for. Useful for enforcing time locks. ## Types of Scripts Refer to Aiken documentation for types of scripts in Cardano. Common types: \* \*\*Minting\*\* \* \*\*Spending\*\* \* \*\*Withdrawing\*\* !\[Aiken script info\](../../../../../public/lessons/03-aiken-contracts/scriptinfo.png) ### Minting Script Minting script validation logic is triggered when assets are minted or burned under the script's policy. Example: \`/aiken-workspace/validators/mint.ak\`: \`\`\`rs use cardano/assets.{PolicyId} use cardano/transaction.{Transaction, placeholder} validator always\_succeed { mint(\_redeemer: Data, \_policy\_id: PolicyId, \_tx: Transaction) { True } else(\_) { fail @"unsupported purpose" } } test test\_always\_succeed\_minting\_policy() { let data = Void always\_succeed.mint(data, #"", placeholder) } \`\`\` This script compiles into a script with hash \`def68337867cb4f1f95b6b811fedbfcdd7780d10a95cc072077088ea\`, also called \`policy Id\`. It validates transactions minting or burning assets under this policy. #### Parameters Upgrade the script to allow minting/burning only when signed by a specific key: \`\`\`rs validator minting\_policy(owner\_vkey: VerificationKeyHash) { mint(\_redeemer: Data, \_policy\_id: PolicyId, tx: Transaction) { key\_signed(tx.extra\_signatories, owner\_vkey) } else(\_) { fail @"unsupported purpose" } } \`\`\` \* \`owner\_vkey\`: Public key hash of the owner allowed to mint/burn assets. \* Use \`key\_signed\` from vodka for validation. #### Redeemer Extend the policy to include a redeemer specifying the transaction action (minting or burning): \`\`\`rs pub type MyRedeemer { MintToken BurnToken } validator minting\_policy( owner\_vkey: VerificationKeyHash, minting\_deadline: Int, ) { mint(redeemer: MyRedeemer, policy\_id: PolicyId, tx: Transaction) { when redeemer is { MintToken -> { let before\_deadline = valid\_before(tx.validity\_range, minting\_deadline) let is\_owner\_signed = key\_signed(tx.extra\_signatories, owner\_vkey) before\_deadline? && is\_owner\_signed? } BurnToken -> check\_policy\_only\_burn(tx.mint, policy\_id) } } else(\_) { fail @"unsupported purpose" } } \`\`\` ### Spending Script Spending script validation is triggered when a UTXO is spent in the transaction. Example: \`/aiken-workspace/validators/spend.ak\`: \`\`\`rs pub type Datum { oracle\_nft: PolicyId, } validator hello\_world { spend( datum\_opt: Option, \_redeemer: Data, \_input: OutputReference, tx: Transaction, ) { when datum\_opt is { Some(datum) -> when inputs\_with\_policy(tx.reference\_inputs, datum.oracle\_nft) is { \[\_ref\_input\] -> True \_ -> False } None -> False } } else(\_) { fail @"unsupported purpose" } } \`\`\` #### Datum \* \`Datum\`: Data attached to UTXOs at script addresses. \* Common design pattern: Use an oracle NFT (state thread token) to ensure UTXO uniqueness. ### Withdrawing Script Withdrawal script validation is triggered when withdrawing from a reward account. Example: \`/aiken-workspace/validators/withdraw.ak\`: \`\`\`rs use aiken/crypto.{VerificationKeyHash} use cardano/address.{Credential, Script} use cardano/certificate.{Certificate} use cardano/transaction.{Transaction, placeholder} validator always\_succeed(\_key\_hash: VerificationKeyHash) { withdraw(\_redeemer: Data, \_credential: Credential, \_tx: Transaction) { True } publish(\_redeemer: Data, \_certificate: Certificate, \_tx: Transaction) { True } else(\_) { fail @"unsupported purpose" } } test test\_always\_succeed\_withdrawal\_policy() { let data = Void always\_succeed.withdraw("", data, Script(#""), placeholder) } \`\`\` #### Handling Publishing All withdrawal scripts must be registered on-chain before they can be used. This is done by publishing a registration certificate with the script hash as the stake credential. The publishing of the script is also validated by the \`publish\` function in the withdrawal script, which is triggered whenever the current withdrawal script is being registered or deregistered. #### When withdrawal script is used? For most Cardano users, we would just use a normal payment key to stake and withdraw rewards. However, it is very popular for Cardano DApps to build withdrawal scripts to enhance the efficiency of validation. We will cover this trick in lesson 5. # Contract Testing URL: /resources/cardano-course/lessons/04-contract-testing Testing Aiken smart contracts. \*\*\* title: "Contract Testing" description: "Testing Aiken smart contracts." --------------------------------------------- import Link from "fumadocs-core/link"; Testing Aiken contracts is crucial to ensure they behave as expected. In this lesson, we will cover: \* Preparing a complex contract for testing \* Building mock transactions in Aiken and running tests ## Preparing a Complex Contract We will enhance the withdrawal contract from the previous lesson to include two user actions: \`ContinueCounting\` or \`StopCounting\`. 1. \*\*ContinueCounting\*\*: \* Verify the transaction is signed by the app owner. \* Ensure the app is not expired (using a POSIX timestamp). \* Carry forward the state thread token to the output. \* Increment the count in the state thread token's datum by 1. 2. \*\*StopCounting\*\*: \* Verify the transaction is signed by the app owner. \* Ensure the state thread token is burned (not carried forward to any output). ### Contract Code \`\`\`rs use aiken/crypto.{VerificationKeyHash} use cardano/address.{Address, Credential} use cardano/assets.{PolicyId} use cardano/certificate.{Certificate} use cardano/transaction.{Transaction} use cocktail.{input\_inline\_datum, inputs\_with\_policy, key\_signed, valid\_before} pub type OracleDatum { app\_owner: VerificationKeyHash, app\_expiry: Int, spending\_validator\_address: Address, state\_thread\_token\_policy\_id: PolicyId, } pub type MyRedeemer { ContinueCounting StopCounting } validator complex\_withdrawal\_contract(oracle\_nft: PolicyId) { withdraw(redeemer: MyRedeemer, \_credential: Credential, tx: Transaction) { let Transaction { reference\_inputs, mint, extra\_signatories, validity\_range, .. } = tx expect \[oracle\_ref\_input\] = inputs\_with\_policy(reference\_inputs, oracle\_nft) expect OracleDatum { app\_owner, app\_expiry, .. } = input\_inline\_datum(oracle\_ref\_input) let is\_app\_owner\_signed = key\_signed(extra\_signatories, app\_owner) when redeemer is { ContinueCounting -> { let is\_app\_not\_expired = valid\_before(validity\_range, app\_expiry) let is\_nothing\_minted = mint == assets.zero is\_app\_owner\_signed? && is\_app\_not\_expired? && is\_nothing\_minted? } StopCounting -> todo } } publish(\_redeemer: Data, \_credential: Certificate, \_tx: Transaction) { True } else(\_) { fail @"unsupported purpose" } } \`\`\` In this setup, we define 2 potential user action with \`MyRedeemer\`, either to \`ContinueCounting\` or \`StopCounting\`. We built the partial logics for \`ContinueCounting\` action, which we put all the logics we have learnt from lesson 3. ### \`expect\` Notice we touch on the syntax of \`expect\` the first time here. \`expect\` is used to enforce the exact pattern for a variable. In above example, \`inputs\_with\_policy(reference\_inputs, oracle\_nft)\` returns \`List\`. However, since in this application we are confident that there is always one item in the list, perhaps since \`oracle\_nft\` is unique, it is impossible to obtain two inputs with \`oracle\_nft\` in value. So that we can use \`expect\` here. ### \`?\` operator In the last line of \`ContinueCounting\` branch, you may notice the use of \`?\` operator. This operator is a tracing operator that helps to trace which condition fails when the validator fails. For example, if \`is\_app\_owner\_signed\` is false, then the validator will fail with message \`is\_app\_owner\_signed?\` which helps to identify the root cause of failure. ## Validating Input & Output We complete the contract by validating inputs and outputs: \`\`\`rs use aiken/crypto.{VerificationKeyHash} use cardano/address.{Address, Credential} use cardano/assets.{PolicyId, without\_lovelace} use cardano/certificate.{Certificate} use cardano/transaction.{Transaction} use cocktail.{ input\_inline\_datum, inputs\_at\_with\_policy, inputs\_with\_policy, key\_signed, output\_inline\_datum, outputs\_at\_with\_policy, valid\_before, } pub type OracleDatum { app\_owner: VerificationKeyHash, app\_expiry: Int, spending\_validator\_address: Address, state\_thread\_token\_policy\_id: PolicyId, } pub type SpendingValidatorDatum { count: Int, } pub type MyRedeemer { ContinueCounting StopCounting } validator complex\_withdrawal\_contract(oracle\_nft: PolicyId) { withdraw(redeemer: MyRedeemer, \_credential: Credential, tx: Transaction) { let Transaction { reference\_inputs, inputs, outputs, mint, extra\_signatories, validity\_range, .. } = tx expect \[oracle\_ref\_input\] = inputs\_with\_policy(reference\_inputs, oracle\_nft) expect OracleDatum { app\_owner, app\_expiry, spending\_validator\_address, state\_thread\_token\_policy\_id, } = input\_inline\_datum(oracle\_ref\_input) expect \[state\_thread\_input\] = inputs\_at\_with\_policy( inputs, spending\_validator\_address, state\_thread\_token\_policy\_id, ) let is\_app\_owner\_signed = key\_signed(extra\_signatories, app\_owner) when redeemer is { ContinueCounting -> { expect \[state\_thread\_output\] = outputs\_at\_with\_policy( outputs, spending\_validator\_address, state\_thread\_token\_policy\_id, ) expect input\_datum: SpendingValidatorDatum = input\_inline\_datum(state\_thread\_input) expect output\_datum: SpendingValidatorDatum = output\_inline\_datum(state\_thread\_output) let is\_app\_not\_expired = valid\_before(validity\_range, app\_expiry) let is\_count\_added = input\_datum.count + 1 == output\_datum.count let is\_nothing\_minted = mint == assets.zero is\_app\_owner\_signed? && is\_app\_not\_expired? && is\_count\_added && is\_nothing\_minted? } StopCounting -> { let state\_thread\_value = state\_thread\_input.output.value |> without\_lovelace() let is\_thread\_token\_burned = mint == assets.negate(state\_thread\_value) is\_app\_owner\_signed? && is\_thread\_token\_burned? } } } publish(\_redeemer: Data, \_credential: Certificate, \_tx: Transaction) { True } else(\_) { fail @"unsupported purpose" } } \`\`\` We have used some new techniques here. We have extracted the inline datum of the state thread token input and output using \`input\_inline\_datum\` and \`output\_inline\_datum\`. We have also used \`inputs\_at\_with\_policy\` and \`outputs\_at\_with\_policy\` to filter the inputs and outputs at a specific address with a specific policy ID. With that, we can compare the datum of input and output to ensure the count is incremented by 1. In \`StopCounting\` case, we ensure the state thread token is burned by checking the \`mint\` field of the transaction. We use \`without\_lovelace\` to ignore the lovelace part of the value when comparing. ## Build mock transaction in Aiken All Aiken contracts can be interpreted as simple functions, which takes in a few parameters and returns a boolean value. This makes it easy to test the contract by providing mock data. In Aiken, we can build testing functions with \`test\` keyword, followed by running \`aiken check\` in project root to execute the tests. The vanilla example: \`\`\`rs test always\_true() { True } \`\`\` With \`aiken check\`, we will see: !\[Dummy Test\](../../../../../public/lessons/04-contract-testing/dummy-test.png) ### Testing always succeed and always fail cases In our complex withdrawal contract, we have a \`publish\` function that always returns \`True\`. We can write a test for it: \`\`\`rs use mocktail.{complete, mock\_utxo\_ref, mocktail\_tx} test test\_publish() { let data = Void complex\_withdrawal\_contract.publish( "", data, RegisterCredential(Script(#""), Never), mocktail\_tx() |> complete(), ) } \`\`\` In this test, we call the \`publish\` function of our contract with mock parameters. We use \`mocktail\_tx()\` to create a mock transaction and \`complete()\` to provide an empty \`Transaction\`. For the rest of script purposes, it will fallback to the \`else\` branch which always fails. We can write a test for it: \`\`\`rs test test\_else() fail { complex\_withdrawal\_contract.else( "", ScriptContext( mocktail\_tx() |> complete(), Void, Spending(mock\_utxo\_ref(0, 0), None), ), ) } \`\`\` Note that the test is not returning a \`False\`, but the programme breaks with \`fail\`. We can indicate that the test is expected to fail by adding \`fail\` after the test name. Running \`aiken check\` will show: !\[Always Succeed and Always Fail Test\](../../../../../public/lessons/04-contract-testing/always-succeed-n-fail.png) ### Testing \`withdraw\` function You will notice the \`withdraw\` function is validated the \`Transaction\` mostly, therefore, we should craft the \`Transaction\` carefully. However, crafting it with mock data is a bit tricky especially when we have to deal with all the Aiken types. \`vodka\` library comes to rescue. In \`vodka\`, the \`mocktail\` module provides a set of functions to create mock data for testing Aiken contracts. We can use \`mocktail\_tx()\` to create a mock \`Transaction\` and then use various functions to modify the transaction to fit our test case. \`\`\`rs const mock\_oracle\_nft = mock\_policy\_id(0) const mock\_oracle\_address = mock\_script\_address(0, None) const mock\_oracle\_value = assets.from\_asset(mock\_oracle\_nft, "", 1) |> assets.add("", "", 2\_000\_000) const mock\_app\_owner = mock\_pub\_key\_hash(0) const mock\_spending\_validator\_address = mock\_script\_address(1, None) const mock\_state\_thread\_token\_policy\_id = mock\_policy\_id(1) const mock\_state\_thread\_value = assets.from\_asset(mock\_state\_thread\_token\_policy\_id, "", 1) |> assets.add("", "", 2\_000\_000) const mock\_oracle\_datum = OracleDatum { app\_owner: mock\_app\_owner, app\_expiry: 1000, spending\_validator\_address: mock\_spending\_validator\_address, state\_thread\_token\_policy\_id: mock\_state\_thread\_token\_policy\_id, } fn mock\_datum(count: Int) -> SpendingValidatorDatum { SpendingValidatorDatum { count } } fn mock\_continue\_counting\_tx() -> Transaction { mocktail\_tx() |> ref\_tx\_in( True, mock\_tx\_hash(0), 0, mock\_oracle\_value, mock\_oracle\_address, ) |> ref\_tx\_in\_inline\_datum(True, mock\_oracle\_datum) |> tx\_in( True, mock\_tx\_hash(1), 0, mock\_state\_thread\_value, mock\_spending\_validator\_address, ) |> tx\_in\_inline\_datum(True, mock\_datum(0)) |> tx\_out(True, mock\_spending\_validator\_address, mock\_state\_thread\_value) |> tx\_out\_inline\_datum(True, mock\_datum(1)) |> required\_signer\_hash(True, mock\_app\_owner) |> invalid\_hereafter(True, 999) |> complete() } \`\`\` We can import all the \`mock\_...\` functions from \`mocktail\` module to build up the types we need. In above example, we create a mock transaction for \`ContinueCounting\` action. We create the oracle NFT input with inline datum, the state thread token input with inline datum, the state thread token output with inline datum, the required signer and the validity range. Now we can write a test for \`ContinueCounting\` action: \`\`\`rs test success\_continue\_counting() { complex\_withdrawal\_contract.withdraw( mock\_oracle\_nft, ContinueCounting, Credential.Script(#""), mock\_continue\_counting\_tx(), ) } \`\`\` ### Dynamically Testing Failure Cases In the mocktail transaction building methods, we can pass a boolean parameter to indicate whether we want the field to be present or not. This allows us to dynamically create failure cases by omitting certain fields. \`\`\`rs type ContinueCountingTest { is\_ref\_input\_presented: Bool, is\_thread\_input\_presented: Bool, is\_thread\_output\_presented: Bool, is\_count\_added: Bool, is\_app\_owner\_signed: Bool, is\_tx\_not\_expired: Bool, } fn mock\_continue\_counting\_tx(test\_case: ContinueCountingTest) -> Transaction { let ContinueCountingTest { is\_ref\_input\_presented, is\_thread\_input\_presented, is\_thread\_output\_presented, is\_count\_added, is\_app\_owner\_signed, is\_tx\_not\_expired, } = test\_case let output\_datum = if is\_count\_added { mock\_datum(1) } else { mock\_datum(0) } mocktail\_tx() |> ref\_tx\_in( is\_ref\_input\_presented, mock\_tx\_hash(0), 0, mock\_oracle\_value, mock\_oracle\_address, ) |> ref\_tx\_in\_inline\_datum(is\_ref\_input\_presented, mock\_oracle\_datum) |> tx\_in( is\_thread\_input\_presented, mock\_tx\_hash(1), 0, mock\_state\_thread\_value, mock\_spending\_validator\_address, ) |> tx\_in\_inline\_datum(is\_thread\_input\_presented, mock\_datum(0)) |> tx\_out( is\_thread\_output\_presented, mock\_spending\_validator\_address, mock\_state\_thread\_value, ) |> tx\_out\_inline\_datum(is\_thread\_output\_presented, output\_datum) |> required\_signer\_hash(is\_app\_owner\_signed, mock\_app\_owner) |> invalid\_hereafter(is\_tx\_not\_expired, 999) |> complete() } \`\`\` And we update the successful test accordingly: \`\`\`rs test success\_continue\_counting() { let test\_case = ContinueCountingTest { is\_ref\_input\_presented: True, is\_thread\_input\_presented: True, is\_thread\_output\_presented: True, is\_count\_added: True, is\_app\_owner\_signed: True, is\_tx\_not\_expired: True, } complex\_withdrawal\_contract.withdraw( mock\_oracle\_nft, ContinueCounting, Credential.Script(#""), mock\_continue\_counting\_tx(test\_case), ) } \`\`\` And we can populate the failure cases at ease: \`\`\`rs test fail\_continue\_counting\_no\_ref\_input() fail { let test\_case = ContinueCountingTest { is\_ref\_input\_presented: False, is\_thread\_input\_presented: True, is\_thread\_output\_presented: True, is\_count\_added: True, is\_app\_owner\_signed: True, is\_tx\_not\_expired: True, } complex\_withdrawal\_contract.withdraw( mock\_oracle\_nft, ContinueCounting, Credential.Script(#""), mock\_continue\_counting\_tx(test\_case), ) } test fail\_continue\_counting\_no\_thread\_input() fail { let test\_case = ContinueCountingTest { is\_ref\_input\_presented: True, is\_thread\_input\_presented: False, is\_thread\_output\_presented: True, is\_count\_added: True, is\_app\_owner\_signed: True, is\_tx\_not\_expired: True, } complex\_withdrawal\_contract.withdraw( mock\_oracle\_nft, ContinueCounting, Credential.Script(#""), mock\_continue\_counting\_tx(test\_case), ) } test fail\_continue\_counting\_no\_thread\_output() fail { let test\_case = ContinueCountingTest { is\_ref\_input\_presented: True, is\_thread\_input\_presented: True, is\_thread\_output\_presented: False, is\_count\_added: True, is\_app\_owner\_signed: True, is\_tx\_not\_expired: True, } complex\_withdrawal\_contract.withdraw( mock\_oracle\_nft, ContinueCounting, Credential.Script(#""), mock\_continue\_counting\_tx(test\_case), ) } test fail\_continue\_counting\_incorrect\_count() { let test\_case = ContinueCountingTest { is\_ref\_input\_presented: True, is\_thread\_input\_presented: True, is\_thread\_output\_presented: True, is\_count\_added: False, is\_app\_owner\_signed: True, is\_tx\_not\_expired: True, } !complex\_withdrawal\_contract.withdraw( mock\_oracle\_nft, ContinueCounting, Credential.Script(#""), mock\_continue\_counting\_tx(test\_case), ) } test fail\_continue\_counting\_not\_signed\_by\_owner() { let test\_case = ContinueCountingTest { is\_ref\_input\_presented: True, is\_thread\_input\_presented: True, is\_thread\_output\_presented: True, is\_count\_added: True, is\_app\_owner\_signed: False, is\_tx\_not\_expired: True, } !complex\_withdrawal\_contract.withdraw( mock\_oracle\_nft, ContinueCounting, Credential.Script(#""), mock\_continue\_counting\_tx(test\_case), ) } test fail\_continue\_counting\_app\_expired() { let test\_case = ContinueCountingTest { is\_ref\_input\_presented: True, is\_thread\_input\_presented: True, is\_thread\_output\_presented: True, is\_count\_added: True, is\_app\_owner\_signed: True, is\_tx\_not\_expired: False, } !complex\_withdrawal\_contract.withdraw( mock\_oracle\_nft, ContinueCounting, Credential.Script(#""), mock\_continue\_counting\_tx(test\_case), ) } \`\`\` Running \`aiken check\` will show: !\[Continue Counting Tests\](../../../../../public/lessons/04-contract-testing/all-tests.png) ### Exercise Write tests for \`StopCounting\` action. Refer to \`ContinueCounting\` tests for guidance. Suggested answers are in the code example. # Avoid Redundant Validation URL: /resources/cardano-course/lessons/05-avoid-redundant-validation Key contract best practice - reduce redundant validation logics being run onchain. \*\*\* title: "Avoid Redundant Validation" description: "Key contract best practice - reduce redundant validation logics being run onchain." ------------------------------------------------------------------------------------------------- import Link from "fumadocs-core/link"; Do you have a question about the previous lessons - why have we performed even minting and state update in spending validators with withdrawal script? We know that every time we spend a UTxO from a spending validator would trigger checks, why can't I validate the counter update in the spending validator directly? ## A Transaction with Multiple Script Validation Imagine there is a complex transaction that involves multiple script validations. For example, a transaction that mints tokens, unlocking multiple script UTxOs, and withdraws funds. Each of these actions may require its own set of checks and validations. \`\`\`mermaid graph TB %% Layout subgraph for labels at top with horizontal alignment subgraph Checks\[" Common Validations "\] direction LR C1\["C1: Check if owner signature exists"\] ~~~ C2\["C2: Check if not expired"\] ~~~ C3\["C3: Any other common checks"\] end %% Remove the connecting lines between checks linkStyle 0 stroke-width:0px linkStyle 1 stroke-width:0px %% Connect checks to components with dotted lines Checks -.-> A1 Checks -.-> A2 Checks -.-> A3 Checks -.-> M Checks -.-> W %% Inputs on left A1\[Script Input 1\] --> TX A2\[Script Input 2\] --> TX A3\[Script Input 3\] --> TX %% Center transaction TX((Transaction)) %% Mint on top M\[Token Minting\] --> TX %% Withdraw at bottom W\[Withdrawal Script\] --> TX %% Clear styling with bright colors and black text style TX fill:#FFA07A,stroke:#333,stroke-width:2px,color:#000 style M fill:#87CEEB,stroke:#333,stroke-width:2px,color:#000 style W fill:#DDA0DD,stroke:#333,stroke-width:2px,color:#000 style A1 fill:#E0E0E0,stroke:#333,stroke-width:2px,color:#000 style A2 fill:#E0E0E0,stroke:#333,stroke-width:2px,color:#000 style A3 fill:#E0E0E0,stroke:#333,stroke-width:2px,color:#000 style C1 fill:#FFFFFF,stroke:#333,stroke-width:1px,color:#000 style C2 fill:#FFFFFF,stroke:#333,stroke-width:1px,color:#000 style C3 fill:#FFFFFF,stroke:#333,stroke-width:1px,color:#000 %% Positioning classDef default text-align:center \`\`\` If we enforced all the common checks in each of the scripts, we would end up with redundant validations that are executed multiple times, leading to inefficiencies and increased transaction costs. ## How can we do better? We can avoid redundant validations by centralizing the common checks in a single script, which is executed only once. This way, we can ensure that all the necessary validations are performed without duplicating the logic across multiple scripts. \`\`\`mermaid graph TB %% Layout subgraph for labels at top with horizontal alignment subgraph Checks\[" Common Validations "\] direction LR C1\["C1: Check if owner signature exists"\] ~~~ C2\["C2: Check if not expired"\] ~~~ C3\["C3: Any other common checks"\] end %% Add spacing WithdrawalCheck\[" Check for Withdrawal Script Validating "\] %% Organize layout with invisible connections for spacing Checks ~~~ WithdrawalCheck %% Connect validation flows Checks -.-> W WithdrawalCheck -.-> A1 WithdrawalCheck -.-> A2 WithdrawalCheck -.-> A3 WithdrawalCheck -.-> M %% Inputs on left with consistent arrows A1\[Script Input 1\] --> TX A2\[Script Input 2\] --> TX A3\[Script Input 3\] --> TX %% Transaction and other components TX((Transaction)) M\[Token Minting\] --> TX W\[Withdrawal Script\] --> TX %% Styling style TX fill:#FFA07A,stroke:#333,stroke-width:2px,color:#000 style M fill:#87CEEB,stroke:#333,stroke-width:2px,color:#000 style W fill:#DDA0DD,stroke:#333,stroke-width:2px,color:#000 style A1 fill:#E0E0E0,stroke:#333,stroke-width:2px,color:#000 style A2 fill:#E0E0E0,stroke:#333,stroke-width:2px,color:#000 style A3 fill:#E0E0E0,stroke:#333,stroke-width:2px,color:#000 style C1 fill:#FFFFFF,stroke:#333,stroke-width:1px,color:#000 style C2 fill:#FFFFFF,stroke:#333,stroke-width:1px,color:#000 style C3 fill:#FFFFFF,stroke:#333,stroke-width:1px,color:#000 style WithdrawalCheck fill:#FFFFFF,stroke:#333,stroke-width:1px,color:#000 %% Remove visible connections between check boxes linkStyle 0 stroke-width:0px linkStyle 1 stroke-width:0px linkStyle 2 stroke-width:0px \`\`\` In the architecture above, we have a single \`WithdrawalCheck\` script that performs the common validations. This script is executed once, and it checks the conditions for all the other scripts involved in the transaction. ## Example: Continue from Lesson 4 Let's assume we have all the common logics checked in the lesson 4's withdrawal script. Rather than copy pasting all checks from withdrawal script to the spending and minting validators, we can do this instead to avoid redundant validations: ### Spending \`\`\`rs use aiken/crypto.{ScriptHash} use cardano/transaction.{OutputReference, Transaction} use cocktail.{withdrawal\_script\_validated} validator spending\_logics\_delegated( delegated\_withdrawal\_script\_hash: ScriptHash, ) { spend( \_datum\_opt: Option, \_redeemer: Data, \_input: OutputReference, tx: Transaction, ) { withdrawal\_script\_validated( tx.withdrawals, delegated\_withdrawal\_script\_hash, ) } else(\_) { fail @"unsupported purpose" } } \`\`\` ### Minting \`\`\`rs use aiken/crypto.{ScriptHash} use cardano/assets.{PolicyId} use cardano/transaction.{Transaction} use cocktail.{withdrawal\_script\_validated} validator minting\_logics\_delegated( delegated\_withdrawal\_script\_hash: ScriptHash, ) { mint(\_redeemer: Data, \_policy\_id: PolicyId, tx: Transaction) { withdrawal\_script\_validated( tx.withdrawals, delegated\_withdrawal\_script\_hash, ) } else(\_) { fail @"unsupported purpose" } } \`\`\` ## Why delegate to withdrawal script? You might notice that we are delegating the validation to the withdrawal script. This is a common pattern in Cardano smart contracts, where a withdrawal script is used to perform common validations for multiple scripts. However, validation delegation can happen in different ways. For example, you can delegate all checks to a spending or minting validator as well, why would we prefer withdrawal script most of the time? ### Clean trigger Recall that spending validation is triggered when a UTxO is spent, and minting validation is triggered when a token is minted. By delegating to a withdrawal script, we can ensure that the common validations are performed only once, regardless of how many scripts are involved in the transaction. And the withdrawal script can be triggered by withdrawing 0 lovelace, aka the community call it \[\`withdraw 0 trick\`\](https://aiken-lang.org/fundamentals/common-design-patterns#forwarding-validation--other-withdrawal-tricks). It is a clean way to trigger the validation without affecting the transaction's logic or state. ## Simplified Explanation ### Why Avoid Redundant Validation? When multiple scripts are involved in a transaction, repeating the same checks in each script leads to inefficiencies and higher costs. Instead, centralizing common checks in a single script ensures that validations are performed only once, saving resources and simplifying logic. ### Centralized Validation By using a single script, such as a withdrawal script, we can delegate common checks to it. This script acts as a central validator for all other scripts in the transaction. ### Example Flow Imagine a transaction with multiple scripts: \* \*\*Minting Script\*\*: Handles token creation. \* \*\*Spending Script\*\*: Manages UTxO spending. \* \*\*Withdrawal Script\*\*: Performs common checks. Instead of duplicating checks in each script, the withdrawal script validates all common conditions, ensuring efficiency. ### Delegation in Practice Here’s how delegation works: \* \*\*Spending Validator\*\*: Delegates validation to the withdrawal script. \* \*\*Minting Validator\*\*: Also delegates validation to the withdrawal script. This approach reduces redundancy and keeps the logic clean and maintainable. ### Clean Trigger with Withdrawal Script The withdrawal script can be triggered using the \`withdraw 0 trick\`, which allows validation without affecting the transaction state. This method is widely used for its simplicity and effectiveness. ### Key Benefits \* \*\*Efficiency\*\*: Reduces redundant checks. \* \*\*Cost-Effective\*\*: Lowers transaction fees. \* \*\*Maintainability\*\*: Simplifies script logic. By following this pattern, developers can create smarter and more efficient Cardano contracts. # Interpreting Blueprint URL: /resources/cardano-course/lessons/06-interpreting-blueprint Understanding, interpreting, and translating Aiken blueprint into offchain code. \*\*\* title: "Interpreting Blueprint" description: "Understanding, interpreting, and translating Aiken blueprint into offchain code." ----------------------------------------------------------------------------------------------- import Link from "fumadocs-core/link"; In this lesson, we will explore how to interpret the blueprint generated from onchain code development and translate it into offchain code. This blueprint serves as a bridge between the onchain and offchain worlds, enabling seamless interaction with smart contracts. ## What is a Blueprint? A blueprint is a standardized JSON file introduced by CIP57. It is the ultimate output of Cardano smart contract development and contains essential information about the contract. Regardless of the development method, the blueprint includes: \* \*\*\`preamble\`\*\*: Meta-information about the contract. \* \*\*\`validators\`\*\*: Named validators with type definitions and compiled code. \* \*\*\`definitions\`\*\*: A registry of reusable definitions across the specification. ### Generating a Blueprint To generate a blueprint using Aiken, follow these steps: 1. Build your contracts by running: \`\`\`sh aiken build \`\`\` 2. Locate the blueprint in the \`plutus.json\` file at the root of your project. ## Understanding the Blueprint ### \`preamble\` The \`preamble\` section contains meta-information about the contract, such as its name, description, version, and Plutus version. The Plutus version is particularly important for preparing offchain code. Example: \`\`\`json { "preamble": { "title": "meshsdk/aiken-template", "description": "Aiken contracts for project 'meshsdk/aiken-template'", "version": "0.0.0", "plutusVersion": "v3", // Key information for offchain code "compiler": { "name": "Aiken", "version": "v1.1.16+23061c0" }, "license": "Apache-2.0" } } \`\`\` ### \`validators\` The \`validators\` section includes type information for \`datum\`, \`redeemer\`, and \`parameters\`, along with the compiled validator code. These definitions may reference reusable types in the \`definitions\` section. Example: \`\`\`json { "title": "spend.spending\_logics\_delegated.spend", "datum": { "title": "\_datum\_opt", "schema": { "$ref": "#/definitions/Data" } }, "redeemer": { "title": "\_redeemer", "schema": { "$ref": "#/definitions/Data" } }, "parameters": \[ { "title": "delegated\_withdrawal\_script\_hash", "schema": { "$ref": "#/definitions/aiken~1crypto~1ScriptHash" } } \], "compiledCode": "58ac010100229800aba2aba1aba0aab9faab9eaab9dab9a9bae0024888888896600264646644b30013370e900118039baa001899914c004c03400a601a601c0052259800800c528456600266ebc00cc02cc03c00629462660040046020002805100d2444660020026eacc040c044c044c044c044c044c044c034dd518080048c020dd500099ba548008cc028dd4802a5eb822c8030c024004c024c028004c024004c010dd5004c52689b2b200401", "hash": "9c9666ddc12fc42f0151cd029c150c7d410ede9fe3885c248c8c26a0" } \`\`\` Notice the \`spend.spending\_logics\_delegated.else\` compiles to the same hash as the \`spend.spending\_logics\_delegated.spend\` function. This is because the \`else\` branch is not executed in this case, but it is still part of the validator code. So when we are building multiple purposes validators, they will compile to the same hash, i.e. same script, which can be utilitized in certain architectures. \`\`\`json { "title": "spend.spending\_logics\_delegated.else", "redeemer": { "schema": {} }, "parameters": \[ { "title": "delegated\_withdrawal\_script\_hash", "schema": { "$ref": "#/definitions/aiken~1crypto~1ScriptHash" } } \], "compiledCode": "58ac010100229800aba2aba1aba0aab9faab9eaab9dab9a9bae0024888888896600264646644b30013370e900118039baa001899914c004c03400a601a601c0052259800800c528456600266ebc00cc02cc03c00629462660040046020002805100d2444660020026eacc040c044c044c044c044c044c044c034dd518080048c020dd500099ba548008cc028dd4802a5eb822c8030c024004c024c028004c024004c010dd5004c52689b2b200401", "hash": "9c9666ddc12fc42f0151cd029c150c7d410ede9fe3885c248c8c26a0" } \`\`\` ### \`definitions\` The \`definitions\` section provides reusable type definitions referenced in the \`validators\` section. This is where you can find schemas for types used in the contract. Example: \`\`\`json { "definitions": { "Data": { "title": "Data", "description": "Any Plutus data." }, "aiken/crypto/ScriptHash": { "title": "ScriptHash", "dataType": "bytes" }, "cardano/assets/PolicyId": { "title": "PolicyId", "dataType": "bytes" }, "withdraw/MyRedeemer": { "title": "MyRedeemer", "anyOf": \[ { "title": "ContinueCounting", "dataType": "constructor", "index": 0, "fields": \[\] }, { "title": "StopCounting", "dataType": "constructor", "index": 1, "fields": \[\] } \] } } } \`\`\` ## Automating Offchain Code Generation Translating the blueprint into offchain code manually can be time-consuming. Fortunately, the Mesh community has developed a tool in the \`Cardano Bar VSCode Extension\` to automate this process. In Mesh community, we have developed a tool in \`Cardano Bar VSCode Extension\` that can automate this process. By running the following below steps, you can generate the offchain code that corresponds to the blueprint: 1. Create a new TypeScript file, e.g., \`offchain.ts\`. 2. Open the command palette in VSCode (Ctrl+Shift+P or Cmd+Shift+P). 3. Type \`Parse blueprint to Typescript - Mesh\` and select it. !\[VSCode command palette\](../../../../../public/lessons/06-interpreting-blueprint/vscode-command.png) 4. Select the \`plutus.json\` file that contains the blueprint. !\[VSCode command palette\](../../../../../public/lessons/06-interpreting-blueprint/select-blueprint.png) The generated \`offchain.ts\` file will include all necessary functions to interact with the onchain code, such as spending, minting, and querying the contract. For more details, refer to the Mesh SDK documentation. ## Conclusion Understanding and interpreting the blueprint is a vital skill for Cardano developers. With tools like the Mesh \`Blueprint\` class, you can streamline the process and focus on building robust applications. # Vesting Contract URL: /resources/cardano-course/lessons/07-vesting Vesting smart contract that locks up funds and allows the beneficiary to withdraw the funds after the lockup period. \*\*\* title: "Vesting Contract" description: "Vesting smart contract that locks up funds and allows the beneficiary to withdraw the funds after the lockup period." ----------------------------------------------------------------------------------------------------------------------------------- import Link from "fumadocs-core/link"; Vesting contracts are a type of smart contract designed to lock funds for a specified period, ensuring that only the designated beneficiary can withdraw them after the lockup period ends. This lesson will guide you through the process of understanding, implementing, and interacting with a vesting contract on Cardano. ## Overview ### What is a Vesting Contract? A vesting contract locks funds and allows the beneficiary to withdraw them after a specified lockup period. It ensures security and control over fund distribution. ### Key Features: \* \*\*Lockup Period\*\*: Funds are locked until a specific timestamp. \* \*\*Owner and Beneficiary\*\*: The owner deposits funds, and the beneficiary withdraws them after the lockup period. ## Smart Contract Details ### Datum Definition The datum serves as the configuration for the vesting contract. It includes: \* \*\*\`lock\_until\`\*\*: The timestamp until which funds are locked. \* \*\*\`owner\`\*\*: Credentials of the fund owner. \* \*\*\`beneficiary\`\*\*: Credentials of the beneficiary. First, we define the datum's shape, as this datum serves as configuration and contains the different parameters of our vesting operation. \`\`\` pub type VestingDatum { /// POSIX time in milliseconds, e.g. 1672843961000 lock\_until: Int, /// Owner's credentials owner: ByteArray, /// Beneficiary's credentials beneficiary: ByteArray, } \`\`\` This datum can be found in \`aiken-vesting/aiken-workspace/lib/vesting/types.ak\`. Next, we define the spend validator. \`\`\` validator vesting { spend( datum\_opt: Option, \_redeemer: Data, \_input: OutputReference, tx: Transaction, ) { // In principle, scripts can be used for different purpose (e.g. minting // assets). Here we make sure it's only used when 'spending' from a eUTxO expect Some(datum) = datum\_opt or { key\_signed(tx.extra\_signatories, datum.owner), and { key\_signed(tx.extra\_signatories, datum.beneficiary), valid\_after(tx.validity\_range, datum.lock\_until), }, } } else(\_) { fail } } \`\`\` In this example, we define a \`vesting\` validator that ensures the following conditions are met: \* The transaction must be signed by owner Or: \* The transaction must be signed by beneficiary \* The transaction must be valid after the lockup period ### How it works The owner of the funds deposits the funds into the vesting contract. The funds are locked up until the lockup period expires. Transactions can include validity intervals that specify when the transaction is valid, both from and until a certain time. The ledger verifies these validity bounds before executing a script and will only proceed if they are legitimate. This approach allows scripts to incorporate a sense of time while maintaining determinism within the script's context. For instance, if a transaction has a lower bound \`A\`, we can infer that the current time is at least \`A\`. It's important to note that since we don't control the upper bound, a transaction might be executed even 30 years after the vesting delay. However, from the script's perspective, this is entirely acceptable. The beneficiary can withdraw the funds after the lockup period expires. The beneficiary can also be different from the owner of the funds. ### Testing To test the vesting contract, we have provided the a comphrehensive test script,you can run tests with \`aiken check\`. The test script includes the following test cases: \* success unlocking \* success unlocking with only owner signature \* success unlocking with beneficiary signature and time passed \* fail unlocking with only beneficiary signature \* fail unlocking with only time passed We recommend you to check out \`vesting.ak\` to learn more. ### Compile and build script To compile the script, run the following command: \`\`\`sh aiken build \`\`\` This command will generate a CIP-0057 Plutus blueprint, which you can find in \`plutus.json\`. ## Deposit funds First, the owner can deposit funds into the vesting contract. The owner can specify the lockup period. \`\`\`ts const assets: Asset\[\] = \[ { unit: "lovelace", quantity: "10000000", }, \]; const lockUntilTimeStamp = new Date(); lockUntilTimeStamp.setMinutes(lockUntilTimeStamp.getMinutes() + 1); \`\`\` In this example, we deposit 10 ADA into the vesting contract. The funds are locked up for 1 minute, and the beneficiary is specified. \`\`\`ts // app wallet const wallet = new MeshWallet({ networkId: 0, key: { type: "mnemonic", words: appWallet, }, fetcher: provider, submitter: provider, }); const utxos = await wallet.getUtxos(); const changeAddress = await wallet.getChangeAddress(); const { pubKeyHash: ownerPubKeyHash } = deserializeAddress(changeAddress); const { pubKeyHash: beneficiaryPubKeyHash } = deserializeAddress(beneficiaryAddress); \`\`\` For this tutorial, we use another wallet to fund the deposit. We get the UTXOs from the app wallet and the change address. We also need both the owner and beneficiary's public key hashes. We can get the public key hash from the address using \`deserializeAddress\`. \`\`\`ts const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true, }); const unsignedTx = await txBuilder .txOut(script.address, amount) .txOutInlineDatumValue( mConStr0(\[lockUntilTimeStampMs, ownerPubKeyHash, beneficiaryPubKeyHash\]) ) .changeAddress(changeAddress) .selectUtxosFrom(utxos) .complete(); \`\`\` We construct the transaction to deposit the funds into the vesting contract. We specify the script address of the vesting contract, the amount to deposit, and the lockup period, owner, and beneficiary of the funds. Finally, we sign and submit the transaction. \`\`\`ts const signedTx = await wallet.signTx(unsignedTx); const txHash = await wallet.submitTx(signedTx); \`\`\` Upon successful execution, you will receive a transaction hash. Save this transaction hash for withdrawing the funds. Example of a successful deposit transaction. ## Withdraw funds After the lockup period expires, the beneficiary can withdraw the funds from the vesting contract. The owner can also withdraw the funds from the vesting contract. First, let's look for the UTxOs containing the funds locked in the vesting contract. \`\`\`ts const txHashFromDesposit = "556f2bfcd447e146509996343178c046b1b9ad4ac091a7a32f85ae206345e925"; const utxos = await provider.fetchUTxOs(txHash); const vestingUtxo = utxos\[0\]; \`\`\` We fetch the UTxOs containing the funds locked in the vesting contract. We specify the transaction hash of the deposit transaction. Like before, we prepare a few variables to be used in the transaction. We get the wallet address and the UTXOs of the wallet. We also get the script address of the vesting contract, to send the funds to the script address. We also get the owner and beneficiary public key hashes. Next, we prepare the datum and the slot number to set the transaction valid interval to be valid only after the slot. \`\`\`ts const datum = deserializeDatum(vestingUtxo.output.plutusData!); const invalidBefore = unixTimeToEnclosingSlot( Math.min(datum.fields\[0\].int as number, Date.now() - 15000), SLOT\_CONFIG\_NETWORK.preprod ) + 1; \`\`\` We prepare the datum and the slot number to set the transaction valid interval to be valid only after the slot. We get the lockup period from the datum and set the transaction valid interval to be valid only after the lockup period. Next, we construct the transaction to withdraw the funds from the vesting contract. \`\`\`ts const txBuilder = new MeshTxBuilder({ fetcher: provider, verbose: true, }); const unsignedTx = await txBuilder .spendingPlutusScript("V3") .txIn( vestingUtxo.input.txHash, vestingUtxo.input.outputIndex, vestingUtxo.output.amount, script.address ) .spendingReferenceTxInInlineDatumPresent() .spendingReferenceTxInRedeemerValue("") .txInScript(script.cbor) .txOut(walletAddress, \[\]) .txInCollateral( collateralInput.txHash, collateralInput.outputIndex, collateralOutput.amount, collateralOutput.address ) .invalidBefore(invalidBefore) .requiredSignerHash(pubKeyHash) .changeAddress(walletAddress) .selectUtxosFrom(inputUtxos) .complete(); \`\`\` we construct the transaction to withdraw the funds from the vesting contract. We specify the UTxO containing the funds locked in the vesting contract, the script address of the vesting contract, the wallet address to send the funds to, and the transaction valid interval. Finally, we sign and submit the transaction. Example of a successful withdraw transaction. ## Source code The source code for this lesson is available on GitHub. ## Challenge Change the vesting contract to gradual vesting schedule where instead of a single unlock date, implement gradual vesting where funds are released on a schedule. Or add a cliff feature where the beneficiary must wait for a minimum period before any tokens become available. # Plutus NFT Contract URL: /resources/cardano-course/lessons/08-plutus-nft Plutus NFT smart contract enforces non-fungibility and uniqueness of the NFT under the same policy. \*\*\* title: "Plutus NFT Contract" description: "Plutus NFT smart contract enforces non-fungibility and uniqueness of the NFT under the same policy." ------------------------------------------------------------------------------------------------------------------ import Link from "fumadocs-core/link"; After the simple vesting contract, let's level up to a more complex contract with multiple validators interacting with each other. This lesson will guide you step-by-step through the process of creating a Plutus NFT contract, ensuring clarity and simplicity. ## Overview This lesson focuses on creating a smart contract for minting NFTs with an automatically incremented index. The contract ensures non-fungibility and uniqueness of the NFTs under the same policy. To achieve this, we will: 1. Set up a one-time minting policy to create an oracle token. 2. Use the oracle token to maintain the state and index of NFTs. 3. Increment the token index with each new NFT minted. ## Step 1: Oracle NFT The oracle NFT acts as the single source of truth for the system. It uses a state thread token to ensure consistency. We will implement a one-time minting policy for the oracle NFT. ### Code Explanation The following code defines the minting policy for the oracle NFT: \`\`\`rs pub type MintPolarity { RMint RBurn } validator oracle\_nft(utxo\_ref: OutputReference) { mint(redeemer: MintPolarity, policy\_id: PolicyId, tx: Transaction) { when redeemer is { RMint -> { let Transaction { inputs, .. } = tx let hash\_equal = fn(input: Input) { let hash = input.output\_reference utxo\_ref == hash } let target\_input\_exist = list.find(inputs, hash\_equal) when target\_input\_exist is { Some(\_) -> True None -> False } } RBurn -> check\_policy\_only\_burn(tx.mint, policy\_id) } } else(\_) { fail } } \`\`\` \*\*Key Points:\*\* \* \`RMint\` ensures the token is minted only once. \* \`RBurn\` allows the token to be burned but prevents reminting. ## Step 2: Oracle Validator The oracle validator holds the current state of the NFT index. It defines the datum and redeemer types for state changes. ### Datum Definition \`\`\`rs pub type OracleDatum { count: Int, lovelace\_price: Int, fee\_address: Address, } \`\`\` ### Redeemer Types \`\`\`rs pub type OracleRedeemer { MintPlutusNFT StopOracle } \`\`\` ### Validator Logic The validator ensures the state changes are valid: \`\`\`rs validator oracle { spend( datum\_opt: Option, redeemer: OracleRedeemer, input: OutputReference, tx: Transaction, ) { let Transaction { mint, inputs, outputs, extra\_signatories, .. } = tx expect Some(OracleDatum { count, lovelace\_price, fee\_address }) = datum\_opt expect Some(own\_input) = find\_input(inputs, input) expect \[(oracle\_nft\_policy, \_, \_)\] = list.filter(flatten(own\_input.output.value), fn(x) { x.1st != "" }) todo } else(\_) { fail } } \`\`\` In this setup, we identified the own input with \`find\_input\` function, which is a utility function that finds the input with the given output reference. We also expect the oracle NFT policy to be present in the own input's value. We know that for state change, we will have exactly one input from current address, and one output to the same address. We can then perform below pattern matching: \`\`\`rs let own\_address = own\_input.output.address when ( redeemer, inputs\_at\_with\_policy(inputs, own\_address, oracle\_nft\_policy), outputs\_at\_with\_policy(outputs, own\_address, oracle\_nft\_policy), ) is { (MintPlutusNFT, \[\_\], \[only\_output\]) -> { todo } \_ -> False } \`\`\` Add in core checks for \`MintPlutusNFT\`: \`\`\`rs let is\_output\_value\_clean = list.length(flatten(only\_output.value)) == 2 let is\_count\_updated = only\_output.datum == InlineDatum( OracleDatum { count: count + 1, lovelace\_price, fee\_address }, ) let is\_fee\_paid = get\_all\_value\_to(outputs, fee\_address) |> value\_geq(from\_lovelace(lovelace\_price)) is\_output\_value\_clean? && is\_count\_updated? && is\_fee\_paid? \`\`\` Notice there is a \`is\_output\_value\_clean\` check here, which ensures the changed state UTxO only contains the state thread token and ADA, i.e. no other assets are present in the output value. This is to prevent a common vulnerability of \`Unbounded Value\`, where people can attach infinitely amount of assets to the output to make it unspendable by overflowing the transaction size. Complete with \`StopOracle\` logics: \`\`\`rs (StopOracle, \[\_\], \_) -> { let is\_oracle\_nft\_burnt = only\_minted\_token(mint, oracle\_nft\_policy, "", -1) let owner\_key = address\_payment\_key(fee\_address) let is\_owner\_signed = key\_signed(extra\_signatories, owner\_key) is\_oracle\_nft\_burnt? && is\_owner\_signed? } \`\`\` A complete oracle validator looks like this: \`\`\`rs validator oracle { spend( datum\_opt: Option, redeemer: OracleRedeemer, input: OutputReference, tx: Transaction, ) { let Transaction { mint, inputs, outputs, extra\_signatories, .. } = tx expect Some(OracleDatum { count, lovelace\_price, fee\_address }) = datum\_opt expect Some(own\_input) = find\_input(inputs, input) expect \[(oracle\_nft\_policy, \_, \_)\] = list.filter(flatten(own\_input.output.value), fn(x) { x.1st != "" }) let own\_address = own\_input.output.address when ( redeemer, inputs\_at\_with\_policy(inputs, own\_address, oracle\_nft\_policy), outputs\_at\_with\_policy(outputs, own\_address, oracle\_nft\_policy), ) is { (MintPlutusNFT, \[\_\], \[only\_output\]) -> { let is\_output\_value\_clean = list.length(flatten(only\_output.value)) == 2 let is\_count\_updated = only\_output.datum == InlineDatum( OracleDatum { count: count + 1, lovelace\_price, fee\_address }, ) let is\_fee\_paid = get\_all\_value\_to(outputs, fee\_address) |> value\_geq(from\_lovelace(lovelace\_price)) is\_output\_value\_clean? && is\_count\_updated? && is\_fee\_paid? } (StopOracle, \[\_\], \_) -> { let is\_oracle\_nft\_burnt = only\_minted\_token(mint, oracle\_nft\_policy, "", -1) let owner\_key = address\_payment\_key(fee\_address) let is\_owner\_signed = key\_signed(extra\_signatories, owner\_key) is\_oracle\_nft\_burnt? && is\_owner\_signed? } \_ -> False } } else(\_) { fail } } \`\`\` \*\*Key Points:\*\* \* \`MintPlutusNFT\` increments the NFT index and ensures fees are paid. \* \`StopOracle\` burns the oracle NFT and requires owner authorization. ## Step 3: Plutus NFT Minting Validator The Plutus NFT minting validator ensures the NFT is unique and non-fungible. ### Code Explanation \`\`\`rs pub type MintPolarity { RMint RBurn } validator plutus\_nft(collection\_name: ByteArray, oracle\_nft: PolicyId) { mint(redeemer: MintPolarity, policy\_id: PolicyId, tx: Transaction) { when redeemer is { RMint -> { let Transaction { inputs, mint, .. } = tx expect \[auth\_input\] = inputs\_with\_policy(inputs, oracle\_nft) expect InlineDatum(input\_datum) = auth\_input.output.datum expect OracleDatum { count, .. }: OracleDatum = input\_datum let asset\_name = collection\_name |> concat(" (") |> concat(convert\_int\_to\_bytes(count)) |> concat(")") only\_minted\_token(mint, policy\_id, asset\_name, 1) } RBurn -> check\_policy\_only\_burn(tx.mint, policy\_id) } } else(\_) { fail } } \`\`\` \*\*Key Points:\*\* \* Ensures the NFT name includes the incremented index. \* Validates the minting and burning process. The code example above is presented in Mesh repository, you can find the equivalent tests there. ### Compile and build script 1. Compile the script using: \`\`\`sh aiken build \`\`\` This command will generate a CIP-0057 Plutus blueprint, which you can find in \`plutus.json\`. ## Setup Oracle To set up the oracle, we need to mint the oracle NFT first and lock it in the oracle validator. This is a one-time operation, and we can do it with the following code: We prepare the wallet and tx-builder similar to previous lessons, and get some static information: \`\`\`ts const compiledCode = ; const utxos = await wallet?.getUtxos(); const collateral = (await wallet.getCollateral())\[0\]!; const walletAddress = await wallet.getChangeAddress() const paramUtxo = utxos\[0\]!; const param: Data = mOutputReference( paramUtxo.input.txHash, paramUtxo.input.outputIndex, ); const paramScript = applyParamsToScript(compiledCode, \[param\]); const policyId = resolveScriptHash(paramScript, "V3"); const tokenName = ""; const { pubKeyHash, stakeCredentialHash } = deserializeAddress(walletAddress); \`\`\` Then we can perform the setup: \`\`\`ts const txHex = await txBuilder .txIn( paramUtxo.input.txHash, paramUtxo.input.outputIndex, paramUtxo.output.amount, paramUtxo.output.address, ) .mintPlutusScriptV3() .mint("1", policyId, tokenName) .mintingScript(paramScript) .mintRedeemerValue(mConStr0(\[\])) .txOut(oracleAddress, \[{ unit: policyId, quantity: "1" }\]) .txOutInlineDatumValue( mConStr0(\[ 0, lovelacePrice, mPubKeyAddress(pubKeyHash, stakeCredentialHash), \]), ) .txInCollateral( collateral.input.txHash, collateral.input.outputIndex, collateral.output.amount, collateral.output.address, ) .changeAddress(walletAddress) .selectUtxosFrom(utxos) .complete(); \`\`\` Important, we need to save the \`paramUtxo\` information for later use: ## Mint Plutus NFT To mint the Plutus NFT, first we need to define static info: \`\`\`ts type OracleDatum = ConStr0<\[Integer, Integer, PubKeyAddress\]>; const oracleCompileCode = ; const oracleNftCbor = applyParamsToScript(blueprint.validators\[2\]!.compiledCode, \[ mOutputReference(paramUtxo.txHash, paramUtxo.outputIndex), \]) const oracleNftPolicyId = resolveScriptHash(oracleNftCbor, "V3"); const oracleCbor = applyCborEncoding() const oracleAddress = serializePlutusScript( { code: oracleCbor, version: "V3", }, "", // the stake credential, we can supply if we have one "preprod", ).address const getAddressUtxosWithToken = async ( walletAddress: string, assetHex: string, ) => { let utxos = await fetcher.fetchAddressUTxOs(walletAddress); return utxos.filter((u) => { const assetAmount = u.output.amount.find( (a: any) => a.unit === assetHex, )?.quantity; return Number(assetAmount) >= 1; }); }; \`\`\` And a helper method to get the existing oracle information: \`\`\`ts const getOracleData = async () => { const oracleUtxo = ( await getAddressUtxosWithToken(oracleAddress, oracleNftPolicyId) )\[0\]!; const oracleDatum: OracleDatum = parseDatumCbor( oracleUtxo!.output.plutusData!, ); const nftIndex = oracleDatum.fields\[0\].int; const lovelacePrice = oracleDatum.fields\[1\].int; const feeCollectorAddressObj = oracleDatum.fields\[2\]; const feeCollectorAddress = serializeAddressObj( feeCollectorAddressObj, "preprod", ); const policyId = resolveScriptHash(oracleNftCbor, "V3"); return { nftIndex, policyId, lovelacePrice, oracleUtxo, oracleNftPolicyId, feeCollectorAddress, feeCollectorAddressObj, }; }; \`\`\` Then we can build the core logic to mint the Plutus NFT: \`\`\`ts const utxos = await wallet?.getUtxos(); const collateral = (await wallet.getCollateral())\[0\]!; const walletAddress = await wallet.getChangeAddress() const collectionName = "MyNFTCollection"; const nftCbor = applyParamsToScript(, \[ stringToHex(collectionName), oracleNftPolicyId, \]); const { nftIndex, policyId, lovelacePrice, oracleUtxo, oracleNftPolicyId, feeCollectorAddress, feeCollectorAddressObj, } = await getOracleData(); const tokenName = \`${collectionName} (${nftIndex})\`; const tokenNameHex = stringToHex(tokenName); const updatedOracleDatum: OracleDatum = conStr0(\[ integer((nftIndex as number) + 1), integer(lovelacePrice), feeCollectorAddressObj, \]); const tx = txBuilder .spendingPlutusScriptV3() .txIn( oracleUtxo.input.txHash, oracleUtxo.input.outputIndex, oracleUtxo.output.amount, oracleUtxo.output.address, 0 ) .txInRedeemerValue(mConStr0(\[\])) .txInScript(oracleCbor) .txInInlineDatumPresent() .txOut(oracleAddress, \[{ unit: oracleNftPolicyId, quantity: "1" }\]) .txOutInlineDatumValue(updatedOracleDatum, "JSON") .mintPlutusScriptV3() .mint("1", policyId, tokenNameHex) .mintingScript(nftCbor); const assetMetadata = { name: \`MyNFTCollection (${nftIndex})\`, image: "ipfs://QmRzicpReutwCkM6aotuKjErFCUD213DpwPq6ByuzMJaua", mediaType: "image/jpg", description: "This NFT was minted by Mesh (https://meshjs.dev/).", }; const metadata = { \[policyId\]: { \[tokenName\]: { ...assetMetadata } } }; tx.metadataValue(721, metadata); tx.mintRedeemerValue(mConStr0(\[\])) .txOut(feeCollectorAddress, \[ { unit: "lovelace", quantity: lovelacePrice.toString() }, \]) .txInCollateral( collateral.input.txHash, collateral.input.outputIndex, collateral.output.amount, collateral.output.address, ) .changeAddress(walletAddress) .selectUtxosFrom(utxos); const txHex = await tx.complete(); \`\`\` ## Packaged functions The Plutus NFT contract has been implemented in \`@meshsdk/contract\` package, you can find further explanation at the Mesh documentation and more details about entire stack source code at Mesh repository. # End-to-End Hydra Happy Flow URL: /resources/cardano-course/lessons/09-hydra Layer 2 scaling solution for Cardano, an end-to-end tutorial for state channel between two participants using the Hydra Head protocol. \*\*\* title: "End-to-End Hydra Happy Flow" description: "Layer 2 scaling solution for Cardano, an end-to-end tutorial for state channel between two participants using the Hydra Head protocol." ----------------------------------------------------------------------------------------------------------------------------------------------------- import Link from "fumadocs-core/link"; > \*\*Note:\*\* Work in progress, come back later. # Web3 Services URL: /resources/cardano-course/lessons/10-web3-services Onboard seamlessly with non-custodial wallet-as-a-service and transaction sponsorship. \*\*\* title: "Web3 Services" description: "Onboard seamlessly with non-custodial wallet-as-a-service and transaction sponsorship." ----------------------------------------------------------------------------------------------------- import Link from "fumadocs-core/link"; ## Wallet as a Service wallet-as-a-service (WaaS) solution provide a seamless way for users to transact on-chain. Developers can integrate social logins and other familiar experiences into their applications, making onboarding fast and effortless. Users can create non-custodial wallets (the user owns the key and have full control over their digital assets) instantly without needing to manage private keys. Users can also recover their wallets and export their private keys at any time. Wallet key management system uses Shamir's Secret Sharing to split the private key into multiple parts. The parts are stored in different locations, such as the user's device and encrypted in the server. Neither UTXOS nor the developer's application has access to the user's keys. The private key is reconstructed only on the user's device during transaction signing, in an isolated iframe, which persists in-memory and is destroyed after the transaction is signed. Overall, the integration with a wallet-as-a-service solution provides a self-custody wallet to end users and accelerates the time-to-market for developers. Visit UTXOS wallet documentation for the latest tutorial on how to integrate UTXOS wallet into your application. ## Transaction Sponsorship Network fees are the costs required to execute transactions, compensating network validators for processing and securing the blockchain. These fees are paid in the network's native token, such as ADA on Cardano. While essential for incentivizing validators and maintaining network security, network fees can pose a challenge for end users, as they must hold tokens to cover these costs when interacting with applications. Sponsorship enables developers to create seamless user experiences by eliminating the need for end-users to hold tokens in their wallets for transactions. Instead, transactions inputs and network fees are deducted from the developer's wallet, solving one of the most significant challenges in blockchain application development and enabling frictionless onboarding and interaction for end-users. Visit UTXOS sponsorship documentation for the latest tutorial on how to integrate UTXOS wallet into your application. # Course Lessons URL: /resources/cardano-course/lessons Step-by-step lessons for mastering Cardano development with Mesh SDK and Aiken. \*\*\* title: "Course Lessons" description: "Step-by-step lessons for mastering Cardano development with Mesh SDK and Aiken." icon: "DocumentTextIcon" ------------------------ import Link from "fumadocs-core/link"; Master Cardano development through our comprehensive lesson series. Each lesson builds upon the previous one, taking you from basic concepts to advanced smart contract development. ## Lesson Overview ### Getting Started \* Lesson 1: Hello World - Set up Mesh SDK and send your first transaction \* Lesson 2: Multi-signature Transactions - Build transactions requiring multiple signatures ### Smart Contract Development \* Lesson 3: Aiken Contracts - Introduction to Aiken smart contract development \* Lesson 4: Contract Testing - Testing strategies and best practices \* Lesson 5: Avoid Redundant Validation - Optimization patterns for efficient contracts \* Lesson 6: Interpreting Blueprint - Understanding and using Aiken blueprints ### Advanced Contracts \* Lesson 7: Vesting Contract - Build a token vesting smart contract \* Lesson 8: Plutus NFT Contract - Create NFT minting contracts with auto-increment ### Scaling & Services \* Lesson 9: Hydra End-to-End - Layer 2 scaling with Hydra Head protocol \* Lesson 10: Web3 Services - Wallet-as-a-service and transaction sponsorship ## Learning Path We recommend following the lessons in order, as each builds upon concepts introduced in previous lessons. However, if you're already familiar with certain topics, feel free to jump to specific lessons that interest you. ## Support If you have questions or need help with any lesson, join our community channels or check out the Developer Resources page for additional support options. ---