Skip to content

Commit

Permalink
Merge branch 'main' into feature/vote
Browse files Browse the repository at this point in the history
  • Loading branch information
twwu123 committed Oct 7, 2024
2 parents 0103133 + 7d32062 commit a4de941
Show file tree
Hide file tree
Showing 20 changed files with 405 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const ReactPage: NextPage = () => {
{ label: "Mint with Plutus Script", to: "mintingPlutusScript" },
{ label: "Mint with CIP-68", to: "mintingCip68" },
{ label: "Mint Royalty Token", to: "mintingRoyaltyToken" },
{ label: "Mask metadata", to: "maskMetadata" },
];

return (
Expand Down
186 changes: 186 additions & 0 deletions apps/playground/src/pages/apis/transaction/minting/mask-metadata.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import {
AssetMetadata,
deserializeAddress,
ForgeScript,
Mint,
NativeScript,
Transaction,
} from "@meshsdk/core";
import { useWallet } from "@meshsdk/react";

import Link from "~/components/link";
import LiveCodeDemo from "~/components/sections/live-code-demo";
import TwoColumnsScroll from "~/components/sections/two-columns-scroll";
import Codeblock from "~/components/text/codeblock";
import { demoAddresses, demoAssetMetadata } from "~/data/cardano";

export default function MintingNativeScript() {
return (
<TwoColumnsScroll
sidebarTo="maskMetadata"
title="Mask asset metadata"
leftSection={Left()}
rightSection={Right()}
/>
);
}

function Left() {
let codeSnippetNative = ``;
codeSnippetNative += `import type { NativeScript } from '@meshsdk/core';\n`;
codeSnippetNative += `\n`;

codeSnippetNative += `const usedAddress = await wallet.getUsedAddresses();\n`;
codeSnippetNative += `const address = usedAddress[0];\n`;
codeSnippetNative += `\n`;
codeSnippetNative += `const { pubKeyHash: keyHash } = deserializeAddress(address);\n\n`;

codeSnippetNative += `const nativeScript: NativeScript = {\n`;
codeSnippetNative += ` type: "all",\n`;
codeSnippetNative += ` scripts: [\n`;
codeSnippetNative += ` {\n`;
codeSnippetNative += ` type: "before",\n`;
codeSnippetNative += ` slot: "99999999",\n`;
codeSnippetNative += ` },\n`;
codeSnippetNative += ` {\n`;
codeSnippetNative += ` type: "sig",\n`;
codeSnippetNative += ` keyHash: keyHash,\n`;
codeSnippetNative += ` },\n`;
codeSnippetNative += ` ],\n`;
codeSnippetNative += `};\n`;

let codeSnippet1 = `const forgingScript = ForgeScript.fromNativeScript(nativeScript);\n`;

let codeSnippet2 = `const assetMetadata: AssetMetadata = ${JSON.stringify(
demoAssetMetadata,
null,
2,
)};\n\n`;
codeSnippet2 += `const asset: Mint = {\n`;
codeSnippet2 += ` assetName: 'MeshToken',\n`;
codeSnippet2 += ` assetQuantity: '1',\n`;
codeSnippet2 += ` metadata: assetMetadata,\n`;
codeSnippet2 += ` label: '721',\n`;
codeSnippet2 += ` recipient: '${demoAddresses.testnet}' \n`;
codeSnippet2 += `};\n`;

let codeSnippet3 = `const tx = new Transaction({ initiator: wallet });\n`;
codeSnippet3 += `tx.mintAsset(\n`;
codeSnippet3 += ` forgingScript,\n`;
codeSnippet3 += ` asset,\n`;
codeSnippet3 += `);\n\n`;
codeSnippet3 += `const unsignedTx = await tx.build();\n`;
codeSnippet3 += `const signedTx = await wallet.signTx(unsignedTx);\n`;
codeSnippet3 += `const txHash = await wallet.submitTx(signedTx);\n`;

return (
<>
<p>
Additionally, you can define the forging script with{" "}
<code>NativeScript</code>. For example if you want to have a policy
locking script, you can create a new <code>ForgeScript</code> from{" "}
<code>NativeScript</code>:
</p>
<Codeblock data={codeSnippetNative} />
<Codeblock data={codeSnippet1} />
<p>
To get the <code>keyHash</code>, use the{" "}
<code>deserializeAddress()</code>. To get the slot, use the{" "}
<code>resolveSlotNo()</code>. Check out{" "}
<Link href="/apis/resolvers">Resolvers</Link> on how to use these
functions.
</p>
<p>
Important: if you are using a policy locking script, you must define{" "}
<code>setTimeToExpire</code> before the expiry; otherwise, you will
catch the <code>ScriptWitnessNotValidatingUTXOW</code> error. See{" "}
<Link href="/apis/transaction#setTime">Transaction - set time</Link>.
</p>

<p>
Next, we define the metadata for the asset and create the asset object:
</p>

<Codeblock data={codeSnippet2} />

<p>
Finally, we create a transaction and mint the asset with the{" "}
<code>mintAsset</code> method:
</p>
<Codeblock data={codeSnippet3} />

<p>
You can get the policy ID for this Native Script with{" "}
<code>resolveNativeScriptHash</code>:
</p>
<Codeblock
data={`const policyId = resolveNativeScriptHash(nativeScript);`}
/>
</>
);
}

function Right() {
const { wallet, connected } = useWallet();

async function runDemo() {
const usedAddress = await wallet.getUsedAddresses();
const address = usedAddress[0];

if (address === undefined) {
throw "Address not found";
}

const { pubKeyHash: keyHash } = deserializeAddress(address);

const nativeScript: NativeScript = {
type: "all",
scripts: [
{
type: "before",
slot: "99999999",
},
{
type: "sig",
keyHash: keyHash,
},
],
};

const forgingScript = ForgeScript.fromNativeScript(nativeScript);

// define asset metadata
const assetMetadata1: AssetMetadata = demoAssetMetadata;

const asset1: Mint = {
assetName: "MeshToken",
assetQuantity: "1",
metadata: assetMetadata1,
label: "721",
recipient: address,
};

const tx = new Transaction({ initiator: wallet }).setNetwork("preprod");
tx.mintAsset(forgingScript, asset1);
tx.setTimeToExpire("99999999");

const unsignedTx = await tx.build();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);

return txHash;
}

return (
<LiveCodeDemo
title="Mint Assets with Native Script"
subtitle="Mint native assets with Native Script"
runCodeFunction={runDemo}
disabled={!connected}
runDemoButtonTooltip={
!connected ? "Connect wallet to run this demo" : undefined
}
runDemoShowBrowseWalletConnect={true}
></LiveCodeDemo>
);
}
48 changes: 34 additions & 14 deletions apps/playground/src/pages/guides/multisig-minting/demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ import { demoAddresses, demoAssetMetadata, demoMnemonic } from "~/data/cardano";
const walletSystemMnemonic = demoMnemonic;
const walletAccountAddress = demoAddresses.testnetPayment;
const mintingFee = "10000000";
let originalMetadata = "";

