Example responses from unlocking assets from the always succeed smart
contract.
- Return a list of assets in connected wallet from all UTXOs.
- Return amount of lovelace in wallet.
- Return the network of connected wallet.
- Returns a list of wallets installed on user's device.
-
+ You can define the NuFi network to connect to by adding the{" "}
+ nufiNetwork
prop.
+
+
<>
-
+
{wallets.map((wallet, i) => {
return (
diff --git a/apps/playground/src/pages/smart-contracts/common.tsx b/apps/playground/src/pages/smart-contracts/common.tsx
index 30699bd4..bed6602f 100644
--- a/apps/playground/src/pages/smart-contracts/common.tsx
+++ b/apps/playground/src/pages/smart-contracts/common.tsx
@@ -7,7 +7,7 @@ export function InstallSmartContract() {
First you can to install the @meshsdk/contracts
package:
-
+
>
);
}
diff --git a/apps/playground/src/pages/smart-contracts/escrow/index.tsx b/apps/playground/src/pages/smart-contracts/escrow/index.tsx
index 79e1444c..179c7568 100644
--- a/apps/playground/src/pages/smart-contracts/escrow/index.tsx
+++ b/apps/playground/src/pages/smart-contracts/escrow/index.tsx
@@ -1,6 +1,7 @@
import type { NextPage } from "next";
import Link from "next/link";
+import MintMeshToken from "~/components/cardano/mint-mesh-token";
import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth";
import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body";
import Metatags from "~/components/site/metatags";
@@ -73,14 +74,16 @@ const ReactPage: NextPage = () => {
provider,{" "}
MeshTxBuilder
and MeshEscrowContract
.
-
+
Both on-chain and off-chain codes are open-source and available on{" "}
-
+
Mesh Github Repository
.
+
+
>
diff --git a/apps/playground/src/pages/smart-contracts/giftcard/index.tsx b/apps/playground/src/pages/smart-contracts/giftcard/index.tsx
index c806e018..edd48305 100644
--- a/apps/playground/src/pages/smart-contracts/giftcard/index.tsx
+++ b/apps/playground/src/pages/smart-contracts/giftcard/index.tsx
@@ -72,10 +72,10 @@ const ReactPage: NextPage = () => {
provider,{" "}
MeshTxBuilder
and MeshGiftCardContract
.
-
+
Both on-chain and off-chain codes are open-source and available on{" "}
-
+
Mesh Github Repository
.
diff --git a/apps/playground/src/pages/smart-contracts/marketplace/index.tsx b/apps/playground/src/pages/smart-contracts/marketplace/index.tsx
index 7caf6d36..b9bc024a 100644
--- a/apps/playground/src/pages/smart-contracts/marketplace/index.tsx
+++ b/apps/playground/src/pages/smart-contracts/marketplace/index.tsx
@@ -1,6 +1,7 @@
import type { NextPage } from "next";
import Link from "next/link";
+import MintMeshToken from "~/components/cardano/mint-mesh-token";
import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth";
import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body";
import Metatags from "~/components/site/metatags";
@@ -81,7 +82,7 @@ const ReactPage: NextPage = () => {
and a connected browser wallet. Here is an example how we can
initialize the Marketplace.
-
+
To initialize the Marketplace, we import the{" "}
MeshMarketplaceContract
. The first JSON object is the{" "}
@@ -102,11 +103,13 @@ const ReactPage: NextPage = () => {
Both on-chain and off-chain codes are open-source and available on{" "}
-
+
Mesh Github Repository
.
+
+
>
diff --git a/apps/playground/src/pages/smart-contracts/marketplace/list-asset.tsx b/apps/playground/src/pages/smart-contracts/marketplace/list-asset.tsx
index aa7c5107..53d50d00 100644
--- a/apps/playground/src/pages/smart-contracts/marketplace/list-asset.tsx
+++ b/apps/playground/src/pages/smart-contracts/marketplace/list-asset.tsx
@@ -2,6 +2,7 @@ import { useState } from "react";
import { useWallet } from "@meshsdk/react";
+import MintMeshToken from "~/components/cardano/mint-mesh-token";
import Input from "~/components/form/input";
import InputTable from "~/components/sections/input-table";
import LiveCodeDemo from "~/components/sections/live-code-demo";
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 8d68e67c..b07edc41 100644
--- a/apps/playground/src/pages/smart-contracts/payment-splitter/index.tsx
+++ b/apps/playground/src/pages/smart-contracts/payment-splitter/index.tsx
@@ -92,10 +92,10 @@ const ReactPage: NextPage = () => {
payees is required to define the allowed payout addresses for the
contract.
-
+
Both on-chain and off-chain codes are open-source and available on{" "}
-
+
Mesh Github Repository
.
diff --git a/apps/playground/src/pages/smart-contracts/swap/index.tsx b/apps/playground/src/pages/smart-contracts/swap/index.tsx
index 968da425..f496e18d 100644
--- a/apps/playground/src/pages/smart-contracts/swap/index.tsx
+++ b/apps/playground/src/pages/smart-contracts/swap/index.tsx
@@ -1,6 +1,7 @@
import type { NextPage } from "next";
import Link from "next/link";
+import MintMeshToken from "~/components/cardano/mint-mesh-token";
import SidebarFullwidth from "~/components/layouts/sidebar-fullwidth";
import TitleIconDescriptionBody from "~/components/sections/title-icon-description-body";
import Metatags from "~/components/site/metatags";
@@ -73,14 +74,16 @@ const ReactPage: NextPage = () => {
provider,{" "}
MeshTxBuilder
and MeshSwapContract
.
-
+
Both on-chain and off-chain codes are open-source and available on{" "}
-
+
Mesh Github Repository
.
+
+
>
diff --git a/apps/playground/src/pages/smart-contracts/vesting/index.tsx b/apps/playground/src/pages/smart-contracts/vesting/index.tsx
index 2e17713c..fe76191a 100644
--- a/apps/playground/src/pages/smart-contracts/vesting/index.tsx
+++ b/apps/playground/src/pages/smart-contracts/vesting/index.tsx
@@ -72,10 +72,10 @@ const ReactPage: NextPage = () => {
provider,{" "}
MeshTxBuilder
and MeshVestingContract
.
-
+
Both on-chain and off-chain codes are open-source and available on{" "}
-
+
Mesh Github Repository
.
diff --git a/package-lock.json b/package-lock.json
index 8381022c..22a43665 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5795,6 +5795,14 @@
"resolved": "packages/mesh-wallet",
"link": true
},
+ "node_modules/@metamask/detect-provider": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@metamask/detect-provider/-/detect-provider-2.0.0.tgz",
+ "integrity": "sha512-sFpN+TX13E9fdBDh9lvQeZdJn4qYoRb/6QF2oZZK/Pn559IhCFacPMU1rMuqyXoFQF3JSJfii2l98B87QDPeCQ==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/@microsoft/tsdoc": {
"version": "0.14.2",
"resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz",
@@ -6080,6 +6088,22 @@
"node": ">= 8"
}
},
+ "node_modules/@nufi/dapp-client-cardano": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@nufi/dapp-client-cardano/-/dapp-client-cardano-0.3.1.tgz",
+ "integrity": "sha512-9anqGHu+OP0U0po/Rk6thmR+qcgqtRY3bppudC3As0dgXIhSfsWJBKIXw2Q/byCYL5l/GsmyC9XgdEKB7+oVeQ==",
+ "dependencies": {
+ "@nufi/dapp-client-core": "0.3.1"
+ }
+ },
+ "node_modules/@nufi/dapp-client-core": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@nufi/dapp-client-core/-/dapp-client-core-0.3.1.tgz",
+ "integrity": "sha512-MexKhCE1dZGYTyxZuqQGCaZN0tZW0RyqDY/wzMafwuP5LUKxoxahCJ5U+SF37v4FrrDz6svNddV69aUSMIldag==",
+ "dependencies": {
+ "@metamask/detect-provider": "^2.0.0"
+ }
+ },
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@@ -8943,6 +8967,7 @@
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
"integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
"funding": [
{
"type": "github",
@@ -11877,7 +11902,8 @@
"node_modules/hosted-git-info": {
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
- "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true
},
"node_modules/html-escaper": {
"version": "2.0.2",
@@ -14677,6 +14703,7 @@
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
"integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
"dependencies": {
"hosted-git-info": "^2.1.4",
"resolve": "^1.10.0",
@@ -14688,6 +14715,7 @@
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+ "dev": true,
"bin": {
"semver": "bin/semver"
}
@@ -18874,6 +18902,7 @@
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
"integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+ "dev": true,
"dependencies": {
"spdx-expression-parse": "^3.0.0",
"spdx-license-ids": "^3.0.0"
@@ -18882,12 +18911,14 @@
"node_modules/spdx-exceptions": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
- "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="
+ "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
+ "dev": true
},
"node_modules/spdx-expression-parse": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
"dependencies": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
@@ -18896,7 +18927,8 @@
"node_modules/spdx-license-ids": {
"version": "3.0.18",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz",
- "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ=="
+ "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==",
+ "dev": true
},
"node_modules/split-ca": {
"version": "1.0.1",
@@ -20469,6 +20501,7 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
"dependencies": {
"spdx-correct": "^3.0.0",
"spdx-expression-parse": "^3.0.0"
@@ -20824,6 +20857,7 @@
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
"integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "dev": true,
"dependencies": {
"imurmurhash": "^0.1.4",
"signal-exit": "^3.0.7"
@@ -20835,7 +20869,8 @@
"node_modules/write-file-atomic/node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
},
"node_modules/ws": {
"version": "7.5.10",
@@ -21029,7 +21064,7 @@
},
"packages/mesh-common": {
"name": "@meshsdk/common",
- "version": "1.5.32",
+ "version": "1.6.1",
"license": "Apache-2.0",
"dependencies": {
"@emurgo/cip14-js": "3.0.1",
@@ -21045,7 +21080,7 @@
},
"packages/mesh-contract": {
"name": "@meshsdk/contract",
- "version": "1.5.32",
+ "version": "1.6.1",
"license": "Apache-2.0",
"dependencies": {
"@meshsdk/common": "*",
@@ -21064,7 +21099,7 @@
},
"packages/mesh-core": {
"name": "@meshsdk/core",
- "version": "1.5.32",
+ "version": "1.6.1",
"license": "Apache-2.0",
"dependencies": {
"@meshsdk/common": "*",
@@ -21085,7 +21120,7 @@
},
"packages/mesh-core-csl": {
"name": "@meshsdk/core-csl",
- "version": "1.5.32",
+ "version": "1.6.1",
"license": "Apache-2.0",
"dependencies": {
"@meshsdk/common": "*",
@@ -21105,7 +21140,7 @@
},
"packages/mesh-core-cst": {
"name": "@meshsdk/core-cst",
- "version": "1.5.32",
+ "version": "1.6.1",
"license": "Apache-2.0",
"dependencies": {
"@cardano-sdk/core": "^0.35.4",
@@ -21128,7 +21163,7 @@
},
"packages/mesh-provider": {
"name": "@meshsdk/provider",
- "version": "1.5.32",
+ "version": "1.6.1",
"license": "Apache-2.0",
"dependencies": {
"@meshsdk/common": "*",
@@ -21144,7 +21179,7 @@
},
"packages/mesh-react": {
"name": "@meshsdk/react",
- "version": "1.5.32",
+ "version": "1.6.1",
"license": "Apache-2.0",
"dependencies": {
"@meshsdk/common": "*",
@@ -21166,7 +21201,7 @@
},
"packages/mesh-transaction": {
"name": "@meshsdk/transaction",
- "version": "1.5.32",
+ "version": "1.6.1",
"license": "Apache-2.0",
"dependencies": {
"@meshsdk/common": "*",
@@ -21184,12 +21219,14 @@
},
"packages/mesh-wallet": {
"name": "@meshsdk/wallet",
- "version": "1.5.32",
+ "version": "1.6.1",
"license": "Apache-2.0",
"dependencies": {
"@meshsdk/common": "*",
"@meshsdk/core-cst": "*",
- "@meshsdk/transaction": "*"
+ "@meshsdk/transaction": "*",
+ "@nufi/dapp-client-cardano": "^0.3.1",
+ "@nufi/dapp-client-core": "^0.3.1"
},
"devDependencies": {
"@meshsdk/typescript-config": "*",
diff --git a/packages/config-jest/jest.config.ts b/packages/config-jest/jest.config.ts
index efbea431..9042e9fd 100644
--- a/packages/config-jest/jest.config.ts
+++ b/packages/config-jest/jest.config.ts
@@ -6,21 +6,14 @@ const jestConfig: Config = {
testEnvironment: "node",
testMatch: ["**/packages/**/*.test.ts"],
setupFiles: ["dotenv/config"],
- preset: "ts-jest/presets/default-esm",
+ preset: "ts-jest",
moduleNameMapper: {
"^(\\.{1,2}/.*)\\.js$": "$1",
},
transform: {
- "^.+\\.tsx?$": [
- "ts-jest",
- {
- useESM: true,
- },
- ],
+ "^.+\\.[jt]s?$": "ts-jest",
},
- transformIgnorePatterns: [
- "/node_modules/(?!@meshsdk/core-csl)", // Add exceptions for ESM packages
- ],
+ transformIgnorePatterns: ["/node_modules/(?!@meshsdk/.*)"],
};
export default jestConfig;
diff --git a/packages/mesh-common/package.json b/packages/mesh-common/package.json
index f2e6771e..56a93883 100644
--- a/packages/mesh-common/package.json
+++ b/packages/mesh-common/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/common",
- "version": "1.6.1",
+ "version": "1.6.2",
"description": "",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
diff --git a/packages/mesh-common/src/data/value.ts b/packages/mesh-common/src/data/value.ts
index f88b7089..cca749b0 100644
--- a/packages/mesh-common/src/data/value.ts
+++ b/packages/mesh-common/src/data/value.ts
@@ -4,6 +4,7 @@
*/
import { Asset } from "../types";
+import { BigNum } from "../utils";
import {
assocMap,
AssocMap,
@@ -15,56 +16,303 @@ import {
tokenName,
} from "./json";
+/**
+ * Aiken alias
+ * Value is the JSON representation of Cardano data Value
+ */
export type Value = AssocMap>;
+/**
+ * Aiken alias
+ * MValue is the Cardano data Value in Mesh Data type
+ */
export type MValue = Map>;
-export const value = (assets: Asset[]): Value => {
- const valueMapToParse: [CurrencySymbol, AssocMap][] = [];
- const valueMap: { [key: string]: { [key: string]: number } } = {};
+/**
+ * The utility function to convert assets into Cardano data Value in JSON
+ * @param assets The assets to convert
+ * @returns The Cardano data Value in JSON
+ */
+export const value = (assets: Asset[]) => {
+ return MeshValue.fromAssets(assets).toJSON();
+};
+
+/**
+ * The utility function to convert assets into Cardano data Value in Mesh Data type
+ * @param assets The assets to convert
+ * @returns The Cardano data Value in Mesh Data type
+ */
+export const mValue = (assets: Asset[]) => {
+ return MeshValue.fromAssets(assets).toData();
+};
+
+/**
+ * MeshValue provide utility to handle the Cardano value manipulation. It offers certain axioms:
+ * 1. No duplication of asset - adding assets with same asset name will increase the quantity of the asset in the same record.
+ * 2. No zero and negative entry - the quantity of the asset should not be zero or negative.
+ * 3. Sanitization of lovelace asset name - the class handle back and forth conversion of lovelace asset name to empty string.
+ * 4. Easy convertion to Cardano data - offer utility to convert into either Mesh Data type and JSON type for its Cardano data representation.
+ */
+export class MeshValue {
+ value: Record;
+
+ constructor(value: Record = {}) {
+ this.value = value;
+ }
+
+ /**
+ * Converting assets into MeshValue
+ * @param assets The assets to convert
+ * @returns MeshValue
+ */
+ static fromAssets = (assets: Asset[]): MeshValue => {
+ const value = new MeshValue();
+ value.addAssets(assets);
+ return value;
+ };
+
+ /**
+ * Converting Value (the JSON representation of Cardano data Value) into MeshValue
+ * @param plutusValue The Value to convert
+ * @returns MeshValue
+ */
+ static fromValue = (plutusValue: Value): MeshValue => {
+ const assets: Asset[] = [];
+
+ plutusValue.map.forEach((policyMap) => {
+ const policy = policyMap.k.bytes;
+ policyMap.v.map.forEach((tokenMap) => {
+ const token = tokenMap.k.bytes;
+ const quantity = tokenMap.v.int.toString();
+ const unsanitizedUnit = policy + token;
+ const unit = unsanitizedUnit === "" ? "lovelace" : unsanitizedUnit;
+ assets.push({ unit, quantity });
+ });
+ });
+
+ return MeshValue.fromAssets(assets);
+ };
- assets.forEach((asset) => {
- const sanitizedName = asset.unit.replace("lovelace", "");
- const policy = sanitizedName.slice(0, 56) || "";
- const token = sanitizedName.slice(56) || "";
+ /**
+ * Add an asset to the Value class's value record.
+ * @param asset The asset to add
+ * @returns The updated MeshValue object
+ */
+ addAsset = (asset: Asset): this => {
+ const quantity = BigInt(asset.quantity);
+ const { unit } = asset;
- if (!valueMap[policy]) {
- valueMap[policy] = {};
+ if (this.value[unit]) {
+ this.value[unit] += quantity;
+ } else {
+ this.value[unit] = quantity;
}
+ return this;
+ };
+
+ /**
+ * Add an array of assets to the Value class's value record.
+ * @param assets The assets to add
+ * @returns The updated MeshValue object
+ */
+ addAssets = (assets: Asset[]): this => {
+ assets.forEach((asset) => {
+ this.addAsset(asset);
+ });
+ return this;
+ };
- if (!valueMap[policy]![token]) {
- valueMap[policy]![token] = Number(asset.quantity);
+ /**
+ * Substract an asset from the Value class's value record.
+ * @param asset The asset to subtract
+ * @returns The updated MeshValue object
+ */
+ negateAsset = (asset: Asset): this => {
+ const { unit, quantity: assetQty } = asset;
+ const quantity = BigNum.new(this.value[unit]);
+ quantity.clampedSub(BigNum.new(assetQty));
+
+ if (quantity.value === BigInt(0)) {
+ delete this.value[unit];
} else {
- valueMap[policy]![token] += Number(asset.quantity);
+ this.value[unit] = quantity.value;
}
- });
+ return this;
+ };
- Object.keys(valueMap).forEach((policy) => {
- const policyByte = currencySymbol(policy);
- const tokens: [TokenName, Integer][] = Object.keys(valueMap[policy]!).map(
- (name) => [tokenName(name), integer(valueMap[policy]![name]!)],
- );
+ /**
+ * Subtract an array of assets from the Value class's value record.
+ * @param assets The assets to subtract
+ * @returns The updated MeshValue object
+ */
+ negateAssets = (assets: Asset[]): this => {
+ assets.forEach((asset) => {
+ this.negateAsset(asset);
+ });
+ return this;
+ };
- const policyMap = assocMap(tokens);
- valueMapToParse.push([policyByte, policyMap]);
- });
+ /**
+ * Get the quantity of asset object per unit
+ * @param unit The unit to get the quantity of
+ * @returns The quantity of the asset
+ */
+ get = (unit: string): bigint => {
+ return this.value[unit] ? BigInt(this.value[unit]) : BigInt(0);
+ };
- return assocMap(valueMapToParse);
-};
+ /**
+ * Get all asset units
+ * @returns The asset units
+ */
+ units = (): string[] => {
+ return Object.keys(this.value);
+ };
-export const parsePlutusValueToAssets = (plutusValue: Value): Asset[] => {
- const assets: Asset[] = [];
-
- plutusValue.map.forEach((policyMap) => {
- const policy = policyMap.k.bytes;
- policyMap.v.map.forEach((tokenMap) => {
- const token = tokenMap.k.bytes;
- const quantity = tokenMap.v.int.toString();
- const unsanitizedUnit = policy + token;
- const unit = unsanitizedUnit === "" ? "lovelace" : unsanitizedUnit;
- assets.push({ unit, quantity });
+ /**
+ * Check if the value is greater than or equal to another value
+ * @param other - The value to compare against
+ * @returns boolean
+ */
+ geq = (other: MeshValue): boolean => {
+ return Object.keys(other.value).every((key) => this.geqUnit(key, other));
+ };
+
+ /**
+ * Check if the specific unit of value is greater than or equal to that unit of another value
+ * @param unit - The unit to compare
+ * @param other - The value to compare against
+ * @returns boolean
+ */
+ geqUnit = (unit: string, other: MeshValue): boolean => {
+ if (this.value[unit] === undefined || other.value[unit] === undefined) {
+ return false;
+ }
+ return BigInt(this.value[unit]) >= BigInt(other.value[unit]);
+ };
+
+ /**
+ * Check if the value is less than or equal to another value
+ * @param other - The value to compare against
+ * @returns boolean
+ */
+ leq = (other: MeshValue): boolean => {
+ return Object.keys(other.value).every((key) => this.leqUnit(key, other));
+ };
+
+ /**
+ * Check if the specific unit of value is less than or equal to that unit of another value
+ * @param unit - The unit to compare
+ * @param other - The value to compare against
+ * @returns boolean
+ */
+ leqUnit = (unit: string, other: MeshValue): boolean => {
+ if (this.value[unit] === undefined || other.value[unit] === undefined) {
+ return false;
+ }
+ return BigInt(this.value[unit]) <= BigInt(other.value[unit]);
+ };
+
+ /**
+ * Check if the value is empty
+ * @returns boolean
+ */
+ isEmpty = (): boolean => {
+ return Object.keys(this.value).length === 0;
+ };
+
+ /**
+ * Merge the given values
+ * @param values The other values to merge
+ * @returns this
+ */
+ merge = (values: MeshValue | MeshValue[]): this => {
+ const valuesArray = Array.isArray(values) ? values : [values];
+
+ valuesArray.forEach((other) => {
+ Object.entries(other.value).forEach(([key, value]) => {
+ this.value[key] =
+ (this.value[key] !== undefined
+ ? BigInt(this.value[key])
+ : BigInt(0)) + BigInt(value);
+ });
});
- });
- return assets;
-};
+ return this;
+ };
+
+ /**
+ * Convert the MeshValue object into an array of Asset
+ * @returns The array of Asset
+ */
+ toAssets = (): Asset[] => {
+ const assets: Asset[] = [];
+ Object.entries(this.value).forEach(([unit, quantity]) => {
+ assets.push({ unit, quantity: quantity.toString() });
+ });
+ return assets;
+ };
+
+ /**
+ * Convert the MeshValue object into Cardano data Value in Mesh Data type
+ */
+ toData = (): MValue => {
+ const valueMap: MValue = new Map();
+ this.toAssets().forEach((asset) => {
+ const policy = asset.unit.slice(0, 56) || "";
+ const token = asset.unit.slice(56) || "";
+
+ if (!valueMap.has(policy)) {
+ valueMap.set(policy, new Map());
+ }
+
+ const tokenMap = valueMap.get(policy)!;
+ const quantity = tokenMap?.get(token);
+ if (!quantity) {
+ tokenMap.set(token, BigInt(asset.quantity));
+ } else {
+ tokenMap.set(token, quantity + BigInt(asset.quantity));
+ }
+ });
+
+ return valueMap;
+ };
+
+ /**
+ * Convert the MeshValue object into a JSON representation of Cardano data Value
+ * @returns Cardano data Value in JSON
+ */
+ toJSON = (): Value => {
+ const valueMapToParse: [CurrencySymbol, AssocMap][] =
+ [];
+ const valueMap: { [key: string]: { [key: string]: number } } = {};
+
+ this.toAssets().forEach((asset) => {
+ const sanitizedName = asset.unit.replace("lovelace", "");
+ const policy = sanitizedName.slice(0, 56) || "";
+ const token = sanitizedName.slice(56) || "";
+
+ if (!valueMap[policy]) {
+ valueMap[policy] = {};
+ }
+
+ if (!valueMap[policy]![token]) {
+ valueMap[policy]![token] = Number(asset.quantity);
+ } else {
+ valueMap[policy]![token] += Number(asset.quantity);
+ }
+ });
+
+ Object.keys(valueMap).forEach((policy) => {
+ const policyByte = currencySymbol(policy);
+ const tokens: [TokenName, Integer][] = Object.keys(valueMap[policy]!).map(
+ (name) => [tokenName(name), integer(valueMap[policy]![name]!)],
+ );
+
+ const policyMap = assocMap(tokens);
+ valueMapToParse.push([policyByte, policyMap]);
+ });
+
+ return assocMap(valueMapToParse);
+ };
+}
diff --git a/packages/mesh-common/src/interfaces/serializer.ts b/packages/mesh-common/src/interfaces/serializer.ts
index 924b120b..b89c6cad 100644
--- a/packages/mesh-common/src/interfaces/serializer.ts
+++ b/packages/mesh-common/src/interfaces/serializer.ts
@@ -19,6 +19,7 @@ export interface IMeshTxSerializer {
deserializer: IDeserializer;
serializeData(data: BuilderData): string;
serializeAddress(address: DeserializedAddress, networkId?: 0 | 1): string;
+ serializePoolId(hash: string): string;
}
export interface IResolver {
keys: {
@@ -36,9 +37,6 @@ export interface IResolver {
script: {
resolveScriptRef(script: NativeScript | PlutusScript): string;
};
- pool: {
- resolvePoolId(hash: string): string;
- };
}
export interface IDeserializer {
@@ -49,4 +47,7 @@ export interface IDeserializer {
deserializeNativeScript(script: NativeScript): DeserializedScript;
deserializePlutusScript(script: PlutusScript): DeserializedScript;
};
+ cert: {
+ deserializePoolId(poolId: string): string;
+ };
}
diff --git a/packages/mesh-common/src/utils/asset-fingerprint.ts b/packages/mesh-common/src/utils/asset-fingerprint.ts
index 2a8e353c..49861be7 100644
--- a/packages/mesh-common/src/utils/asset-fingerprint.ts
+++ b/packages/mesh-common/src/utils/asset-fingerprint.ts
@@ -5,7 +5,7 @@ import { toBytes } from "../data";
export const AssetFingerprint = CIP14;
export const resolveFingerprint = (policyId: string, assetName: string) => {
- return (AssetFingerprint as any).default
+ return (AssetFingerprint as any).default // todo: check the behaviour
.fromParts(toBytes(policyId), toBytes(assetName))
.fingerprint();
};
diff --git a/packages/mesh-common/src/utils/bigNum.ts b/packages/mesh-common/src/utils/bigNum.ts
index bbded1a0..b6acc44c 100644
--- a/packages/mesh-common/src/utils/bigNum.ts
+++ b/packages/mesh-common/src/utils/bigNum.ts
@@ -1,10 +1,21 @@
export class BigNum {
value: bigint;
- constructor(value: number | string) {
+ constructor(value?: bigint | number | string) {
+ if (!value) {
+ this.value = BigInt(0);
+ return;
+ }
this.value = BigInt(value);
}
+ static new(value: number | string | bigint | undefined): BigNum {
+ if (!value) {
+ return new BigNum(0);
+ }
+ return new BigNum(value);
+ }
+
// Operators
divFloor(other: BigNum): BigNum {
@@ -49,10 +60,6 @@ export class BigNum {
}
}
- static new = (value: number | string): BigNum => {
- return new BigNum(value);
- };
-
// Override
toString(): string {
diff --git a/packages/mesh-common/test/data/mesh/aliases.test.ts b/packages/mesh-common/test/data/mesh/aliases.test.ts
index c9cb4d3a..fe07568f 100644
--- a/packages/mesh-common/test/data/mesh/aliases.test.ts
+++ b/packages/mesh-common/test/data/mesh/aliases.test.ts
@@ -5,7 +5,8 @@ import {
mTxOutRef,
outputReference,
txOutRef,
-} from "../../../src";
+} from "@meshsdk/common";
+
import { serializeData } from "./common";
const testHash = "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc81700";
diff --git a/packages/mesh-common/test/data/mesh/common.ts b/packages/mesh-common/test/data/mesh/common.ts
index b19bbac3..99f6336d 100644
--- a/packages/mesh-common/test/data/mesh/common.ts
+++ b/packages/mesh-common/test/data/mesh/common.ts
@@ -1,7 +1,6 @@
+import { Data } from "@meshsdk/common";
import { castDataToPlutusData } from "@meshsdk/core-csl";
-import { Data } from "../../../src";
-
export const serializeData = (mesh: Data, json: any) => {
const meshData = castDataToPlutusData({
type: "Mesh",
diff --git a/packages/mesh-common/test/data/mesh/constructors.test.ts b/packages/mesh-common/test/data/mesh/constructors.test.ts
index ab2c1820..46ea1350 100644
--- a/packages/mesh-common/test/data/mesh/constructors.test.ts
+++ b/packages/mesh-common/test/data/mesh/constructors.test.ts
@@ -4,12 +4,12 @@ import {
conStr0,
conStr1,
conStr2,
- Data,
mConStr,
mConStr0,
mConStr1,
mConStr2,
-} from "../../../src";
+} from "@meshsdk/common";
+
import { serializeData } from "./common";
const testByteString = "abcd";
diff --git a/packages/mesh-common/test/data/mesh/credentials.test.ts b/packages/mesh-common/test/data/mesh/credentials.test.ts
index 097e393a..72db3cd8 100644
--- a/packages/mesh-common/test/data/mesh/credentials.test.ts
+++ b/packages/mesh-common/test/data/mesh/credentials.test.ts
@@ -1,15 +1,12 @@
import {
- conStr0,
- conStr1,
maybeStakingHash,
mMaybeStakingHash,
mPubKeyAddress,
mScriptAddress,
pubKeyAddress,
- pubKeyHash,
scriptAddress,
- scriptHash,
-} from "../../../src";
+} from "@meshsdk/common";
+
import { serializeData } from "./common";
const testKeyHash1 = "1e4eb194e3335a0dcc4f5c5d009318167c583bb3b0879d9f718cd9e0";
diff --git a/packages/mesh-common/test/data/mesh/primitives.test.ts b/packages/mesh-common/test/data/mesh/primitives.test.ts
index aaebd06b..65e92aa6 100644
--- a/packages/mesh-common/test/data/mesh/primitives.test.ts
+++ b/packages/mesh-common/test/data/mesh/primitives.test.ts
@@ -3,7 +3,8 @@ import {
mBool,
mPlutusBSArrayToString,
mStringToPlutusBSArray,
-} from "../../../src";
+} from "@meshsdk/common";
+
import { serializeData } from "./common";
describe("Plutus data type", () => {
diff --git a/packages/mesh-common/test/data/value.test.ts b/packages/mesh-common/test/data/value.test.ts
deleted file mode 100644
index 94d65ab5..00000000
--- a/packages/mesh-common/test/data/value.test.ts
+++ /dev/null
@@ -1,108 +0,0 @@
-import {
- Asset,
- byteString,
- ByteString,
- dict,
- Dict,
- Integer,
- integer,
- parsePlutusValueToAssets,
- Value,
- value,
-} from "../../src";
-
-describe("value", () => {
- test("Simple ADA Value", () => {
- const val: Asset[] = [{ unit: "lovelace", quantity: "1000000" }];
- const datum: Value = value(val);
-
- const nameMap = dict([[byteString(""), integer(1000000)]]);
- const valMap = dict>([[byteString(""), nameMap]]);
- expect(JSON.stringify(datum)).toBe(JSON.stringify(valMap));
- });
- test("Simple token Value", () => {
- const val: Asset[] = [
- {
- unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc8170074657374696e676e657777616c2e616461",
- quantity: "345",
- },
- ];
- const datum: Value = value(val);
-
- const nameMap = dict([
- [byteString("74657374696e676e657777616c2e616461"), integer(345)],
- ]);
- const valMap = dict>([
- [
- byteString("baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc81700"),
- nameMap,
- ],
- ]);
- expect(JSON.stringify(datum)).toBe(JSON.stringify(valMap));
- });
- test("Complex Value", () => {
- const val: Asset[] = [
- { unit: "lovelace", quantity: "1000000" },
- {
- unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc8170074657374696e676e657777616c2e616461",
- quantity: "345",
- },
- {
- unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234",
- quantity: "567",
- },
- ];
- const datum: Value = value(val);
-
- const nameMap = dict([
- [byteString("1234"), integer(567)],
- [byteString("74657374696e676e657777616c2e616461"), integer(345)],
- ]);
- const valMap = dict>([
- [byteString(""), dict([[byteString(""), integer(1000000)]])],
- [
- byteString("baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc81700"),
- nameMap,
- ],
- ]);
- expect(JSON.stringify(datum)).toBe(JSON.stringify(valMap));
- });
-});
-
-describe("Value", () => {
- test("Simple ADA Value", () => {
- const val: Asset[] = [{ unit: "lovelace", quantity: "1000000" }];
- const plutusValue: Value = value(val);
- const assets: Asset[] = parsePlutusValueToAssets(plutusValue);
-
- expect(JSON.stringify(val)).toBe(JSON.stringify(assets));
- });
- test("Simple token Value", () => {
- const val: Asset[] = [
- {
- unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc8170074657374696e676e657777616c2e616461",
- quantity: "345",
- },
- ];
- const plutusValue: Value = value(val);
- const assets: Asset[] = parsePlutusValueToAssets(plutusValue);
-
- expect(JSON.stringify(val)).toBe(JSON.stringify(assets));
- });
- test("Complex Value", () => {
- const val: Asset[] = [
- { unit: "lovelace", quantity: "1000000" },
- {
- unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234",
- quantity: "567",
- },
- {
- unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc8170074657374696e676e657777616c2e616461",
- quantity: "345",
- },
- ];
- const plutusValue: Value = value(val);
- const assets: Asset[] = parsePlutusValueToAssets(plutusValue);
- expect(JSON.stringify(val)).toBe(JSON.stringify(assets));
- });
-});
diff --git a/packages/mesh-common/test/data/value/accessor.test.ts b/packages/mesh-common/test/data/value/accessor.test.ts
new file mode 100644
index 00000000..4e9e1573
--- /dev/null
+++ b/packages/mesh-common/test/data/value/accessor.test.ts
@@ -0,0 +1,68 @@
+import { MeshValue } from "@meshsdk/common";
+
+import { mockUnit } from "./common";
+
+describe("MeshValue class", () => {
+ describe("get", () => {
+ it("should return the quantity of an existing asset", () => {
+ const value = new MeshValue({
+ lovelace: 20n,
+ [mockUnit]: 10n,
+ });
+ expect(value.get("lovelace")).toEqual(BigInt(20));
+ expect(value.get(mockUnit)).toEqual(BigInt(10));
+ });
+
+ it("should return 0 for a non-existing asset", () => {
+ const value = new MeshValue({ lovelace: 20n });
+ expect(value.get(mockUnit)).toEqual(BigInt(0));
+ });
+
+ it("should handle an empty value object", () => {
+ const value = new MeshValue();
+ expect(value.get("lovelace")).toEqual(BigInt(0));
+ });
+
+ it("should return the correct quantity after adding assets", () => {
+ const value = new MeshValue({ lovelace: 20n });
+ value.addAsset({
+ unit: mockUnit,
+ quantity: "10",
+ });
+ expect(value.get(mockUnit)).toEqual(BigInt(10));
+ });
+
+ it("should return the correct quantity after subtracting assets", () => {
+ const value = new MeshValue({
+ lovelace: 20n,
+ [mockUnit]: 10n,
+ });
+ value.negateAssets([
+ {
+ unit: mockUnit,
+ quantity: "5",
+ },
+ ]);
+ expect(value.get(mockUnit)).toEqual(BigInt(5));
+ });
+ });
+ describe("units", () => {
+ it("should return an empty object when value is empty", () => {
+ const value = new MeshValue();
+ expect(value.units()).toEqual([]);
+ });
+
+ it("should return the correct structure for a single asset", () => {
+ const value = new MeshValue({ lovelace: 20n });
+ expect(value.units()).toEqual(["lovelace"]);
+ });
+
+ it("should return the correct structure for multiple assets", () => {
+ const value = new MeshValue({
+ lovelace: 20n,
+ [mockUnit]: 10n,
+ });
+ expect(value.units()).toEqual(["lovelace", mockUnit]);
+ });
+ });
+});
diff --git a/packages/mesh-common/test/data/value/common.ts b/packages/mesh-common/test/data/value/common.ts
new file mode 100644
index 00000000..8c531bda
--- /dev/null
+++ b/packages/mesh-common/test/data/value/common.ts
@@ -0,0 +1,4 @@
+export const mockPolicyId =
+ "c21d710605bb00e69f3c175150552fc498316d80e7efdb1b186db38c";
+export const mockAssetName = "000643b04d65736820676f6f64";
+export const mockUnit = mockPolicyId + mockAssetName;
diff --git a/packages/mesh-common/test/data/value/comparator.test.ts b/packages/mesh-common/test/data/value/comparator.test.ts
new file mode 100644
index 00000000..f035ca05
--- /dev/null
+++ b/packages/mesh-common/test/data/value/comparator.test.ts
@@ -0,0 +1,111 @@
+import { MeshValue } from "@meshsdk/common";
+
+import { mockUnit } from "./common";
+
+describe("MeshValue class", () => {
+ describe("geq", () => {
+ it("should return true if the value is greater than or equal to the target value for a specific unit", () => {
+ const value = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ const target = new MeshValue({ lovelace: 10n, [mockUnit]: 5n });
+ expect(value.geq(target)).toBe(true);
+ });
+
+ it("should return false if the value is less than the target value for a specific unit", () => {
+ const value = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ const target = new MeshValue({ lovelace: 30n, [mockUnit]: 15n });
+ expect(value.geq(target)).toBe(false);
+ });
+
+ it("should return true if the value is equal to the target value for a specific unit", () => {
+ const value = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ const target = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ expect(value.geq(target)).toBe(true);
+ });
+ });
+ describe("geqUnit", () => {
+ it("should return true if the value is greater than or equal to the target value for a specific unit", () => {
+ const value = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ const target = new MeshValue({ lovelace: 10n, [mockUnit]: 5n });
+ expect(value.geqUnit("lovelace", target)).toBe(true);
+ expect(value.geqUnit(mockUnit, target)).toBe(true);
+ });
+
+ it("should return false if the value is less than the target value for a specific unit", () => {
+ const value = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ const target = new MeshValue({ lovelace: 30n, [mockUnit]: 15n });
+ expect(value.geqUnit("lovelace", target)).toBe(false);
+ expect(value.geqUnit(mockUnit, target)).toBe(false);
+ });
+
+ it("should return true if the value is equal to the target value for a specific unit", () => {
+ const value = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ const target = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ expect(value.geqUnit("lovelace", target)).toBe(true);
+ expect(value.geqUnit(mockUnit, target)).toBe(true);
+ });
+
+ it("should return false if the unit does not exist in value.value", () => {
+ const value = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ const target = new MeshValue({ somethingElse: 5n });
+ expect(value.geqUnit("somethingElse", target)).toBe(false);
+ });
+ });
+ describe("leq", () => {
+ it("should return true if the value is less than or equal to the target value for a specific unit", () => {
+ const value = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ const target = new MeshValue({ lovelace: 30n, [mockUnit]: 15n });
+ expect(value.leq(target)).toBe(true);
+ });
+
+ it("should return false if the value is greater than the target value for a specific unit", () => {
+ const value = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ const target = new MeshValue({ lovelace: 10n, [mockUnit]: 5n });
+ expect(value.leq(target)).toBe(false);
+ });
+
+ it("should return true if the value is equal to the target value for a specific unit", () => {
+ const value = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ const target = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ expect(value.leq(target)).toBe(true);
+ });
+ });
+ describe("leqUnit", () => {
+ it("should return true if the value is less than or equal to the target value for a specific unit", () => {
+ const value = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ const target = new MeshValue({ lovelace: 30n, [mockUnit]: 15n });
+ expect(value.leqUnit("lovelace", target)).toBe(true);
+ expect(value.leqUnit(mockUnit, target)).toBe(true);
+ });
+
+ it("should return false if the value is greater than the target value for a specific unit", () => {
+ const value = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ const target = new MeshValue({ lovelace: 10n, [mockUnit]: 5n });
+ expect(value.leqUnit("lovelace", target)).toBe(false);
+ expect(value.leqUnit(mockUnit, target)).toBe(false);
+ });
+
+ it("should return true if the value is equal to the target value for a specific unit", () => {
+ const value = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ const target = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ expect(value.leqUnit("lovelace", target)).toBe(true);
+ expect(value.leqUnit(mockUnit, target)).toBe(true);
+ });
+
+ it("should return false if the unit does not exist in value.value", () => {
+ const value = new MeshValue({ lovelace: 20n, [mockUnit]: 10n });
+ const target = new MeshValue({ somethingElse: 5n });
+ expect(value.leqUnit("somethingElse", target)).toBe(false);
+ });
+ });
+ describe("isEmpty", () => {
+ it("should return true if the value is empty", () => {
+ const value = new MeshValue();
+ expect(value.isEmpty()).toBe(true);
+ });
+
+ it("should return false if the value is not empty", () => {
+ const value = new MeshValue({ lovelace: 20n });
+ expect(value.isEmpty()).toBe(false);
+ });
+ });
+});
diff --git a/packages/mesh-common/test/data/value/convertor.test.ts b/packages/mesh-common/test/data/value/convertor.test.ts
new file mode 100644
index 00000000..bfff721f
--- /dev/null
+++ b/packages/mesh-common/test/data/value/convertor.test.ts
@@ -0,0 +1,173 @@
+import {
+ Asset,
+ byteString,
+ dict,
+ Dict,
+ Integer,
+ integer,
+ MeshValue,
+ MValue,
+ mValue,
+ Value,
+ value,
+} from "@meshsdk/common";
+
+import { mockUnit } from "./common";
+
+describe("value", () => {
+ it("should create a new Value instance with the correct value", () => {
+ const val: Asset[] = [{ unit: "lovelace", quantity: "1000000" }];
+ const datum: Value = value(val);
+ const nameMap = dict([[byteString(""), integer(1000000)]]);
+ const valMap = dict>([[byteString(""), nameMap]]);
+ expect(JSON.stringify(datum)).toBe(JSON.stringify(valMap));
+ });
+ it("Simple token Value", () => {
+ const val: Asset[] = [
+ {
+ unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc8170074657374696e676e657777616c2e616461",
+ quantity: "345",
+ },
+ ];
+ const datum: Value = value(val);
+ const nameMap = dict([
+ [byteString("74657374696e676e657777616c2e616461"), integer(345)],
+ ]);
+ const valMap = dict>([
+ [
+ byteString("baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc81700"),
+ nameMap,
+ ],
+ ]);
+ expect(JSON.stringify(datum)).toBe(JSON.stringify(valMap));
+ });
+ it("Complex Value", () => {
+ const val: Asset[] = [
+ { unit: "lovelace", quantity: "1000000" },
+ {
+ unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc8170074657374696e676e657777616c2e616461",
+ quantity: "345",
+ },
+ {
+ unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234",
+ quantity: "567",
+ },
+ ];
+ const datum: Value = value(val);
+
+ const nameMap = dict([
+ [byteString("1234"), integer(567)],
+ [byteString("74657374696e676e657777616c2e616461"), integer(345)],
+ ]);
+ const valMap = dict>([
+ [byteString(""), dict([[byteString(""), integer(1000000)]])],
+ [
+ byteString("baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc81700"),
+ nameMap,
+ ],
+ ]);
+ expect(JSON.stringify(datum)).toBe(JSON.stringify(valMap));
+ });
+});
+
+describe("mValue", () => {
+ it("should create a new Value instance with the correct value", () => {
+ const val: Asset[] = [{ unit: "lovelace", quantity: "1000000" }];
+ const datum: MValue = mValue(val);
+ const nameMap = new Map().set("", 1000000);
+ const valMap = new Map().set("", nameMap);
+ expect(JSON.stringify(datum)).toBe(JSON.stringify(valMap));
+ });
+ it("Simple token Value", () => {
+ const val: Asset[] = [
+ {
+ unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc8170074657374696e676e657777616c2e616461",
+ quantity: "345",
+ },
+ ];
+ const datum: MValue = mValue(val);
+ const nameMap = new Map().set("74657374696e676e657777616c2e616461", 345);
+ const valMap = new Map().set(
+ "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc81700",
+ nameMap,
+ );
+ expect(JSON.stringify(datum)).toBe(JSON.stringify(valMap));
+ });
+ it("Complex Value", () => {
+ const val: Asset[] = [
+ { unit: "lovelace", quantity: "1000000" },
+ {
+ unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc8170074657374696e676e657777616c2e616461",
+ quantity: "345",
+ },
+ {
+ unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234",
+ quantity: "567",
+ },
+ ];
+ const datum: MValue = mValue(val);
+
+ const lovelaceMap = new Map().set("", 1000000);
+ const tokenMap = new Map()
+ .set("1234", 567)
+ .set("74657374696e676e657777616c2e616461", 345);
+ const valMap = new Map()
+ .set("", lovelaceMap)
+ .set(
+ "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc81700",
+ tokenMap,
+ );
+ expect(JSON.stringify(datum)).toBe(JSON.stringify(valMap));
+ });
+});
+
+describe("MeshValue class", () => {
+ describe("fromAssets", () => {
+ it("should create a new Value instance with the correct value", () => {
+ const assets: Asset[] = [
+ { unit: mockUnit, quantity: "100" },
+ { unit: "lovelace", quantity: "10" },
+ ];
+ const value = MeshValue.fromAssets(assets);
+ expect(value.value).toEqual({
+ [mockUnit]: BigInt(100),
+ lovelace: BigInt(10),
+ });
+ });
+ });
+ describe("toAssets", () => {
+ test("Simple ADA Value", () => {
+ const val: Asset[] = [{ unit: "lovelace", quantity: "1000000" }];
+ const plutusValue: Value = value(val);
+ const assets: Asset[] = MeshValue.fromValue(plutusValue).toAssets();
+ expect(JSON.stringify(val)).toBe(JSON.stringify(assets));
+ });
+ test("Simple token Value", () => {
+ const val: Asset[] = [
+ {
+ unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc8170074657374696e676e657777616c2e616461",
+ quantity: "345",
+ },
+ ];
+ const plutusValue: Value = value(val);
+ const assets: Asset[] = MeshValue.fromValue(plutusValue).toAssets();
+ expect(JSON.stringify(val)).toBe(JSON.stringify(assets));
+ });
+ test("Complex Value", () => {
+ const val: Asset[] = [
+ { unit: "lovelace", quantity: "1000000" },
+ {
+ unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc817001234",
+ quantity: "567",
+ },
+ {
+ unit: "baefdc6c5b191be372a794cd8d40d839ec0dbdd3c28957267dc8170074657374696e676e657777616c2e616461",
+ quantity: "345",
+ },
+ ];
+ const plutusValue: Value = value(val);
+ const assets: Asset[] = MeshValue.fromValue(plutusValue).toAssets();
+ expect(JSON.stringify(val)).toBe(JSON.stringify(assets));
+ });
+ });
+});
diff --git a/packages/mesh-common/test/data/value/operators.test.ts b/packages/mesh-common/test/data/value/operators.test.ts
new file mode 100644
index 00000000..aac75488
--- /dev/null
+++ b/packages/mesh-common/test/data/value/operators.test.ts
@@ -0,0 +1,153 @@
+import { Asset, MeshValue } from "@meshsdk/common";
+
+import { mockUnit } from "./common";
+
+describe("MeshValue class", () => {
+ describe("addAsset", () => {
+ it("should add a new asset correctly", () => {
+ const value = new MeshValue();
+ const singleAsset: Asset = { unit: mockUnit, quantity: "100" };
+ value.addAsset(singleAsset);
+ expect(value.value).toEqual({ [mockUnit]: BigInt(100) });
+ });
+ it("should add to an existing asset correctly", () => {
+ const value = new MeshValue();
+ const singleAsset: Asset = { unit: mockUnit, quantity: "100" };
+ value.addAsset(singleAsset);
+ value.addAsset(singleAsset);
+ expect(value.value).toEqual({ [mockUnit]: BigInt(200) });
+ });
+ it("should add multiple assets correctly", () => {
+ const value = new MeshValue();
+ const assets: Asset[] = [
+ { unit: mockUnit, quantity: "100" },
+ { unit: "lovelace", quantity: "10" },
+ ];
+ value.addAsset(assets[0]!).addAsset(assets[1]!);
+ expect(value.value).toEqual({
+ [mockUnit]: BigInt(100),
+ lovelace: BigInt(10),
+ });
+ });
+ });
+ describe("addAssets", () => {
+ it("should add multiple assets correctly", () => {
+ const value = new MeshValue();
+ const assets: Asset[] = [
+ { unit: mockUnit, quantity: "100" },
+ { unit: "lovelace", quantity: "10" },
+ { unit: mockUnit, quantity: "100" },
+ { unit: "lovelace", quantity: "10" },
+ ];
+ value.addAssets(assets);
+ expect(value.value).toEqual({
+ [mockUnit]: BigInt(200),
+ lovelace: BigInt(20),
+ });
+ });
+ it("should add multiple assets correctly with different units", () => {
+ const value = new MeshValue();
+ const assets: Asset[] = [
+ { unit: mockUnit, quantity: "100" },
+ { unit: "lovelace", quantity: "10" },
+ { unit: "USDC", quantity: "100" },
+ { unit: "lovelace", quantity: "10" },
+ ];
+ value.addAssets(assets);
+ expect(value.value).toEqual({
+ [mockUnit]: BigInt(100),
+ lovelace: BigInt(20),
+ USDC: BigInt(100),
+ });
+ });
+ });
+ describe("negateAsset", () => {
+ describe("negateAsset", () => {
+ it("should subtract quantity from an existing asset", () => {
+ const value = new MeshValue();
+ value.value = { lovelace: 10n };
+ value.negateAsset({ unit: "lovelace", quantity: "5" });
+ expect(value.value).toEqual({ lovelace: BigInt(5) });
+ });
+
+ it("should remove the asset if the resulting quantity is zero", () => {
+ const value = new MeshValue();
+ value.value = { lovelace: 10n };
+ value.negateAsset({ unit: "lovelace", quantity: "10" });
+ expect(value.value.lovelace).toBeUndefined();
+ });
+
+ it("should allow negative quantity if the subtraction results in negative value", () => {
+ const value = new MeshValue();
+ value.value = { lovelace: 10n };
+ value.negateAsset({ unit: "lovelace", quantity: "15" });
+ expect(Object.keys(value.value).length).toBe(0);
+ });
+
+ it("should add a new asset with negative quantity if the asset does not exist", () => {
+ const value = new MeshValue();
+ value.negateAsset({ unit: "lovelace", quantity: "5" });
+ expect(Object.keys(value.value).length).toBe(0);
+ });
+ });
+ });
+ describe("negateAssets", () => {
+ it("should subtract quantities from existing assets", () => {
+ const value = new MeshValue();
+ value.value = { lovelace: 20n, [mockUnit]: 10n };
+ value.negateAssets([
+ { unit: "lovelace", quantity: "5" },
+ { unit: mockUnit, quantity: "3" },
+ ]);
+ expect(value.value).toEqual({
+ lovelace: BigInt(15),
+ [mockUnit]: BigInt(7),
+ });
+ });
+
+ it("should remove the asset if the resulting quantity is zero", () => {
+ const value = new MeshValue();
+ value.value = { lovelace: 10n, [mockUnit]: 5n };
+ value.negateAssets([
+ { unit: "lovelace", quantity: "10" },
+ { unit: mockUnit, quantity: "5" },
+ ]);
+ expect(Object.keys(value.value).length).toBe(0);
+ });
+
+ it("should allow negative quantity if the subtraction results in negative value", () => {
+ const value = new MeshValue();
+ value.value = { lovelace: 10n, [mockUnit]: 5n };
+ value.negateAssets([
+ { unit: "lovelace", quantity: "15" },
+ { unit: mockUnit, quantity: "10" },
+ ]);
+ expect(Object.keys(value.value).length).toBe(0);
+ });
+ });
+
+ describe("merge", () => {
+ it("should merge two values correctly", () => {
+ const value1 = new MeshValue();
+ value1.value = { lovelace: 20n, [mockUnit]: 10n };
+ const value2 = new MeshValue();
+ value2.value = { lovelace: 10n, [mockUnit]: 5n };
+ expect(value1.merge(value2).value).toEqual({
+ lovelace: 30n,
+ [mockUnit]: 15n,
+ });
+ });
+
+ it("should merge two values correctly with different units", () => {
+ const value1 = new MeshValue();
+ value1.value = { lovelace: 20n, [mockUnit]: 10n };
+ const value2 = new MeshValue();
+ value2.value = { ETH: 10n, [mockUnit]: 5n };
+ expect(value1.merge(value2).value).toEqual({
+ lovelace: 20n,
+ [mockUnit]: 15n,
+ ETH: 10n,
+ });
+ });
+ });
+});
diff --git a/packages/mesh-common/test/utils/bigNum.test.ts b/packages/mesh-common/test/utils/bigNum.test.ts
new file mode 100644
index 00000000..22cd1109
--- /dev/null
+++ b/packages/mesh-common/test/utils/bigNum.test.ts
@@ -0,0 +1,157 @@
+import { BigNum } from "@meshsdk/common";
+
+describe("BigNum class", () => {
+ describe("constructor", () => {
+ it("should get correct new BigNum with number", () => {
+ const bigNum = new BigNum(100);
+ expect(bigNum.value).toBe(BigInt(100));
+ });
+ it("should get correct new BigNum with string", () => {
+ const bigNum = new BigNum("100");
+ expect(bigNum.value).toBe(BigInt(100));
+ });
+ it("should get correct new BigNum with bigint", () => {
+ const bigNum = new BigNum(BigInt(100));
+ expect(bigNum.value).toBe(BigInt(100));
+ });
+ it("should get correct new BigNum without param", () => {
+ const bigNum = new BigNum();
+ expect(bigNum.value).toBe(BigInt(0));
+ });
+ });
+ describe("new", () => {
+ it("should get correct new BigNum with number", () => {
+ const bigNum = BigNum.new(100);
+ expect(bigNum.value).toBe(BigInt(100));
+ });
+ it("should get correct new BigNum with string", () => {
+ const bigNum = BigNum.new("100");
+ expect(bigNum.value).toBe(BigInt(100));
+ });
+ it("should get correct new BigNum with bigint", () => {
+ const bigNum = BigNum.new(BigInt(100));
+ expect(bigNum.value).toBe(BigInt(100));
+ });
+ it("should get correct new BigNum without param", () => {
+ const bigNum = BigNum.new(undefined);
+ expect(bigNum.value).toBe(BigInt(0));
+ });
+ });
+ describe("divFloor", () => {
+ it("should get correct divFloor", () => {
+ const bigNum = new BigNum(100);
+ const other = new BigNum(10);
+ const result = bigNum.divFloor(other);
+ expect(result.value).toBe(BigInt(10));
+ });
+ it("should get correct divFloor with remainder", () => {
+ const bigNum = new BigNum(101);
+ const other = new BigNum(10);
+ const result = bigNum.divFloor(other);
+ expect(result.value).toBe(BigInt(10));
+ });
+ });
+ describe("checkedMul", () => {
+ it("should get correct checkedMul", () => {
+ const bigNum = new BigNum(100);
+ const other = new BigNum(10);
+ const result = bigNum.checkedMul(other);
+ expect(result.value).toBe(BigInt(1000));
+ });
+ it("should get correct checkedMul with negative", () => {
+ const bigNum = new BigNum(100);
+ const other = new BigNum(-10);
+ const result = bigNum.checkedMul(other);
+ expect(result.value).toBe(BigInt(-1000));
+ });
+ });
+ describe("checkedAdd", () => {
+ it("should get correct checkedAdd", () => {
+ const bigNum = new BigNum(100);
+ const other = new BigNum(10);
+ const result = bigNum.checkedAdd(other);
+ expect(result.value).toBe(BigInt(110));
+ });
+ it("should get correct checkedAdd with negative", () => {
+ const bigNum = new BigNum(100);
+ const other = new BigNum(-10);
+ const result = bigNum.checkedAdd(other);
+ expect(result.value).toBe(BigInt(90));
+ });
+ });
+ describe("checkedSub", () => {
+ it("should get correct checkedSub", () => {
+ const bigNum = new BigNum(100);
+ const other = new BigNum(10);
+ const result = bigNum.checkedSub(other);
+ expect(result.value).toBe(BigInt(90));
+ });
+ it("should get correct checkedSub with negative", () => {
+ const bigNum = new BigNum(100);
+ const other = new BigNum(110);
+ const result = bigNum.checkedSub(other);
+ expect(result.value).toBe(BigInt(-10));
+ });
+ });
+ describe("clampedSub", () => {
+ it("should get correct clampedSub", () => {
+ const bigNum = new BigNum(100);
+ const other = new BigNum(10);
+ const result = bigNum.clampedSub(other);
+ expect(result.value).toBe(BigInt(90));
+ });
+ it("should get correct clampedSub with negative", () => {
+ const bigNum = new BigNum(100);
+ const other = new BigNum(110);
+ const result = bigNum.clampedSub(other);
+ expect(result.value).toBe(BigInt(0));
+ });
+ });
+ describe("lessThan", () => {
+ it("should get correct lessThan", () => {
+ const bigNum = new BigNum(100);
+ const other = new BigNum(110);
+ const result = bigNum.lessThan(other);
+ expect(result).toBe(true);
+ });
+ it("should get correct lessThan with equal", () => {
+ const bigNum = new BigNum(100);
+ const other = new BigNum(100);
+ const result = bigNum.lessThan(other);
+ expect(result).toBe(false);
+ });
+ it("should get correct lessThan with greater", () => {
+ const bigNum = new BigNum(100);
+ const other = new BigNum(90);
+ const result = bigNum.lessThan(other);
+ expect(result).toBe(false);
+ });
+ });
+ describe("compare", () => {
+ it("should get correct compare", () => {
+ const bigNum = new BigNum(100);
+ const other = new BigNum(110);
+ const result = bigNum.compare(other);
+ expect(result).toBe(-1);
+ });
+ it("should get correct compare with equal", () => {
+ const bigNum = new BigNum(100);
+ const other = new BigNum(100);
+ const result = bigNum.compare(other);
+ expect(result).toBe(0);
+ });
+ it("should get correct compare with greater", () => {
+ const bigNum = new BigNum(100);
+ const other = new BigNum(90);
+ const result = bigNum.compare(other);
+ expect(result).toBe(1);
+ });
+ });
+ describe("toString", () => {
+ it("should get correct toString", () => {
+ const bigNum = new BigNum(100);
+ const result = bigNum.toString();
+ expect(result).toBe("100");
+ });
+ });
+});
diff --git a/packages/mesh-contract/package.json b/packages/mesh-contract/package.json
index 135cc3d4..24d7121e 100644
--- a/packages/mesh-contract/package.json
+++ b/packages/mesh-contract/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/contract",
- "version": "1.6.1",
+ "version": "1.6.2",
"description": "",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
diff --git a/packages/mesh-contract/src/common.ts b/packages/mesh-contract/src/common.ts
index cb87309f..5562367f 100644
--- a/packages/mesh-contract/src/common.ts
+++ b/packages/mesh-contract/src/common.ts
@@ -164,20 +164,24 @@ export class MeshTxInitiator {
};
protected _getUtxoByTxHash = async (
- scriptCbor: string,
txHash: string,
+ scriptCbor?: string,
): Promise => {
if (this.fetcher) {
const utxos = await this.fetcher?.fetchUTxOs(txHash);
- const scriptAddr = v2ScriptToBech32(
- scriptCbor,
- undefined,
- this.networkId,
- );
+ let scriptUtxo = utxos[0];
- const scriptUtxo =
- utxos.filter((utxo) => utxo.output.address === scriptAddr)[0] ||
- utxos[0];
+ if (scriptCbor) {
+ const scriptAddr = v2ScriptToBech32(
+ scriptCbor,
+ undefined,
+ this.networkId,
+ );
+ scriptUtxo =
+ utxos.filter((utxo) => utxo.output.address === scriptAddr)[0] ||
+ utxos[0];
+ }
+
return scriptUtxo;
}
diff --git a/packages/mesh-contract/src/escrow/offchain.ts b/packages/mesh-contract/src/escrow/offchain.ts
index 892ed333..8530ef32 100644
--- a/packages/mesh-contract/src/escrow/offchain.ts
+++ b/packages/mesh-contract/src/escrow/offchain.ts
@@ -5,11 +5,11 @@ import {
conStr1,
mConStr1,
mConStr2,
- parsePlutusValueToAssets,
PubKeyAddress,
pubKeyAddress,
Value,
value,
+ MeshValue
} from "@meshsdk/common";
import {
Asset,
@@ -113,8 +113,8 @@ export class MeshEscrowContract extends MeshTxInitiator {
const initiatorAddress = serializeAddressObj(initiatorAddressObj);
const recipientAddress = serializeAddressObj(recipientAddressObj!);
- const initiatorToReceive = parsePlutusValueToAssets(initiatorAmount);
- const recipientToReceive = parsePlutusValueToAssets(recipientAmount!);
+ const initiatorToReceive = MeshValue.fromValue(initiatorAmount).toAssets();
+ const recipientToReceive = MeshValue.fromValue(recipientAmount!).toAssets();
this.mesh
.txOut(initiatorAddress, initiatorToReceive)
.txOut(recipientAddress, recipientToReceive);
@@ -164,7 +164,7 @@ export class MeshEscrowContract extends MeshTxInitiator {
depositAmount,
);
- const inputAssets = parsePlutusValueToAssets(inputDatum.fields[1]);
+ const inputAssets = MeshValue.fromValue(inputDatum.fields[1]).toAssets();
const escrowAmount = mergeAssets([...depositAmount, ...inputAssets]);
await this.mesh
@@ -218,8 +218,8 @@ export class MeshEscrowContract extends MeshTxInitiator {
] = inputDatum.fields;
const initiatorAddress = serializeAddressObj(initiatorAddressObj);
const recipientAddress = serializeAddressObj(recipientAddressObj);
- const initiatorToReceive = parsePlutusValueToAssets(recipientAmount);
- const recipientToReceive = parsePlutusValueToAssets(initiatorAmount);
+ const initiatorToReceive = MeshValue.fromValue(recipientAmount).toAssets();
+ const recipientToReceive = MeshValue.fromValue(initiatorAmount).toAssets();
await this.mesh
.spendingPlutusScriptV2()
@@ -249,6 +249,6 @@ export class MeshEscrowContract extends MeshTxInitiator {
};
getUtxoByTxHash = async (txHash: string): Promise => {
- return await this._getUtxoByTxHash(this.scriptCbor, txHash);
+ return await this._getUtxoByTxHash(txHash, this.scriptCbor);
};
}
diff --git a/packages/mesh-contract/src/giftcard/offchain.ts b/packages/mesh-contract/src/giftcard/offchain.ts
index dae67bae..379edcf4 100644
--- a/packages/mesh-contract/src/giftcard/offchain.ts
+++ b/packages/mesh-contract/src/giftcard/offchain.ts
@@ -27,12 +27,17 @@ export class MeshGiftCardContract extends MeshTxInitiator {
tokenNameHex: string = "";
paramUtxo: UTxO["input"] = { outputIndex: 0, txHash: "" };
- giftCardCbor = (tokenNameHex: string, utxoTxHash: string, utxoTxId: number) =>
- applyParamsToScript(
+ giftCardCbor = (
+ tokenNameHex: string,
+ utxoTxHash: string,
+ utxoTxId: number,
+ ) => {
+ return applyParamsToScript(
blueprint.validators[0]!.compiledCode,
[builtinByteString(tokenNameHex), txOutRef(utxoTxHash, utxoTxId)],
"JSON",
);
+ };
redeemCbor = (tokenNameHex: string, policyId: string) =>
applyParamsToScript(blueprint.validators[1]!.compiledCode, [
@@ -167,8 +172,7 @@ export class MeshGiftCardContract extends MeshTxInitiator {
};
getUtxoByTxHash = async (txHash: string): Promise => {
- const { redeemScript } = this.getScripts();
- return await this._getUtxoByTxHash(redeemScript, txHash);
+ return await this._getUtxoByTxHash(txHash);
};
private getScripts = () => {
diff --git a/packages/mesh-contract/src/hello-world/offchain.ts b/packages/mesh-contract/src/hello-world/offchain.ts
index 8cbccf5f..df9048be 100644
--- a/packages/mesh-contract/src/hello-world/offchain.ts
+++ b/packages/mesh-contract/src/hello-world/offchain.ts
@@ -19,6 +19,6 @@ export class MeshHelloWorldContract extends MeshTxInitiator {
}
getUtxoByTxHash = async (txHash: string): Promise => {
- return await this._getUtxoByTxHash(this.scriptCbor, txHash);
+ return await this._getUtxoByTxHash(txHash, this.scriptCbor);
};
}
diff --git a/packages/mesh-contract/src/marketplace/offchain.ts b/packages/mesh-contract/src/marketplace/offchain.ts
index ab1fc487..7e943f3c 100644
--- a/packages/mesh-contract/src/marketplace/offchain.ts
+++ b/packages/mesh-contract/src/marketplace/offchain.ts
@@ -240,6 +240,6 @@ export class MeshMarketplaceContract extends MeshTxInitiator {
};
getUtxoByTxHash = async (txHash: string): Promise => {
- return await this._getUtxoByTxHash(this.scriptCbor, txHash);
+ return await this._getUtxoByTxHash(txHash, this.scriptCbor);
};
}
diff --git a/packages/mesh-contract/src/swap/offchain.ts b/packages/mesh-contract/src/swap/offchain.ts
index 47c60874..40abc2b0 100644
--- a/packages/mesh-contract/src/swap/offchain.ts
+++ b/packages/mesh-contract/src/swap/offchain.ts
@@ -4,12 +4,12 @@ import {
ConStr0,
mConStr0,
mConStr1,
- parsePlutusValueToAssets,
pubKeyAddress,
PubKeyAddress,
UTxO,
value,
Value,
+ MeshValue
} from "@meshsdk/common";
import {
deserializeAddress,
@@ -89,7 +89,7 @@ export class MeshSwapContract extends MeshTxInitiator {
.spendingReferenceTxInInlineDatumPresent()
.spendingReferenceTxInRedeemerValue(mConStr1([]))
.txInScript(this.scriptCbor)
- .txOut(initiatorAddress, parsePlutusValueToAssets(initiatorToReceive))
+ .txOut(initiatorAddress, MeshValue.fromValue(initiatorToReceive).toAssets())
.changeAddress(walletAddress)
.txInCollateral(
collateral.input.txHash,
@@ -134,6 +134,6 @@ export class MeshSwapContract extends MeshTxInitiator {
};
getUtxoByTxHash = async (txHash: string): Promise => {
- return await this._getUtxoByTxHash(this.scriptCbor, txHash);
+ return await this._getUtxoByTxHash(txHash, this.scriptCbor);
};
}
diff --git a/packages/mesh-contract/src/vesting/offchain.ts b/packages/mesh-contract/src/vesting/offchain.ts
index dea32460..c5ebe3c8 100644
--- a/packages/mesh-contract/src/vesting/offchain.ts
+++ b/packages/mesh-contract/src/vesting/offchain.ts
@@ -112,6 +112,6 @@ export class MeshVestingContract extends MeshTxInitiator {
};
getUtxoByTxHash = async (txHash: string): Promise => {
- return await this._getUtxoByTxHash(this.scriptCbor, txHash);
+ return await this._getUtxoByTxHash(txHash, this.scriptCbor);
};
}
diff --git a/packages/mesh-core-csl/package.json b/packages/mesh-core-csl/package.json
index d212607d..808c36b9 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.6.1",
+ "version": "1.6.2",
"description": "",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
@@ -20,10 +20,10 @@
"build:mesh": "tsup src/index.ts --format esm,cjs --dts",
"dev": "tsup src/index.ts --format esm,cjs --watch --dts",
"lint": "eslint",
- "test": "jest --verbose",
"clean": "rm -rf .turbo && rm -rf dist && rm -rf node_modules",
"format": "prettier --check . --ignore-path ../../.gitignore",
- "build:docs": "typedoc src/index.ts --json ../../apps/docs/src/data/mesh-core-csl.json"
+ "build:docs": "typedoc src/index.ts --json ../../apps/docs/src/data/mesh-core-csl.json",
+ "test": "jest"
},
"browser": {
"@sidan-lab/sidan-csl-rs-nodejs": "@sidan-lab/sidan-csl-rs-browser"
diff --git a/packages/mesh-core-csl/src/core/serializer.ts b/packages/mesh-core-csl/src/core/serializer.ts
index 97f07c59..c535498e 100644
--- a/packages/mesh-core-csl/src/core/serializer.ts
+++ b/packages/mesh-core-csl/src/core/serializer.ts
@@ -26,10 +26,10 @@ import {
deserializePlutusScript,
resolveDataHash,
resolveEd25519KeyHash,
- resolvePoolId,
resolvePrivateKey,
resolveRewardAddress,
resolveScriptRef,
+ serializePoolId,
toNativeScript,
} from "../deser";
import {
@@ -43,12 +43,17 @@ import { meshTxBuilderBodyToObj } from "./adaptor";
import { builderDataToCbor } from "./adaptor/data";
export class CSLSerializer implements IMeshTxSerializer {
+ /**
+ * Set to true to enable verbose logging for the txBodyJson prior going into build
+ */
+ verbose: boolean;
protocolParams: Protocol;
meshTxBuilderBody: MeshTxBuilderBody = emptyTxBuilderBody();
- constructor(protocolParams?: Protocol) {
+ constructor(protocolParams?: Protocol, verbose = false) {
this.protocolParams = protocolParams || DEFAULT_PROTOCOL_PARAMETERS;
+ this.verbose = verbose;
}
serializeTxBody(
@@ -59,7 +64,9 @@ export class CSLSerializer implements IMeshTxSerializer {
const params = JSONbig.stringify(protocolParams || this.protocolParams);
- console.log("txBodyJson", txBodyJson);
+ if (this.verbose) {
+ console.log("txBodyJson", txBodyJson);
+ }
const txBuildResult = csl.js_serialize_tx_body(txBodyJson, params);
if (txBuildResult.get_status() !== "success") {
throw new Error(txBuildResult.get_data());
@@ -85,6 +92,10 @@ export class CSLSerializer implements IMeshTxSerializer {
return serialzeAddress(address, networkId);
}
+ serializePoolId(hash: string): string {
+ return serializePoolId(hash);
+ }
+
deserializer: IDeserializer = {
key: {
deserializeAddress: function (bech32: string): DeserializedAddress {
@@ -112,6 +123,11 @@ export class CSLSerializer implements IMeshTxSerializer {
return { scriptHash, scriptCbor: script.code };
},
},
+ cert: {
+ deserializePoolId: function (poolId: string): string {
+ return resolveEd25519KeyHash(poolId);
+ },
+ },
};
resolver: IResolver = {
@@ -147,10 +163,5 @@ export class CSLSerializer implements IMeshTxSerializer {
return resolveScriptRef(script);
},
},
- pool: {
- resolvePoolId: function (hash: string): string {
- return resolvePoolId(hash);
- },
- },
};
}
diff --git a/packages/mesh-core-csl/src/deser/resolver.ts b/packages/mesh-core-csl/src/deser/resolver.ts
index efc11b80..6b9a6ffa 100644
--- a/packages/mesh-core-csl/src/deser/resolver.ts
+++ b/packages/mesh-core-csl/src/deser/resolver.ts
@@ -122,7 +122,7 @@ export const resolveNativeScriptHex = (script: NativeScript) => {
return toNativeScript(script).to_hex();
};
-export const resolvePoolId = (hash: string) => {
+export const serializePoolId = (hash: string) => {
return csl.Ed25519KeyHash.from_hex(hash).to_bech32("pool1");
};
diff --git a/packages/mesh-core-csl/test/core/builder.test.ts b/packages/mesh-core-csl/test/core/builder.test.ts
index 7c02467a..ed1836ca 100644
--- a/packages/mesh-core-csl/test/core/builder.test.ts
+++ b/packages/mesh-core-csl/test/core/builder.test.ts
@@ -3,8 +3,7 @@ import {
DEFAULT_PROTOCOL_PARAMETERS,
MeshTxBuilderBody,
} from "@meshsdk/common";
-
-import { CSLSerializer } from "../../src";
+import { CSLSerializer } from "@meshsdk/core-csl";
describe("Builder", () => {
test("serializeTxBody - send lovelace", () => {
diff --git a/packages/mesh-core-csl/test/utils/address.test.ts b/packages/mesh-core-csl/test/utils/address.test.ts
index fb02f4c5..74c8f6db 100644
--- a/packages/mesh-core-csl/test/utils/address.test.ts
+++ b/packages/mesh-core-csl/test/utils/address.test.ts
@@ -1,10 +1,9 @@
import { pubKeyAddress, scriptAddress } from "@meshsdk/common";
-
import {
deserializeBech32Address,
scriptHashToBech32,
serializeAddressObj,
-} from "../../src";
+} from "@meshsdk/core-csl";
describe("Address", () => {
test("deserializeBech32Address", () => {
diff --git a/packages/mesh-core-csl/test/utils/aiken.test.ts b/packages/mesh-core-csl/test/utils/aiken.test.ts
index a77a39cf..24e89920 100644
--- a/packages/mesh-core-csl/test/utils/aiken.test.ts
+++ b/packages/mesh-core-csl/test/utils/aiken.test.ts
@@ -1,6 +1,8 @@
import { builtinByteString } from "@meshsdk/common";
-
-import { applyParamsToScript, deserializeBech32Address } from "../../src";
+import {
+ applyParamsToScript,
+ deserializeBech32Address,
+} from "@meshsdk/core-csl";
describe("Aiken", () => {
test("applyParamsToScript 1", () => {
diff --git a/packages/mesh-core-csl/test/utils/scripts.test.ts b/packages/mesh-core-csl/test/utils/scripts.test.ts
index fe26894a..7204d523 100644
--- a/packages/mesh-core-csl/test/utils/scripts.test.ts
+++ b/packages/mesh-core-csl/test/utils/scripts.test.ts
@@ -1,4 +1,4 @@
-import { applyParamsToScript, getV2ScriptHash } from "../../src";
+import { applyParamsToScript, getV2ScriptHash } from "@meshsdk/core-csl";
describe("Scripts", () => {
test("getV2ScriptHash", () => {
diff --git a/packages/mesh-core-csl/test/utils/transaction.test.ts b/packages/mesh-core-csl/test/utils/transaction.test.ts
index a377425d..f121b41b 100644
--- a/packages/mesh-core-csl/test/utils/transaction.test.ts
+++ b/packages/mesh-core-csl/test/utils/transaction.test.ts
@@ -1,4 +1,4 @@
-import { calculateTxHash } from "../../src";
+import { calculateTxHash } from "@meshsdk/core-csl";
describe("Transaction", () => {
test("calculateTxHash", () => {
diff --git a/packages/mesh-core-cst/package.json b/packages/mesh-core-cst/package.json
index 3f816be1..ef2b784f 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.6.1",
+ "version": "1.6.2",
"description": "",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
@@ -20,7 +20,7 @@
"build:mesh": "tsup src/index.ts --format esm,cjs --dts --minify",
"dev": "tsup src/index.ts --format esm,cjs --watch --dts",
"lint": "eslint",
- "test": "jest --verbose",
+ "test": "jest",
"clean": "rm -rf .turbo && rm -rf dist && rm -rf node_modules",
"format": "prettier --check . --ignore-path ../../.gitignore"
},
diff --git a/packages/mesh-core-cst/src/resolvers/index.ts b/packages/mesh-core-cst/src/resolvers/index.ts
index 930970d1..a5fb4a05 100644
--- a/packages/mesh-core-cst/src/resolvers/index.ts
+++ b/packages/mesh-core-cst/src/resolvers/index.ts
@@ -93,7 +93,6 @@ export const resolvePoolId = (hash: string) => {
};
export const resolvePrivateKey = (words: string[]) => {
- console.log(words);
return "not implemented";
};
diff --git a/packages/mesh-core-cst/src/serializer/index.ts b/packages/mesh-core-cst/src/serializer/index.ts
index 3c85deaa..8536ee46 100644
--- a/packages/mesh-core-cst/src/serializer/index.ts
+++ b/packages/mesh-core-cst/src/serializer/index.ts
@@ -96,6 +96,9 @@ export class CardanoSDKSerializer implements IMeshTxSerializer {
);
this.txWitnessSet = new TransactionWitnessSet();
}
+ serializePoolId(hash: string): string {
+ throw new Error("Method not implemented.");
+ }
serializeAddress(address: DeserializedAddress, networkId?: 0 | 1): string {
throw new Error("Method not implemented.");
@@ -130,6 +133,11 @@ export class CardanoSDKSerializer implements IMeshTxSerializer {
throw new Error("Function not implemented.");
},
},
+ cert: {
+ deserializePoolId: function (poolId: string): string {
+ throw new Error("Function not implemented.");
+ },
+ },
};
resolver: IResolver = {
@@ -192,11 +200,6 @@ export class CardanoSDKSerializer implements IMeshTxSerializer {
throw new Error("Function not implemented.");
},
},
- pool: {
- resolvePoolId: function (hash: string): string {
- throw new Error("Function not implemented.");
- },
- },
};
serializeTxBody = (
@@ -647,21 +650,27 @@ export class CardanoSDKSerializer implements IMeshTxSerializer {
case "V1":
this.scriptsProvided.add(
Script.newPlutusV1Script(
- PlutusV1Script.fromCbor(HexBlob(plutusScriptSource.script.code)),
+ PlutusV1Script.fromCbor(
+ HexBlob(plutusScriptSource.script.code),
+ ),
),
);
break;
case "V2":
this.scriptsProvided.add(
Script.newPlutusV2Script(
- PlutusV2Script.fromCbor(HexBlob(plutusScriptSource.script.code)),
+ PlutusV2Script.fromCbor(
+ HexBlob(plutusScriptSource.script.code),
+ ),
),
);
break;
case "V3":
this.scriptsProvided.add(
Script.newPlutusV3Script(
- PlutusV3Script.fromCbor(HexBlob(plutusScriptSource.script.code)),
+ PlutusV3Script.fromCbor(
+ HexBlob(plutusScriptSource.script.code),
+ ),
),
);
break;
diff --git a/packages/mesh-core-cst/src/stricahq/index.ts b/packages/mesh-core-cst/src/stricahq/index.ts
index b9910e05..7d5a7cb7 100644
--- a/packages/mesh-core-cst/src/stricahq/index.ts
+++ b/packages/mesh-core-cst/src/stricahq/index.ts
@@ -1,17 +1,4 @@
-import strica from "@stricahq/bip32ed25519"; // This works with broswer, but not node
-
-// import * as strica from "@stricahq/bip32ed25519"; // This works with node, but not browser
-
-// let strica: any;
-
-// if (typeof window !== "undefined") {
-// // Browser environment
-// strica = await import("@stricahq/bip32ed25519");
-// } else {
-// // Node.js environment
-// strica = require("@stricahq/bip32ed25519");
-// }
-
+import strica from "@stricahq/bip32ed25519";
import hash from "hash.js";
class PrivateKey extends strica.PrivateKey {
diff --git a/packages/mesh-core-cst/test/resolvers.test.ts b/packages/mesh-core-cst/test/resolvers.test.ts
index 94ab149b..115aef10 100644
--- a/packages/mesh-core-cst/test/resolvers.test.ts
+++ b/packages/mesh-core-cst/test/resolvers.test.ts
@@ -3,7 +3,6 @@ import {
PlutusScript,
resolveFingerprint,
} from "@meshsdk/common";
-
import {
resolveDataHash,
resolveNativeScriptAddress,
@@ -11,10 +10,9 @@ import {
resolvePaymentKeyHash,
resolvePlutusScriptAddress,
resolvePlutusScriptHash,
- resolvePrivateKey,
resolveRewardAddress,
resolveStakeKeyHash,
-} from "../src";
+} from "@meshsdk/core-cst";
describe("resolveDataHash", () => {
it("should return correct data", () => {
diff --git a/packages/mesh-core-cst/test/utils/converter.test.ts b/packages/mesh-core-cst/test/utils/converter.test.ts
index bb57e248..076e83f4 100644
--- a/packages/mesh-core-cst/test/utils/converter.test.ts
+++ b/packages/mesh-core-cst/test/utils/converter.test.ts
@@ -1,6 +1,5 @@
import { PlutusScript } from "@meshsdk/common";
-
-import { fromScriptRef } from "../../src/utils/converter";
+import { fromScriptRef } from "@meshsdk/core-cst";
describe("fromScriptRef", () => {
// it("with native script cbor should return correct NativeScript", () => {});
diff --git a/packages/mesh-core/package.json b/packages/mesh-core/package.json
index 2d4603e0..e2618ec0 100644
--- a/packages/mesh-core/package.json
+++ b/packages/mesh-core/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/core",
- "version": "1.6.1",
+ "version": "1.6.2",
"description": "",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
diff --git a/packages/mesh-core/src/utils/deserializer.ts b/packages/mesh-core/src/utils/deserializer.ts
index 9c6e0e18..db4db004 100644
--- a/packages/mesh-core/src/utils/deserializer.ts
+++ b/packages/mesh-core/src/utils/deserializer.ts
@@ -21,3 +21,11 @@ export const deserializeAddress = (bech32: string): DeserializedAddress =>
*/
export const deserializeDatum = (datumCbor: string): T =>
core.parseDatumCbor(datumCbor);
+
+/**
+ * Deserialize a script from a poolxxxx to Ed25519 key hash
+ * @param poolId The poolxxxx bech32 pool id
+ * @returns The Ed25519 key hash
+ */
+export const deserializePoolId = (poolId: string): string =>
+ core.resolveEd25519KeyHash(poolId);
diff --git a/packages/mesh-core/src/utils/resolver.ts b/packages/mesh-core/src/utils/resolver.ts
index 7434c787..03b589b1 100644
--- a/packages/mesh-core/src/utils/resolver.ts
+++ b/packages/mesh-core/src/utils/resolver.ts
@@ -56,13 +56,6 @@ export const resolveScriptHash = (
return core.deserializePlutusScript(scriptCode, version).hash().to_hex();
};
-/**
- * Resolve the pool id from hash
- * @param hash The pool hash
- * @returns The pool id
- */
-export const resolvePoolId = (hash: string) => core.resolvePoolId(hash);
-
/**
* Resolve the Ed25519 key hash from bech32 address
* @param bech32 The bech32 address
@@ -71,6 +64,14 @@ export const resolvePoolId = (hash: string) => core.resolvePoolId(hash);
export const resolveRewardAddress = (bech32: string) =>
core.resolveRewardAddress(bech32);
+/**
+ * Resolve the stake key hash from bech32 address
+ * @param bech32 The bech32 address, either in addrxxx or stakexxx
+ * @returns The stake key hash
+ */
+export const resolveStakeKeyHash = (bech32: string) =>
+ core.resolveStakeKeyHash(bech32);
+
// ------------------- Deprecated zone ---------------------
/**
@@ -107,12 +108,6 @@ export const resolvePaymentKeyHash = (bech32: string) =>
export const resolvePlutusScriptHash = (bech32: string) =>
core.deserializeBech32Address(bech32).scriptHash;
-/**
- * Deprecated - use `deserializeAddress` instead
- */
-export const resolveStakeKeyHash = (bech32: string) =>
- core.deserializeBech32Address(bech32).stakeCredentialHash;
-
/**
* Deprecated - this is more used with the low level process inside Mesh
*
@@ -120,3 +115,8 @@ export const resolveStakeKeyHash = (bech32: string) =>
*/
export const resolveScriptRef = (script: NativeScript | PlutusScript) =>
core.resolveScriptRef(script);
+
+/**
+ * Deprecated - use `serializePoolId` instead
+ */
+export const resolvePoolId = (hash: string) => core.serializePoolId(hash);
diff --git a/packages/mesh-core/src/utils/serializer.ts b/packages/mesh-core/src/utils/serializer.ts
index 6dcd6da1..7cc2ba06 100644
--- a/packages/mesh-core/src/utils/serializer.ts
+++ b/packages/mesh-core/src/utils/serializer.ts
@@ -68,3 +68,10 @@ export const serializePlutusScript = (
export const serializeAddressObj = (address: PubKeyAddress | ScriptAddress) => {
return core.serializeAddressObj(address);
};
+
+/**
+ * Resolve the pool id from hash
+ * @param hash The pool hash
+ * @returns The pool id
+ */
+export const serializePoolId = (hash: string) => core.serializePoolId(hash);
diff --git a/.env.example b/packages/mesh-provider/.env.example
similarity index 100%
rename from .env.example
rename to packages/mesh-provider/.env.example
diff --git a/packages/mesh-provider/package.json b/packages/mesh-provider/package.json
index e244c407..4449ea87 100644
--- a/packages/mesh-provider/package.json
+++ b/packages/mesh-provider/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/provider",
- "version": "1.6.1",
+ "version": "1.6.2",
"description": "",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
@@ -21,7 +21,7 @@
"dev": "tsup src/index.ts --format esm,cjs --watch --dts",
"lint": "eslint",
"clean": "rm -rf .turbo && rm -rf dist && rm -rf node_modules",
- "test": "jest --verbose",
+ "test": "jest",
"format": "prettier --check . --ignore-path ../../.gitignore",
"build:docs": "typedoc src/index.ts --json ../../apps/docs/src/data/mesh-providers.json"
},
diff --git a/packages/mesh-provider/src/blockfrost.ts b/packages/mesh-provider/src/blockfrost.ts
index 2444f143..8f8a3af9 100644
--- a/packages/mesh-provider/src/blockfrost.ts
+++ b/packages/mesh-provider/src/blockfrost.ts
@@ -99,7 +99,7 @@ export class BlockfrostProvider implements IFetcher, IListener, ISubmitter {
throw parseHttpError(data);
} catch (error) {
- console.log("error", error);
+ console.error("error", error);
throw parseHttpError(error);
}
}
@@ -196,7 +196,6 @@ export class BlockfrostProvider implements IFetcher, IListener, ISubmitter {
const { data, status } = await this._axiosInstance.get(
`assets/${policyId}${assetName}`,
);
- console.log(3, data)
if (status === 200 || status == 202)
return {
...data.onchain_metadata,
diff --git a/packages/mesh-provider/src/koios.ts b/packages/mesh-provider/src/koios.ts
index 1354c151..1e3cb847 100644
--- a/packages/mesh-provider/src/koios.ts
+++ b/packages/mesh-provider/src/koios.ts
@@ -325,8 +325,6 @@ export class KoiosProvider implements IFetcher, IListener, ISubmitter {
_tx_hashes: [hash],
});
- console.log(88, data);
-
if (status === 200) {
const utxos = data[0].outputs.map((utxo: KoiosUTxO) =>
this.toUTxO(utxo, "undefined"),
diff --git a/packages/mesh-provider/src/maestro.ts b/packages/mesh-provider/src/maestro.ts
index 995dcd24..f1f4d1bd 100644
--- a/packages/mesh-provider/src/maestro.ts
+++ b/packages/mesh-provider/src/maestro.ts
@@ -200,8 +200,6 @@ export class MaestroProvider
const { data: timestampedData, status } = await this._axiosInstance.get(
`assets/${policyId}${assetName}`,
);
-
- console.log(2, timestampedData)
if (status === 200) {
const data = timestampedData.data;
return {
diff --git a/packages/mesh-provider/src/ogmios.ts b/packages/mesh-provider/src/ogmios.ts
index 9705255c..502988bf 100644
--- a/packages/mesh-provider/src/ogmios.ts
+++ b/packages/mesh-provider/src/ogmios.ts
@@ -32,8 +32,6 @@ export class OgmiosProvider implements IEvaluator, ISubmitter {
(response: MessageEvent) => {
try {
const { result } = JSON.parse(response.data);
- console.log(1, 'result', result)
-
if (result.EvaluationResult) {
resolve(
Object.keys(result.EvaluationResult).map((key) => {
diff --git a/packages/mesh-provider/src/yaci.ts b/packages/mesh-provider/src/yaci.ts
index 8f6f581a..4cfd8e4d 100644
--- a/packages/mesh-provider/src/yaci.ts
+++ b/packages/mesh-provider/src/yaci.ts
@@ -380,7 +380,7 @@ export class YaciProvider implements IFetcher, IListener, ISubmitter {
throw parseHttpError(data);
} catch (error) {
- console.log("error", error);
+ console.error("error", error);
throw parseHttpError(error);
}
}
@@ -402,7 +402,7 @@ export class YaciProvider implements IFetcher, IListener, ISubmitter {
throw parseHttpError(data);
} catch (error) {
- console.log("error", error);
+ console.error("error", error);
throw parseHttpError(error);
}
}
diff --git a/packages/mesh-provider/test/blockfrost/evaluator.test.ts b/packages/mesh-provider/test/blockfrost/evaluator.test.ts
index 2a9f6893..3322eb8f 100644
--- a/packages/mesh-provider/test/blockfrost/evaluator.test.ts
+++ b/packages/mesh-provider/test/blockfrost/evaluator.test.ts
@@ -1,6 +1,6 @@
import dotenv from "dotenv";
-import { BlockfrostProvider } from "../../src";
+import { BlockfrostProvider } from "@meshsdk/provider";
dotenv.config();
const apiKey = process.env.BLOCKFROST_API_KEY_PREPROD!;
diff --git a/packages/mesh-provider/test/maestro/evaluator.test.ts b/packages/mesh-provider/test/maestro/evaluator.test.ts
index d3cba2a1..7a92933a 100644
--- a/packages/mesh-provider/test/maestro/evaluator.test.ts
+++ b/packages/mesh-provider/test/maestro/evaluator.test.ts
@@ -1,6 +1,6 @@
import dotenv from "dotenv";
-import { MaestroProvider } from "../../src/maestro";
+import { MaestroProvider } from "@meshsdk/provider";
dotenv.config();
const apiKey = process.env.MAESTRO_API_KEY!;
diff --git a/packages/mesh-react/package.json b/packages/mesh-react/package.json
index ae04c77d..ef7fb748 100644
--- a/packages/mesh-react/package.json
+++ b/packages/mesh-react/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/react",
- "version": "1.6.1",
+ "version": "1.6.2",
"description": "",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
diff --git a/packages/mesh-react/src/cardano-wallet/index.tsx b/packages/mesh-react/src/cardano-wallet/index.tsx
index 0e925ce9..b69c3d8f 100644
--- a/packages/mesh-react/src/cardano-wallet/index.tsx
+++ b/packages/mesh-react/src/cardano-wallet/index.tsx
@@ -1,10 +1,7 @@
import { useEffect, useState } from "react";
-import { Wallet } from "@meshsdk/common";
-import { BrowserWallet } from "@meshsdk/wallet";
-
import Button from "../common/button";
-import { useWallet } from "../hooks";
+import { useWallet, useWalletList } from "../hooks";
import { MenuItem } from "./menu-item";
import { WalletBalance } from "./wallet-balance";
@@ -12,18 +9,20 @@ interface ButtonProps {
label?: string;
onConnected?: Function;
isDark?: boolean;
+ nufiNetwork?: string;
}
export const CardanoWallet = ({
label = "Connect Wallet",
onConnected = undefined,
isDark = false,
+ nufiNetwork = "preprod",
}: ButtonProps) => {
const [isDarkMode, setIsDarkMode] = useState(false);
const [hideMenuList, setHideMenuList] = useState(true);
- const [wallets, setWallets] = useState([]);
const { connect, connecting, connected, disconnect, name } = useWallet();
+ const wallets = useWalletList({ nufiNetwork });
useEffect(() => {
if (connected && onConnected) {
@@ -31,19 +30,15 @@ export const CardanoWallet = ({
}
}, [connected]);
- useEffect(() => {
- setWallets(BrowserWallet.getInstalledWallets());
- }, []);
-
useEffect(() => {
setIsDarkMode(isDark);
}, [isDark]);
return (
setHideMenuList(false)}
onMouseLeave={() => setHideMenuList(true)}
+ style={{ width: "min-content", zIndex: 50 }}
>
wallet.name === name)}
+ wallet={wallets.find((wallet) => wallet.id === name)}
/>
{
- connect(wallet.name);
+ connect(wallet.id);
setHideMenuList(!hideMenuList);
}}
- active={name === wallet.name}
+ active={name === wallet.id}
/>
))}
{/*
void;
+ onMouseEnter?: () => void;
+ onMouseLeave?: () => void;
}) {
return (
setHideMenuList && setHideMenuList(!hideMenuList)}
+ onMouseEnter={onMouseEnter}
+ onMouseLeave={onMouseLeave}
>
{children}
diff --git a/packages/mesh-react/src/hooks/useWalletList.ts b/packages/mesh-react/src/hooks/useWalletList.ts
index 480f01e8..246707bd 100644
--- a/packages/mesh-react/src/hooks/useWalletList.ts
+++ b/packages/mesh-react/src/hooks/useWalletList.ts
@@ -3,11 +3,18 @@ import { useEffect, useState } from "react";
import type { Wallet } from "@meshsdk/common";
import { BrowserWallet } from "@meshsdk/wallet";
-export const useWalletList = () => {
+export const useWalletList = ({
+ nufiNetwork = "preprod",
+}: {
+ nufiNetwork?: string;
+} = {}) => {
const [wallets, setWallets] = useState([]);
useEffect(() => {
- setWallets(BrowserWallet.getInstalledWallets());
+ async function get() {
+ setWallets(await BrowserWallet.getAvailableWallets({ nufiNetwork }));
+ }
+ get();
}, []);
return wallets;
diff --git a/packages/mesh-transaction/package.json b/packages/mesh-transaction/package.json
index a3fe0f6a..55201c07 100644
--- a/packages/mesh-transaction/package.json
+++ b/packages/mesh-transaction/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/transaction",
- "version": "1.6.1",
+ "version": "1.6.2",
"description": "",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
diff --git a/packages/mesh-transaction/src/mesh-tx-builder/index.ts b/packages/mesh-transaction/src/mesh-tx-builder/index.ts
index 547e774f..42d17e3a 100644
--- a/packages/mesh-transaction/src/mesh-tx-builder/index.ts
+++ b/packages/mesh-transaction/src/mesh-tx-builder/index.ts
@@ -105,7 +105,6 @@ export class MeshTxBuilder extends MeshTxBuilderCore {
this._protocolParams,
);
}
- console.log(txHex);
this.txHex = txHex;
return txHex;
diff --git a/packages/mesh-transaction/src/transaction/index.ts b/packages/mesh-transaction/src/transaction/index.ts
index 0113311c..29c2d872 100644
--- a/packages/mesh-transaction/src/transaction/index.ts
+++ b/packages/mesh-transaction/src/transaction/index.ts
@@ -1,32 +1,34 @@
import {
Action,
Asset,
+ AssetMetadata,
Budget,
CIP68_100,
CIP68_222,
- DEFAULT_REDEEMER_BUDGET,
Data,
+ DEFAULT_REDEEMER_BUDGET,
+ hexToString,
IInitiator,
+ metadataToCip68,
Mint,
NativeScript,
- POLICY_ID_LENGTH,
PlutusScript,
+ POLICY_ID_LENGTH,
PoolParams,
Recipient,
+ stringToHex,
SUPPORTED_TOKENS,
Token,
UTxO,
- hexToString,
- metadataToCip68,
- stringToHex,
} from "@meshsdk/common";
-import { MeshTxBuilder, MeshTxBuilderOptions } from "../mesh-tx-builder";
import {
deserializeNativeScript,
deserializePlutusScript,
fromScriptRef,
} from "@meshsdk/core-cst";
+import { MeshTxBuilder, MeshTxBuilderOptions } from "../mesh-tx-builder";
+
export interface TransactionOptions extends MeshTxBuilderOptions {
initiator: IInitiator;
}
@@ -145,7 +147,7 @@ export class Transaction {
input.input.txHash,
input.input.outputIndex,
input.output.amount,
- input.output.address
+ input.output.address,
);
});
@@ -162,7 +164,7 @@ export class Transaction {
inputs.forEach((input) => {
this.txBuilder.readOnlyTxInReference(
input.input.txHash,
- input.input.outputIndex
+ input.input.outputIndex,
);
});
@@ -178,14 +180,14 @@ export class Transaction {
setNativeScriptInput(script: NativeScript, utxo: UTxO): Transaction {
const { scriptCbor } =
this.txBuilder.serializer.deserializer.script.deserializeNativeScript(
- script
+ script,
);
this.txBuilder
.txIn(
utxo.input.txHash,
utxo.input.outputIndex,
utxo.output.amount,
- utxo.output.address
+ utxo.output.address,
)
.txInScript(scriptCbor!);
@@ -213,7 +215,7 @@ export class Transaction {
value.input.txHash,
value.input.outputIndex,
value.output.amount,
- value.output.address
+ value.output.address,
)
.txInScript(script.code)
.txInRedeemerValue(red.data, "Mesh", red.budget);
@@ -235,12 +237,12 @@ export class Transaction {
value.input.txHash,
value.input.outputIndex,
value.output.amount,
- value.output.address
+ value.output.address,
)
.spendingTxInReference(
script.input.txHash,
script.input.outputIndex,
- script.output.scriptHash
+ script.output.scriptHash,
)
.txInRedeemerValue(red.data, "Mesh", red.budget);
}
@@ -267,7 +269,7 @@ export class Transaction {
mintAsset(
forgeScript: string | PlutusScript | UTxO,
mint: Mint,
- redeemer?: Pick & { budget?: Budget }
+ redeemer?: Pick & { budget?: Budget },
): Transaction {
const assetQuantity = mint.assetQuantity;
let assetNameHex = stringToHex(mint.assetName);
@@ -293,13 +295,13 @@ export class Transaction {
case "object":
if (!redeemer)
throw new Error(
- "burnAsset: Redeemer data is required for Plutus minting"
+ "burnAsset: Redeemer data is required for Plutus minting",
);
if ("code" in forgeScript) {
// Burn plutus script assets with provided script
policyId = deserializePlutusScript(
forgeScript.code,
- forgeScript.version
+ forgeScript.version,
)
.hash()
.toString();
@@ -337,7 +339,7 @@ export class Transaction {
.mint(assetQuantity, policyId, assetNameHex)
.mintTxInReference(
forgeScript.input.txHash,
- forgeScript.input.outputIndex
+ forgeScript.input.outputIndex,
)
.mintRedeemerValue(redeemer.data, "Mesh", redeemer.budget);
if (mint.cip68ScriptAddress) {
@@ -345,7 +347,7 @@ export class Transaction {
.mint(assetQuantity, policyId, referenceAssetNameHex)
.mintTxInReference(
forgeScript.input.txHash,
- forgeScript.input.outputIndex
+ forgeScript.input.outputIndex,
)
.mintRedeemerValue(redeemer.data, "Mesh", redeemer.budget);
break;
@@ -355,7 +357,7 @@ export class Transaction {
} else {
// TODO: to implement reference script minting for native script tokens
throw new Error(
- "mintAsset: Reference script minting not implemented"
+ "mintAsset: Reference script minting not implemented",
);
// this.txBuilder
// .mint(assetQuantity, policyId, assetName)
@@ -368,14 +370,6 @@ export class Transaction {
break;
}
- if (mint.metadata && mint.label) {
- this.setMetadata(Number(mint.label), {
- [policyId]: {
- [mint.assetName]: mint.metadata,
- },
- version: 1,
- });
- }
if (mint.recipient) {
this.sendAssets(mint.recipient, [
{ unit: policyId + assetNameHex, quantity: mint.assetQuantity },
@@ -392,9 +386,17 @@ export class Transaction {
unit: policyId + referenceAssetNameHex,
quantity: mint.assetQuantity,
},
- ]
+ ],
);
}
+ if (!mint.cip68ScriptAddress && mint.metadata && mint.label) {
+ if (mint.label === "721" || mint.label === "20") {
+ this.setMetadata(Number(mint.label), {
+ [policyId]: { [mint.assetName]: mint.metadata },
+ });
+ }
+ this.setMetadata(Number(mint.label), mint.metadata);
+ }
return this;
}
@@ -404,7 +406,7 @@ export class Transaction {
burnAsset(
forgeScript: string | PlutusScript | UTxO,
asset: Asset,
- redeemer?: Pick & { budget?: Budget }
+ redeemer?: Pick & { budget?: Budget },
): Transaction {
const assetQuantity = "-" + asset.quantity;
const mint: Mint = {
@@ -443,7 +445,7 @@ export class Transaction {
collateralUtxo.input.txHash,
collateralUtxo.input.outputIndex,
collateralUtxo.output.amount,
- collateralUtxo.output.address
+ collateralUtxo.output.address,
);
});
@@ -511,23 +513,27 @@ export class Transaction {
delegateStake(rewardAddress: string, poolId: string): Transaction {
this.txBuilder.delegateStakeCertificate(
this.txBuilder.serializer.resolver.keys.resolveStakeKeyHash(
- rewardAddress
+ rewardAddress,
),
- this.txBuilder.serializer.resolver.keys.resolveEd25519KeyHash(poolId)
+ this.txBuilder.serializer.resolver.keys.resolveEd25519KeyHash(poolId),
);
return this;
}
deregisterStake(rewardAddress: string): Transaction {
this.txBuilder.deregisterStakeCertificate(
- this.txBuilder.serializer.resolver.keys.resolveStakeKeyHash(rewardAddress)
+ this.txBuilder.serializer.resolver.keys.resolveStakeKeyHash(
+ rewardAddress,
+ ),
);
return this;
}
registerStake(rewardAddress: string): Transaction {
this.txBuilder.registerStakeCertificate(
- this.txBuilder.serializer.resolver.keys.resolveStakeKeyHash(rewardAddress)
+ this.txBuilder.serializer.resolver.keys.resolveStakeKeyHash(
+ rewardAddress,
+ ),
);
return this;
}
@@ -553,7 +559,7 @@ export class Transaction {
return this.txBuilder.complete();
} catch (error) {
throw new Error(
- `[Transaction] An error occurred during build: ${error}.`
+ `[Transaction] An error occurred during build: ${error}.`,
);
}
}
diff --git a/packages/mesh-wallet/package.json b/packages/mesh-wallet/package.json
index d2a45f08..3c0403b8 100644
--- a/packages/mesh-wallet/package.json
+++ b/packages/mesh-wallet/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/wallet",
- "version": "1.6.1",
+ "version": "1.6.2",
"description": "",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
@@ -21,7 +21,7 @@
"dev": "tsup src/index.ts --format esm,cjs --watch --dts",
"lint": "eslint",
"clean": "rm -rf .turbo && rm -rf dist && rm -rf node_modules",
- "test": "jest --verbose",
+ "test": "jest",
"format": "prettier --check . --ignore-path ../../.gitignore",
"build:docs": "typedoc src/index.ts --json ../../apps/docs/src/data/mesh-wallets.json"
},
@@ -29,13 +29,15 @@
"@meshsdk/typescript-config": "*",
"eslint": "^8.57.0",
"tsup": "^8.0.2",
- "typescript": "^5.3.3",
- "typedoc": "^0.26.3"
+ "typedoc": "^0.26.3",
+ "typescript": "^5.3.3"
},
"dependencies": {
"@meshsdk/common": "*",
"@meshsdk/core-cst": "*",
- "@meshsdk/transaction": "*"
+ "@meshsdk/transaction": "*",
+ "@nufi/dapp-client-cardano": "^0.3.1",
+ "@nufi/dapp-client-core": "^0.3.1"
},
"prettier": "@meshsdk/prettier-config",
"publishConfig": {
@@ -49,4 +51,4 @@
"blockchain",
"sdk"
]
-}
\ No newline at end of file
+}
diff --git a/packages/mesh-wallet/src/browser/index.ts b/packages/mesh-wallet/src/browser/index.ts
index 95341f58..a0fc9f10 100644
--- a/packages/mesh-wallet/src/browser/index.ts
+++ b/packages/mesh-wallet/src/browser/index.ts
@@ -30,6 +30,7 @@ import {
} from "@meshsdk/core-cst";
import { Cardano, WalletInstance } from "../types";
+import { checkIfMetamaskInstalled } from "./metamask";
declare global {
interface Window {
@@ -69,7 +70,7 @@ export class BrowserWallet implements IInitiator, ISigner, ISubmitter {
if (_wallet.apiVersion === undefined) continue;
wallets.push({
id: key,
- name: _wallet.name,
+ name: key == "nufiSnap" ? "MetaMask" : _wallet.name,
icon: _wallet.icon,
version: _wallet.apiVersion,
});
@@ -79,6 +80,25 @@ export class BrowserWallet implements IInitiator, ISigner, ISubmitter {
return wallets;
}
+ /**
+ * Returns a list of wallets installed on user's device. Each wallet is an object with the following properties:
+ * - A name is provided to display wallet's name on the user interface.
+ * - A version is provided to display wallet's version on the user interface.
+ * - An icon is provided to display wallet's icon on the user interface.
+ *
+ * @returns a list of wallet names
+ */
+ static async getAvailableWallets({
+ nufiNetwork = "preprod",
+ }: {
+ nufiNetwork?: string;
+ } = {}): Promise {
+ if (window === undefined) return [];
+ await checkIfMetamaskInstalled(nufiNetwork);
+ const wallets = BrowserWallet.getInstalledWallets();
+ return wallets;
+ }
+
/**
* This is the entrypoint to start communication with the user's wallet. The wallet should request the user's permission to connect the web page to the user's wallet, and if permission has been granted, the wallet will be returned and exposing the full API for the dApp to use.
*
@@ -237,7 +257,6 @@ export class BrowserWallet implements IInitiator, ISigner, ISubmitter {
*/
async signTx(unsignedTx: string, partialSign = false): Promise {
const witness = await this._walletInstance.signTx(unsignedTx, partialSign);
- console.log("witness", witness);
return BrowserWallet.addBrowserWitnesses(unsignedTx, witness);
}
diff --git a/packages/mesh-wallet/src/browser/metamask.ts b/packages/mesh-wallet/src/browser/metamask.ts
new file mode 100644
index 00000000..58af1f56
--- /dev/null
+++ b/packages/mesh-wallet/src/browser/metamask.ts
@@ -0,0 +1,46 @@
+import { initNufiDappCardanoSdk } from "@nufi/dapp-client-cardano";
+import nufiCoreSdk from "@nufi/dapp-client-core";
+
+import { Wallet } from "@meshsdk/common";
+
+const nufiDomain: { [key: string]: string } = {
+ production: "https://wallet.nu.fi",
+ mainnet: "https://wallet-staging.nu.fi",
+ preprod: "https://wallet-testnet-staging.nu.fi",
+ preview: "https://wallet-preview-staging.nu.fi",
+};
+
+export function checkIfMetamaskInstalled(
+ network = "preprod",
+): Promise {
+ try {
+ const _nufiCoreSdk = (nufiCoreSdk as any).default;
+
+ if (Object.keys(nufiDomain).includes(network)) {
+ _nufiCoreSdk.init(nufiDomain[network]);
+ } else {
+ _nufiCoreSdk.init(network);
+ }
+
+ return new Promise((resolve) => {
+ _nufiCoreSdk
+ .getApi()
+ .isMetamaskInstalled()
+ .then((isMetamaskInstalled: boolean) => {
+ if (isMetamaskInstalled) {
+ initNufiDappCardanoSdk(_nufiCoreSdk, "snap");
+ resolve({
+ id: "nufiSnap",
+ name: "MetaMask",
+ icon: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBpZD0iTGF5ZXJfMiIgZGF0YS1uYW1lPSJMYXllciAyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNjkuMiAxNjMuNzEiPgogIDxkZWZzPgogICAgPHN0eWxlPgogICAgICAuY2xzLTEgewogICAgICAgIGZpbGw6ICNlMjc2MjU7CiAgICAgIH0KCiAgICAgIC5jbHMtMSwgLmNscy0yLCAuY2xzLTMsIC5jbHMtNCwgLmNscy01LCAuY2xzLTYsIC5jbHMtNywgLmNscy04LCAuY2xzLTkgewogICAgICAgIHN0cm9rZS13aWR0aDogMHB4OwogICAgICB9CgogICAgICAuY2xzLTIgewogICAgICAgIGZpbGw6ICM3NjNlMWE7CiAgICAgIH0KCiAgICAgIC5jbHMtMyB7CiAgICAgICAgZmlsbDogI2MwYWQ5ZTsKICAgICAgfQoKICAgICAgLmNscy00IHsKICAgICAgICBmaWxsOiAjMzQ2OGQxOwogICAgICB9CgogICAgICAuY2xzLTUgewogICAgICAgIGZpbGw6ICNjYzYyMjg7CiAgICAgIH0KCiAgICAgIC5jbHMtNiB7CiAgICAgICAgZmlsbDogI2Y1ODQxZjsKICAgICAgfQoKICAgICAgLmNscy03IHsKICAgICAgICBmaWxsOiAjZDdjMWIzOwogICAgICB9CgogICAgICAuY2xzLTggewogICAgICAgIGZpbGw6ICNmZmY7CiAgICAgICAgZmlsbC1ydWxlOiBldmVub2RkOwogICAgICB9CgogICAgICAuY2xzLTkgewogICAgICAgIGZpbGw6ICMyZjM0M2I7CiAgICAgIH0KICAgIDwvc3R5bGU+CiAgPC9kZWZzPgogIDxnIGlkPSJMYXllcl8xLTIiIGRhdGEtbmFtZT0iTGF5ZXIgMSI+CiAgICA8ZyBpZD0iTU1fSGVhZF9iYWNrZ3JvdW5kX0RvX25vdF9lZGl0XyIgZGF0YS1uYW1lPSJNTSBIZWFkIGJhY2tncm91bmQgKERvIG5vdCBlZGl0KSI+CiAgICAgIDxwYXRoIGNsYXNzPSJjbHMtNiIgZD0iTTE0MS44LDcwLjVsNi45LTguMS0zLTIuMiw0LjgtNC40LTMuNy0yLjgsNC44LTMuNi0zLjEtMi40LDUtMjQuNC03LjYtMjIuNk0xNDUuOSwwbC00OC44LDE4LjFoLTQwLjdMNy42LDBsLjMuMkw3LjYsMCwwLDIyLjZsNS4xLDI0LjQtMy4yLDIuNCw0LjksMy42LTMuNywyLjgsNC44LDQuNC0zLDIuMiw2LjksOC4xTDEuMywxMDIuOWgwbDkuNywzMy4xLDM0LjEtOS40di0uMS4xaDBsNi42LDUuNCwxMy41LDkuMmgyMy4xbDEzLjUtOS4yLDYuNi01LjRoMGwzNC4yLDkuNCw5LjgtMzMuMWgwbC0xMC42LTMyLjQiLz4KICAgIDwvZz4KICAgIDxnIGlkPSJMb2dvcyI+CiAgICAgIDxnPgogICAgICAgIDxwb2x5Z29uIGNsYXNzPSJjbHMtMSIgcG9pbnRzPSIxNDUuOSAwIDg2IDQ0LjEgOTcuMSAxOC4xIDE0NS45IDAiLz4KICAgICAgICA8cG9seWdvbiBjbGFzcz0iY2xzLTEiIHBvaW50cz0iNy42IDAgNjcgNDQuNSA1Ni40IDE4LjEgNy42IDAiLz4KICAgICAgICA8cG9seWdvbiBjbGFzcz0iY2xzLTEiIHBvaW50cz0iMTI0LjQgMTAyLjMgMTA4LjQgMTI2LjUgMTQyLjYgMTM1LjkgMTUyLjQgMTAyLjggMTI0LjQgMTAyLjMiLz4KICAgICAgICA8cG9seWdvbiBjbGFzcz0iY2xzLTEiIHBvaW50cz0iMS4zIDEwMi44IDExIDEzNS45IDQ1LjEgMTI2LjUgMjkuMiAxMDIuMyAxLjMgMTAyLjgiLz4KICAgICAgICA8cG9seWdvbiBjbGFzcz0iY2xzLTEiIHBvaW50cz0iNDMuMyA2MS4zIDMzLjggNzUuNiA2Ny42IDc3LjEgNjYuNSA0MC45IDQzLjMgNjEuMyIvPgogICAgICAgIDxwb2x5Z29uIGNsYXNzPSJjbHMtMSIgcG9pbnRzPSIxMTAuMyA2MS4zIDg2LjcgNDAuNSA4NiA3Ny4xIDExOS44IDc1LjYgMTEwLjMgNjEuMyIvPgogICAgICAgIDxwb2x5Z29uIGNsYXNzPSJjbHMtMSIgcG9pbnRzPSI0NS4xIDEyNi41IDY1LjYgMTE2LjcgNDcuOSAxMDMuMSA0NS4xIDEyNi41Ii8+CiAgICAgICAgPHBvbHlnb24gY2xhc3M9ImNscy0xIiBwb2ludHM9Ijg4IDExNi43IDEwOC40IDEyNi41IDEwNS42IDEwMy4xIDg4IDExNi43Ii8+CiAgICAgICAgPHBvbHlnb24gY2xhc3M9ImNscy03IiBwb2ludHM9IjEwOC40IDEyNi41IDg4IDExNi43IDg5LjcgMTI5LjkgODkuNSAxMzUuNSAxMDguNCAxMjYuNSIvPgogICAgICAgIDxwb2x5Z29uIGNsYXNzPSJjbHMtNyIgcG9pbnRzPSI0NS4xIDEyNi41IDY0LjEgMTM1LjUgNjQgMTI5LjkgNjUuNiAxMTYuNyA0NS4xIDEyNi41Ii8+CiAgICAgICAgPHBvbHlnb24gY2xhc3M9ImNscy05IiBwb2ludHM9IjY0LjQgOTQuMyA0Ny41IDg5LjQgNTkuNSA4My45IDY0LjQgOTQuMyIvPgogICAgICAgIDxwb2x5Z29uIGNsYXNzPSJjbHMtOSIgcG9pbnRzPSI4OS4xIDk0LjMgOTQuMSA4My45IDEwNi4xIDg5LjQgODkuMSA5NC4zIi8+CiAgICAgICAgPHBvbHlnb24gY2xhc3M9ImNscy01IiBwb2ludHM9IjQ1LjEgMTI2LjUgNDguMSAxMDIuMyAyOS4yIDEwMi44IDQ1LjEgMTI2LjUiLz4KICAgICAgICA8cG9seWdvbiBjbGFzcz0iY2xzLTUiIHBvaW50cz0iMTA1LjUgMTAyLjMgMTA4LjQgMTI2LjUgMTI0LjQgMTAyLjggMTA1LjUgMTAyLjMiLz4KICAgICAgICA8cG9seWdvbiBjbGFzcz0iY2xzLTUiIHBvaW50cz0iMTE5LjggNzUuNiA4NiA3Ny4xIDg5LjEgOTQuMyA5NC4xIDgzLjkgMTA2LjEgODkuNCAxMTkuOCA3NS42Ii8+CiAgICAgICAgPHBvbHlnb24gY2xhc3M9ImNscy01IiBwb2ludHM9IjQ3LjUgODkuNCA1OS41IDgzLjkgNjQuNCA5NC4zIDY3LjYgNzcuMSAzMy44IDc1LjYgNDcuNSA4OS40Ii8+CiAgICAgICAgPHBvbHlnb24gY2xhc3M9ImNscy0xIiBwb2ludHM9IjMzLjggNzUuNiA0Ny45IDEwMy4xIDQ3LjUgODkuNCAzMy44IDc1LjYiLz4KICAgICAgICA8cG9seWdvbiBjbGFzcz0iY2xzLTEiIHBvaW50cz0iMTA2LjEgODkuNCAxMDUuNiAxMDMuMSAxMTkuOCA3NS42IDEwNi4xIDg5LjQiLz4KICAgICAgICA8cG9seWdvbiBjbGFzcz0iY2xzLTEiIHBvaW50cz0iNjcuNiA3Ny4xIDY0LjQgOTQuMyA2OC40IDExNC43IDY5LjMgODcuOSA2Ny42IDc3LjEiLz4KICAgICAgICA8cG9seWdvbiBjbGFzcz0iY2xzLTEiIHBvaW50cz0iODYgNzcuMSA4NC4zIDg3LjggODUuMSAxMTQuNyA4OS4xIDk0LjMgODYgNzcuMSIvPgogICAgICAgIDxwb2x5Z29uIGNsYXNzPSJjbHMtNiIgcG9pbnRzPSI4OS4xIDk0LjMgODUuMSAxMTQuNyA4OCAxMTYuNyAxMDUuNiAxMDMuMSAxMDYuMSA4OS40IDg5LjEgOTQuMyIvPgogICAgICAgIDxwb2x5Z29uIGNsYXNzPSJjbHMtNiIgcG9pbnRzPSI0Ny41IDg5LjQgNDcuOSAxMDMuMSA2NS42IDExNi43IDY4LjQgMTE0LjcgNjQuNCA5NC4zIDQ3LjUgODkuNCIvPgogICAgICAgIDxwb2x5Z29uIGNsYXNzPSJjbHMtMyIgcG9pbnRzPSI4OS41IDEzNS41IDg5LjcgMTI5LjkgODguMSAxMjguNiA2NS40IDEyOC42IDY0IDEyOS45IDY0LjEgMTM1LjUgNDUuMSAxMjYuNSA1MS43IDEzMS45IDY1LjIgMTQxLjIgODguMyAxNDEuMiAxMDEuOCAxMzEuOSAxMDguNCAxMjYuNSA4OS41IDEzNS41Ii8+CiAgICAgICAgPHBvbHlnb24gY2xhc3M9ImNscy05IiBwb2ludHM9Ijg4IDExNi43IDg1LjEgMTE0LjcgNjguNCAxMTQuNyA2NS42IDExNi43IDY0IDEyOS45IDY1LjQgMTI4LjYgODguMSAxMjguNiA4OS43IDEyOS45IDg4IDExNi43Ii8+CiAgICAgICAgPHBvbHlnb24gY2xhc3M9ImNscy0yIiBwb2ludHM9IjE0OC41IDQ3IDE1My41IDIyLjYgMTQ1LjkgMCA4OCA0Mi42IDExMC4zIDYxLjMgMTQxLjggNzAuNSAxNDguNyA2Mi40IDE0NS43IDYwLjIgMTUwLjUgNTUuOSAxNDYuOCA1MyAxNTEuNiA0OS40IDE0OC41IDQ3Ii8+CiAgICAgICAgPHBvbHlnb24gY2xhc3M9ImNscy0yIiBwb2ludHM9IjAgMjIuNiA1LjEgNDcgMS45IDQ5LjQgNi43IDUzLjEgMyA1NS45IDcuOCA2MC4yIDQuOCA2Mi40IDExLjggNzAuNSA0My4zIDYxLjMgNjUuNiA0Mi42IDcuNiAwIDAgMjIuNiIvPgogICAgICAgIDxwb2x5Z29uIGNsYXNzPSJjbHMtNiIgcG9pbnRzPSIxNDEuOCA3MC41IDExMC4zIDYxLjMgMTE5LjggNzUuNiAxMDUuNiAxMDMuMSAxMjQuNCAxMDIuOCAxNTIuNCAxMDIuOCAxNDEuOCA3MC41Ii8+CiAgICAgICAgPHBvbHlnb24gY2xhc3M9ImNscy02IiBwb2ludHM9IjQzLjMgNjEuMyAxMS44IDcwLjUgMS4zIDEwMi44IDI5LjIgMTAyLjggNDcuOSAxMDMuMSAzMy44IDc1LjYgNDMuMyA2MS4zIi8+CiAgICAgICAgPHBvbHlnb24gY2xhc3M9ImNscy02IiBwb2ludHM9Ijg2IDc3LjEgODggNDIuNiA5Ny4xIDE4LjEgNTYuNCAxOC4xIDY1LjYgNDIuNiA2Ny42IDc3LjEgNjguNCA4Ny45IDY4LjQgMTE0LjcgODUuMSAxMTQuNyA4NS4yIDg3LjkgODYgNzcuMSIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyBpZD0iY2FyZGFub19hZGEiIGRhdGEtbmFtZT0iY2FyZGFubyBhZGEiPgogICAgICA8ZyBpZD0iY2FyZGFub19hZGEtMiIgZGF0YS1uYW1lPSJjYXJkYW5vIGFkYS0yIj4KICAgICAgICA8Y2lyY2xlIGlkPSJf0K3Qu9C70LjQv9GBXzYiIGRhdGEtbmFtZT0i0K3Qu9C70LjQv9GBIDYiIGNsYXNzPSJjbHMtNCIgY3g9IjEyOC4wNSIgY3k9IjEyMi41NiIgcj0iNDEuMTUiLz4KICAgICAgICA8cGF0aCBpZD0iX9Ct0LvQu9C40L/RgV82X9C60L7Qv9C40Y9fMjkiIGRhdGEtbmFtZT0i0K3Qu9C70LjQv9GBIDYg0LrQvtC/0LjRjyAyOSIgY2xhc3M9ImNscy04IiBkPSJNMTIzLjQ2LDEwOS45M2MyLjI1LDAsNC4wNywxLjgyLDQuMDcsNC4wNywwLDIuMjUtMS44Miw0LjA3LTQuMDcsNC4wNy0yLjI1LDAtNC4wNy0xLjgyLTQuMDctNC4wNywwLTIuMjUsMS44Mi00LjA3LDQuMDctNC4wN1pNMTMzLjI4LDEwOS45M2MyLjI1LDAsNC4wNywxLjgyLDQuMDcsNC4wNywwLDIuMjUtMS44Miw0LjA3LTQuMDcsNC4wNy0yLjI1LDAtNC4wNy0xLjgyLTQuMDctNC4wNywwLTIuMjUsMS44Mi00LjA3LDQuMDctNC4wN2gwWk0xMzMuMjgsMTI3LjA1YzIuMjUsMCw0LjA3LDEuODIsNC4wNyw0LjA3LDAsMi4yNS0xLjgyLDQuMDctNC4wNyw0LjA3LTIuMjUsMC00LjA3LTEuODItNC4wNy00LjA3LDAtMi4yNSwxLjgyLTQuMDcsNC4wNy00LjA3aDAsMFpNMTIzLjQ2LDEyNy4wNWMyLjI1LDAsNC4wNywxLjgyLDQuMDcsNC4wNywwLDIuMjUtMS44Miw0LjA3LTQuMDcsNC4wNy0yLjI1LDAtNC4wNy0xLjgyLTQuMDctNC4wNywwLTIuMjUsMS44Mi00LjA3LDQuMDctNC4wN1pNMTE4LjQxLDExOC42M2MyLjI1LDAsNC4wNywxLjgyLDQuMDcsNC4wNywwLDIuMjUtMS44Miw0LjA3LTQuMDcsNC4wNy0yLjI1LDAtNC4wNy0xLjgyLTQuMDctNC4wNywwLTIuMjUsMS44Mi00LjA3LDQuMDctNC4wN2gwWk0xMzguMzMsMTE4LjYzYzIuMjUsMCw0LjA3LDEuODIsNC4wNyw0LjA3LDAsMi4yNS0xLjgyLDQuMDctNC4wNyw0LjA3LTIuMjUsMC00LjA3LTEuODItNC4wNy00LjA3LDAtMi4yNSwxLjgyLTQuMDcsNC4wNy00LjA3aDBaTTE0Mi45NiwxMTEuNjJjMS4zOSwwLDIuNTIsMS4xMywyLjUyLDIuNTMsMCwxLjM5LTEuMTMsMi41Mi0yLjUzLDIuNTItMS4zOSwwLTIuNTItMS4xMy0yLjUyLTIuNTJzMS4xMy0yLjUyLDIuNTItMi41MmgwWk0xNDIuOTYsMTI4LjQ1YzEuMzksMCwyLjUyLDEuMTMsMi41MiwyLjUzLDAsMS4zOS0xLjEzLDIuNTItMi41MywyLjUyLTEuMzksMC0yLjUyLTEuMTMtMi41Mi0yLjUyczEuMTMtMi41MiwyLjUyLTIuNTJoMFpNMTEzLjc4LDEyOC40NWMxLjM5LDAsMi41MiwxLjEzLDIuNTIsMi41MywwLDEuMzktMS4xMywyLjUyLTIuNTMsMi41Mi0xLjM5LDAtMi41Mi0xLjEzLTIuNTItMi41MiwwLTEuMzksMS4xMy0yLjUyLDIuNTMtMi41MmgwWk0xMTMuNzgsMTExLjYyYzEuMzksMCwyLjUyLDEuMTMsMi41MiwyLjUzLDAsMS4zOS0xLjEzLDIuNTItMi41MywyLjUyLTEuMzksMC0yLjUyLTEuMTMtMi41Mi0yLjUyLDAtMS4zOSwxLjEzLTIuNTIsMi41My0yLjUyaDBaTTEyOC4zNywxMDMuMmMxLjM5LDAsMi41MiwxLjEzLDIuNTIsMi41MywwLDEuMzktMS4xMywyLjUyLTIuNTMsMi41Mi0xLjM5LDAtMi41Mi0xLjEzLTIuNTItMi41MnMxLjEzLTIuNTIsMi41Mi0yLjUyaDBaTTEyOC4zNywxMzYuODZjMS4zOSwwLDIuNTIsMS4xMywyLjUyLDIuNTMsMCwxLjM5LTEuMTMsMi41Mi0yLjUzLDIuNTItMS4zOSwwLTIuNTItMS4xMy0yLjUyLTIuNTJzMS4xMy0yLjUyLDIuNTItMi41MmgwWk0xMzkuMTcsMTM5LjM5YzEuMTYsMCwyLjEuOTQsMi4xLDIuMSwwLDEuMTYtLjk0LDIuMS0yLjEsMi4xLTEuMTYsMC0yLjEtLjk0LTIuMS0yLjFzLjk0LTIuMSwyLjEtMi4xaDBaTTExNy41NywxMzkuMzljMS4xNiwwLDIuMS45NCwyLjEsMi4xLDAsMS4xNi0uOTQsMi4xLTIuMSwyLjEtMS4xNiwwLTIuMS0uOTQtMi4xLTIuMXMuOTQtMi4xLDIuMS0yLjFoMFpNMTE3LjU3LDEwMS41MmMxLjE2LDAsMi4xLjk0LDIuMSwyLjEsMCwxLjE2LS45NCwyLjEtMi4xLDIuMS0xLjE2LDAtMi4xLS45NC0yLjEtMi4xcy45NC0yLjEsMi4xLTIuMWgwWk0xMzkuMTcsMTAxLjUyYzEuMTYsMCwyLjEuOTQsMi4xLDIuMSwwLDEuMTYtLjk0LDIuMS0yLjEsMi4xLTEuMTYsMC0yLjEtLjk0LTIuMS0yLjFzLjk0LTIuMSwyLjEtMi4xaDBaTTE1MC4xMSwxMjAuMzFjMS4xNiwwLDIuMS45NCwyLjEsMi4xLDAsMS4xNi0uOTQsMi4xLTIuMSwyLjEtMS4xNiwwLTIuMS0uOTQtMi4xLTIuMSwwLTEuMTYuOTQtMi4xLDIuMS0yLjFoMFpNMTA2LjYyLDEyMC4zMWMxLjE2LDAsMi4xLjk0LDIuMSwyLjEsMCwxLjE2LS45NCwyLjEtMi4xLDIuMS0xLjE2LDAtMi4xLS45NC0yLjEtMi4xcy45NC0yLjEsMi4xLTIuMWgwWk0xMDUuMDgsMTA3LjQxYy45MywwLDEuNjguNzUsMS42OCwxLjY4cy0uNzUsMS42OC0xLjY4LDEuNjgtMS42OC0uNzUtMS42OC0xLjY4aDBjMC0uOTMuNzUtMS42OCwxLjY4LTEuNjhoMFpNMTA1LjA4LDEzNC4zNGMuOTMsMCwxLjY4Ljc1LDEuNjgsMS42OHMtLjc1LDEuNjgtMS42OCwxLjY4LTEuNjgtLjc1LTEuNjgtMS42OGgwYzAtLjkzLjc1LTEuNjgsMS42OC0xLjY4aDBaTTE1MS42NiwxMzQuMzRjLjkzLDAsMS42OC43NSwxLjY4LDEuNjgsMCwuOTMtLjc1LDEuNjgtMS42OCwxLjY4cy0xLjY4LS43NS0xLjY4LTEuNjhoMGMwLS45My43NS0xLjY4LDEuNjgtMS42OGgwWk0xNTEuNjYsMTA3LjQxYy45MywwLDEuNjguNzUsMS42OCwxLjY4LDAsLjkzLS43NSwxLjY4LTEuNjgsMS42OHMtMS42OC0uNzUtMS42OC0xLjY4aDBjMC0uOTMuNzUtMS42OCwxLjY4LTEuNjhoMFpNMTI4LjM3LDkzLjk0Yy45MywwLDEuNjguNzUsMS42OCwxLjY4LDAsLjkzLS43NSwxLjY4LTEuNjgsMS42OC0uOTMsMC0xLjY4LS43NS0xLjY4LTEuNjhoMGMwLS45My43NS0xLjY4LDEuNjgtMS42OGgwWk0xMjguMzcsMTQ3LjhjLjkzLDAsMS42OC43NSwxLjY4LDEuNjgsMCwuOTMtLjc1LDEuNjgtMS42OCwxLjY4LS45MywwLTEuNjgtLjc1LTEuNjgtMS42OHMuNzUtMS42OCwxLjY4LTEuNjhoMFpNMTQzLjI0LDE0Ni42OGMuNzcsMCwxLjQuNjMsMS40LDEuNCwwLC43Ny0uNjMsMS40LTEuNCwxLjRzLTEuNC0uNjMtMS40LTEuNGgwYzAtLjc3LjYzLTEuNCwxLjQtMS40Wk0xMTMuNSwxNDYuNjhjLjc3LDAsMS40LjYzLDEuNCwxLjRzLS42MywxLjQtMS40LDEuNC0xLjQtLjYzLTEuNC0xLjRoMGMwLS43Ny42My0xLjQsMS40LTEuNFpNMTEzLjUsOTUuNjNjLjc3LDAsMS40LjYzLDEuNCwxLjRzLS42MywxLjQtMS40LDEuNC0xLjQtLjYzLTEuNC0xLjRoMGMwLS43Ny42My0xLjQsMS40LTEuNGgwWk0xNDMuMjQsOTUuNjNjLjc3LDAsMS40LjYzLDEuNCwxLjQsMCwuNzctLjYzLDEuNC0xLjQsMS40cy0xLjQtLjYzLTEuNC0xLjRoMGMwLS43Ny42My0xLjQsMS40LTEuNGgwWk0xNTcuODMsMTIxLjE2Yy43NywwLDEuNC42MywxLjQsMS40LDAsLjc3LS42MywxLjQtMS40LDEuNHMtMS40LS42My0xLjQtMS40aDBjMC0uNzguNjMtMS40LDEuNC0xLjRoMFpNOTguOTEsMTIxLjE2Yy43NywwLDEuNC42MywxLjQsMS40cy0uNjMsMS40LTEuNCwxLjQtMS40LS42My0xLjQtMS40aDBjMC0uNzguNjMtMS40LDEuNC0xLjRoMFoiLz4KICAgICAgPC9nPgogICAgPC9nPgogIDwvZz4KPC9zdmc+",
+ version: "version",
+ });
+ } else {
+ resolve(undefined);
+ }
+ });
+ });
+ } catch (err) {
+ return Promise.resolve(undefined);
+ }
+}
diff --git a/packages/mesh-wallet/src/mesh/index.ts b/packages/mesh-wallet/src/mesh/index.ts
index d36b8769..7531fd18 100644
--- a/packages/mesh-wallet/src/mesh/index.ts
+++ b/packages/mesh-wallet/src/mesh/index.ts
@@ -15,19 +15,27 @@ import {
} from "@meshsdk/common";
import {
Address,
+ buildBaseAddress,
+ buildEnterpriseAddress,
+ buildRewardAddress,
+ CardanoSDKSerializer,
+ deserializeAddress,
+ deserializeTx,
+ Ed25519KeyHashHex,
fromTxUnspentOutput,
+ Hash28ByteBase16,
resolvePrivateKey,
+ toAddress,
toTxUnspentOutput,
TransactionUnspentOutput,
} from "@meshsdk/core-cst";
import { Transaction } from "@meshsdk/transaction";
-import { AppWallet } from "../app";
import { EmbeddedWallet } from "../embedded";
import { GetAddressType } from "../types";
export type CreateMeshWalletOptions = {
- networkId: number;
+ networkId: 0 | 1;
fetcher?: IFetcher;
submitter?: ISubmitter;
key:
@@ -44,6 +52,12 @@ export type CreateMeshWalletOptions = {
type: "mnemonic";
words: string[];
};
+ // | {
+ // type: "address";
+ // address: string;
+ // }
+ accountIndex?: number;
+ keyIndex?: number;
};
/**
@@ -68,45 +82,69 @@ export type CreateMeshWalletOptions = {
* ```
*/
export class MeshWallet implements IInitiator, ISigner, ISubmitter {
- private readonly _wallet: AppWallet;
+ private readonly _wallet: EmbeddedWallet | null;
+ // private readonly _account: Account;
+ private readonly _accountIndex: number = 0;
+ private readonly _keyIndex: number = 0;
+ private readonly _fetcher?: IFetcher;
+ private readonly _submitter?: ISubmitter;
+ private readonly _networkId: 0 | 1;
+ private _addresses: {
+ baseAddress?: Address;
+ enterpriseAddress?: Address;
+ rewardAddress?: Address;
+ baseAddressBech32?: string;
+ enterpriseAddressBech32?: string;
+ rewardAddressBech32?: string;
+ } = {};
constructor(options: CreateMeshWalletOptions) {
switch (options.key.type) {
case "root":
- this._wallet = new AppWallet({
+ this._wallet = new EmbeddedWallet({
networkId: options.networkId,
- fetcher: options.fetcher,
- submitter: options.submitter,
key: {
type: "root",
bech32: options.key.bech32,
},
});
+ this.getAddressesFromWallet(this._wallet);
break;
case "cli":
- this._wallet = new AppWallet({
+ this._wallet = new EmbeddedWallet({
networkId: options.networkId,
- fetcher: options.fetcher,
- submitter: options.submitter,
key: {
type: "cli",
payment: options.key.payment,
stake: options.key.stake,
},
});
+ this.getAddressesFromWallet(this._wallet);
break;
case "mnemonic":
- this._wallet = new AppWallet({
+ this._wallet = new EmbeddedWallet({
networkId: options.networkId,
- fetcher: options.fetcher,
- submitter: options.submitter,
key: {
type: "mnemonic",
words: options.key.words,
},
});
+ this.getAddressesFromWallet(this._wallet);
break;
+ // case "address":
+ // console.log(4);
+ // this._wallet = null;
+ // this.buildAddressFromBech32Address(options.key.address);
+ // console.log(5);
+ // break;
}
+
+ this._networkId = options.networkId;
+
+ if (options.fetcher) this._fetcher = options.fetcher;
+ if (options.submitter) this._submitter = options.submitter;
+ if (options.accountIndex) this._accountIndex = options.accountIndex;
+ if (options.keyIndex) this._keyIndex = options.keyIndex;
}
/**
@@ -148,7 +186,7 @@ export class MeshWallet implements IInitiator, ISigner, ISubmitter {
* @returns an address
*/
getChangeAddress(): string {
- return this._wallet.getPaymentAddress();
+ return this._addresses.baseAddressBech32!;
}
/**
@@ -162,19 +200,53 @@ export class MeshWallet implements IInitiator, ISigner, ISubmitter {
async getCollateral(
addressType: GetAddressType = "payment",
): Promise {
- const utxos = await this._wallet.getCollateralUnspentOutput(0, addressType);
+ const utxos = await this.getCollateralUnspentOutput(addressType);
return utxos.map((utxo, i) => {
return fromTxUnspentOutput(utxo);
});
}
+ /**
+ * Get a list of UTXOs to be used as collateral inputs for transactions with plutus script inputs.
+ *
+ * This is used in transaction building.
+ *
+ * @returns a list of UTXOs
+ */
+ async getCollateralUnspentOutput(
+ addressType: GetAddressType = "payment",
+ ): Promise {
+ const utxos = await this.getUnspentOutputs(addressType);
+
+ // find utxos that are pure ADA-only
+ const pureAdaUtxos = utxos.filter((utxo) => {
+ return utxo.output().amount().multiasset() === undefined;
+ });
+
+ // sort utxos by their lovelace amount
+ pureAdaUtxos.sort((a, b) => {
+ return (
+ Number(a.output().amount().coin()) - Number(b.output().amount().coin())
+ );
+ });
+
+ // return the smallest utxo but not less than 5000000 lovelace
+ for (const utxo of pureAdaUtxos) {
+ if (Number(utxo.output().amount().coin()) >= 5000000) {
+ return [utxo];
+ }
+ }
+
+ return [];
+ }
+
/**
* Returns the network ID of the currently connected account. 0 is testnet and 1 is mainnet but other networks can possibly be returned by wallets. Those other network ID values are not governed by CIP-30. This result will stay the same unless the connected account has changed.
*
* @returns network ID
*/
getNetworkId(): number {
- return this._wallet.getNetworkId();
+ return this._networkId;
}
/**
@@ -183,7 +255,7 @@ export class MeshWallet implements IInitiator, ISigner, ISubmitter {
* @returns a list of reward addresses
*/
getRewardAddresses(): string[] {
- return [this._wallet.getRewardAddress()];
+ return [this._addresses.rewardAddressBech32!];
}
/**
@@ -254,6 +326,11 @@ export class MeshWallet implements IInitiator, ISigner, ISubmitter {
* @returns a signature
*/
signData(payload: string): DataSignature {
+ if (!this._wallet) {
+ throw new Error(
+ "[MeshWallet] Read only wallet does not support signing data.",
+ );
+ }
return this._wallet.signData(this.getChangeAddress(), payload);
}
@@ -265,7 +342,30 @@ export class MeshWallet implements IInitiator, ISigner, ISubmitter {
* @returns a signed transaction in CBOR
*/
signTx(unsignedTx: string, partialSign = false): string {
- return this._wallet.signTx(unsignedTx, partialSign);
+ if (!this._wallet) {
+ throw new Error(
+ "[MeshWallet] Read only wallet does not support signing data.",
+ );
+ }
+
+ const tx = deserializeTx(unsignedTx);
+ if (
+ !partialSign &&
+ tx.witnessSet().vkeys() !== undefined &&
+ tx.witnessSet().vkeys()!.size() !== 0
+ )
+ throw new Error(
+ "Signatures already exist in the transaction in a non partial sign call",
+ );
+
+ const newSignatures = this._wallet.signTx(
+ unsignedTx,
+ this._accountIndex,
+ this._keyIndex,
+ );
+
+ let signedTx = EmbeddedWallet.addWitnessSets(unsignedTx, [newSignatures]);
+ return signedTx;
}
/**
@@ -295,7 +395,12 @@ export class MeshWallet implements IInitiator, ISigner, ISubmitter {
* @returns a transaction hash
*/
async submitTx(tx: string): Promise {
- return await this._wallet.submitTx(tx);
+ if (!this._submitter) {
+ throw new Error(
+ "[AppWallet] Submitter is required to submit transactions. Please provide a submitter.",
+ );
+ }
+ return this._submitter.submitTx(tx);
}
/**
@@ -306,7 +411,11 @@ export class MeshWallet implements IInitiator, ISigner, ISubmitter {
* @returns an Address object
*/
getUsedAddress(addressType?: GetAddressType): Address {
- return this._wallet.getUsedAddress(0, 0, addressType);
+ if (addressType === "enterprise") {
+ return toAddress(this._addresses.enterpriseAddressBech32!);
+ } else {
+ return toAddress(this._addresses.baseAddressBech32!);
+ }
}
/**
@@ -319,7 +428,19 @@ export class MeshWallet implements IInitiator, ISigner, ISubmitter {
async getUnspentOutputs(
addressType?: GetAddressType,
): Promise {
- return await this._wallet.getUnspentOutputs(0, addressType);
+ if (!this._fetcher) {
+ throw new Error(
+ "[AppWallet] Fetcher is required to fetch UTxOs. Please provide a fetcher.",
+ );
+ }
+
+ const utxos = await this._fetcher.fetchAddressUTxOs(
+ addressType == "enterprise"
+ ? this._addresses.enterpriseAddressBech32!
+ : this._addresses.baseAddressBech32!,
+ );
+
+ return utxos.map((utxo) => toTxUnspentOutput(utxo));
}
/**
@@ -410,4 +531,66 @@ export class MeshWallet implements IInitiator, ISigner, ISubmitter {
return mnemonic;
}
+
+ getAddressesFromWallet(wallet: EmbeddedWallet) {
+ const account = wallet.getAccount(this._accountIndex, this._keyIndex);
+
+ this._addresses = {
+ baseAddress: account.baseAddress,
+ enterpriseAddress: account.enterpriseAddress,
+ rewardAddress: account.rewardAddress,
+ baseAddressBech32: account.baseAddressBech32,
+ enterpriseAddressBech32: account.enterpriseAddressBech32,
+ rewardAddressBech32: account.rewardAddressBech32,
+ };
+ }
+
+ buildAddressFromBech32Address(address: string) {
+ const serializer = new CardanoSDKSerializer();
+
+ const deserializedAddress =
+ serializer.deserializer.key.deserializeAddress(address);
+
+ if (
+ deserializedAddress.pubKeyHash &&
+ deserializedAddress.stakeCredentialHash
+ ) {
+ this._addresses.baseAddress = buildBaseAddress(
+ this._networkId,
+ Hash28ByteBase16.fromEd25519KeyHashHex(
+ Ed25519KeyHashHex(deserializedAddress.pubKeyHash),
+ ),
+ Hash28ByteBase16.fromEd25519KeyHashHex(
+ Ed25519KeyHashHex(
+ Ed25519KeyHashHex(deserializedAddress.stakeCredentialHash),
+ ),
+ ),
+ ).toAddress();
+ this._addresses.baseAddressBech32 =
+ this._addresses.baseAddress.toBech32();
+ }
+
+ if (deserializedAddress.pubKeyHash) {
+ this._addresses.enterpriseAddress = buildEnterpriseAddress(
+ this._networkId,
+ Hash28ByteBase16.fromEd25519KeyHashHex(
+ Ed25519KeyHashHex(deserializedAddress.pubKeyHash),
+ ),
+ ).toAddress();
+ this._addresses.enterpriseAddressBech32 =
+ this._addresses.enterpriseAddress.toBech32();
+ }
+
+ if (deserializedAddress.stakeCredentialHash) {
+ this._addresses.rewardAddress = buildRewardAddress(
+ this._networkId,
+ Hash28ByteBase16.fromEd25519KeyHashHex(
+ Ed25519KeyHashHex(deserializedAddress.stakeCredentialHash),
+ ),
+ ).toAddress();
+
+ this._addresses.rewardAddressBech32 =
+ this._addresses.rewardAddress.toBech32();
+ }
+ }
}
diff --git a/packages/mesh-wallet/src/mesh_old/index.ts b/packages/mesh-wallet/src/mesh_old/index.ts
new file mode 100644
index 00000000..d36b8769
--- /dev/null
+++ b/packages/mesh-wallet/src/mesh_old/index.ts
@@ -0,0 +1,413 @@
+import type {
+ Asset,
+ AssetExtended,
+ DataSignature,
+ UTxO,
+} from "@meshsdk/common";
+import {
+ IFetcher,
+ IInitiator,
+ ISigner,
+ ISubmitter,
+ POLICY_ID_LENGTH,
+ resolveFingerprint,
+ toUTF8,
+} from "@meshsdk/common";
+import {
+ Address,
+ fromTxUnspentOutput,
+ resolvePrivateKey,
+ toTxUnspentOutput,
+ TransactionUnspentOutput,
+} from "@meshsdk/core-cst";
+import { Transaction } from "@meshsdk/transaction";
+
+import { AppWallet } from "../app";
+import { EmbeddedWallet } from "../embedded";
+import { GetAddressType } from "../types";
+
+export type CreateMeshWalletOptions = {
+ networkId: number;
+ fetcher?: IFetcher;
+ submitter?: ISubmitter;
+ key:
+ | {
+ type: "root";
+ bech32: string;
+ }
+ | {
+ type: "cli";
+ payment: string;
+ stake?: string;
+ }
+ | {
+ type: "mnemonic";
+ words: string[];
+ };
+};
+
+/**
+ * Mesh Wallet provides a set of APIs to interact with the blockchain. This wallet is compatible with Mesh transaction builders.
+ *
+ * It is a single address wallet, a wrapper around the AppWallet class.
+ *
+ * ```javascript
+ * import { MeshWallet, BlockfrostProvider } from '@meshsdksdk/core';
+ *
+ * const blockchainProvider = new BlockfrostProvider('');
+ *
+ * const wallet = new MeshWallet({
+ * networkId: 0,
+ * fetcher: blockchainProvider,
+ * submitter: blockchainProvider,
+ * key: {
+ * type: 'mnemonic',
+ * words: ["solution","solution","solution","solution","solution",","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution","solution"],
+ * },
+ * });
+ * ```
+ */
+export class MeshWallet implements IInitiator, ISigner, ISubmitter {
+ private readonly _wallet: AppWallet;
+
+ constructor(options: CreateMeshWalletOptions) {
+ switch (options.key.type) {
+ case "root":
+ this._wallet = new AppWallet({
+ networkId: options.networkId,
+ fetcher: options.fetcher,
+ submitter: options.submitter,
+ key: {
+ type: "root",
+ bech32: options.key.bech32,
+ },
+ });
+ break;
+ case "cli":
+ this._wallet = new AppWallet({
+ networkId: options.networkId,
+ fetcher: options.fetcher,
+ submitter: options.submitter,
+ key: {
+ type: "cli",
+ payment: options.key.payment,
+ stake: options.key.stake,
+ },
+ });
+ break;
+ case "mnemonic":
+ this._wallet = new AppWallet({
+ networkId: options.networkId,
+ fetcher: options.fetcher,
+ submitter: options.submitter,
+ key: {
+ type: "mnemonic",
+ words: options.key.words,
+ },
+ });
+ break;
+ }
+ }
+
+ /**
+ * Returns a list of assets in the wallet. This API will return every assets in the wallet. Each asset is an object with the following properties:
+ * - A unit is provided to display asset's name on the user interface.
+ * - A quantity is provided to display asset's quantity on the user interface.
+ *
+ * @returns a list of assets and their quantities
+ */
+ async getBalance(): Promise {
+ const utxos = await this.getUnspentOutputs();
+
+ const assets = new Map();
+ utxos.map((utxo) => {
+ const _utxo = fromTxUnspentOutput(utxo);
+ _utxo.output.amount.map((asset) => {
+ const assetId = asset.unit;
+ const amount = Number(asset.quantity);
+ if (assets.has(assetId)) {
+ const quantity = assets.get(assetId)!;
+ assets.set(assetId, quantity + amount);
+ } else {
+ assets.set(assetId, amount);
+ }
+ });
+ });
+
+ const arrayAssets: Asset[] = Array.from(assets, ([unit, quantity]) => ({
+ unit,
+ quantity: quantity.toString(),
+ }));
+
+ return arrayAssets;
+ }
+
+ /**
+ * Returns an address owned by the wallet that should be used as a change address to return leftover assets during transaction creation back to the connected wallet.
+ *
+ * @returns an address
+ */
+ getChangeAddress(): string {
+ return this._wallet.getPaymentAddress();
+ }
+
+ /**
+ * This function shall return a list of one or more UTXOs (unspent transaction outputs) controlled by the wallet that are required to reach AT LEAST the combined ADA value target specified in amount AND the best suitable to be used as collateral inputs for transactions with plutus script inputs (pure ADA-only UTXOs).
+ *
+ * If this cannot be attained, an error message with an explanation of the blocking problem shall be returned. NOTE: wallets are free to return UTXOs that add up to a greater total ADA value than requested in the amount parameter, but wallets must never return any result where UTXOs would sum up to a smaller total ADA value, instead in a case like that an error message must be returned.
+ *
+ * @returns a list of UTXOs
+ */
+
+ async getCollateral(
+ addressType: GetAddressType = "payment",
+ ): Promise {
+ const utxos = await this._wallet.getCollateralUnspentOutput(0, addressType);
+ return utxos.map((utxo, i) => {
+ return fromTxUnspentOutput(utxo);
+ });
+ }
+
+ /**
+ * Returns the network ID of the currently connected account. 0 is testnet and 1 is mainnet but other networks can possibly be returned by wallets. Those other network ID values are not governed by CIP-30. This result will stay the same unless the connected account has changed.
+ *
+ * @returns network ID
+ */
+ getNetworkId(): number {
+ return this._wallet.getNetworkId();
+ }
+
+ /**
+ * Returns a list of reward addresses owned by the wallet. A reward address is a stake address that is used to receive rewards from staking, generally starts from `stake` prefix.
+ *
+ * @returns a list of reward addresses
+ */
+ getRewardAddresses(): string[] {
+ return [this._wallet.getRewardAddress()];
+ }
+
+ /**
+ * Returns a list of unused addresses controlled by the wallet.
+ *
+ * @returns a list of unused addresses
+ */
+ getUnusedAddresses(): string[] {
+ return [this.getChangeAddress()];
+ }
+
+ /**
+ * Returns a list of used addresses controlled by the wallet.
+ *
+ * @returns a list of used addresses
+ */
+ getUsedAddresses(): string[] {
+ return [this.getChangeAddress()];
+ }
+
+ /**
+ * Get a list of UTXOs to be used as collateral inputs for transactions with plutus script inputs.
+ *
+ * This is used in transaction building.
+ *
+ * @returns a list of UTXOs
+ */
+ async getUsedCollateral(): Promise {
+ const collateralUtxo = await this.getCollateral();
+
+ const unspentOutput = collateralUtxo.map((utxo) => {
+ return toTxUnspentOutput(utxo);
+ });
+
+ return unspentOutput;
+ }
+
+ /**
+ * Get a list of UTXOs to be used for transaction building.
+ *
+ * This is used in transaction building.
+ *
+ * @returns a list of UTXOs
+ */
+ async getUsedUTxOs(
+ addressType?: GetAddressType,
+ ): Promise {
+ return await this.getUnspentOutputs(addressType);
+ }
+
+ /**
+ * Return a list of all UTXOs (unspent transaction outputs) controlled by the wallet.
+ *
+ * @returns a list of UTXOs
+ */
+ async getUtxos(addressType?: GetAddressType): Promise {
+ const utxos = await this.getUsedUTxOs(addressType);
+ return utxos.map((c) => fromTxUnspentOutput(c));
+ }
+
+ /**
+ * This endpoint utilizes the [CIP-8 - Message Signing](https://github.com/cardano-foundation/CIPs/tree/master/CIP-0030) to sign arbitrary data, to verify the data was signed by the owner of the private key.
+ *
+ * Here, we get the first wallet's address with wallet.getUsedAddresses(), alternativelly you can use reward addresses (getRewardAddresses()) too. It's really up to you as the developer which address you want to use in your application.
+ *
+ * @param address
+ * @param payload
+ * @returns a signature
+ */
+ signData(payload: string): DataSignature {
+ return this._wallet.signData(this.getChangeAddress(), payload);
+ }
+
+ /**
+ * Requests user to sign the provided transaction (tx). The wallet should ask the user for permission, and if given, try to sign the supplied body and return a signed transaction. partialSign should be true if the transaction provided requires multiple signatures.
+ *
+ * @param unsignedTx
+ * @param partialSign
+ * @returns a signed transaction in CBOR
+ */
+ signTx(unsignedTx: string, partialSign = false): string {
+ return this._wallet.signTx(unsignedTx, partialSign);
+ }
+
+ /**
+ * Experimental feature - sign multiple transactions at once.
+ *
+ * @param unsignedTxs - array of unsigned transactions in CborHex string
+ * @param partialSign - if the transactions are signed partially
+ * @returns array of signed transactions CborHex string
+ */
+ signTxs(unsignedTxs: string[], partialSign = false): string[] {
+ const signedTxs: string[] = [];
+
+ for (const unsignedTx of unsignedTxs) {
+ const signedTx = this.signTx(unsignedTx, partialSign);
+ signedTxs.push(signedTx);
+ }
+
+ return signedTxs;
+ }
+
+ /**
+ * Submits the signed transaction to the blockchain network.
+ *
+ * As wallets should already have this ability to submit transaction, we allow dApps to request that a transaction be sent through it. If the wallet accepts the transaction and tries to send it, it shall return the transaction ID for the dApp to track. The wallet can return error messages or failure if there was an error in sending it.
+ *
+ * @param tx
+ * @returns a transaction hash
+ */
+ async submitTx(tx: string): Promise {
+ return await this._wallet.submitTx(tx);
+ }
+
+ /**
+ * Get a used address of type Address from the wallet.
+ *
+ * This is used in transaction building.
+ *
+ * @returns an Address object
+ */
+ getUsedAddress(addressType?: GetAddressType): Address {
+ return this._wallet.getUsedAddress(0, 0, addressType);
+ }
+
+ /**
+ * Get a list of UTXOs to be used for transaction building.
+ *
+ * This is used in transaction building.
+ *
+ * @returns a list of UTXOs
+ */
+ async getUnspentOutputs(
+ addressType?: GetAddressType,
+ ): Promise {
+ return await this._wallet.getUnspentOutputs(0, addressType);
+ }
+
+ /**
+ * A helper function to get the assets in the wallet.
+ *
+ * @returns a list of assets
+ */
+ async getAssets(): Promise {
+ const balance = await this.getBalance();
+ return balance
+ .filter((v) => v.unit !== "lovelace")
+ .map((v) => {
+ const policyId = v.unit.slice(0, POLICY_ID_LENGTH);
+ const assetName = v.unit.slice(POLICY_ID_LENGTH);
+ const fingerprint = resolveFingerprint(policyId, assetName);
+
+ return {
+ unit: v.unit,
+ policyId,
+ assetName: toUTF8(assetName),
+ fingerprint,
+ quantity: v.quantity,
+ };
+ });
+ }
+
+ /**
+ * A helper function to get the lovelace balance in the wallet.
+ *
+ * @returns lovelace balance
+ */
+ async getLovelace(): Promise {
+ const balance = await this.getBalance();
+ const nativeAsset = balance.find((v) => v.unit === "lovelace");
+
+ return nativeAsset !== undefined ? nativeAsset.quantity : "0";
+ }
+
+ /**
+ * A helper function to get the assets of a specific policy ID in the wallet.
+ *
+ * @param policyId
+ * @returns a list of assets
+ */
+ async getPolicyIdAssets(policyId: string): Promise {
+ const assets = await this.getAssets();
+ return assets.filter((v) => v.policyId === policyId);
+ }
+
+ /**
+ * A helper function to get the policy IDs of all the assets in the wallet.
+ *
+ * @returns a list of policy IDs
+ */
+ async getPolicyIds(): Promise {
+ const balance = await this.getBalance();
+ return Array.from(
+ new Set(balance.map((v) => v.unit.slice(0, POLICY_ID_LENGTH))),
+ ).filter((p) => p !== "lovelace");
+ }
+
+ /**
+ * A helper function to create a collateral input for a transaction.
+ *
+ * @returns a transaction hash
+ */
+ async createCollateral(): Promise {
+ const tx = new Transaction({ initiator: this });
+ tx.sendLovelace(this.getChangeAddress(), "5000000");
+ const unsignedTx = await tx.build();
+ const signedTx = await this.signTx(unsignedTx);
+ const txHash = await this.submitTx(signedTx);
+ return txHash;
+ }
+
+ /**
+ * Generate mnemonic or private key
+ *
+ * @param privateKey return private key if true
+ * @returns a transaction hash
+ */
+ static brew(privateKey = false, strength = 256): string[] | string {
+ const mnemonic = EmbeddedWallet.generateMnemonic(strength);
+
+ if (privateKey) {
+ return resolvePrivateKey(mnemonic);
+ }
+
+ return mnemonic;
+ }
+}
diff --git a/packages/mesh-wallet/test/app.test.ts b/packages/mesh-wallet/test/app.test.ts
index fed9c007..02c6730f 100644
--- a/packages/mesh-wallet/test/app.test.ts
+++ b/packages/mesh-wallet/test/app.test.ts
@@ -1,4 +1,4 @@
-import { AppWallet } from "../src";
+import { AppWallet } from "@meshsdk/wallet";
describe("AppWallet", () => {
const wallet = new AppWallet({
diff --git a/packages/mesh-wallet/test/browser.test.ts b/packages/mesh-wallet/test/browser.test.ts
index ac7d6f9c..e2db9b52 100644
--- a/packages/mesh-wallet/test/browser.test.ts
+++ b/packages/mesh-wallet/test/browser.test.ts
@@ -1,6 +1,5 @@
import { CardanoSDKUtil, Serialization } from "@meshsdk/core-cst";
-
-import { WalletStaticMethods } from "../src";
+import { WalletStaticMethods } from "@meshsdk/wallet";
describe("BroswerWallet", () => {
it("signTx: addWitnessSet", () => {
diff --git a/packages/mesh-wallet/test/embedded.test.ts b/packages/mesh-wallet/test/embedded.test.ts
index 7c95132e..9b0e84c2 100644
--- a/packages/mesh-wallet/test/embedded.test.ts
+++ b/packages/mesh-wallet/test/embedded.test.ts
@@ -1,6 +1,5 @@
import { checkSignature } from "@meshsdk/core-cst";
-
-import { EmbeddedWallet } from "../src";
+import { EmbeddedWallet } from "@meshsdk/wallet";
describe("EmbeddedWallet mnemonic", () => {
const wallet = new EmbeddedWallet({
diff --git a/packages/mesh-wallet/test/mesh.test.ts b/packages/mesh-wallet/test/mesh.test.ts
index 7b78638c..0b3bbf20 100644
--- a/packages/mesh-wallet/test/mesh.test.ts
+++ b/packages/mesh-wallet/test/mesh.test.ts
@@ -1,4 +1,4 @@
-import { MeshWallet } from "../src";
+import { MeshWallet } from "@meshsdk/wallet";
describe("MeshWallet", () => {
const wallet = new MeshWallet({