diff --git a/apps/playground/package.json b/apps/playground/package.json index 2d7a48ba..549ed060 100644 --- a/apps/playground/package.json +++ b/apps/playground/package.json @@ -21,17 +21,17 @@ "@next/mdx": "^14.2.3", "@next/third-parties": "^14.2.5", "copy-to-clipboard": "^3.3.3", - "flowbite": "^2.3.0", + "flowbite": "^2.5.1", "flowbite-react": "^0.9.0", "flowbite-typography": "^1.0.3", + "json-bigint": "^1.0.0", "next": "^14.1.1", "persist-and-sync": "^1.2.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-highlight": "^0.15.0", "react-scroll": "^1.9.0", - "zustand": "^4.5.4", - "json-bigint": "^1.0.0" + "zustand": "^4.5.4" }, "devDependencies": { "@meshsdk/configs": "*", @@ -51,4 +51,4 @@ "typescript": "^5.3.3" }, "prettier": "@meshsdk/configs/prettier" -} \ No newline at end of file +} diff --git a/apps/playground/public/drep/meshjs.jsonld b/apps/playground/public/governance/meshjs.jsonld similarity index 100% rename from apps/playground/public/drep/meshjs.jsonld rename to apps/playground/public/governance/meshjs.jsonld diff --git a/apps/playground/public/governance/network-3524352_640.jpg b/apps/playground/public/governance/network-3524352_640.jpg new file mode 100644 index 00000000..6e6af8b2 Binary files /dev/null and b/apps/playground/public/governance/network-3524352_640.jpg differ diff --git a/apps/playground/src/components/button/button-float-documentation.tsx b/apps/playground/src/components/button/button-float-documentation.tsx new file mode 100644 index 00000000..3e1814c0 --- /dev/null +++ b/apps/playground/src/components/button/button-float-documentation.tsx @@ -0,0 +1,14 @@ +import { DocumentTextIcon } from "@heroicons/react/24/solid"; + +import Link from "../link"; +import Button from "./button"; + +export default function ButtonFloatDocumentation({ href }: { href: string }) { + return ( + + + + ); +} diff --git a/apps/playground/src/components/button/button.tsx b/apps/playground/src/components/button/button.tsx index f035f8ad..4fe0cea6 100644 --- a/apps/playground/src/components/button/button.tsx +++ b/apps/playground/src/components/button/button.tsx @@ -4,6 +4,8 @@ export default function Button({ style, onClick, disabled, + id, + tooltip, }: { children: React.ReactNode; className?: string; @@ -15,8 +17,10 @@ export default function Button({ | "info" | "light" | "dark"; - onClick: () => void; + onClick?: () => void; disabled?: boolean; + id?: string; + tooltip?: string; }) { const styles = { primary: @@ -36,24 +40,32 @@ export default function Button({ let _style = style && styles[style] ? styles[style] : styles.primary; if (className) { - style += ` ${className}`; + _style += ` ${className}`; } if (disabled) { _style += ` cursor-not-allowed`; } - style += ` not-format`; + _style += ` not-format button-with-tooltip`; return ( - + <> + + ); } diff --git a/apps/playground/src/components/layouts/image-header-and-body.tsx b/apps/playground/src/components/layouts/image-header-and-body.tsx index e5c6c74a..cc36613f 100644 --- a/apps/playground/src/components/layouts/image-header-and-body.tsx +++ b/apps/playground/src/components/layouts/image-header-and-body.tsx @@ -1,5 +1,6 @@ import Metatags from "~/components/site/metatags"; import Markdown from "./markdown"; +import StickySidebar from "./sidebar/sticky-sidebar"; export default function LayoutImageHeaderAndBody({ children, @@ -7,12 +8,16 @@ export default function LayoutImageHeaderAndBody({ description, image, cover, + sidebarItems, + authors, }: { children: React.ReactNode; title: string; description: string; image: string; cover: string; + sidebarItems?: { to: string; label: string }[]; + authors?: { url: string; image: string; name: string; about: string }[]; }) { return ( <> @@ -34,16 +39,21 @@ export default function LayoutImageHeaderAndBody({
{children}
- {/* */} + + )} diff --git a/apps/playground/src/components/layouts/markdown.tsx b/apps/playground/src/components/layouts/markdown.tsx index 5566f7eb..e92c4ac1 100644 --- a/apps/playground/src/components/layouts/markdown.tsx +++ b/apps/playground/src/components/layouts/markdown.tsx @@ -16,6 +16,7 @@ export default function Markdown({ children }: { children: React.ReactNode }) { components={{ //@ts-ignore pre: (props) => , + h2: (props) =>

{props.children}

, }} > {children} diff --git a/apps/playground/src/components/layouts/sidebar/sticky-sidebar.tsx b/apps/playground/src/components/layouts/sidebar/sticky-sidebar.tsx new file mode 100644 index 00000000..a3c1c117 --- /dev/null +++ b/apps/playground/src/components/layouts/sidebar/sticky-sidebar.tsx @@ -0,0 +1,97 @@ +import { Link } from "react-scroll"; + +export default function StickySidebar({ + sidebarItems, + authors, +}: { + sidebarItems: { to: string; label: string }[]; + authors?: { url: string; image: string; name: string; about: string }[]; +}) { + return ( +
+
+ {authors && ( +
+ {authors && + authors!.map((author, i) => { + return ( + +
+ {author.name} +
+
+ + {author.name} + + {author.about} +
+
+ ); + })} +
+ )} + + + {/* */} +
+
+ ); +} diff --git a/apps/playground/src/pages/apis/transaction/basics/index.tsx b/apps/playground/src/pages/apis/transaction/basics/index.tsx index dc0e7c3f..05218de2 100644 --- a/apps/playground/src/pages/apis/transaction/basics/index.tsx +++ b/apps/playground/src/pages/apis/transaction/basics/index.tsx @@ -1,5 +1,6 @@ import type { NextPage } from "next"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body"; import Metatags from "~/components/site/metatags"; @@ -66,6 +67,7 @@ const ReactPage: NextPage = () => { sending assets and various options to customize the transaction.

+ diff --git a/apps/playground/src/pages/apis/transaction/minting/index.tsx b/apps/playground/src/pages/apis/transaction/minting/index.tsx index b348f370..5a392a02 100644 --- a/apps/playground/src/pages/apis/transaction/minting/index.tsx +++ b/apps/playground/src/pages/apis/transaction/minting/index.tsx @@ -1,5 +1,6 @@ import type { NextPage } from "next"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body"; import Metatags from "~/components/site/metatags"; @@ -44,6 +45,7 @@ const ReactPage: NextPage = () => { minting and burning assets.

+ diff --git a/apps/playground/src/pages/apis/transaction/smart-contract/index.tsx b/apps/playground/src/pages/apis/transaction/smart-contract/index.tsx index 54c88300..4d0212b5 100644 --- a/apps/playground/src/pages/apis/transaction/smart-contract/index.tsx +++ b/apps/playground/src/pages/apis/transaction/smart-contract/index.tsx @@ -1,5 +1,6 @@ import type { NextPage } from "next"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body"; import Metatags from "~/components/site/metatags"; @@ -48,6 +49,7 @@ const ReactPage: NextPage = () => { smart contracts.

+ diff --git a/apps/playground/src/pages/apis/transaction/staking/index.tsx b/apps/playground/src/pages/apis/transaction/staking/index.tsx index 8df2b89f..4cf2adcc 100644 --- a/apps/playground/src/pages/apis/transaction/staking/index.tsx +++ b/apps/playground/src/pages/apis/transaction/staking/index.tsx @@ -1,5 +1,6 @@ import type { NextPage } from "next"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body"; import Metatags from "~/components/site/metatags"; @@ -42,6 +43,8 @@ const ReactPage: NextPage = () => { staking process.

+ + diff --git a/apps/playground/src/pages/apis/txbuilder/basics/index.tsx b/apps/playground/src/pages/apis/txbuilder/basics/index.tsx index 1db052e1..62d79334 100644 --- a/apps/playground/src/pages/apis/txbuilder/basics/index.tsx +++ b/apps/playground/src/pages/apis/txbuilder/basics/index.tsx @@ -1,5 +1,6 @@ import type { NextPage } from "next"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import Link from "~/components/link"; import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body"; @@ -11,11 +12,11 @@ import TxbuilderCip20 from "./cip20"; import TxbuilderCoinSelection from "./coin-selection"; import TxbuilderInitializeTxbuilder from "./initialize-txbuilder"; import TxbuilderMultisig from "./multisig"; +import TxbuilderMultisigNativeScript from "./multisig-native-script"; import TxbuilderSendValues from "./send-values"; import TxbuilderSetNetwork from "./set-network"; import TxbuilderSetRequiredSigners from "./set-required-signers"; import TxbuilderSetTime from "./set-time"; -import TxbuilderMultisigNativeScript from "./multisig-native-script"; const ReactPage: NextPage = () => { const sidebarItems = [ @@ -65,6 +66,7 @@ const ReactPage: NextPage = () => {

+ {/* */} diff --git a/apps/playground/src/pages/apis/txbuilder/minting/index.tsx b/apps/playground/src/pages/apis/txbuilder/minting/index.tsx index 9a3662dd..e2b3b1f2 100644 --- a/apps/playground/src/pages/apis/txbuilder/minting/index.tsx +++ b/apps/playground/src/pages/apis/txbuilder/minting/index.tsx @@ -1,5 +1,6 @@ import type { NextPage } from "next"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body"; import Metatags from "~/components/site/metatags"; @@ -47,6 +48,7 @@ const ReactPage: NextPage = () => {

+ diff --git a/apps/playground/src/pages/apis/txbuilder/smart-contract/index.tsx b/apps/playground/src/pages/apis/txbuilder/smart-contract/index.tsx index 58441a9a..c0511613 100644 --- a/apps/playground/src/pages/apis/txbuilder/smart-contract/index.tsx +++ b/apps/playground/src/pages/apis/txbuilder/smart-contract/index.tsx @@ -1,5 +1,6 @@ import type { NextPage } from "next"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body"; import Metatags from "~/components/site/metatags"; @@ -53,6 +54,7 @@ const ReactPage: NextPage = () => { + diff --git a/apps/playground/src/pages/apis/txbuilder/staking/index.tsx b/apps/playground/src/pages/apis/txbuilder/staking/index.tsx index 84012996..ec98f2a5 100644 --- a/apps/playground/src/pages/apis/txbuilder/staking/index.tsx +++ b/apps/playground/src/pages/apis/txbuilder/staking/index.tsx @@ -1,5 +1,6 @@ import type { NextPage } from "next"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body"; import Metatags from "~/components/site/metatags"; @@ -33,6 +34,8 @@ const ReactPage: NextPage = () => { > <> + + diff --git a/apps/playground/src/pages/apis/wallets/appwallet/index.tsx b/apps/playground/src/pages/apis/wallets/appwallet/index.tsx index faba4f39..5632baca 100644 --- a/apps/playground/src/pages/apis/wallets/appwallet/index.tsx +++ b/apps/playground/src/pages/apis/wallets/appwallet/index.tsx @@ -1,5 +1,6 @@ import type { NextPage } from "next"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body"; import Metatags from "~/components/site/metatags"; @@ -39,6 +40,7 @@ const ReactPage: NextPage = () => { fully customed applications's backend.

+ diff --git a/apps/playground/src/pages/apis/wallets/browserwallet/index.tsx b/apps/playground/src/pages/apis/wallets/browserwallet/index.tsx index e15d2eec..a98b0e14 100644 --- a/apps/playground/src/pages/apis/wallets/browserwallet/index.tsx +++ b/apps/playground/src/pages/apis/wallets/browserwallet/index.tsx @@ -1,5 +1,6 @@ import type { NextPage } from "next"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import Link from "~/components/link"; import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body"; @@ -78,12 +79,16 @@ const ReactPage: NextPage = () => { are useful for building dApps.

+

Check out the full documentation on

+

In this section, you can connect wallet and try APIs for dApps to communicate with your wallet.

+ + diff --git a/apps/playground/src/pages/apis/wallets/meshwallet/index.tsx b/apps/playground/src/pages/apis/wallets/meshwallet/index.tsx index 680e2f34..f6dc6ade 100644 --- a/apps/playground/src/pages/apis/wallets/meshwallet/index.tsx +++ b/apps/playground/src/pages/apis/wallets/meshwallet/index.tsx @@ -1,5 +1,6 @@ import type { NextPage } from "next"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body"; import Metatags from "~/components/site/metatags"; @@ -63,6 +64,7 @@ const ReactPage: NextPage = () => { get started.

+ diff --git a/apps/playground/src/pages/governance/index.mdx b/apps/playground/src/pages/governance/index.mdx new file mode 100644 index 00000000..cb10eaaf --- /dev/null +++ b/apps/playground/src/pages/governance/index.mdx @@ -0,0 +1,29 @@ +import { useState } from "react"; + +import { checkSignature, generateNonce } from "@meshsdk/core"; +import { CardanoWallet, useWallet } from "@meshsdk/react"; + +import Button from "~/components/button/button"; +import LayoutImageHeaderAndBody from "~/components/layouts/image-header-and-body"; + +export default function MDXPage({ children }) { + return ( + + <>{children} + + ); +} + +## Intro + +With the adoption of Voltaire, we have created and followed certain guidelines and directives that will help us make our decision regarding governance actions as a dRep at the Cardano Ecosystem. This is NOT a document aimed at becoming a large set of strict rules for the whole community through social contract and to dictate how they make their decisions. It simply contains some guidelines we thought are important and we abide by them to the extent that it’s possible. Meaning, it’s a subjective assessment which we use and participants of Cardano's governance and its partner chains are free to adopt in order to make their own decisions. + +## Principles on Treasury Proposals at CardanoGov + +### 1. On-Chain Identity Verification + +Whenever possible, proposers must verify their on-chain identities to enhance trust and transparency. In cases where full on-chain verification isn’t available, proposers should make efforts to prove their web2 or web3 identities through alternative means. The reason for this, is that a lack of a verified ID, makes it difficult for all proposals to prove on-chain and to people without first-hand knowledge of the team, whether or not they are legitimate. Also, it perpetuates the risk of unknown malicious actors pretending to be other characters with a better reputation in future referendums. diff --git a/apps/playground/src/pages/guides/nextjs.mdx b/apps/playground/src/pages/guides/nextjs.mdx index 8f302173..a24b8f7b 100644 --- a/apps/playground/src/pages/guides/nextjs.mdx +++ b/apps/playground/src/pages/guides/nextjs.mdx @@ -2,12 +2,17 @@ import LayoutImageHeaderAndBody from "~/components/layouts/image-header-and-body import { guidenextjs } from "~/data/links-guides"; export default function MDXPage({ children }) { + // const sidebarItems = [ + // { label: 'System setup', to: 'systemsetup' }, + // ]; + return ( {children} diff --git a/apps/playground/src/pages/guides/prove-wallet-ownership/index.mdx b/apps/playground/src/pages/guides/prove-wallet-ownership/index.mdx index dc548e82..cc28230d 100644 --- a/apps/playground/src/pages/guides/prove-wallet-ownership/index.mdx +++ b/apps/playground/src/pages/guides/prove-wallet-ownership/index.mdx @@ -132,7 +132,7 @@ import { checkSignature } from '@meshsdk/core'; async function backendVerifySignature(userAddress, signature) { // do: get 'nonce' from user (database) using 'userAddress' - const result = checkSignature(nonce, userAddress, signature); + const result = checkSignature(nonce, signature); // do: update 'nonce' in the database with another random string @@ -206,7 +206,7 @@ async function backendGetNonce(userAddress) { async function backendVerifySignature(userAddress, signature) { // do: get 'nonce' from database - const result = checkSignature(nonce, userAddress, signature); + const result = checkSignature(nonce, signature); if(result){ // create JWT or approve certain process } diff --git a/apps/playground/src/pages/providers/blockfrost.tsx b/apps/playground/src/pages/providers/blockfrost.tsx index b507a2c5..0786ade9 100644 --- a/apps/playground/src/pages/providers/blockfrost.tsx +++ b/apps/playground/src/pages/providers/blockfrost.tsx @@ -2,6 +2,7 @@ import type { NextPage } from "next"; import { BlockfrostProvider } from "@meshsdk/core"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import Link from "~/components/link"; import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body"; @@ -69,6 +70,7 @@ const ReactPage: NextPage = () => {

+ { + { const sidebarItems = [ @@ -75,6 +76,7 @@ const ReactPage: NextPage = () => {

Get started:

+ {

Get started:

+ {

Get started:

+ { const sidebarItems = [ @@ -86,6 +87,7 @@ const ReactPage: NextPage = () => { + diff --git a/apps/playground/src/pages/smart-contracts/giftcard/common.tsx b/apps/playground/src/pages/smart-contracts/giftcard/common.tsx index 40b3a4e0..8ada0da9 100644 --- a/apps/playground/src/pages/smart-contracts/giftcard/common.tsx +++ b/apps/playground/src/pages/smart-contracts/giftcard/common.tsx @@ -9,7 +9,6 @@ export function getContract(wallet: BrowserWallet) { const meshTxBuilder = new MeshTxBuilder({ fetcher: blockchainProvider, submitter: blockchainProvider, - verbose: true, }); const contract = new MeshGiftCardContract({ @@ -17,6 +16,7 @@ export function getContract(wallet: BrowserWallet) { fetcher: blockchainProvider, wallet: wallet, networkId: 0, + version: 2, }); return contract; diff --git a/apps/playground/src/pages/smart-contracts/giftcard/index.tsx b/apps/playground/src/pages/smart-contracts/giftcard/index.tsx index 768fbf1c..fa713bb0 100644 --- a/apps/playground/src/pages/smart-contracts/giftcard/index.tsx +++ b/apps/playground/src/pages/smart-contracts/giftcard/index.tsx @@ -1,5 +1,6 @@ import type { NextPage } from "next"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import Link from "~/components/link"; import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body"; @@ -82,6 +83,7 @@ const ReactPage: NextPage = () => {

+ diff --git a/apps/playground/src/pages/smart-contracts/marketplace/index.tsx b/apps/playground/src/pages/smart-contracts/marketplace/index.tsx index f7f98a4d..4e60d9ce 100644 --- a/apps/playground/src/pages/smart-contracts/marketplace/index.tsx +++ b/apps/playground/src/pages/smart-contracts/marketplace/index.tsx @@ -13,6 +13,7 @@ import MarketplaceBuyAsset from "./buy-asset"; import MarketplaceCancelListing from "./cancel-listing"; import MarketplaceListAsset from "./list-asset"; import MarketplaceUpdateListing from "./update-listing"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; const ReactPage: NextPage = () => { const sidebarItems = [ @@ -112,6 +113,8 @@ const ReactPage: NextPage = () => { + + diff --git a/apps/playground/src/pages/smart-contracts/payment-splitter/index.tsx b/apps/playground/src/pages/smart-contracts/payment-splitter/index.tsx index 4c4691b1..59f10f1a 100644 --- a/apps/playground/src/pages/smart-contracts/payment-splitter/index.tsx +++ b/apps/playground/src/pages/smart-contracts/payment-splitter/index.tsx @@ -1,5 +1,6 @@ import type { NextPage } from "next"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import Link from "~/components/link"; import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body"; @@ -102,6 +103,7 @@ const ReactPage: NextPage = () => {

+ diff --git a/apps/playground/src/pages/smart-contracts/swap/index.tsx b/apps/playground/src/pages/smart-contracts/swap/index.tsx index 72864e3e..cffbf8f3 100644 --- a/apps/playground/src/pages/smart-contracts/swap/index.tsx +++ b/apps/playground/src/pages/smart-contracts/swap/index.tsx @@ -1,5 +1,6 @@ import type { NextPage } from "next"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import MintMeshToken from "~/components/cardano/mint-mesh-token"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import Link from "~/components/link"; @@ -86,6 +87,7 @@ const ReactPage: NextPage = () => { + diff --git a/apps/playground/src/pages/smart-contracts/vesting/index.tsx b/apps/playground/src/pages/smart-contracts/vesting/index.tsx index 555d3e1a..933bd34a 100644 --- a/apps/playground/src/pages/smart-contracts/vesting/index.tsx +++ b/apps/playground/src/pages/smart-contracts/vesting/index.tsx @@ -1,5 +1,6 @@ import type { NextPage } from "next"; +import ButtonFloatDocumentation from "~/components/button/button-float-documentation"; import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth"; import Link from "~/components/link"; import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body"; @@ -84,6 +85,7 @@ const ReactPage: NextPage = () => {

+ diff --git a/apps/playground/src/styles/globals.css b/apps/playground/src/styles/globals.css index b5c61c95..404c03a1 100644 --- a/apps/playground/src/styles/globals.css +++ b/apps/playground/src/styles/globals.css @@ -1,3 +1,7 @@ @tailwind base; @tailwind components; @tailwind utilities; + +.button-with-tooltip:hover .button-with-tooltip-content { + visibility: visible; +} diff --git a/apps/playground/tailwind.config.js b/apps/playground/tailwind.config.js index 6255a9d6..17994b23 100644 --- a/apps/playground/tailwind.config.js +++ b/apps/playground/tailwind.config.js @@ -1,11 +1,12 @@ +const flowbite = require("flowbite-react/tailwind"); + /** @type {import('tailwindcss').Config} */ module.exports = { darkMode: "class", content: [ - "./node_modules/flowbite/**/*.js", - "./node_modules/flowbite-react/**/*.js", "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", "./src/components/**/*.{js,ts,jsx,tsx,mdx}", + flowbite.content(), ], theme: { extend: { @@ -73,5 +74,5 @@ module.exports = { ], }, }, - plugins: [require("flowbite-typography"), require("flowbite/plugin")], + plugins: [require("flowbite-typography"), flowbite.plugin()], }; diff --git a/package-lock.json b/package-lock.json index 984b0b97..b5465bd4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -276,7 +276,7 @@ "@next/mdx": "^14.2.3", "@next/third-parties": "^14.2.5", "copy-to-clipboard": "^3.3.3", - "flowbite": "^2.3.0", + "flowbite": "^2.5.1", "flowbite-react": "^0.9.0", "flowbite-typography": "^1.0.3", "json-bigint": "^1.0.0", @@ -22364,7 +22364,7 @@ }, "packages/mesh-common": { "name": "@meshsdk/common", - "version": "1.7.0", + "version": "1.7.2", "license": "Apache-2.0", "dependencies": { "bech32": "^2.0.0", @@ -22381,14 +22381,14 @@ }, "packages/mesh-contract": { "name": "@meshsdk/contract", - "version": "1.7.0", + "version": "1.7.2", "license": "Apache-2.0", "dependencies": { - "@meshsdk/common": "1.7.0", - "@meshsdk/core": "1.7.0", - "@meshsdk/core-csl": "1.7.0", - "@meshsdk/core-cst": "1.7.0", - "@meshsdk/transaction": "1.7.0" + "@meshsdk/common": "1.7.2", + "@meshsdk/core": "1.7.2", + "@meshsdk/core-csl": "1.7.2", + "@meshsdk/core-cst": "1.7.2", + "@meshsdk/transaction": "1.7.2" }, "devDependencies": { "@meshsdk/configs": "*", @@ -22399,16 +22399,16 @@ }, "packages/mesh-core": { "name": "@meshsdk/core", - "version": "1.7.0", + "version": "1.7.2", "license": "Apache-2.0", "dependencies": { - "@meshsdk/common": "1.7.0", - "@meshsdk/core-csl": "1.7.0", - "@meshsdk/core-cst": "1.7.0", - "@meshsdk/provider": "1.7.0", - "@meshsdk/react": "1.7.0", - "@meshsdk/transaction": "1.7.0", - "@meshsdk/wallet": "1.7.0" + "@meshsdk/common": "1.7.2", + "@meshsdk/core-csl": "1.7.2", + "@meshsdk/core-cst": "1.7.2", + "@meshsdk/provider": "1.7.2", + "@meshsdk/react": "1.7.2", + "@meshsdk/transaction": "1.7.2", + "@meshsdk/wallet": "1.7.2" }, "devDependencies": { "@meshsdk/configs": "*", @@ -22419,10 +22419,10 @@ }, "packages/mesh-core-csl": { "name": "@meshsdk/core-csl", - "version": "1.7.0", + "version": "1.7.2", "license": "Apache-2.0", "dependencies": { - "@meshsdk/common": "1.7.0", + "@meshsdk/common": "1.7.2", "@sidan-lab/sidan-csl-rs-browser": "0.8.0", "@sidan-lab/sidan-csl-rs-nodejs": "0.8.0", "json-bigint": "^1.0.0" @@ -22438,7 +22438,7 @@ }, "packages/mesh-core-cst": { "name": "@meshsdk/core-cst", - "version": "1.7.0", + "version": "1.7.2", "license": "Apache-2.0", "dependencies": { "@cardano-sdk/core": "^0.35.4", @@ -22447,7 +22447,7 @@ "@harmoniclabs/cbor": "1.3.0", "@harmoniclabs/plutus-data": "1.2.4", "@harmoniclabs/uplc": "1.2.4", - "@meshsdk/common": "1.7.0", + "@meshsdk/common": "1.7.2", "@stricahq/bip32ed25519": "^1.1.0", "@stricahq/cbors": "^1.0.0", "pbkdf2": "^3.1.2" @@ -22464,11 +22464,11 @@ }, "packages/mesh-provider": { "name": "@meshsdk/provider", - "version": "1.7.0", + "version": "1.7.2", "license": "Apache-2.0", "dependencies": { - "@meshsdk/common": "1.7.0", - "@meshsdk/core-cst": "1.7.0", + "@meshsdk/common": "1.7.2", + "@meshsdk/core-cst": "1.7.2", "axios": "^1.7.2" }, "devDependencies": { @@ -22480,12 +22480,12 @@ }, "packages/mesh-react": { "name": "@meshsdk/react", - "version": "1.7.0", + "version": "1.7.2", "license": "Apache-2.0", "dependencies": { - "@meshsdk/common": "1.7.0", - "@meshsdk/transaction": "1.7.0", - "@meshsdk/wallet": "1.7.0", + "@meshsdk/common": "1.7.2", + "@meshsdk/transaction": "1.7.2", + "@meshsdk/wallet": "1.7.2", "react": "^18.2.0" }, "devDependencies": { @@ -22500,12 +22500,12 @@ }, "packages/mesh-transaction": { "name": "@meshsdk/transaction", - "version": "1.7.0", + "version": "1.7.2", "license": "Apache-2.0", "dependencies": { - "@meshsdk/common": "1.7.0", - "@meshsdk/core-csl": "1.7.0", - "@meshsdk/core-cst": "1.7.0", + "@meshsdk/common": "1.7.2", + "@meshsdk/core-csl": "1.7.2", + "@meshsdk/core-cst": "1.7.2", "json-bigint": "^1.0.0" }, "devDependencies": { @@ -22518,13 +22518,13 @@ }, "packages/mesh-wallet": { "name": "@meshsdk/wallet", - "version": "1.7.0", + "version": "1.7.2", "license": "Apache-2.0", "dependencies": { - "@meshsdk/common": "1.7.0", - "@meshsdk/core-csl": "1.7.0", - "@meshsdk/core-cst": "1.7.0", - "@meshsdk/transaction": "1.7.0", + "@meshsdk/common": "1.7.2", + "@meshsdk/core-csl": "1.7.2", + "@meshsdk/core-cst": "1.7.2", + "@meshsdk/transaction": "1.7.2", "@nufi/dapp-client-cardano": "^0.3.1", "@nufi/dapp-client-core": "^0.3.1" }, @@ -22538,7 +22538,7 @@ }, "scripts/mesh-cli": { "name": "meshjs", - "version": "1.7.0", + "version": "1.7.2", "license": "Apache-2.0", "dependencies": { "chalk": "5.3.0", diff --git a/packages/mesh-common/package.json b/packages/mesh-common/package.json index 8bcde54c..dcdae5d5 100644 --- a/packages/mesh-common/package.json +++ b/packages/mesh-common/package.json @@ -1,6 +1,6 @@ { "name": "@meshsdk/common", - "version": "1.7.2", + "version": "1.7.3", "description": "", "main": "./dist/index.cjs", "module": "./dist/index.js", diff --git a/packages/mesh-common/src/data/json/aliases.ts b/packages/mesh-common/src/data/json/aliases.ts index 9d3a9c59..e0e89c9d 100644 --- a/packages/mesh-common/src/data/json/aliases.ts +++ b/packages/mesh-common/src/data/json/aliases.ts @@ -52,7 +52,7 @@ export type AssetClass = ConStr0<[CurrencySymbol, TokenName]>; * Aiken alias * The Plutus Data output reference in JSON */ -export type OutputReference = ConStr0<[ConStr0<[ByteString]>, Integer]>; +export type OutputReference = ConStr0<[ByteString, Integer]>; /** * PlutusTx alias @@ -166,7 +166,9 @@ export const assetClass = ( conStr0([currencySymbol(currencySymbolHex), tokenName(tokenNameHex)]); /** - * The utility function to create a Plutus Data output reference in JSON + * The utility function to create a Plutus Data output reference in JSON. + * Note that it is updated since aiken version v1.1.0. + * If you want to build the type before Chang, please use txOutRef instead. * @param txHash The transaction hash * @param index The index of the output * @returns The Plutus Data output reference object @@ -178,7 +180,7 @@ export const outputReference = ( if (txHash.length !== 64) { throw new Error("Invalid transaction hash - should be 32 bytes long"); } - return conStr0([conStr0([byteString(txHash)]), integer(index)]); + return conStr0([byteString(txHash), integer(index)]); }; /** @@ -187,8 +189,12 @@ export const outputReference = ( * @param index The index of the output * @returns The Plutus Data TxOutRef object */ -export const txOutRef = (txHash: string, index: number): TxOutRef => - outputReference(txHash, index); +export const txOutRef = (txHash: string, index: number): TxOutRef => { + if (txHash.length !== 64) { + throw new Error("Invalid transaction hash - should be 32 bytes long"); + } + return conStr0([conStr0([byteString(txHash)]), integer(index)]); +}; /** * The utility function to create a Plutus Data POSIX time in JSON diff --git a/packages/mesh-common/src/data/mesh/aliases.ts b/packages/mesh-common/src/data/mesh/aliases.ts index 59af2590..942552e4 100644 --- a/packages/mesh-common/src/data/mesh/aliases.ts +++ b/packages/mesh-common/src/data/mesh/aliases.ts @@ -11,7 +11,7 @@ export type MAssetClass = MConStr0<[string, string]>; * Aiken alias * The Mesh Data output reference */ -export type MOutputReference = MConStr0<[MConStr0<[string]>, number]>; +export type MOutputReference = MConStr0<[string, number]>; /** * PlutusTx alias @@ -63,7 +63,7 @@ export const mOutputReference = ( if (txHash.length !== 64) { throw new Error("Invalid transaction hash - should be 32 bytes long"); } - return mConStr0([mConStr0([txHash]), index]); + return mConStr0([txHash, index]); }; /** @@ -72,8 +72,12 @@ export const mOutputReference = ( * @param index The index of the output * @returns The Mesh Data TxOutRef object */ -export const mTxOutRef = (txHash: string, index: number): MTxOutRef => - mOutputReference(txHash, index); +export const mTxOutRef = (txHash: string, index: number): MTxOutRef => { + if (txHash.length !== 64) { + throw new Error("Invalid transaction hash - should be 32 bytes long"); + } + return mConStr0([mConStr0([txHash]), index]); +}; /** * The utility function to create a Mesh Data tuple in Mesh Data type diff --git a/packages/mesh-contract/package.json b/packages/mesh-contract/package.json index ddef3309..756481b4 100644 --- a/packages/mesh-contract/package.json +++ b/packages/mesh-contract/package.json @@ -1,6 +1,6 @@ { "name": "@meshsdk/contract", - "version": "1.7.2", + "version": "1.7.3", "description": "", "main": "./dist/index.cjs", "module": "./dist/index.js", @@ -33,11 +33,11 @@ "typescript": "^5.3.3" }, "dependencies": { - "@meshsdk/common": "1.7.2", - "@meshsdk/core": "1.7.2", - "@meshsdk/core-csl": "1.7.2", - "@meshsdk/core-cst": "1.7.2", - "@meshsdk/transaction": "1.7.2" + "@meshsdk/common": "1.7.3", + "@meshsdk/core": "1.7.3", + "@meshsdk/core-csl": "1.7.3", + "@meshsdk/core-cst": "1.7.3", + "@meshsdk/transaction": "1.7.3" }, "prettier": "@meshsdk/configs/prettier", "publishConfig": { diff --git a/packages/mesh-contract/src/common.ts b/packages/mesh-contract/src/common.ts index c577de45..8f15b432 100644 --- a/packages/mesh-contract/src/common.ts +++ b/packages/mesh-contract/src/common.ts @@ -1,6 +1,7 @@ import { BrowserWallet, IFetcher, + LanguageVersion, MeshTxBuilder, MeshWallet, UTxO, @@ -13,6 +14,7 @@ export type MeshTxInitiatorInput = { wallet?: BrowserWallet | MeshWallet; networkId?: number; stakeCredential?: string; + version?: number; }; export class MeshTxInitiator { @@ -21,6 +23,8 @@ export class MeshTxInitiator { wallet?: BrowserWallet | MeshWallet; stakeCredential?: string; networkId = 0; + version = 2; + languageVersion: LanguageVersion = "V2"; constructor({ mesh, @@ -28,6 +32,7 @@ export class MeshTxInitiator { wallet, networkId = 0, stakeCredential, + version = 2, }: MeshTxInitiatorInput) { this.mesh = mesh; if (fetcher) { @@ -47,6 +52,15 @@ export class MeshTxInitiator { if (stakeCredential) { this.stakeCredential = this.stakeCredential; } + + this.version = version; + switch (this.version) { + case 1: + this.languageVersion = "V2"; + break; + default: + this.languageVersion = "V3"; + } } protected signSubmitReset = async () => { diff --git a/packages/mesh-contract/src/escrow/offchain.ts b/packages/mesh-contract/src/escrow/offchain.ts index f3309e57..e9f0795c 100644 --- a/packages/mesh-contract/src/escrow/offchain.ts +++ b/packages/mesh-contract/src/escrow/offchain.ts @@ -68,7 +68,6 @@ export class MeshEscrowContract extends MeshTxInitiator { constructor(inputs: MeshTxInitiatorInput) { super(inputs); - this.mesh.setNetwork(inputs.networkId === 1 ? "mainnet" : "preprod"); } initiateEscrow = async (escrowAmount: Asset[]): Promise => { @@ -112,8 +111,14 @@ export class MeshEscrowContract extends MeshTxInitiator { recipientAmount, ] = inputDatum.fields; - const initiatorAddress = serializeAddressObj(initiatorAddressObj); - const recipientAddress = serializeAddressObj(recipientAddressObj!); + const initiatorAddress = serializeAddressObj( + initiatorAddressObj, + this.networkId, + ); + const recipientAddress = serializeAddressObj( + recipientAddressObj!, + this.networkId, + ); const initiatorToReceive = MeshValue.fromValue(initiatorAmount).toAssets(); const recipientToReceive = MeshValue.fromValue( @@ -220,8 +225,14 @@ export class MeshEscrowContract extends MeshTxInitiator { recipientAddressObj, recipientAmount, ] = inputDatum.fields; - const initiatorAddress = serializeAddressObj(initiatorAddressObj); - const recipientAddress = serializeAddressObj(recipientAddressObj); + const initiatorAddress = serializeAddressObj( + initiatorAddressObj, + this.networkId, + ); + const recipientAddress = serializeAddressObj( + recipientAddressObj, + this.networkId, + ); const initiatorToReceive = MeshValue.fromValue(recipientAmount).toAssets(); const recipientToReceive = MeshValue.fromValue(initiatorAmount).toAssets(); diff --git a/packages/mesh-contract/src/giftcard/aiken-workspace/.gitignore b/packages/mesh-contract/src/giftcard/aiken-workspace-v1/.gitignore similarity index 100% rename from packages/mesh-contract/src/giftcard/aiken-workspace/.gitignore rename to packages/mesh-contract/src/giftcard/aiken-workspace-v1/.gitignore diff --git a/packages/mesh-contract/src/giftcard/aiken-workspace/aiken.lock b/packages/mesh-contract/src/giftcard/aiken-workspace-v1/aiken.lock similarity index 100% rename from packages/mesh-contract/src/giftcard/aiken-workspace/aiken.lock rename to packages/mesh-contract/src/giftcard/aiken-workspace-v1/aiken.lock diff --git a/packages/mesh-contract/src/giftcard/aiken-workspace/aiken.toml b/packages/mesh-contract/src/giftcard/aiken-workspace-v1/aiken.toml similarity index 100% rename from packages/mesh-contract/src/giftcard/aiken-workspace/aiken.toml rename to packages/mesh-contract/src/giftcard/aiken-workspace-v1/aiken.toml diff --git a/packages/mesh-contract/src/giftcard/aiken-workspace/plutus.json b/packages/mesh-contract/src/giftcard/aiken-workspace-v1/plutus.json similarity index 100% rename from packages/mesh-contract/src/giftcard/aiken-workspace/plutus.json rename to packages/mesh-contract/src/giftcard/aiken-workspace-v1/plutus.json diff --git a/packages/mesh-contract/src/giftcard/aiken-workspace/readme.md b/packages/mesh-contract/src/giftcard/aiken-workspace-v1/readme.md similarity index 100% rename from packages/mesh-contract/src/giftcard/aiken-workspace/readme.md rename to packages/mesh-contract/src/giftcard/aiken-workspace-v1/readme.md diff --git a/packages/mesh-contract/src/giftcard/aiken-workspace/validators/oneshot.ak b/packages/mesh-contract/src/giftcard/aiken-workspace-v1/validators/oneshot.ak similarity index 100% rename from packages/mesh-contract/src/giftcard/aiken-workspace/validators/oneshot.ak rename to packages/mesh-contract/src/giftcard/aiken-workspace-v1/validators/oneshot.ak diff --git a/packages/mesh-contract/src/vesting/aiken-workspace/.gitignore b/packages/mesh-contract/src/giftcard/aiken-workspace-v2/.gitignore similarity index 100% rename from packages/mesh-contract/src/vesting/aiken-workspace/.gitignore rename to packages/mesh-contract/src/giftcard/aiken-workspace-v2/.gitignore diff --git a/packages/mesh-contract/src/giftcard/aiken-workspace-v2/aiken.lock b/packages/mesh-contract/src/giftcard/aiken-workspace-v2/aiken.lock new file mode 100644 index 00000000..efe3a839 --- /dev/null +++ b/packages/mesh-contract/src/giftcard/aiken-workspace-v2/aiken.lock @@ -0,0 +1,27 @@ +# This file was generated by Aiken +# You typically do not need to edit this file + +[[requirements]] +name = "aiken-lang/stdlib" +version = "v2" +source = "github" + +[[requirements]] +name = "sidan-lab/vodka" +version = "0.1.0-beta" +source = "github" + +[[packages]] +name = "aiken-lang/stdlib" +version = "v2" +requirements = [] +source = "github" + +[[packages]] +name = "sidan-lab/vodka" +version = "0.1.0-beta" +requirements = [] +source = "github" + +[etags] +"aiken-lang/stdlib@v2" = [{ secs_since_epoch = 1725550729, nanos_since_epoch = 704384000 }, "d79382d2b6ecb3aee9b0755c31d8a5bbafe88a7b3706d7fb8a52fd4d05818501"] diff --git a/packages/mesh-contract/src/giftcard/aiken-workspace-v2/aiken.toml b/packages/mesh-contract/src/giftcard/aiken-workspace-v2/aiken.toml new file mode 100644 index 00000000..e63c5800 --- /dev/null +++ b/packages/mesh-contract/src/giftcard/aiken-workspace-v2/aiken.toml @@ -0,0 +1,23 @@ +name = "meshjs/giftcard" +version = "0.0.0" +compiler = "v1.1.0" +plutus = "v3" +license = "Apache-2.0" +description = "Aiken contracts for project 'meshjs/giftcard'" + +[repository] +user = "meshjs" +project = "giftcard" +platform = "github" + +[[dependencies]] +name = "aiken-lang/stdlib" +version = "v2" +source = "github" + +[[dependencies]] +name = "sidan-lab/vodka" +version = "0.1.0-beta" +source = "github" + +[config] diff --git a/packages/mesh-contract/src/giftcard/aiken-workspace-v2/plutus.json b/packages/mesh-contract/src/giftcard/aiken-workspace-v2/plutus.json new file mode 100644 index 00000000..69d6487a --- /dev/null +++ b/packages/mesh-contract/src/giftcard/aiken-workspace-v2/plutus.json @@ -0,0 +1,159 @@ +{ + "preamble": { + "title": "meshjs/giftcard", + "description": "Aiken contracts for project 'meshjs/giftcard'", + "version": "0.0.0", + "plutusVersion": "v3", + "compiler": { + "name": "Aiken", + "version": "v1.1.0+unknown" + }, + "license": "Apache-2.0" + }, + "validators": [ + { + "title": "oneshot.gift_card.mint", + "redeemer": { + "title": "rdmr", + "schema": { + "$ref": "#/definitions/oneshot~1Action" + } + }, + "parameters": [ + { + "title": "token_name", + "schema": { + "$ref": "#/definitions/ByteArray" + } + }, + { + "title": "utxo_ref", + "schema": { + "$ref": "#/definitions/cardano~1transaction~1OutputReference" + } + } + ], + "compiledCode": "5901ae01010032323232323232232225333005323232323253323300b3001300c3754004264646464a66601e600a0022a66602460226ea801c540085854ccc03cc00c00454ccc048c044dd50038a8010b0b18079baa006132323232533301430170021323253330133009301437540162a666026601260286ea8c8cc004004018894ccc0600045300103d87a80001323253330173375e603860326ea80080504cdd2a40006603600497ae0133004004001301c002301a00115333013300700113371e00402229405854ccc04ccdc3800a4002266e3c0080445281bad3014002375c60240022c602a00264a666020600860226ea800452f5bded8c026eacc054c048dd500099198008009bab3015301630163016301600322533301400114c103d87a80001323232325333015337220140042a66602a66e3c0280084cdd2a4000660326e980052f5c02980103d87a80001330060060033756602c0066eb8c050008c060008c058004dd6180980098079baa007370e90011bae3010300d37540046e1d200016300e300f002300d001300d002300b0013007375400229309b2b1bae0015734aae7555cf2ab9f5740ae855d11", + "hash": "401c967008d42885400991f9225715e1c3a8e43757b1fd36a1328195" + }, + { + "title": "oneshot.gift_card.else", + "parameters": [ + { + "title": "token_name", + "schema": { + "$ref": "#/definitions/ByteArray" + } + }, + { + "title": "utxo_ref", + "schema": { + "$ref": "#/definitions/cardano~1transaction~1OutputReference" + } + } + ], + "compiledCode": "5901ae01010032323232323232232225333005323232323253323300b3001300c3754004264646464a66601e600a0022a66602460226ea801c540085854ccc03cc00c00454ccc048c044dd50038a8010b0b18079baa006132323232533301430170021323253330133009301437540162a666026601260286ea8c8cc004004018894ccc0600045300103d87a80001323253330173375e603860326ea80080504cdd2a40006603600497ae0133004004001301c002301a00115333013300700113371e00402229405854ccc04ccdc3800a4002266e3c0080445281bad3014002375c60240022c602a00264a666020600860226ea800452f5bded8c026eacc054c048dd500099198008009bab3015301630163016301600322533301400114c103d87a80001323232325333015337220140042a66602a66e3c0280084cdd2a4000660326e980052f5c02980103d87a80001330060060033756602c0066eb8c050008c060008c058004dd6180980098079baa007370e90011bae3010300d37540046e1d200016300e300f002300d001300d002300b0013007375400229309b2b1bae0015734aae7555cf2ab9f5740ae855d11", + "hash": "401c967008d42885400991f9225715e1c3a8e43757b1fd36a1328195" + }, + { + "title": "oneshot.redeem.spend", + "datum": { + "title": "_d", + "schema": { + "$ref": "#/definitions/Data" + } + }, + "redeemer": { + "title": "_r", + "schema": { + "$ref": "#/definitions/Data" + } + }, + "parameters": [ + { + "title": "token_name", + "schema": { + "$ref": "#/definitions/ByteArray" + } + }, + { + "title": "policy_id", + "schema": { + "$ref": "#/definitions/ByteArray" + } + } + ], + "compiledCode": "59011501010032323232323232232232253330063232323232533300b3370e900118061baa001132323232325333013301600213253330113370e6eb4c04c009200113371e00201e2940dd718088008b180a00099299980799b8748008c040dd50008a5eb7bdb1804dd5980a18089baa001323300100137566028602a602a602a602a60226ea8020894ccc04c004530103d87a80001323232325333014337220200042a66602866e3c0400084cdd2a4000660306e980052f5c02980103d87a80001330060060033756602a0066eb8c04c008c05c008c054004c048c04c008c044004c034dd50008b1807980800118070009807001180600098041baa00114984d958dd70009bae0015734aae7555cf2ab9f5740ae855d101", + "hash": "b2386630f1b210c58d0e46f132e931b362c3f373685118018e4d956f" + }, + { + "title": "oneshot.redeem.else", + "parameters": [ + { + "title": "token_name", + "schema": { + "$ref": "#/definitions/ByteArray" + } + }, + { + "title": "policy_id", + "schema": { + "$ref": "#/definitions/ByteArray" + } + } + ], + "compiledCode": "59011501010032323232323232232232253330063232323232533300b3370e900118061baa001132323232325333013301600213253330113370e6eb4c04c009200113371e00201e2940dd718088008b180a00099299980799b8748008c040dd50008a5eb7bdb1804dd5980a18089baa001323300100137566028602a602a602a602a60226ea8020894ccc04c004530103d87a80001323232325333014337220200042a66602866e3c0400084cdd2a4000660306e980052f5c02980103d87a80001330060060033756602a0066eb8c04c008c05c008c054004c048c04c008c044004c034dd50008b1807980800118070009807001180600098041baa00114984d958dd70009bae0015734aae7555cf2ab9f5740ae855d101", + "hash": "b2386630f1b210c58d0e46f132e931b362c3f373685118018e4d956f" + } + ], + "definitions": { + "ByteArray": { + "dataType": "bytes" + }, + "Data": { + "title": "Data", + "description": "Any Plutus data." + }, + "Int": { + "dataType": "integer" + }, + "cardano/transaction/OutputReference": { + "title": "OutputReference", + "description": "An `OutputReference` is a unique reference to an output on-chain. The `output_index`\n corresponds to the position in the output list of the transaction (identified by its id)\n that produced that output", + "anyOf": [ + { + "title": "OutputReference", + "dataType": "constructor", + "index": 0, + "fields": [ + { + "title": "transaction_id", + "$ref": "#/definitions/ByteArray" + }, + { + "title": "output_index", + "$ref": "#/definitions/Int" + } + ] + } + ] + }, + "oneshot/Action": { + "title": "Action", + "anyOf": [ + { + "title": "Mint", + "dataType": "constructor", + "index": 0, + "fields": [] + }, + { + "title": "Burn", + "dataType": "constructor", + "index": 1, + "fields": [] + } + ] + } + } +} \ No newline at end of file diff --git a/packages/mesh-contract/src/giftcard/aiken-workspace-v2/readme.md b/packages/mesh-contract/src/giftcard/aiken-workspace-v2/readme.md new file mode 100644 index 00000000..2c92a664 --- /dev/null +++ b/packages/mesh-contract/src/giftcard/aiken-workspace-v2/readme.md @@ -0,0 +1,55 @@ +# giftcard + +Write validators in the `validators` folder, and supporting functions in the `lib` folder using `.ak` as a file extension. + +For example, as `validators/always_true.ak` + +```gleam +validator { + fn spend(_datum: Data, _redeemer: Data, _context: Data) -> Bool { + True + } +} +``` + +## Building + +```sh +aiken build +``` + +## Testing + +You can write tests in any module using the `test` keyword. For example: + +```gleam +test foo() { + 1 + 1 == 2 +} +``` + +To run all tests, simply do: + +```sh +aiken check +``` + +To run only tests matching the string `foo`, do: + +```sh +aiken check -m foo +``` + +## Documentation + +If you're writing a library, you might want to generate an HTML documentation for it. + +Use: + +```sh +aiken docs +``` + +## Resources + +Find more on the [Aiken's user manual](https://aiken-lang.org). diff --git a/packages/mesh-contract/src/giftcard/aiken-workspace-v2/validators/oneshot.ak b/packages/mesh-contract/src/giftcard/aiken-workspace-v2/validators/oneshot.ak new file mode 100644 index 00000000..4089af17 --- /dev/null +++ b/packages/mesh-contract/src/giftcard/aiken-workspace-v2/validators/oneshot.ak @@ -0,0 +1,164 @@ +use aiken/collection/dict +use aiken/collection/list +use cardano/assets.{PolicyId, from_asset, zero} +use cardano/transaction.{Input, OutputReference, Transaction, placeholder} as tx +use mocktail.{complete, mint, mocktail_tx, tx_in} +use mocktail/virgin_address.{mock_pub_key_address} +use mocktail/virgin_key_hash.{mock_policy_id} +use mocktail/virgin_output_reference.{mock_tx_hash, mock_utxo_ref} + +validator redeem(token_name: ByteArray, policy_id: ByteArray) { + spend(_d: Option, _r: Data, _input: OutputReference, tx: Transaction) { + let Transaction { mint, .. } = tx + expect [Pair(asset_name, amount)] = + mint + |> assets.tokens(policy_id) + |> dict.to_pairs() + amount == -1 && asset_name == token_name + } + + else(_) { + fail + } +} + +pub type Action { + Mint + Burn +} + +validator gift_card(token_name: ByteArray, utxo_ref: OutputReference) { + mint(rdmr: Action, policy_id: PolicyId, tx: Transaction) { + let Transaction { inputs, mint, .. } = tx + expect [Pair(asset_name, amount)] = + mint + |> assets.tokens(policy_id) + |> dict.to_pairs() + when rdmr is { + Mint -> { + expect Some(_input) = + list.find(inputs, fn(input) { input.output_reference == utxo_ref }) + amount == 1 && asset_name == token_name + } + Burn -> amount == -1 && asset_name == token_name + } + } + + else(_) { + fail + } +} + +type TestCase { + is_mint_info_correct: Bool, + is_token_name_correct: Bool, +} + +fn get_mint_test_tx(test_case: TestCase) -> Transaction { + let TestCase { is_mint_info_correct, is_token_name_correct } = test_case + + let token_name = + if is_token_name_correct { + "hello world" + } else { + "goodbye" + } + + mocktail_tx() + |> tx_in(True, mock_tx_hash(0), 0, zero, mock_pub_key_address(0, None)) + |> mint(is_mint_info_correct, 1, mock_policy_id(0), token_name) + |> mint(!is_mint_info_correct, 2, mock_policy_id(0), token_name) + |> complete() +} + +test success_mint() { + let test_gift_card_name = "hello world" + let utxo = mock_utxo_ref(0, 0) + let test_case = + TestCase { is_mint_info_correct: True, is_token_name_correct: True } + let tx = get_mint_test_tx(test_case) + gift_card.mint(test_gift_card_name, utxo, Mint, mock_policy_id(0), tx) +} + +test fail_mint_with_more_than_1_mint() { + let test_gift_card_name = "hello world" + let utxo = mock_utxo_ref(0, 0) + let test_case = + TestCase { is_mint_info_correct: False, is_token_name_correct: True } + let tx = get_mint_test_tx(test_case) + !gift_card.mint(test_gift_card_name, utxo, Mint, mock_policy_id(0), tx) +} + +test fail_mint_without_param_name_minted() { + let test_gift_card_name = "hello world" + let utxo = mock_utxo_ref(0, 0) + let test_case = + TestCase { is_mint_info_correct: True, is_token_name_correct: False } + let tx = get_mint_test_tx(test_case) + !gift_card.mint(test_gift_card_name, utxo, Mint, mock_policy_id(0), tx) +} + +fn get_redeem_test_tx(test_case: TestCase) -> Transaction { + let TestCase { is_mint_info_correct, is_token_name_correct } = test_case + + let token_name = + if is_token_name_correct { + "hello world" + } else { + "goodbye" + } + + let mint = + if is_mint_info_correct { + from_asset(mock_policy_id(0), token_name, -1) + } else { + from_asset(mock_policy_id(0), token_name, -2) + } + + Transaction { ..placeholder, mint: mint } +} + +test success_redeem() { + let test_gift_card_name = "hello world" + let utxo = mock_utxo_ref(0, 0) + let test_case = + TestCase { is_token_name_correct: True, is_mint_info_correct: True } + let tx = get_redeem_test_tx(test_case) + redeem.spend(test_gift_card_name, mock_policy_id(0), None, "", utxo, tx) && gift_card.mint( + test_gift_card_name, + utxo, + Burn, + mock_policy_id(0), + tx, + ) +} + +test fail_redeem_without_correct_name() { + let test_gift_card_name = "hello world" + let utxo = mock_utxo_ref(0, 0) + let test_case = + TestCase { is_token_name_correct: False, is_mint_info_correct: True } + let tx = get_redeem_test_tx(test_case) + !(redeem.spend(test_gift_card_name, mock_policy_id(0), None, "", utxo, tx) && gift_card.mint( + test_gift_card_name, + utxo, + Burn, + mock_policy_id(0), + tx, + )) +} + +test fail_redeem_without_correct_mint_info() { + let test_gift_card_name = "hello world" + let utxo = mock_utxo_ref(0, 0) + let test_case = + TestCase { is_token_name_correct: True, is_mint_info_correct: False } + let tx = get_redeem_test_tx(test_case) + !(redeem.spend(test_gift_card_name, mock_policy_id(0), None, "", utxo, tx) && gift_card.mint( + test_gift_card_name, + utxo, + Burn, + mock_policy_id(0), + tx, + )) +} diff --git a/packages/mesh-contract/src/giftcard/offchain.ts b/packages/mesh-contract/src/giftcard/offchain.ts index 50de3d35..26fa6157 100644 --- a/packages/mesh-contract/src/giftcard/offchain.ts +++ b/packages/mesh-contract/src/giftcard/offchain.ts @@ -5,6 +5,7 @@ import { List, mConStr0, mConStr1, + outputReference, PlutusScript, stringToHex, txOutRef, @@ -19,9 +20,8 @@ import { import { applyParamsToScript } from "@meshsdk/core-csl"; import { MeshTxInitiator, MeshTxInitiatorInput } from "../common"; -import blueprint from "./aiken-workspace/plutus.json"; - -export const MeshGiftCardBlueprint = blueprint; +import blueprintV1 from "./aiken-workspace-v1/plutus.json"; +import blueprintV2 from "./aiken-workspace-v2/plutus.json"; export class MeshGiftCardContract extends MeshTxInitiator { tokenNameHex: string = ""; @@ -32,18 +32,38 @@ export class MeshGiftCardContract extends MeshTxInitiator { utxoTxHash: string, utxoTxId: number, ) => { + let scriptCbor; + let utxo; + switch (this.version) { + case 2: + scriptCbor = blueprintV2.validators[0]!.compiledCode; + utxo = outputReference(utxoTxHash, utxoTxId); + break; + default: + scriptCbor = blueprintV1.validators[0]!.compiledCode; + utxo = txOutRef(utxoTxHash, utxoTxId); + break; + } + return applyParamsToScript( - blueprint.validators[0]!.compiledCode, - [builtinByteString(tokenNameHex), txOutRef(utxoTxHash, utxoTxId)], + scriptCbor, + [builtinByteString(tokenNameHex), utxo], "JSON", ); }; - redeemCbor = (tokenNameHex: string, policyId: string) => - applyParamsToScript(blueprint.validators[1]!.compiledCode, [ - tokenNameHex, - policyId, - ]); + redeemCbor = (tokenNameHex: string, policyId: string) => { + let scriptCbor; + switch (this.version) { + case 2: + scriptCbor = blueprintV2.validators[2]!.compiledCode; + break; + default: + scriptCbor = blueprintV1.validators[1]!.compiledCode; + } + + return applyParamsToScript(scriptCbor, [tokenNameHex, policyId]); + }; constructor( inputs: MeshTxInitiatorInput, @@ -57,7 +77,6 @@ export class MeshGiftCardContract extends MeshTxInitiator { if (paramUtxo) { this.paramUtxo = paramUtxo; } - this.mesh.setNetwork(inputs.networkId === 1 ? "mainnet" : "preprod"); } createGiftCard = async ( @@ -76,11 +95,14 @@ export class MeshGiftCardContract extends MeshTxInitiator { firstUtxo.input.outputIndex, ); - const giftCardPolicy = resolveScriptHash(giftCardScript, "V2"); + const giftCardPolicy = resolveScriptHash( + giftCardScript, + this.languageVersion, + ); const redeemScript: PlutusScript = { code: this.redeemCbor(tokenNameHex, giftCardPolicy), - version: "V2", + version: this.languageVersion, }; const redeemAddr = serializePlutusScript( @@ -96,7 +118,7 @@ export class MeshGiftCardContract extends MeshTxInitiator { firstUtxo.output.amount, firstUtxo.output.address, ) - .mintPlutusScriptV2() + .mintPlutusScript(this.languageVersion) .mint("1", giftCardPolicy, tokenNameHex) .mintingScript(giftCardScript) .mintRedeemerValue(mConStr0([])) @@ -141,12 +163,15 @@ export class MeshGiftCardContract extends MeshTxInitiator { paramTxId, ); - const giftCardPolicy = resolveScriptHash(giftCardScript, "V2"); + const giftCardPolicy = resolveScriptHash( + giftCardScript, + this.languageVersion, + ); const redeemScript = this.redeemCbor(tokenNameHex, giftCardPolicy); await this.mesh - .spendingPlutusScriptV2() + .spendingPlutusScript(this.languageVersion) .txIn( giftCardUtxo.input.txHash, giftCardUtxo.input.outputIndex, @@ -156,7 +181,7 @@ export class MeshGiftCardContract extends MeshTxInitiator { .spendingReferenceTxInInlineDatumPresent() .spendingReferenceTxInRedeemerValue("") .txInScript(redeemScript) - .mintPlutusScriptV2() + .mintPlutusScript(this.languageVersion) .mint("-1", giftCardPolicy, tokenNameHex) .mintingScript(giftCardScript) .mintRedeemerValue(mConStr1([])) diff --git a/packages/mesh-contract/src/hello-world/offchain.ts b/packages/mesh-contract/src/hello-world/offchain.ts index a275194a..0932d417 100644 --- a/packages/mesh-contract/src/hello-world/offchain.ts +++ b/packages/mesh-contract/src/hello-world/offchain.ts @@ -25,7 +25,6 @@ export class MeshHelloWorldContract extends MeshTxInitiator { constructor(inputs: MeshTxInitiatorInput) { super(inputs); - this.mesh.setNetwork(inputs.networkId === 1 ? "mainnet" : "preprod"); } getScript = () => { diff --git a/packages/mesh-contract/src/marketplace/offchain.ts b/packages/mesh-contract/src/marketplace/offchain.ts index 85a01f2b..3f0fdbff 100644 --- a/packages/mesh-contract/src/marketplace/offchain.ts +++ b/packages/mesh-contract/src/marketplace/offchain.ts @@ -70,7 +70,6 @@ export class MeshMarketplaceContract extends MeshTxInitiator { ], "JSON", ); - this.mesh.setNetwork(inputs.networkId === 1 ? "mainnet" : "preprod"); } listAsset = async (asset: string, price: number) => { @@ -183,7 +182,10 @@ export class MeshMarketplaceContract extends MeshTxInitiator { (inputDatum.fields[1].int as number) + Number(inputLovelace); if (sellerToReceiveLovelace > 0) { - const sellerAddress = serializeAddressObj(inputDatum.fields[0]); + const sellerAddress = serializeAddressObj( + inputDatum.fields[0], + this.networkId, + ); const sellerToReceive = [ { unit: "lovelace", diff --git a/packages/mesh-contract/src/payment-splitter/offchain.ts b/packages/mesh-contract/src/payment-splitter/offchain.ts index 476f78bd..3a99c8ab 100644 --- a/packages/mesh-contract/src/payment-splitter/offchain.ts +++ b/packages/mesh-contract/src/payment-splitter/offchain.ts @@ -48,8 +48,6 @@ export class MeshPaymentSplitterContract extends MeshTxInitiator { "Wallet not provided. Therefore the payment address will not be added to the payees list which makes it impossible to trigger the payout.", ); } - - this.mesh.setNetwork(inputs.networkId === 1 ? "mainnet" : "preprod"); } sendLovelaceToSplitter = async (lovelaceAmount: number): Promise => { diff --git a/packages/mesh-contract/src/swap/offchain.ts b/packages/mesh-contract/src/swap/offchain.ts index 0d6c254b..2a0c4afe 100644 --- a/packages/mesh-contract/src/swap/offchain.ts +++ b/packages/mesh-contract/src/swap/offchain.ts @@ -37,7 +37,6 @@ export class MeshSwapContract extends MeshTxInitiator { undefined, inputs.networkId, ).address; - this.mesh.setNetwork(inputs.networkId === 1 ? "mainnet" : "preprod"); } initiateSwap = async ( @@ -76,7 +75,10 @@ export class MeshSwapContract extends MeshTxInitiator { const inlineDatum = deserializeDatum( swapUtxo.output.plutusData!, ); - const initiatorAddress = serializeAddressObj(inlineDatum.fields[0]); + const initiatorAddress = serializeAddressObj( + inlineDatum.fields[0], + this.networkId, + ); const initiatorToReceive = inlineDatum.fields[2]; await this.mesh @@ -112,7 +114,10 @@ export class MeshSwapContract extends MeshTxInitiator { const inlineDatum = deserializeDatum( swapUtxo.output.plutusData!, ); - const initiatorAddress = serializeAddressObj(inlineDatum.fields[0]); + const initiatorAddress = serializeAddressObj( + inlineDatum.fields[0], + this.networkId, + ); await this.mesh .spendingPlutusScriptV2() .txIn( diff --git a/packages/mesh-contract/src/vesting/aiken-workspace-v1/.gitignore b/packages/mesh-contract/src/vesting/aiken-workspace-v1/.gitignore new file mode 100644 index 00000000..ff7811b1 --- /dev/null +++ b/packages/mesh-contract/src/vesting/aiken-workspace-v1/.gitignore @@ -0,0 +1,6 @@ +# Aiken compilation artifacts +artifacts/ +# Aiken's project working directory +build/ +# Aiken's default documentation export +docs/ diff --git a/packages/mesh-contract/src/vesting/aiken-workspace/README.md b/packages/mesh-contract/src/vesting/aiken-workspace-v1/README.md similarity index 100% rename from packages/mesh-contract/src/vesting/aiken-workspace/README.md rename to packages/mesh-contract/src/vesting/aiken-workspace-v1/README.md diff --git a/packages/mesh-contract/src/vesting/aiken-workspace/aiken.lock b/packages/mesh-contract/src/vesting/aiken-workspace-v1/aiken.lock similarity index 100% rename from packages/mesh-contract/src/vesting/aiken-workspace/aiken.lock rename to packages/mesh-contract/src/vesting/aiken-workspace-v1/aiken.lock diff --git a/packages/mesh-contract/src/vesting/aiken-workspace/aiken.toml b/packages/mesh-contract/src/vesting/aiken-workspace-v1/aiken.toml similarity index 100% rename from packages/mesh-contract/src/vesting/aiken-workspace/aiken.toml rename to packages/mesh-contract/src/vesting/aiken-workspace-v1/aiken.toml diff --git a/packages/mesh-contract/src/vesting/aiken-workspace/lib/vesting/types.ak b/packages/mesh-contract/src/vesting/aiken-workspace-v1/lib/vesting/types.ak similarity index 100% rename from packages/mesh-contract/src/vesting/aiken-workspace/lib/vesting/types.ak rename to packages/mesh-contract/src/vesting/aiken-workspace-v1/lib/vesting/types.ak diff --git a/packages/mesh-contract/src/vesting/aiken-workspace/plutus.json b/packages/mesh-contract/src/vesting/aiken-workspace-v1/plutus.json similarity index 100% rename from packages/mesh-contract/src/vesting/aiken-workspace/plutus.json rename to packages/mesh-contract/src/vesting/aiken-workspace-v1/plutus.json diff --git a/packages/mesh-contract/src/vesting/aiken-workspace/validators/tests/vesting.ak b/packages/mesh-contract/src/vesting/aiken-workspace-v1/validators/tests/vesting.ak similarity index 100% rename from packages/mesh-contract/src/vesting/aiken-workspace/validators/tests/vesting.ak rename to packages/mesh-contract/src/vesting/aiken-workspace-v1/validators/tests/vesting.ak diff --git a/packages/mesh-contract/src/vesting/aiken-workspace/validators/vesting.ak b/packages/mesh-contract/src/vesting/aiken-workspace-v1/validators/vesting.ak similarity index 100% rename from packages/mesh-contract/src/vesting/aiken-workspace/validators/vesting.ak rename to packages/mesh-contract/src/vesting/aiken-workspace-v1/validators/vesting.ak diff --git a/packages/mesh-contract/src/vesting/aiken-workspace-v2/.gitignore b/packages/mesh-contract/src/vesting/aiken-workspace-v2/.gitignore new file mode 100644 index 00000000..ff7811b1 --- /dev/null +++ b/packages/mesh-contract/src/vesting/aiken-workspace-v2/.gitignore @@ -0,0 +1,6 @@ +# Aiken compilation artifacts +artifacts/ +# Aiken's project working directory +build/ +# Aiken's default documentation export +docs/ diff --git a/packages/mesh-contract/src/vesting/aiken-workspace-v2/README.md b/packages/mesh-contract/src/vesting/aiken-workspace-v2/README.md new file mode 100644 index 00000000..a0ec1de0 --- /dev/null +++ b/packages/mesh-contract/src/vesting/aiken-workspace-v2/README.md @@ -0,0 +1,24 @@ +# Vesting - Specification + +## Scripts - VestingValidator + +The validator of locking vesting value. + +### Parameter - no parameter + +### Datum + +- `lock_until`: POSIX time in second at locking end, e.g. 1672843961000 +- `owner`: Owner's pub key hash +- `beneficiary`: Beneficiary's pub key hash + +### User Action + +1. Unlock by owner + + - Signed by `owner` + +2. Unlock by beneficiary + + - Signed by `beneficiary` + - Only valid after `lock_until` diff --git a/packages/mesh-contract/src/vesting/aiken-workspace-v2/aiken.lock b/packages/mesh-contract/src/vesting/aiken-workspace-v2/aiken.lock new file mode 100644 index 00000000..a89d05d9 --- /dev/null +++ b/packages/mesh-contract/src/vesting/aiken-workspace-v2/aiken.lock @@ -0,0 +1,27 @@ +# This file was generated by Aiken +# You typically do not need to edit this file + +[[requirements]] +name = "aiken-lang/stdlib" +version = "v2" +source = "github" + +[[requirements]] +name = "sidan-lab/vodka" +version = "0.1.0-beta" +source = "github" + +[[packages]] +name = "aiken-lang/stdlib" +version = "v2" +requirements = [] +source = "github" + +[[packages]] +name = "sidan-lab/vodka" +version = "0.1.0-beta" +requirements = [] +source = "github" + +[etags] +"aiken-lang/stdlib@v2" = [{ secs_since_epoch = 1725554519, nanos_since_epoch = 649340000 }, "d79382d2b6ecb3aee9b0755c31d8a5bbafe88a7b3706d7fb8a52fd4d05818501"] diff --git a/packages/mesh-contract/src/vesting/aiken-workspace-v2/aiken.toml b/packages/mesh-contract/src/vesting/aiken-workspace-v2/aiken.toml new file mode 100644 index 00000000..d539e9a8 --- /dev/null +++ b/packages/mesh-contract/src/vesting/aiken-workspace-v2/aiken.toml @@ -0,0 +1,23 @@ +name = "meshjs/vesting" +version = "0.0.0" +compiler = "v1.1.0" +plutus = "v3" +license = "Apache-2.0" +description = "Aiken contracts for project 'meshjs/vesting'" + +[repository] +user = "meshjs" +project = "vesting" +platform = "github" + +[[dependencies]] +name = "aiken-lang/stdlib" +version = "v2" +source = "github" + +[[dependencies]] +name = "sidan-lab/vodka" +version = "0.1.0-beta" +source = "github" + +[config] diff --git a/packages/mesh-contract/src/vesting/aiken-workspace-v2/plutus.json b/packages/mesh-contract/src/vesting/aiken-workspace-v2/plutus.json new file mode 100644 index 00000000..901f57a3 --- /dev/null +++ b/packages/mesh-contract/src/vesting/aiken-workspace-v2/plutus.json @@ -0,0 +1,76 @@ +{ + "preamble": { + "title": "meshjs/vesting", + "description": "Aiken contracts for project 'meshjs/vesting'", + "version": "0.0.0", + "plutusVersion": "v3", + "compiler": { + "name": "Aiken", + "version": "v1.1.0+unknown" + }, + "license": "Apache-2.0" + }, + "validators": [ + { + "title": "vesting.vesting.spend", + "datum": { + "title": "datum_opt", + "schema": { + "$ref": "#/definitions/vesting~1VestingDatum" + } + }, + "redeemer": { + "title": "_redeemer", + "schema": { + "$ref": "#/definitions/Data" + } + }, + "compiledCode": "5901a7010100323232323232322533300232323232325332330083001300937540042646464a66601666e1d2000300c37540022646464a66601c660026eb0c008c040dd50059bae3013301430103754006294454ccc038cc004dd6180118081baa00b375c60266028602860206ea800c4c8cc88c8c8c8c8c94ccc058c03cc05cdd5001099299980b802099b88007001002375a603660306ea80080044c94ccc058c03cc05cdd5001099299980b802001099b89007001375a603660306ea8008004528180c8011806180a1baa3018301900133016301700133016333012300b30133754602e603000298103d87a80004c0103d87980004bd7018099baa3003301337540046028602a602a602a602a602a602a602a60226ea8030dd6980098089baa0042301400114a044646600200200644a66602800229404c94ccc048cdc79bae301700200414a2266006006002602e00246024602660266026602660266026602660260026020601a6ea800458c03cc040008c038004c028dd50011b874800858c02cc030008c028004c028008c020004c010dd50008a4c26cacae6955ceaab9e5573eae815d0aba21", + "hash": "d13324c13a48b69d67ccfc88e3e87f046f4417f57f5c740d515249fb" + }, + { + "title": "vesting.vesting.else", + "compiledCode": "5901a7010100323232323232322533300232323232325332330083001300937540042646464a66601666e1d2000300c37540022646464a66601c660026eb0c008c040dd50059bae3013301430103754006294454ccc038cc004dd6180118081baa00b375c60266028602860206ea800c4c8cc88c8c8c8c8c94ccc058c03cc05cdd5001099299980b802099b88007001002375a603660306ea80080044c94ccc058c03cc05cdd5001099299980b802001099b89007001375a603660306ea8008004528180c8011806180a1baa3018301900133016301700133016333012300b30133754602e603000298103d87a80004c0103d87980004bd7018099baa3003301337540046028602a602a602a602a602a602a602a60226ea8030dd6980098089baa0042301400114a044646600200200644a66602800229404c94ccc048cdc79bae301700200414a2266006006002602e00246024602660266026602660266026602660260026020601a6ea800458c03cc040008c038004c028dd50011b874800858c02cc030008c028004c028008c020004c010dd50008a4c26cacae6955ceaab9e5573eae815d0aba21", + "hash": "d13324c13a48b69d67ccfc88e3e87f046f4417f57f5c740d515249fb" + } + ], + "definitions": { + "ByteArray": { + "dataType": "bytes" + }, + "Data": { + "title": "Data", + "description": "Any Plutus data." + }, + "Int": { + "dataType": "integer" + }, + "vesting/VestingDatum": { + "title": "VestingDatum", + "anyOf": [ + { + "title": "VestingDatum", + "dataType": "constructor", + "index": 0, + "fields": [ + { + "title": "lock_until", + "description": "POSIX time in milliseconds, e.g. 1672843961000", + "$ref": "#/definitions/Int" + }, + { + "title": "owner", + "description": "Owner's credentials", + "$ref": "#/definitions/ByteArray" + }, + { + "title": "beneficiary", + "description": "Beneficiary's credentials", + "$ref": "#/definitions/ByteArray" + } + ] + } + ] + } + } +} \ No newline at end of file diff --git a/packages/mesh-contract/src/vesting/aiken-workspace-v2/validators/vesting.ak b/packages/mesh-contract/src/vesting/aiken-workspace-v2/validators/vesting.ak new file mode 100644 index 00000000..7ea75b4f --- /dev/null +++ b/packages/mesh-contract/src/vesting/aiken-workspace-v2/validators/vesting.ak @@ -0,0 +1,134 @@ +use cardano/transaction.{OutputReference, Transaction} +use mocktail.{complete, invalid_before, mocktail_tx, required_signer_hash} +use mocktail/virgin_key_hash.{mock_pub_key_hash} +use mocktail/virgin_output_reference.{mock_utxo_ref} +use vodka_extra_signatories.{key_signed} +use vodka_validity_range.{valid_after} + +pub type VestingDatum { + /// POSIX time in milliseconds, e.g. 1672843961000 + lock_until: Int, + /// Owner's credentials + owner: ByteArray, + /// Beneficiary's credentials + beneficiary: ByteArray, +} + +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 + } +} + +type TestCase { + is_owner_signed: Bool, + is_beneficiary_signed: Bool, + is_lock_time_passed: Bool, +} + +fn get_test_tx(test_case: TestCase) { + let TestCase { is_owner_signed, is_beneficiary_signed, is_lock_time_passed } = + test_case + + mocktail_tx() + |> required_signer_hash(is_owner_signed, mock_pub_key_hash(1)) + |> required_signer_hash(is_beneficiary_signed, mock_pub_key_hash(2)) + |> invalid_before(is_lock_time_passed, 1672843961001) + |> complete() +} + +fn vesting_datum() { + VestingDatum { + lock_until: 1672843961000, + owner: mock_pub_key_hash(1), + beneficiary: mock_pub_key_hash(2), + } +} + +test success_unlocking() { + let output_reference = mock_utxo_ref(0, 1) + let datum = Some(vesting_datum()) + let test_case = + TestCase { + is_owner_signed: True, + is_beneficiary_signed: True, + is_lock_time_passed: True, + } + + let tx = get_test_tx(test_case) + vesting.spend(datum, Void, output_reference, tx) +} + +test success_unlocking_with_only_owner_signature() { + let output_reference = mock_utxo_ref(0, 1) + let datum = Some(vesting_datum()) + let test_case = + TestCase { + is_owner_signed: True, + is_beneficiary_signed: False, + is_lock_time_passed: False, + } + + let tx = get_test_tx(test_case) + vesting.spend(datum, Void, output_reference, tx) +} + +test success_unlocking_with_beneficiary_signature_and_time_passed() { + let output_reference = mock_utxo_ref(0, 1) + let datum = Some(vesting_datum()) + let test_case = + TestCase { + is_owner_signed: False, + is_beneficiary_signed: True, + is_lock_time_passed: True, + } + + let tx = get_test_tx(test_case) + vesting.spend(datum, Void, output_reference, tx) +} + +test fail_unlocking_with_only_beneficiary_signature() { + let output_reference = mock_utxo_ref(0, 1) + let datum = Some(vesting_datum()) + let test_case = + TestCase { + is_owner_signed: False, + is_beneficiary_signed: True, + is_lock_time_passed: False, + } + + let tx = get_test_tx(test_case) + !vesting.spend(datum, Void, output_reference, tx) +} + +test fail_unlocking_with_only_time_passed() { + let output_reference = mock_utxo_ref(0, 1) + let datum = Some(vesting_datum()) + let test_case = + TestCase { + is_owner_signed: False, + is_beneficiary_signed: False, + is_lock_time_passed: True, + } + + let tx = get_test_tx(test_case) + !vesting.spend(datum, Void, output_reference, tx) +} diff --git a/packages/mesh-contract/src/vesting/offchain.ts b/packages/mesh-contract/src/vesting/offchain.ts index 28d85c56..c1f325b9 100644 --- a/packages/mesh-contract/src/vesting/offchain.ts +++ b/packages/mesh-contract/src/vesting/offchain.ts @@ -16,22 +16,37 @@ import { import { applyParamsToScript } from "@meshsdk/core-csl"; import { MeshTxInitiator, MeshTxInitiatorInput } from "../common"; -import blueprint from "./aiken-workspace/plutus.json"; - -export const MeshVestingBlueprint = blueprint; +import blueprintV1 from "./aiken-workspace-v1/plutus.json"; +import blueprintV2 from "./aiken-workspace-v2/plutus.json"; export type VestingDatum = ConStr0< [Integer, BuiltinByteString, BuiltinByteString] >; export class MeshVestingContract extends MeshTxInitiator { - scriptCbor = applyParamsToScript(blueprint.validators[0]!.compiledCode, []); - constructor(inputs: MeshTxInitiatorInput) { super(inputs); - this.mesh.setNetwork(inputs.networkId === 1 ? "mainnet" : "preprod"); } + getScriptCbor = () => { + let scriptCbor; + switch (this.version) { + case 2: + scriptCbor = applyParamsToScript( + blueprintV2.validators[0]!.compiledCode, + [], + ); + break; + default: + scriptCbor = applyParamsToScript( + blueprintV1.validators[0]!.compiledCode, + [], + ); + break; + } + return scriptCbor; + }; + depositFund = async ( amount: Asset[], lockUntilTimeStampMs: number, @@ -40,7 +55,7 @@ export class MeshVestingContract extends MeshTxInitiator { const { utxos, walletAddress } = await this.getWalletInfoForTx(); const scriptAddr = serializePlutusScript( - { code: this.scriptCbor, version: "V2" }, + { code: this.getScriptCbor(), version: this.languageVersion }, undefined, this.networkId, ).address; @@ -67,8 +82,10 @@ export class MeshVestingContract extends MeshTxInitiator { const { utxos, walletAddress, collateral } = await this.getWalletInfoForTx(); const { input: collateralInput, output: collateralOutput } = collateral; + + const scriptCbor = this.getScriptCbor(); const scriptAddr = serializePlutusScript( - { code: this.scriptCbor, version: "V2" }, + { code: scriptCbor, version: this.languageVersion }, undefined, this.networkId, ).address; @@ -87,7 +104,7 @@ export class MeshVestingContract extends MeshTxInitiator { ) + 1; await this.mesh - .spendingPlutusScriptV2() + .spendingPlutusScript(this.languageVersion) .txIn( vestingUtxo.input.txHash, vestingUtxo.input.outputIndex, @@ -96,7 +113,7 @@ export class MeshVestingContract extends MeshTxInitiator { ) .spendingReferenceTxInInlineDatumPresent() .spendingReferenceTxInRedeemerValue("") - .txInScript(this.scriptCbor) + .txInScript(scriptCbor) .txOut(walletAddress, []) .txInCollateral( collateralInput.txHash, @@ -113,6 +130,6 @@ export class MeshVestingContract extends MeshTxInitiator { }; getUtxoByTxHash = async (txHash: string): Promise => { - return await this._getUtxoByTxHash(txHash, this.scriptCbor); + return await this._getUtxoByTxHash(txHash, this.getScriptCbor()); }; } diff --git a/packages/mesh-core-csl/package.json b/packages/mesh-core-csl/package.json index c12da575..c0d0d514 100644 --- a/packages/mesh-core-csl/package.json +++ b/packages/mesh-core-csl/package.json @@ -1,6 +1,6 @@ { "name": "@meshsdk/core-csl", - "version": "1.7.2", + "version": "1.7.3", "description": "", "main": "./dist/index.cjs", "module": "./dist/index.js", @@ -38,7 +38,7 @@ "typescript": "^5.3.3" }, "dependencies": { - "@meshsdk/common": "1.7.2", + "@meshsdk/common": "1.7.3", "@sidan-lab/sidan-csl-rs-browser": "0.8.0", "@sidan-lab/sidan-csl-rs-nodejs": "0.8.0", "json-bigint": "^1.0.0" diff --git a/packages/mesh-core-cst/package.json b/packages/mesh-core-cst/package.json index a2ef47a2..f8cf429f 100644 --- a/packages/mesh-core-cst/package.json +++ b/packages/mesh-core-cst/package.json @@ -1,6 +1,6 @@ { "name": "@meshsdk/core-cst", - "version": "1.7.2", + "version": "1.7.3", "description": "", "main": "./dist/index.cjs", "module": "./dist/index.js", @@ -41,7 +41,7 @@ "@harmoniclabs/cbor": "1.3.0", "@harmoniclabs/plutus-data": "1.2.4", "@harmoniclabs/uplc": "1.2.4", - "@meshsdk/common": "1.7.2", + "@meshsdk/common": "1.7.3", "@stricahq/bip32ed25519": "^1.1.0", "@stricahq/cbors": "^1.0.0", "pbkdf2": "^3.1.2" diff --git a/packages/mesh-core/package.json b/packages/mesh-core/package.json index 04edf735..c97ac433 100644 --- a/packages/mesh-core/package.json +++ b/packages/mesh-core/package.json @@ -1,6 +1,6 @@ { "name": "@meshsdk/core", - "version": "1.7.2", + "version": "1.7.3", "description": "", "main": "./dist/index.cjs", "module": "./dist/index.js", @@ -32,13 +32,13 @@ "typescript": "^5.3.3" }, "dependencies": { - "@meshsdk/common": "1.7.2", - "@meshsdk/core-csl": "1.7.2", - "@meshsdk/core-cst": "1.7.2", - "@meshsdk/provider": "1.7.2", - "@meshsdk/react": "1.7.2", - "@meshsdk/transaction": "1.7.2", - "@meshsdk/wallet": "1.7.2" + "@meshsdk/common": "1.7.3", + "@meshsdk/core-csl": "1.7.3", + "@meshsdk/core-cst": "1.7.3", + "@meshsdk/provider": "1.7.3", + "@meshsdk/react": "1.7.3", + "@meshsdk/transaction": "1.7.3", + "@meshsdk/wallet": "1.7.3" }, "prettier": "@meshsdk/configs/prettier", "publishConfig": { diff --git a/packages/mesh-core/src/utils/serializer.ts b/packages/mesh-core/src/utils/serializer.ts index d22c2b5e..325cf53b 100644 --- a/packages/mesh-core/src/utils/serializer.ts +++ b/packages/mesh-core/src/utils/serializer.ts @@ -63,10 +63,14 @@ export const serializePlutusScript = ( /** * Serialize address in Cardano data JSON format into bech32 address * @param address The Cardano address in data JSON format + * @param networkId 0 (testnet) or 1 (mainnet). Default to be 0 (testnet). * @returns Bech32 address */ -export const serializeAddressObj = (address: PubKeyAddress | ScriptAddress) => { - return core.serializeAddressObj(address); +export const serializeAddressObj = ( + address: PubKeyAddress | ScriptAddress, + networkId = 0, +) => { + return core.serializeAddressObj(address, networkId); }; /** diff --git a/packages/mesh-provider/package.json b/packages/mesh-provider/package.json index 9452f5f9..6185a574 100644 --- a/packages/mesh-provider/package.json +++ b/packages/mesh-provider/package.json @@ -1,6 +1,6 @@ { "name": "@meshsdk/provider", - "version": "1.7.2", + "version": "1.7.3", "description": "", "main": "./dist/index.cjs", "module": "./dist/index.js", @@ -33,8 +33,8 @@ "typescript": "^5.3.3" }, "dependencies": { - "@meshsdk/common": "1.7.2", - "@meshsdk/core-cst": "1.7.2", + "@meshsdk/common": "1.7.3", + "@meshsdk/core-cst": "1.7.3", "axios": "^1.7.2" }, "prettier": "@meshsdk/configs/prettier", diff --git a/packages/mesh-react/package.json b/packages/mesh-react/package.json index 67daff57..22637bbf 100644 --- a/packages/mesh-react/package.json +++ b/packages/mesh-react/package.json @@ -1,6 +1,6 @@ { "name": "@meshsdk/react", - "version": "1.7.2", + "version": "1.7.3", "description": "", "main": "./dist/index.cjs", "module": "./dist/index.js", @@ -29,9 +29,9 @@ }, "dependencies": { "react": "^18.2.0", - "@meshsdk/common": "1.7.2", - "@meshsdk/transaction": "1.7.2", - "@meshsdk/wallet": "1.7.2" + "@meshsdk/common": "1.7.3", + "@meshsdk/transaction": "1.7.3", + "@meshsdk/wallet": "1.7.3" }, "devDependencies": { "@meshsdk/configs": "*", diff --git a/packages/mesh-transaction/package.json b/packages/mesh-transaction/package.json index b0c42275..407e31e5 100644 --- a/packages/mesh-transaction/package.json +++ b/packages/mesh-transaction/package.json @@ -1,6 +1,6 @@ { "name": "@meshsdk/transaction", - "version": "1.7.2", + "version": "1.7.3", "description": "", "main": "./dist/index.cjs", "module": "./dist/index.js", @@ -34,9 +34,9 @@ "typescript": "^5.3.3" }, "dependencies": { - "@meshsdk/common": "1.7.2", - "@meshsdk/core-csl": "1.7.2", - "@meshsdk/core-cst": "1.7.2", + "@meshsdk/common": "1.7.3", + "@meshsdk/core-csl": "1.7.3", + "@meshsdk/core-cst": "1.7.3", "json-bigint": "^1.0.0" }, "prettier": "@meshsdk/configs/prettier", diff --git a/packages/mesh-transaction/src/mesh-tx-builder/tx-builder-core.ts b/packages/mesh-transaction/src/mesh-tx-builder/tx-builder-core.ts index a2b2c766..52d7903e 100644 --- a/packages/mesh-transaction/src/mesh-tx-builder/tx-builder-core.ts +++ b/packages/mesh-transaction/src/mesh-tx-builder/tx-builder-core.ts @@ -413,6 +413,20 @@ export class MeshTxBuilderCore { return this; }; + /** + * Set the reference script to be attached with the output + * @param languageVersion The Plutus script version + * @returns The MeshTxBuilder instance + */ + spendingPlutusScript = (languageVersion: LanguageVersion) => { + // This flag should signal a start to a script input + // The next step after will be to add a tx-in + // After which, we will REQUIRE, script, datum and redeemer info + // for unlocking this particular input + this.addingPlutusScriptInput = true; + this.plutusSpendingScriptVersion = languageVersion; + return this; + }; /** * Set the instruction that it is currently using V1 Plutus spending scripts * @returns The MeshTxBuilder instance @@ -525,6 +539,16 @@ export class MeshTxBuilderCore { return this; }; + /** + * Set the minting script for the current mint + * @param languageVersion The Plutus script version + * @returns The MeshTxBuilder instance + */ + mintPlutusScript = (languageVersion: LanguageVersion) => { + this.addingPlutusMint = true; + this.plutusMintingScriptVersion = languageVersion; + return this; + }; /** * Set the instruction that it is currently using V1 Plutus minting scripts * @returns The MeshTxBuilder instance @@ -720,6 +744,16 @@ export class MeshTxBuilderCore { return this; }; + /** + * Set the instruction that it is currently using V1 Plutus withdrawal scripts + * @param languageVersion The Plutus script version + * @returns The MeshTxBuilder instance + */ + withdrawalPlutusScript = (languageVersion: LanguageVersion) => { + this.addingPlutusWithdrawal = true; + this.plutusWithdrawalScriptVersion = languageVersion; + return this; + }; /** * Set the instruction that it is currently using V1 Plutus withdrawal scripts * @returns The MeshTxBuilder instance diff --git a/packages/mesh-transaction/src/transaction/index.ts b/packages/mesh-transaction/src/transaction/index.ts index e678f0e1..6300f8ca 100644 --- a/packages/mesh-transaction/src/transaction/index.ts +++ b/packages/mesh-transaction/src/transaction/index.ts @@ -633,8 +633,10 @@ export class Transaction { } private async addTxInputsAsNeeded() { - const utxos = await this.initiator.getUtxos(); - this.txBuilder.selectUtxosFrom(utxos); + if (this.txBuilder.meshTxBuilderBody.extraInputs.length === 0) { + const utxos = await this.initiator.getUtxos(); + this.txBuilder.selectUtxosFrom(utxos); + } } private async addChangeAddress() { diff --git a/packages/mesh-wallet/package.json b/packages/mesh-wallet/package.json index 45b05494..374e15d9 100644 --- a/packages/mesh-wallet/package.json +++ b/packages/mesh-wallet/package.json @@ -1,6 +1,6 @@ { "name": "@meshsdk/wallet", - "version": "1.7.2", + "version": "1.7.3", "description": "", "main": "./dist/index.cjs", "module": "./dist/index.js", @@ -34,10 +34,10 @@ "typescript": "^5.3.3" }, "dependencies": { - "@meshsdk/common": "1.7.2", - "@meshsdk/core-csl": "1.7.2", - "@meshsdk/core-cst": "1.7.2", - "@meshsdk/transaction": "1.7.2", + "@meshsdk/common": "1.7.3", + "@meshsdk/core-csl": "1.7.3", + "@meshsdk/core-cst": "1.7.3", + "@meshsdk/transaction": "1.7.3", "@nufi/dapp-client-cardano": "^0.3.1", "@nufi/dapp-client-core": "^0.3.1" }, diff --git a/scripts/mesh-cli/package.json b/scripts/mesh-cli/package.json index 4599d416..72463fb9 100644 --- a/scripts/mesh-cli/package.json +++ b/scripts/mesh-cli/package.json @@ -3,7 +3,7 @@ "description": "A quick and easy way to bootstrap your dApps on Cardano using Mesh.", "homepage": "https://meshjs.dev", "author": "MeshJS", - "version": "1.7.2", + "version": "1.7.3", "license": "Apache-2.0", "type": "module", "main": "./dist/index.cjs",