const blockchainProvider = getProvider();

const systemWallet = new MeshWallet({
networkId: 0,
fetcher: blockchainProvider,
submitter: blockchainProvider,
key: {
type: "mnemonic",
words: walletSystemMnemonic,
},
});

export default function Demo() {
const { wallet, connected } = useWallet();
Expand All @@ -46,26 +59,20 @@ export default function Demo() {

// backend to build tx
const unsignedTx = await backendBuildTx(selectedUtxos, recipientAddress);

// user sign
const signedTx = await wallet.signTx(unsignedTx, true);
const txHash = await wallet.submitTx(signedTx);

// backend sign and submit
const backendSignedTx = await backendSignTx(signedTx);

const txHash = await wallet.submitTx(backendSignedTx);

setResponse(txHash);
setLoading(false);
}

async function backendBuildTx(userUtxos: UTxO[], recipientAddress: string) {
const blockchainProvider = getProvider();

const systemWallet = new MeshWallet({
networkId: 0,
fetcher: blockchainProvider,
submitter: blockchainProvider,
key: {
type: "mnemonic",
words: walletSystemMnemonic,
},
});

const systemWalletAddress = systemWallet.getChangeAddress();
const forgingScript = ForgeScript.withOneSignature(systemWalletAddress);
const assetName = "MeshToken";
Expand All @@ -85,8 +92,21 @@ export default function Demo() {
tx.setChangeAddress(recipientAddress);
const unsignedTx = await tx.build();

const meshWalletSignedTx = await systemWallet.signTx(unsignedTx, true);
originalMetadata = Transaction.readMetadata(unsignedTx);

const maskedTx = Transaction.maskMetadata(unsignedTx);
return maskedTx;
}

async function backendSignTx(unsignedTx: string) {
const signedOriginalTx = Transaction.writeMetadata(
unsignedTx,
originalMetadata,
);
const meshWalletSignedTx = await systemWallet.signTx(
signedOriginalTx,
true,
);
return meshWalletSignedTx;
}

Expand Down
42 changes: 36 additions & 6 deletions apps/playground/src/pages/guides/multisig-minting/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ In this guide, we will build a multi-sig transaction for minting. There are 2 wa
1. client wallet belonging to the user who wishes to buy a native asset
2. application wallet that holds the forging script

## See it in action

In this guide, we will connect to user's CIP30 wallet (`BrowserWallet`) to request for a minting transaction. Then, the backend application wallet (`MeshWallet`) will build the transaction, and we will sign it with our wallet.
In this guide, we will connect to user's CIP30 wallet (`BrowserWallet`) to request for a minting transaction. Then, the backend application wallet (`MeshWallet`) will build the transaction, and we will sign it with our wallet. [Check out the code here](https://github.com/MeshJS/mesh/blob/main/apps/playground/src/pages/guides/multisig-minting/demo.tsx).

## Connect wallet (client)

Expand Down Expand Up @@ -140,21 +138,53 @@ tx.setChangeAddress(recipientAddress);
const unsignedTx = await tx.build();
```

The backend will sign the transaction with the application wallet:
Optionally, we can mask the metadata so users do not see the NFT metadata:

```
const meshWalletSignedTx = await systemWallet.signTx(unsignedTx, true);
originalMetadata = Transaction.readMetadata(unsignedTx);
```

And send the signed transaction to the client for their signature.
This `originalMetadata` can be stored in a database to merge with the original transaction after user signature.

Send the transaction to the client for their signature.

## Sign transaction (client)

In this section, we need the client's signature to send the payment to the `bankWalletAddress`. The client's wallet will open and prompts for payment password. Note that the partial sign is set to `true`.

```
const signedTx = await wallet.signTx(unsignedTx, true);
```

## Sign transaction (application)

The backend will sign the transaction with the application wallet:

```
const meshWalletSignedTx = await systemWallet.signTx(unsignedTx, true);
```

If you have masked the metadata, you can merge the metadata with the signed transaction:

```
const signedOriginalTx = Transaction.writeMetadata(
unsignedTx,
originalMetadata,
);
const meshWalletSignedTx = await systemWallet.signTx(
signedOriginalTx,
true,
);
```

## Submit transaction (application)

Finally, we submit the transaction to the blockchain:

```
const txHash = await wallet.submitTx(signedTx);
```

Voila! You can build any multi-sig transactions!

[Check out the code here](https://github.com/MeshJS/mesh/blob/main/apps/playground/src/pages/guides/multisig-minting/demo.tsx).
2 changes: 1 addition & 1 deletion packages/mesh-common/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/common",
"version": "1.7.6",
"version": "1.7.7",
"description": "",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
Expand Down
12 changes: 6 additions & 6 deletions packages/mesh-contract/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/contract",
"version": "1.7.6",
"version": "1.7.7",
"description": "",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
Expand Down Expand Up @@ -34,11 +34,11 @@
"typescript": "^5.3.3"
},
"dependencies": {
"@meshsdk/common": "1.7.6",
"@meshsdk/core": "1.7.6",
"@meshsdk/core-csl": "1.7.6",
"@meshsdk/core-cst": "1.7.6",
"@meshsdk/transaction": "1.7.6"
"@meshsdk/common": "1.7.7",
"@meshsdk/core": "1.7.7",
"@meshsdk/core-csl": "1.7.7",
"@meshsdk/core-cst": "1.7.7",
"@meshsdk/transaction": "1.7.7"
},
"prettier": "@meshsdk/configs/prettier",
"publishConfig": {
Expand Down
4 changes: 2 additions & 2 deletions packages/mesh-core-csl/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/core-csl",
"version": "1.7.6",
"version": "1.7.7",
"description": "",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
Expand Down Expand Up @@ -38,7 +38,7 @@
"typescript": "^5.3.3"
},
"dependencies": {
"@meshsdk/common": "1.7.6",
"@meshsdk/common": "1.7.7",
"@sidan-lab/sidan-csl-rs-browser": "0.8.6",
"@sidan-lab/sidan-csl-rs-nodejs": "0.8.6",
"json-bigint": "^1.0.0"
Expand Down
Loading

0 comments on commit a4de941

Please sign in to comment.