Skip to content

Commit

Permalink
Merge pull request #348 from MeshJS/aiken-lib-part-2
Browse files Browse the repository at this point in the history
Aiken lib part 2
  • Loading branch information
HinsonSIDAN authored Oct 28, 2024
2 parents d5c39e1 + 5b2d78c commit ff89007
Show file tree
Hide file tree
Showing 183 changed files with 12,306 additions and 302 deletions.
1 change: 0 additions & 1 deletion apps/playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
"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",
Expand Down
3 changes: 0 additions & 3 deletions apps/playground/src/data/cardano.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { MeshMarketplaceBlueprint } from "@meshsdk/contract";
import { applyParamsToScript } from "@meshsdk/core-csl";

export const demoAddresses = {
Expand Down Expand Up @@ -42,8 +41,6 @@ export const demoAssetMetadata = {
export const demoPool =
"pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx";

export const demoMarketplaceCompiledCode = MeshMarketplaceBlueprint;

export const demoPubKeyHash =
"aa048e4cc8a1e67e1d97ffbd4be614388014cbc2b2451527202943b6";

Expand Down
17 changes: 16 additions & 1 deletion apps/playground/src/data/links-smart-contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import {
DocumentCheckIcon,
GiftIcon,
LockClosedIcon,
PhotoIcon,
ShoppingCartIcon,
} from "@heroicons/react/24/solid";

import { MenuItem } from "~/types/menu-item";

export const metaMarketplace = {
title: "Marketplace",
desc: "Build a NFT marketplace effortlessly",
desc: "Build a NFT marketplace to buy and sell NFTs",
link: "/smart-contracts/marketplace",
icon: ShoppingCartIcon,
};
Expand Down Expand Up @@ -45,11 +46,25 @@ export const metaPaymentSplitter = {
link: "/smart-contracts/payment-splitter",
icon: ArrowsPointingOutIcon,
};
export const metaContentOwnership = {
title: "Content Ownership",
desc: "Manage ownership of digital content and assets",
link: "/smart-contracts/content-ownership",
icon: DocumentCheckIcon,
};
export const metaMintPlutusNft = {
title: "Mint Plutus NFT",
desc: "Mint NFT that ensure the token name is incremented by a counter",
link: "/smart-contracts/plutus-nft",
icon: PhotoIcon,
};

export const linksSmartContracts: MenuItem[] = [
// metaContentOwnership,
metaEscrow,
metaGiftcard,
metaMarketplace,
metaMintPlutusNft,
metaPaymentSplitter,
metaSwap,
metaVesting,
Expand Down
12 changes: 7 additions & 5 deletions apps/playground/src/hooks/useDarkmode.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import { persistNSync } from "persist-and-sync";
import { create } from "zustand";
import { persist } from "zustand/middleware";

interface State {
isDark: boolean;
setDarkMode: (isDark: boolean) => void;
}

export const useDarkmode = create<State>(
persistNSync(
(set) => ({
export const useDarkmode = create<State>()(
persist(
(set, get) => ({
isDark: false,
setDarkMode: (bool) => set((state) => ({ isDark: bool })),
}),
{ name: "mesh-darkmode" },
{
name: "mesh-darkmode",
},
),
);
12 changes: 7 additions & 5 deletions apps/playground/src/hooks/useProviders.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { persistNSync } from "persist-and-sync";
import { create } from "zustand";
import { persist } from "zustand/middleware";

import { KoiosSupportedNetworks } from "@meshsdk/core";

Expand All @@ -25,9 +25,9 @@ interface State {
setHydraUrl: (url: string) => void;
}

export const useProviders = create<State>(
persistNSync(
(set) => ({
export const useProviders = create<State>()(
persist(
(set, get) => ({
blockfrostKey: undefined,
setBlockfrostKey: (key) => set({ blockfrostKey: key }),
maestroKey: undefined,
Expand All @@ -44,6 +44,8 @@ export const useProviders = create<State>(
hydraUrl: "",
setHydraUrl: (url) => set({ hydraUrl: url }),
}),
{ name: "mesh-providers" },
{
name: "mesh-providers",
},
),
);
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MeshMarketplaceBlueprint } from "@meshsdk/contract";
import { MeshMarketplaceContract } from "@meshsdk/contract";
import { integer, mPubKeyAddress, pubKeyAddress } from "@meshsdk/core";
import { applyParamsToScript, CSLSerializer } from "@meshsdk/core-csl";

Expand All @@ -14,7 +14,7 @@ import {

const serializer = new CSLSerializer();

const demoCompiledCode = MeshMarketplaceBlueprint.validators[0]!.compiledCode;
const demoCompiledCode = MeshMarketplaceContract.getCompiledCode();

export default function ContractApplyParamToScript() {
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useState } from "react";

import { checkSignature } from "@meshsdk/core";
import { useWallet } from "@meshsdk/react";

import Input from "~/components/form/input";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ async function frontendStartLoginProcess() {

## Server: Generate Nonce and Store in Database

In the backend, we first need to generate a new nonce, which is initialized as a random string. The purpose of this is to create a unique message that can be used for authentication of the user's wallet. This nonce will be the payload for the user to prove ownership of the wallet. With Mesh, you can generate a new nonce with **generateNonce()**, and set the message as **Sign to login in to Mesh: nonce**.
In the backend, we first need to generate a new nonce, which is initialized as a random string. The purpose of this is to create a unique message that can be used for authentication of the user's wallet. This nonce will be the payload for the user to prove ownership of the wallet. With Mesh, you can generate a new nonce with **generateNonce()**, and set the message as **I agree to the term and conditions of the Mesh: nonce**.

By utilizing the **userAddress**, we can look up the database to determine whether the user is new or already exists.

Expand All @@ -87,7 +87,7 @@ import { generateNonce } from '@meshsdk/core';
async function backendGetNonce(userAddress) {
// do: if new user, create new user model in the database
const nonce = generateNonce('Sign to login in to Mesh: ');
const nonce = generateNonce('I agree to the term and conditions of the Mesh: ');
// do: store 'nonce' in user model in the database
Expand All @@ -101,7 +101,7 @@ Lastly, we will return the **nonce** for the user to sign using their private ke

We are ready to use the private key associated with the wallet to sign the nonce with **await wallet.signData(nonce, userAddress)**, which enables the dApp to request the user to sign a payload according to [CIP-8](https://cips.cardano.org/cips/cip8/).

We request the user's authorization and show them the message that is to be signed: **Sign to login in to Mesh: nonce**. Once accepted, the signature will be generated and the dApp will process the signature to authenticate the user.
We request the user's authorization and show them the message that is to be signed: **I agree to the term and conditions of the Mesh: nonce**. Once accepted, the signature will be generated and the dApp will process the signature to authenticate the user.

```
async function frontendSignMessage(nonce) {
Expand Down Expand Up @@ -199,7 +199,7 @@ And the server side code should have 2 REST endpoints, **backendGetNonce(userAdd
import { checkSignature, generateNonce } from '@meshsdk/core';
async function backendGetNonce(userAddress) {
const nonce = generateNonce('Sign to login in to Mesh: ');
const nonce = generateNonce('I agree to the term and conditions of the Mesh: ');
return nonce;
}
Expand Down
209 changes: 209 additions & 0 deletions apps/playground/src/pages/smart-contracts/content-ownership/common.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
import { create } from "zustand";
import { persist } from "zustand/middleware";

import { MeshContentOwnershipContract } from "@meshsdk/contract";
import { BrowserWallet, MeshTxBuilder, UTxO } from "@meshsdk/core";

import Input from "~/components/form/input";
import InputTable from "~/components/sections/input-table";
import { demoAddresses } from "~/data/cardano";
import { getProvider } from "../../../components/cardano/mesh-wallet";

export function getContract(
wallet: BrowserWallet,
operationAddress: string,
paramUtxo?: UTxO["input"],
refScriptUtxos?: {
contentRegistry: UTxO["input"];
contentRefToken: UTxO["input"];
ownershipRegistry: UTxO["input"];
ownershipRefToken: UTxO["input"];
},
) {
const blockchainProvider = getProvider();

const meshTxBuilder = new MeshTxBuilder({
fetcher: blockchainProvider,
submitter: blockchainProvider,
verbose: true,
});

const contract = new MeshContentOwnershipContract(
{
mesh: meshTxBuilder,
fetcher: blockchainProvider,
wallet: wallet,
networkId: 0,
},
{
operationAddress: operationAddress,
paramUtxo: paramUtxo,
refScriptUtxos: refScriptUtxos,
},
);

return contract;
}

export const sampleParamUtxo = {
outputIndex: 0,
txHash: "e781a02ed4159b47b144e960c4b155918f50b4841eafc443c66fec40616b6df2",
};

interface State {
operationAddress: string;
setOperationAddress: (address: string) => void;
paramUtxo: string;
setParamUtxo: (paramUtxo: string) => void;

contentRegistry: string;
setContentRegistry: (address: string) => void;
contentRefToken: string;
setContentRefToken: (address: string) => void;
ownershipRegistry: string;
setOwnershipRegistry: (address: string) => void;
ownershipRefToken: string;
setOwnershipRefToken: (address: string) => void;
}

export const useContentOwnership = create<State>()(
persist(
(set) => ({
operationAddress: demoAddresses.testnet,
setOperationAddress: (address: string) => {
set(() => ({
operationAddress: address,
}));
},
paramUtxo: JSON.stringify(sampleParamUtxo),
setParamUtxo: (paramUtxo: string) =>
set(() => ({
paramUtxo: paramUtxo,
})),
contentRegistry: "",
setContentRegistry: (address: string) =>
set(() => ({
contentRegistry: address,
})),
contentRefToken: "",
setContentRefToken: (address: string) =>
set(() => ({
contentRefToken: address,
})),
ownershipRegistry: "",
setOwnershipRegistry: (address: string) =>
set(() => ({
ownershipRegistry: address,
})),
ownershipRefToken: "",
setOwnershipRefToken: (address: string) =>
set(() => ({
ownershipRefToken: address,
})),
}),
{
name: "mesh-contentownership",
},
),
);

export function InputsOperationAddress() {
const operationAddress = useContentOwnership(
(state) => state.operationAddress,
);
const setOperationAddress = useContentOwnership(
(state) => state.setOperationAddress,
);
return (
<InputTable
listInputs={[
<Input
value={operationAddress}
onChange={(e) => setOperationAddress(e.target.value)}
placeholder="addr1..."
label="Operation address"
key={0}
/>,
]}
/>
);
}

export function InputsParamUtxo() {
const paramUtxo = useContentOwnership((state) => state.paramUtxo);
const setParamUtxo = useContentOwnership((state) => state.setParamUtxo);
return (
<InputTable
listInputs={[
<Input
value={paramUtxo}
onChange={(e) => setParamUtxo(e.target.value)}
placeholder="{outputIndex: 0, txHash: 'txhash...txhash'}"
label="Param UTxO"
key={0}
/>,
]}
/>
);
}

export function InputsRefScriptUtxos() {
const contentRegistry = useContentOwnership((state) => state.contentRegistry);
const setContentRegistry = useContentOwnership(
(state) => state.setContentRegistry,
);
const contentRefToken = useContentOwnership((state) => state.contentRefToken);
const setContentRefToken = useContentOwnership(
(state) => state.setContentRefToken,
);
const ownershipRegistry = useContentOwnership(
(state) => state.ownershipRegistry,
);
const setOwnershipRegistry = useContentOwnership(
(state) => state.setOwnershipRegistry,
);
const ownershipRefToken = useContentOwnership(
(state) => state.ownershipRefToken,
);
const setOwnershipRefToken = useContentOwnership(
(state) => state.setOwnershipRefToken,
);
return (
<InputTable
listInputs={[
<Input
value={contentRegistry}
onChange={(e) => setContentRegistry(e.target.value)}
placeholder="txhash...txhash"
label="Content Registry Tx Hash"
key={0}
/>,
<Input
value={contentRefToken}
onChange={(e) => setContentRefToken(e.target.value)}
placeholder="txhash...txhash"
label="Content Ref Token Tx Hash"
key={1}
/>,
<Input
value={ownershipRegistry}
onChange={(e) => setOwnershipRegistry(e.target.value)}
placeholder="txhash...txhash"
label="Ownership Registry Tx Hash"
key={2}
/>,
<Input
value={ownershipRefToken}
onChange={(e) => setOwnershipRefToken(e.target.value)}
placeholder="txhash...txhash"
label="Ownership Ref Token Tx Hash"
key={3}
/>,
]}
/>
);
}

export default function Placeholder() {
return <></>;
}
Loading

0 comments on commit ff89007

Please sign in to comment.