-
- npm install @meshsdk/core @meshsdk/react
+
+ npm install @meshsdk/core
{/* */}
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/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
index 94d65ab5..82267685 100644
--- a/packages/mesh-common/test/data/value.test.ts
+++ b/packages/mesh-common/test/data/value.test.ts
@@ -9,7 +9,7 @@ import {
parsePlutusValueToAssets,
Value,
value,
-} from "../../src";
+} from "@meshsdk/common";
describe("value", () => {
test("Simple ADA Value", () => {
diff --git a/packages/mesh-core-csl/package.json b/packages/mesh-core-csl/package.json
index d212607d..9edef3e6 100644
--- a/packages/mesh-core-csl/package.json
+++ b/packages/mesh-core-csl/package.json
@@ -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..f5bc705d 100644
--- a/packages/mesh-core-csl/src/core/serializer.ts
+++ b/packages/mesh-core-csl/src/core/serializer.ts
@@ -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());
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..a2cf110a 100644
--- a/packages/mesh-core-cst/package.json
+++ b/packages/mesh-core-cst/package.json
@@ -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/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/.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..244ee2af 100644
--- a/packages/mesh-provider/package.json
+++ b/packages/mesh-provider/package.json
@@ -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/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-wallet/package.json b/packages/mesh-wallet/package.json
index d2a45f08..569239dd 100644
--- a/packages/mesh-wallet/package.json
+++ b/packages/mesh-wallet/package.json
@@ -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"
},
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({
From a8dc534c1a144b77a7600e413b16dc18cfec1bae Mon Sep 17 00:00:00 2001
From: SIDANPillow
Date: Sat, 3 Aug 2024 11:23:45 +0800
Subject: [PATCH 02/17] feat:update value implementation
---
packages/mesh-common/src/data/value.ts | 182 +++++++++++++++++++++++++
1 file changed, 182 insertions(+)
diff --git a/packages/mesh-common/src/data/value.ts b/packages/mesh-common/src/data/value.ts
index f88b7089..5599af87 100644
--- a/packages/mesh-common/src/data/value.ts
+++ b/packages/mesh-common/src/data/value.ts
@@ -68,3 +68,185 @@ export const parsePlutusValueToAssets = (plutusValue: Value): Asset[] => {
return assets;
};
+
+export class MMValue {
+ value: Record;
+
+ constructor() {
+ this.value = {};
+ }
+
+ /**
+ * Add an asset to the Value class's value record. If an asset with the same unit already exists in the value record, the quantity of the
+ * existing asset will be increased by the quantity of the new asset. If no such asset exists, the new asset will be added to the value record.
+ * Implementation:
+ * 1. Check if the unit of the asset already exists in the value record.
+ * 2. If the unit exists, add the new quantity to the existing quantity.
+ * 3. If the unit does not exist, add the unti to the object.
+ * 4. Return the Value class instance.
+ * @param asset
+ * @returns this
+ */
+ addAsset = (asset: Asset): this => {
+ const quantity = BigInt(asset.quantity);
+ const { unit } = asset;
+
+ 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. If an asset with the same unit already exists in the value record, the quantity of the
+ * existing asset will be increased by the quantity of the new asset. If no such asset exists, the new assets under the array of assets will be added to the value record.
+ * Implementation:
+ * 1. Iterate over each asset in the 'assets' array.
+ * 2. For each asset, check if the unit of the asset already exists in the value record.
+ * 3. If the unit exists, add the new quantity to the existing quantity.
+ * 4. If the unit does not exist, add the unti to the object.
+ * 5. Return the Value class instance.
+ * @param assets
+ * @returns this
+ */
+ addAssets = (assets: Asset[]): this => {
+ assets.forEach((asset) => {
+ this.addAsset(asset);
+ });
+ return this;
+ };
+
+ /**
+ * Substract an asset from the Value class's value record. If an asset with the same unit already exists in the value record, the quantity of the
+ * existing asset will be decreased by the quantity of the new asset. If no such asset exists, an error message should be printed.
+ * Implementation:
+ * 1. Check if the unit of the asset already exists in the value record.
+ * 2. If the unit exists, subtract the new quantity from the existing quantity.
+ * 3. If the unit does not exist, print an error message.
+ * @param asset
+ * @returns this
+ */
+ negateAsset = (asset: Asset): this => {
+ const { unit, quantity } = asset;
+
+ const currentQuantity = this.value[unit] || BigInt(0);
+ const newQuantity = currentQuantity - BigInt(quantity);
+
+ if (newQuantity === BigInt(0)) {
+ delete this.value[unit];
+ } else {
+ this.value[unit] = newQuantity;
+ }
+ return this;
+ };
+
+ /**
+ * Subtract an array of assets from the Value class's value record. If an asset with the same unit already exists in the value record, the quantity of the
+ * existing asset will be decreased by the quantity of the new asset. If no such asset exists, an error message should be printed.
+ * @param assets
+ * @returns this
+ */
+ negateAssets = (assets: Asset[]): this => {
+ assets.forEach((asset) => {
+ this.negateAsset(asset);
+ });
+ return this;
+ };
+
+ /**
+ * Get the quantity of asset object per unit
+ * @param unit
+ * @returns
+ */
+ get = (unit: string): bigint => {
+ return this.value[unit] ? BigInt(this.value[unit]) : BigInt(0);
+ };
+
+ /**
+ * Get all assets (return Record of Asset[])
+ * @param
+ * @returns Record
+ */
+ units = (): Record => {
+ const result: Record = {};
+ Object.keys(this.value).forEach((unit) => {
+ if (!result[unit]) {
+ result[unit] = [];
+ }
+ result[unit].push({ unit, quantity: BigInt(this.value[unit]) });
+ });
+ return result;
+ };
+
+ /**
+ * Check if the value is greater than or equal to an inputted value
+ * @param unit - The unit to compare (e.g., "ADA")
+ * @param other - The value to compare against
+ * @returns boolean
+ */
+ // geq = (unit: string, other: Value): boolean => {
+ // const thisValue = this.get(unit);
+ // const otherValue = other.get(unit);
+ // return thisValue >= otherValue;
+ // };
+
+ geq = (unit: string, other: Value): 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 an inputted value
+ * @param unit - The unit to compare (e.g., "ADA")
+ * @param other - The value to compare against
+ * @returns boolean
+ */
+ // leq = (unit: string, other: Value): boolean => {
+ // const thisValue = this.get(unit);
+ // const otherValue = other.get(unit);
+ // if (otherValue === undefined) {
+ // return false;
+ // }
+
+ // return thisValue <= otherValue;
+ // };
+
+ leq = (unit: string, other: Value): 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
+ * @param
+ * @returns boolean
+ */
+ isEmpty = (): boolean => {
+ return Object.keys(this.value).length === 0;
+ };
+
+ /**
+ * Merge the given values
+ * @param values
+ * @returns this
+ */
+ merge = (values: Value | Value[]): 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 this;
+ };
+}
\ No newline at end of file
From c0fbb2f5592b8e24032be02671f36ae19055450d Mon Sep 17 00:00:00 2001
From: SIDANWhatever
Date: Sat, 3 Aug 2024 11:27:10 +0800
Subject: [PATCH 03/17] wip
---
apps/playground/src/data/links-api.ts | 4 +-
.../pages/apis/txbuilder/minting/index.tsx | 2 +
.../minting/minting-royalty-token.tsx | 188 ++++++++++++++++++
.../src/utils/asset-fingerprint.ts | 2 +-
.../mesh-transaction/src/transaction/index.ts | 130 ++++++++----
5 files changed, 288 insertions(+), 38 deletions(-)
create mode 100644 apps/playground/src/pages/apis/txbuilder/minting/minting-royalty-token.tsx
diff --git a/apps/playground/src/data/links-api.ts b/apps/playground/src/data/links-api.ts
index b0975b52..35c0fabd 100644
--- a/apps/playground/src/data/links-api.ts
+++ b/apps/playground/src/data/links-api.ts
@@ -3,14 +3,14 @@ import { metaData } from "./links-data";
import { metaProviders } from "./links-providers";
import { metaReact } from "./links-react";
import { metaTransaction } from "./links-transactions";
-// import { metaTxbuilder } from "./links-txbuilders";
+import { metaTxbuilder } from "./links-txbuilders";
import { metaUtilities } from "./links-utilities";
import { metaWallets } from "./links-wallets";
export const linksApi: MenuItem[] = [
metaWallets,
metaTransaction,
- // metaTxbuilder, // todo, work on txbuilder docs
+ metaTxbuilder, // todo, work on txbuilder docs
metaData,
metaReact,
metaProviders,
diff --git a/apps/playground/src/pages/apis/txbuilder/minting/index.tsx b/apps/playground/src/pages/apis/txbuilder/minting/index.tsx
index 30339ac0..a07c4acb 100644
--- a/apps/playground/src/pages/apis/txbuilder/minting/index.tsx
+++ b/apps/playground/src/pages/apis/txbuilder/minting/index.tsx
@@ -9,6 +9,7 @@ import TxbuilderMintingCip68 from "./minting-cip68";
import TxbuilderMintingNativeScript from "./minting-native-script";
import TxbuilderMintAsset from "./minting-one-signature";
import TxbuilderMintingPlutusScript from "./minting-plutus-script";
+import TxbuilderMintingRoyaltyToken from "./minting-royalty-token";
const ReactPage: NextPage = () => {
const sidebarItems = [
@@ -42,6 +43,7 @@ const ReactPage: NextPage = () => {
+
>
);
diff --git a/apps/playground/src/pages/apis/txbuilder/minting/minting-royalty-token.tsx b/apps/playground/src/pages/apis/txbuilder/minting/minting-royalty-token.tsx
new file mode 100644
index 00000000..30a2ac88
--- /dev/null
+++ b/apps/playground/src/pages/apis/txbuilder/minting/minting-royalty-token.tsx
@@ -0,0 +1,188 @@
+import { useState } from "react";
+import Link from "next/link";
+
+import {
+ ForgeScript,
+ MeshTxBuilder,
+ Mint,
+ resolveScriptHash,
+ RoyaltiesStandard,
+ Transaction,
+} from "@meshsdk/core";
+import { useWallet } from "@meshsdk/react";
+
+import Input from "~/components/form/input";
+import InputTable from "~/components/sections/input-table";
+import LiveCodeDemo from "~/components/sections/live-code-demo";
+import TwoColumnsScroll from "~/components/sections/two-columns-scroll";
+import Codeblock from "~/components/text/codeblock";
+import { demoAddresses } from "~/data/cardano";
+
+export default function MintingRoyaltyToken() {
+ return (
+
+ );
+}
+
+function Left() {
+ let codeSnippet = ``;
+ codeSnippet += `const usedAddress = await wallet.getUsedAddresses();\n`;
+ codeSnippet += `const address = usedAddress[0];\n`;
+ codeSnippet += `\n`;
+ codeSnippet += `// create forgingScript, you can also use native script here\n`;
+ codeSnippet += `const forgingScript = ForgeScript.withOneSignature(address);\n`;
+ codeSnippet += `\n`;
+ codeSnippet += `const tx = new Transaction({ initiator: wallet });\n`;
+ codeSnippet += `\n`;
+ codeSnippet += `const _assetMetadata = {\n`;
+ codeSnippet += ` rate: '0.2',\n`;
+ codeSnippet += ` addr: '${demoAddresses.testnet}'\n`;
+ codeSnippet += `};\n`;
+ codeSnippet += `const asset: Mint = {\n`;
+ codeSnippet += ` assetName: '',\n`;
+ codeSnippet += ` assetQuantity: '1',\n`;
+ codeSnippet += ` metadata: _assetMetadata,\n`;
+ codeSnippet += ` label: '777',\n`;
+ codeSnippet += ` recipient: address,\n`;
+ codeSnippet += `};\n`;
+ codeSnippet += `\n`;
+ codeSnippet += `tx.mintAsset(forgingScript, asset);\n`;
+ codeSnippet += `\n`;
+ codeSnippet += `const unsignedTx = await tx.build();\n`;
+ codeSnippet += `const signedTx = await wallet.signTx(unsignedTx);\n`;
+ codeSnippet += `const txHash = await wallet.submitTx(signedTx);\n`;
+
+ return (
+ <>
+
+ Royalty tokens is a special type of token that allows the creator to
+ collect a royalty fee, this proposed standard will allow for uniform
+ royalties' distributions across the secondary market space. Read{" "}
+
+ CIP-27
+ {" "}
+ for more information.
+
+
+ The implementation of royalty tokens is very simple, minting a token
+ with 777 label, with "rate" and "addr" in the metadata.
+
+
+
Here is the full code:
+
+ >
+ );
+}
+
+function Right() {
+ const { wallet, connected } = useWallet();
+ const [userInput, setUserInput] = useState("0.2");
+ const [userInput2, setUserInput2] = useState(demoAddresses.testnet);
+
+ async function runDemo() {
+ const utxos = await wallet.getUtxos();
+ const usedAddress = await wallet.getUsedAddresses();
+ const address = usedAddress[0];
+
+ if (address === undefined) {
+ throw "No address found";
+ }
+
+ const forgingScript = ForgeScript.withOneSignature(address);
+ const policyId = resolveScriptHash(forgingScript);
+
+ const assetMetadata: RoyaltiesStandard = {
+ rate: userInput,
+ address: userInput2,
+ };
+
+ const metadata = { [policyId]: { [""]: { ...assetMetadata } } };
+
+ const txBuilder = new MeshTxBuilder();
+
+ const unsignedTx = await txBuilder
+ .mint("1", policyId, "")
+ .mintingScript(forgingScript)
+ .metadataValue("777", metadata)
+ .changeAddress(address)
+ .selectUtxosFrom(utxos)
+ .complete();
+
+ const signedTx = await wallet.signTx(unsignedTx);
+ const txHash = await wallet.submitTx(signedTx);
+
+ return txHash;
+ }
+
+ let code = ``;
+ code += `const usedAddress = await wallet.getUsedAddresses();\n`;
+ code += `const address = usedAddress[0];\n`;
+ code += `\n`;
+ code += `const forgingScript = ForgeScript.withOneSignature(address);\n`;
+ code += `\n`;
+ code += `const tx = new Transaction({ initiator: wallet });\n`;
+ code += `\n`;
+ code += `const _assetMetadata: RoyaltiesStandard = {\n`;
+ code += ` rate: '${userInput}',\n`;
+ code += ` address: '${userInput2}',\n`;
+ code += `};\n`;
+ code += `const asset: Mint = {\n`;
+ code += ` assetName: "",\n`;
+ code += ` assetQuantity: "1",\n`;
+ code += ` metadata: _assetMetadata,\n`;
+ code += ` label: "777",\n`;
+ code += ` recipient: address,\n`;
+ code += `};\n`;
+ code += `\n`;
+ code += `tx.mintAsset(forgingScript, asset);\n`;
+ code += `\n`;
+ code += `const unsignedTx = await tx.build();\n`;
+ code += `const signedTx = await wallet.signTx(unsignedTx);\n`;
+ code += `const txHash = await wallet.submitTx(signedTx);\n`;
+
+ return (
+
+ setUserInput(e.target.value)}
+ placeholder="Rate"
+ label="Rate"
+ key={0}
+ />,
+ ]}
+ />
+ setUserInput2(e.target.value)}
+ placeholder="Address"
+ label="Address"
+ key={1}
+ />,
+ ]}
+ />
+
+ );
+}
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-transaction/src/transaction/index.ts b/packages/mesh-transaction/src/transaction/index.ts
index 0113311c..883b5675 100644
--- a/packages/mesh-transaction/src/transaction/index.ts
+++ b/packages/mesh-transaction/src/transaction/index.ts
@@ -1,37 +1,40 @@
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;
}
export class Transaction {
+ private mints: Mint[] = [];
txBuilder: MeshTxBuilder;
initiator: IInitiator;
isCollateralNeeded: boolean = false;
@@ -145,7 +148,7 @@ export class Transaction {
input.input.txHash,
input.input.outputIndex,
input.output.amount,
- input.output.address
+ input.output.address,
);
});
@@ -162,7 +165,7 @@ export class Transaction {
inputs.forEach((input) => {
this.txBuilder.readOnlyTxInReference(
input.input.txHash,
- input.input.outputIndex
+ input.input.outputIndex,
);
});
@@ -178,14 +181,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 +216,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 +238,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 +270,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 +296,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 +340,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 +348,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 +358,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 +371,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 +387,12 @@ export class Transaction {
unit: policyId + referenceAssetNameHex,
quantity: mint.assetQuantity,
},
- ]
+ ],
);
}
+ if (!mint.cip68ScriptAddress && mint.metadata && mint.label) {
+ this.mints.push(mint);
+ }
return this;
}
@@ -404,7 +402,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 +441,7 @@ export class Transaction {
collateralUtxo.input.txHash,
collateralUtxo.input.outputIndex,
collateralUtxo.output.amount,
- collateralUtxo.output.address
+ collateralUtxo.output.address,
);
});
@@ -511,23 +509,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;
}
@@ -549,11 +551,12 @@ export class Transaction {
await this.addCollateralIfNeeded();
await this.addTxInputsAsNeeded();
await this.addChangeAddress();
+ this.addMintMetadata();
return this.txBuilder.complete();
} catch (error) {
throw new Error(
- `[Transaction] An error occurred during build: ${error}.`
+ `[Transaction] An error occurred during build: ${error}.`,
);
}
}
@@ -588,6 +591,63 @@ export class Transaction {
return this.txBuilder;
}
+ protected addMintMetadata() {
+ // type Mintdata = { unit: string; data: Mint };
+ // type Metadata = Record>;
+ // const forge = (mint: Mintdata, meta?: Metadata): Metadata => {
+ // const name = mint.data.assetName;
+ // const metadata = mint.data.metadata;
+ // const collection = mint.unit.slice(0, POLICY_ID_LENGTH);
+ // if (mint.data.label === "777") {
+ // return metadata as any; // TODO: fix this
+ // }
+ // if (meta && meta[collection]) {
+ // const { [collection]: oldCollection, ...rest } = meta;
+ // const newCollection = {
+ // [name]: metadata,
+ // ...oldCollection,
+ // };
+ // return {
+ // [collection]: {
+ // ...newCollection,
+ // },
+ // ...rest,
+ // };
+ // }
+ // if (meta !== undefined) {
+ // return {
+ // [collection]: {
+ // [name]: metadata,
+ // },
+ // ...meta,
+ // };
+ // }
+ // return {
+ // [collection]: { [name]: metadata },
+ // };
+ // };
+ // Array.from(
+ // this.mints,
+ // (mint) =>
+ // {
+ // unit: mint[0],
+ // data: mint[1],
+ // }
+ // )
+ // .reduce((metadatums, mint) => {
+ // return metadatums.set(
+ // mint.data.label,
+ // forge(mint, metadatums.get(mint.data.label))
+ // );
+ // }, new Map())
+ // .forEach((metadata, label) => {
+ // this._txBuilder.add_json_metadatum(
+ // csl.BigNum.from_str(label),
+ // JSON.stringify(metadata)
+ // );
+ // });
+ }
+
private async addCollateralIfNeeded() {
if (this.isCollateralNeeded) {
const collaterals = await this.initiator.getCollateral();
From a02d7870f1c5750a8468d46df728dbebf6aa871e Mon Sep 17 00:00:00 2001
From: SIDANPillow
Date: Sat, 3 Aug 2024 11:32:28 +0800
Subject: [PATCH 04/17] feat:add value test cases
---
packages/mesh-common/test/data/value.test.ts | 317 +++++++++++++++++++
1 file changed, 317 insertions(+)
diff --git a/packages/mesh-common/test/data/value.test.ts b/packages/mesh-common/test/data/value.test.ts
index 82267685..1488a5fb 100644
--- a/packages/mesh-common/test/data/value.test.ts
+++ b/packages/mesh-common/test/data/value.test.ts
@@ -106,3 +106,320 @@ describe("Value", () => {
expect(JSON.stringify(val)).toBe(JSON.stringify(assets));
});
});
+
+// tests/value.test.ts
+import { Asset } from '@meshsdk/core';
+import { Value } from '../src/types';
+
+describe('Value class', () => {
+ describe('addAsset', () => {
+ it('should add a new asset correctly', () => {
+ const value = new Value();
+ const singleAsset: Asset = { unit: 'USDM', quantity: '100' };
+ value.addAsset(singleAsset);
+ // Assertions to verify the behavior of addAsset...
+ expect(value.value).toEqual({ USDM: BigInt(100) });
+ });
+ it('should add to an existing asset correctly', () => {
+ const value = new Value();
+ const singleAsset: Asset = { unit: 'USDM', quantity: '100' };
+ value.addAsset(singleAsset);
+ value.addAsset(singleAsset);
+ // Assertions to verify the behavior of addAsset...
+ expect(value.value).toEqual({ USDM: BigInt(200) });
+ });
+ it('should add multiple assets correctly', () => {
+ const value = new Value();
+ const assets: Asset[] = [
+ { unit: 'USDM', quantity: '100' },
+ { unit: 'ADA', quantity: '10' },
+ ];
+ value.addAsset(assets[0]).addAsset(assets[1]);
+ // Assertions to verify the behavior of addAsset...
+ expect(value.value).toEqual({ USDM: BigInt(100), ADA: BigInt(10) });
+ });
+ });
+ describe('addAssets', () => {
+ it('should add multiple assets correctly', () => {
+ const value = new Value();
+ const assets: Asset[] = [
+ { unit: 'USDM', quantity: '100' },
+ { unit: 'ADA', quantity: '10' },
+ { unit: 'USDM', quantity: '100' },
+ { unit: 'ADA', quantity: '10' },
+ ];
+ value.addAssets(assets);
+ // Assertions to verify the behavior of addAssets...
+ expect(value.value).toEqual({ USDM: BigInt(200), ADA: BigInt(20) });
+ });
+ it('should add multiple assets correctly with different units', () => {
+ const value = new Value();
+ const assets: Asset[] = [
+ { unit: 'USDM', quantity: '100' },
+ { unit: 'ADA', quantity: '10' },
+ { unit: 'USDC', quantity: '100' },
+ { unit: 'ADA', quantity: '10' },
+ ];
+ value.addAssets(assets);
+ // Assertions to verify the behavior of addAssets...
+ expect(value.value).toEqual({ USDM: BigInt(100), ADA: BigInt(20), USDC: BigInt(100) });
+ });
+ });
+ describe('negateAsset', () => {
+ describe('negateAsset', () => {
+ it('should subtract quantity from an existing asset', () => {
+ const value = new Value();
+ value.value = { ADA: 10n };
+ value.negateAsset({ unit: 'ADA', quantity: '5' });
+ expect(value.value).toEqual({ ADA: BigInt(5) });
+ });
+
+ it('should remove the asset if the resulting quantity is zero', () => {
+ const value = new Value();
+ value.value = { ADA: 10n };
+ value.negateAsset({ unit: 'ADA', quantity: '10' });
+ expect(value.value.ADA).toBeUndefined();
+ });
+
+ it('should allow negative quantity if the subtraction results in negative value', () => {
+ const value = new Value();
+ value.value = { ADA: 10n };
+ value.negateAsset({ unit: 'ADA', quantity: '15' });
+ expect(value.value).toEqual({ ADA: BigInt(-5) });
+ });
+
+ it('should add a new asset with negative quantity if the asset does not exist', () => {
+ const value = new Value();
+ value.negateAsset({ unit: 'ADA', quantity: '5' });
+ expect(value.value).toEqual({ ADA: BigInt(-5) });
+ });
+ });
+ });
+ describe('negateAssets', () => {
+ it('should subtract quantities from existing assets', () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ value.negateAssets([
+ { unit: 'ADA', quantity: '5' },
+ { unit: 'BTC', quantity: '3' },
+ ]);
+ expect(value.value).toEqual({ ADA: BigInt(15), BTC: BigInt(7) });
+ });
+
+ it('should remove the asset if the resulting quantity is zero', () => {
+ const value = new Value();
+ value.value = { ADA: 10n, BTC: 5n };
+ value.negateAssets([
+ { unit: 'ADA', quantity: '10' },
+ { unit: 'BTC', quantity: '5' },
+ ]);
+ expect(value.value.ADA).toBeUndefined();
+ expect(value.value.BTC).toBeUndefined();
+ });
+
+ it('should allow negative quantity if the subtraction results in negative value', () => {
+ const value = new Value();
+ value.value = { ADA: 10n, BTC: 5n };
+ value.negateAssets([
+ { unit: 'ADA', quantity: '15' },
+ { unit: 'BTC', quantity: '10' },
+ ]);
+ expect(value.value).toEqual({ ADA: BigInt(-5), BTC: BigInt(-5) });
+ });
+
+ it('should add new assets with negative quantities if the assets do not exist', () => {
+ const value = new Value();
+ value.negateAssets([
+ { unit: 'ADA', quantity: '5' },
+ { unit: 'BTC', quantity: '3' },
+ ]);
+ expect(value.value).toEqual({ ADA: BigInt(-5), BTC: BigInt(-3) });
+ });
+
+ it('should handle a mix of existing and non-existing assets', () => {
+ const value = new Value();
+ value.value = { ADA: 10n };
+ value.negateAssets([
+ { unit: 'ADA', quantity: '5' },
+ { unit: 'BTC', quantity: '3' },
+ ]);
+ expect(value.value).toEqual({ ADA: BigInt(5), BTC: BigInt(-3) });
+ });
+ });
+ describe('get', () => {
+ it('should return the quantity of an existing asset', () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ expect(value.get('ADA')).toEqual(BigInt(20));
+ expect(value.get('BTC')).toEqual(BigInt(10));
+ });
+
+ it('should return 0 for a non-existing asset', () => {
+ const value = new Value();
+ value.value = { ADA: 20n };
+ expect(value.get('BTC')).toEqual(BigInt(0));
+ });
+
+ it('should handle an empty value object', () => {
+ const value = new Value();
+ expect(value.get('ADA')).toEqual(BigInt(0));
+ });
+
+ it('should return the correct quantity after adding assets', () => {
+ const value = new Value();
+ value.value = { ADA: 20n };
+ value.addAsset({ unit: 'BTC', quantity: '10' });
+ expect(value.get('BTC')).toEqual(BigInt(10));
+ });
+
+ it('should return the correct quantity after subtracting assets', () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ value.negateAssets([{ unit: 'BTC', quantity: '5' }]);
+ expect(value.get('BTC')).toEqual(BigInt(5));
+ });
+ });
+ describe('units', () => {
+ it('should return an empty object when value is empty', () => {
+ const value = new Value();
+ value.value = {};
+ expect(value.units()).toEqual({});
+ });
+
+ it('should return the correct structure for a single asset', () => {
+ const value = new Value();
+ value.value = { ADA: 20n };
+ expect(value.units()).toEqual({
+ ADA: [{ unit: 'ADA', quantity: BigInt(20) }],
+ });
+ });
+
+ it('should return the correct structure for multiple assets', () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ expect(value.units()).toEqual({
+ ADA: [{ unit: 'ADA', quantity: BigInt(20) }],
+ BTC: [{ unit: 'BTC', quantity: BigInt(10) }],
+ });
+ });
+
+ it('should handle both positive and negative quantities correctly', () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: -10n };
+ expect(value.units()).toEqual({
+ ADA: [{ unit: 'ADA', quantity: BigInt(20) }],
+ BTC: [{ unit: 'BTC', quantity: BigInt(-10) }],
+ });
+ });
+ });
+ 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 Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ADA: 10n, BTC: 5n };
+ expect(value.geq('ADA', target)).toBe(true);
+ expect(value.geq('BTC', target)).toBe(true);
+ });
+
+ it('should return false if the value is less than the target value for a specific unit', () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ADA: 30n, BTC: 15n };
+ expect(value.geq('ADA', target)).toBe(false);
+ expect(value.geq('BTC', target)).toBe(false);
+ });
+
+ it('should return true if the value is equal to the target value for a specific unit', () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ADA: 20n, BTC: 10n };
+ expect(value.geq('ADA', target)).toBe(true);
+ expect(value.geq('BTC', target)).toBe(true);
+ });
+
+ it('should return false if the unit does not exist in value.value', () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ETH: 5n };
+ expect(value.geq('ETH', 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 Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ADA: 30n, BTC: 15n };
+ expect(value.leq('ADA', target)).toBe(true);
+ expect(value.leq('BTC', target)).toBe(true);
+ });
+
+ it('should return false if the value is greater than the target value for a specific unit', () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ADA: 10n, BTC: 5n };
+ expect(value.leq('ADA', target)).toBe(false);
+ expect(value.leq('BTC', target)).toBe(false);
+ });
+
+ it('should return true if the value is equal to the target value for a specific unit', () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ADA: 20n, BTC: 10n };
+ expect(value.leq('ADA', target)).toBe(true);
+ expect(value.leq('BTC', target)).toBe(true);
+ });
+
+ it('should return false if the unit does not exist in value.value', () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ETH: 5n };
+ expect(value.leq('ETH', target)).toBe(false);
+ });
+ });
+ describe('isEmpty', () => {
+ it('should return true if the value is empty', () => {
+ const value = new Value();
+ value.value = {};
+ expect(value.isEmpty()).toBe(true);
+ });
+
+ it('should return false if the value is not empty', () => {
+ const value = new Value();
+ value.value = { ADA: 20n };
+ expect(value.isEmpty()).toBe(false);
+ });
+ });
+ describe('merge', () => {
+ it('should merge two values correctly', () => {
+ const value1 = new Value();
+ value1.value = { ADA: 20n, BTC: 10n };
+ const value2 = new Value();
+ value2.value = { ADA: 10n, BTC: 5n };
+ expect(value1.merge(value2).value).toEqual({ ADA: 30n, BTC: 15n });
+ });
+
+ it('should merge two values correctly with different units', () => {
+ const value1 = new Value();
+ value1.value = { ADA: 20n, BTC: 10n };
+ const value2 = new Value();
+ value2.value = { ETH: 10n, BTC: 5n };
+ expect(value1.merge(value2).value).toEqual({ ADA: 20n, BTC: 15n, ETH: 10n });
+ });
+
+ it('should merge two values correctly with negative quantities', () => {
+ const value1 = new Value();
+ value1.value = { ADA: 20n, BTC: -10n };
+ const value2 = new Value();
+ value2.value = { ADA: 10n, BTC: 5n };
+ expect(value1.merge(value2).value).toEqual({ ADA: 30n, BTC: -5n });
+ });
+ });
+});
\ No newline at end of file
From 423cc4a687fa3ce5c575ce566447b42e80b54715 Mon Sep 17 00:00:00 2001
From: SIDANPillow
Date: Sat, 3 Aug 2024 11:37:55 +0800
Subject: [PATCH 05/17] feat:comment out some value implementation and test
cases
---
package-lock.json | 37 +-
packages/mesh-common/src/data/value.ts | 459 +++++-----
packages/mesh-common/test/data/value.test.ts | 839 ++++++++++---------
3 files changed, 677 insertions(+), 658 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 8381022c..3aa6bcad 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8943,6 +8943,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 +11878,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 +14679,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 +14691,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 +18878,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 +18887,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 +18903,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 +20477,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 +20833,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 +20845,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 +21040,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 +21056,7 @@
},
"packages/mesh-contract": {
"name": "@meshsdk/contract",
- "version": "1.5.32",
+ "version": "1.6.1",
"license": "Apache-2.0",
"dependencies": {
"@meshsdk/common": "*",
@@ -21064,7 +21075,7 @@
},
"packages/mesh-core": {
"name": "@meshsdk/core",
- "version": "1.5.32",
+ "version": "1.6.1",
"license": "Apache-2.0",
"dependencies": {
"@meshsdk/common": "*",
@@ -21085,7 +21096,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 +21116,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 +21139,7 @@
},
"packages/mesh-provider": {
"name": "@meshsdk/provider",
- "version": "1.5.32",
+ "version": "1.6.1",
"license": "Apache-2.0",
"dependencies": {
"@meshsdk/common": "*",
@@ -21144,7 +21155,7 @@
},
"packages/mesh-react": {
"name": "@meshsdk/react",
- "version": "1.5.32",
+ "version": "1.6.1",
"license": "Apache-2.0",
"dependencies": {
"@meshsdk/common": "*",
@@ -21166,7 +21177,7 @@
},
"packages/mesh-transaction": {
"name": "@meshsdk/transaction",
- "version": "1.5.32",
+ "version": "1.6.1",
"license": "Apache-2.0",
"dependencies": {
"@meshsdk/common": "*",
@@ -21184,7 +21195,7 @@
},
"packages/mesh-wallet": {
"name": "@meshsdk/wallet",
- "version": "1.5.32",
+ "version": "1.6.1",
"license": "Apache-2.0",
"dependencies": {
"@meshsdk/common": "*",
diff --git a/packages/mesh-common/src/data/value.ts b/packages/mesh-common/src/data/value.ts
index 5599af87..1da217e6 100644
--- a/packages/mesh-common/src/data/value.ts
+++ b/packages/mesh-common/src/data/value.ts
@@ -15,238 +15,239 @@ import {
tokenName,
} from "./json";
-export type Value = AssocMap>;
-
-export type MValue = Map>;
-
-export const value = (assets: Asset[]): Value => {
- const valueMapToParse: [CurrencySymbol, AssocMap][] = [];
- const valueMap: { [key: string]: { [key: string]: number } } = {};
-
- assets.forEach((asset) => {
- const sanitizedName = asset.unit.replace("lovelace", "");
- const policy = sanitizedName.slice(0, 56) || "";
- const token = sanitizedName.slice(56) || "";
-
- if (!valueMap[policy]) {
- valueMap[policy] = {};
+// export type Value = AssocMap>;
+
+// export type MValue = Map>;
+
+// export const value = (assets: Asset[]): Value => {
+// const valueMapToParse: [CurrencySymbol, AssocMap][] = [];
+// const valueMap: { [key: string]: { [key: string]: number } } = {};
+
+// assets.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);
+// };
+
+// 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 });
+// });
+// });
+
+// return assets;
+// };
+
+export class Value {
+ value: Record;
+
+ constructor() {
+ this.value = {};
+ }
+
+ /**
+ * Add an asset to the Value class's value record. If an asset with the same unit already exists in the value record, the quantity of the
+ * existing asset will be increased by the quantity of the new asset. If no such asset exists, the new asset will be added to the value record.
+ * Implementation:
+ * 1. Check if the unit of the asset already exists in the value record.
+ * 2. If the unit exists, add the new quantity to the existing quantity.
+ * 3. If the unit does not exist, add the unti to the object.
+ * 4. Return the Value class instance.
+ * @param asset
+ * @returns this
+ */
+ addAsset = (asset: Asset): this => {
+ const quantity = BigInt(asset.quantity);
+ const { unit } = asset;
+
+ if (this.value[unit]) {
+ this.value[unit] += quantity;
+ } else {
+ this.value[unit] = quantity;
}
-
- if (!valueMap[policy]![token]) {
- valueMap[policy]![token] = Number(asset.quantity);
+ return this;
+ };
+
+ /**
+ * Add an array of assets to the Value class's value record. If an asset with the same unit already exists in the value record, the quantity of the
+ * existing asset will be increased by the quantity of the new asset. If no such asset exists, the new assets under the array of assets will be added to the value record.
+ * Implementation:
+ * 1. Iterate over each asset in the 'assets' array.
+ * 2. For each asset, check if the unit of the asset already exists in the value record.
+ * 3. If the unit exists, add the new quantity to the existing quantity.
+ * 4. If the unit does not exist, add the unti to the object.
+ * 5. Return the Value class instance.
+ * @param assets
+ * @returns this
+ */
+ addAssets = (assets: Asset[]): this => {
+ assets.forEach((asset) => {
+ this.addAsset(asset);
+ });
+ return this;
+ };
+
+ /**
+ * Substract an asset from the Value class's value record. If an asset with the same unit already exists in the value record, the quantity of the
+ * existing asset will be decreased by the quantity of the new asset. If no such asset exists, an error message should be printed.
+ * Implementation:
+ * 1. Check if the unit of the asset already exists in the value record.
+ * 2. If the unit exists, subtract the new quantity from the existing quantity.
+ * 3. If the unit does not exist, print an error message.
+ * @param asset
+ * @returns this
+ */
+ negateAsset = (asset: Asset): this => {
+ const { unit, quantity } = asset;
+
+ const currentQuantity = this.value[unit] || BigInt(0);
+ const newQuantity = currentQuantity - BigInt(quantity);
+
+ if (newQuantity === BigInt(0)) {
+ delete this.value[unit];
} else {
- valueMap[policy]![token] += Number(asset.quantity);
+ this.value[unit] = newQuantity;
}
- });
-
- 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);
-};
-
-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 });
+ return this;
+ };
+
+ /**
+ * Subtract an array of assets from the Value class's value record. If an asset with the same unit already exists in the value record, the quantity of the
+ * existing asset will be decreased by the quantity of the new asset. If no such asset exists, an error message should be printed.
+ * @param assets
+ * @returns this
+ */
+ negateAssets = (assets: Asset[]): this => {
+ assets.forEach((asset) => {
+ this.negateAsset(asset);
});
- });
-
- return assets;
-};
-
-export class MMValue {
- value: Record;
-
- constructor() {
- this.value = {};
+ return this;
+ };
+
+ /**
+ * Get the quantity of asset object per unit
+ * @param unit
+ * @returns
+ */
+ get = (unit: string): bigint => {
+ return this.value[unit] ? BigInt(this.value[unit]) : BigInt(0);
+ };
+
+ /**
+ * Get all assets (return Record of Asset[])
+ * @param
+ * @returns Record
+ */
+ units = (): Record => {
+ const result: Record = {};
+ Object.keys(this.value).forEach((unit) => {
+ if (!result[unit]) {
+ result[unit] = [];
+ }
+ result[unit].push({ unit, quantity: BigInt(this.value[unit]) });
+ });
+ return result;
+ };
+
+ /**
+ * Check if the value is greater than or equal to an inputted value
+ * @param unit - The unit to compare (e.g., "ADA")
+ * @param other - The value to compare against
+ * @returns boolean
+ */
+ // geq = (unit: string, other: Value): boolean => {
+ // const thisValue = this.get(unit);
+ // const otherValue = other.get(unit);
+ // return thisValue >= otherValue;
+ // };
+
+ geq = (unit: string, other: Value): 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 an inputted value
+ * @param unit - The unit to compare (e.g., "ADA")
+ * @param other - The value to compare against
+ * @returns boolean
+ */
+ // leq = (unit: string, other: Value): boolean => {
+ // const thisValue = this.get(unit);
+ // const otherValue = other.get(unit);
+ // if (otherValue === undefined) {
+ // return false;
+ // }
+
+ // return thisValue <= otherValue;
+ // };
+
+ leq = (unit: string, other: Value): 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
+ * @param
+ * @returns boolean
+ */
+ isEmpty = (): boolean => {
+ return Object.keys(this.value).length === 0;
+ };
+
+ /**
+ * Merge the given values
+ * @param values
+ * @returns this
+ */
+ merge = (values: Value | Value[]): 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);
+ });
+ });
- /**
- * Add an asset to the Value class's value record. If an asset with the same unit already exists in the value record, the quantity of the
- * existing asset will be increased by the quantity of the new asset. If no such asset exists, the new asset will be added to the value record.
- * Implementation:
- * 1. Check if the unit of the asset already exists in the value record.
- * 2. If the unit exists, add the new quantity to the existing quantity.
- * 3. If the unit does not exist, add the unti to the object.
- * 4. Return the Value class instance.
- * @param asset
- * @returns this
- */
- addAsset = (asset: Asset): this => {
- const quantity = BigInt(asset.quantity);
- const { unit } = asset;
-
- 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. If an asset with the same unit already exists in the value record, the quantity of the
- * existing asset will be increased by the quantity of the new asset. If no such asset exists, the new assets under the array of assets will be added to the value record.
- * Implementation:
- * 1. Iterate over each asset in the 'assets' array.
- * 2. For each asset, check if the unit of the asset already exists in the value record.
- * 3. If the unit exists, add the new quantity to the existing quantity.
- * 4. If the unit does not exist, add the unti to the object.
- * 5. Return the Value class instance.
- * @param assets
- * @returns this
- */
- addAssets = (assets: Asset[]): this => {
- assets.forEach((asset) => {
- this.addAsset(asset);
- });
- return this;
- };
-
- /**
- * Substract an asset from the Value class's value record. If an asset with the same unit already exists in the value record, the quantity of the
- * existing asset will be decreased by the quantity of the new asset. If no such asset exists, an error message should be printed.
- * Implementation:
- * 1. Check if the unit of the asset already exists in the value record.
- * 2. If the unit exists, subtract the new quantity from the existing quantity.
- * 3. If the unit does not exist, print an error message.
- * @param asset
- * @returns this
- */
- negateAsset = (asset: Asset): this => {
- const { unit, quantity } = asset;
-
- const currentQuantity = this.value[unit] || BigInt(0);
- const newQuantity = currentQuantity - BigInt(quantity);
-
- if (newQuantity === BigInt(0)) {
- delete this.value[unit];
- } else {
- this.value[unit] = newQuantity;
- }
- return this;
- };
-
- /**
- * Subtract an array of assets from the Value class's value record. If an asset with the same unit already exists in the value record, the quantity of the
- * existing asset will be decreased by the quantity of the new asset. If no such asset exists, an error message should be printed.
- * @param assets
- * @returns this
- */
- negateAssets = (assets: Asset[]): this => {
- assets.forEach((asset) => {
- this.negateAsset(asset);
- });
- return this;
- };
-
- /**
- * Get the quantity of asset object per unit
- * @param unit
- * @returns
- */
- get = (unit: string): bigint => {
- return this.value[unit] ? BigInt(this.value[unit]) : BigInt(0);
- };
-
- /**
- * Get all assets (return Record of Asset[])
- * @param
- * @returns Record
- */
- units = (): Record => {
- const result: Record = {};
- Object.keys(this.value).forEach((unit) => {
- if (!result[unit]) {
- result[unit] = [];
- }
- result[unit].push({ unit, quantity: BigInt(this.value[unit]) });
- });
- return result;
- };
-
- /**
- * Check if the value is greater than or equal to an inputted value
- * @param unit - The unit to compare (e.g., "ADA")
- * @param other - The value to compare against
- * @returns boolean
- */
- // geq = (unit: string, other: Value): boolean => {
- // const thisValue = this.get(unit);
- // const otherValue = other.get(unit);
- // return thisValue >= otherValue;
- // };
-
- geq = (unit: string, other: Value): 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 an inputted value
- * @param unit - The unit to compare (e.g., "ADA")
- * @param other - The value to compare against
- * @returns boolean
- */
- // leq = (unit: string, other: Value): boolean => {
- // const thisValue = this.get(unit);
- // const otherValue = other.get(unit);
- // if (otherValue === undefined) {
- // return false;
- // }
-
- // return thisValue <= otherValue;
- // };
-
- leq = (unit: string, other: Value): 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
- * @param
- * @returns boolean
- */
- isEmpty = (): boolean => {
- return Object.keys(this.value).length === 0;
- };
-
- /**
- * Merge the given values
- * @param values
- * @returns this
- */
- merge = (values: Value | Value[]): 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 this;
- };
-}
\ No newline at end of file
+ return this;
+ };
+}
diff --git a/packages/mesh-common/test/data/value.test.ts b/packages/mesh-common/test/data/value.test.ts
index 1488a5fb..7ef3ef2b 100644
--- a/packages/mesh-common/test/data/value.test.ts
+++ b/packages/mesh-common/test/data/value.test.ts
@@ -1,425 +1,432 @@
-import {
- Asset,
- byteString,
- ByteString,
- dict,
- Dict,
- Integer,
- integer,
- parsePlutusValueToAssets,
- Value,
- value,
-} from "@meshsdk/common";
-
-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));
+// import {
+// Asset,
+// byteString,
+// ByteString,
+// dict,
+// Dict,
+// Integer,
+// integer,
+// parsePlutusValueToAssets,
+// Value,
+// value,
+// } from "@meshsdk/common";
+
+// 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));
+// });
+// });
+
+// tests/value.test.ts
+import { Asset, Value } from "@meshsdk/common";
+
+describe("Value class", () => {
+ describe("addAsset", () => {
+ it("should add a new asset correctly", () => {
+ const value = new Value();
+ const singleAsset: Asset = { unit: "USDM", quantity: "100" };
+ value.addAsset(singleAsset);
+ // Assertions to verify the behavior of addAsset...
+ expect(value.value).toEqual({ USDM: BigInt(100) });
+ });
+ it("should add to an existing asset correctly", () => {
+ const value = new Value();
+ const singleAsset: Asset = { unit: "USDM", quantity: "100" };
+ value.addAsset(singleAsset);
+ value.addAsset(singleAsset);
+ // Assertions to verify the behavior of addAsset...
+ expect(value.value).toEqual({ USDM: BigInt(200) });
+ });
+ it("should add multiple assets correctly", () => {
+ const value = new Value();
+ const assets: Asset[] = [
+ { unit: "USDM", quantity: "100" },
+ { unit: "ADA", quantity: "10" },
+ ];
+ value.addAsset(assets[0]).addAsset(assets[1]);
+ // Assertions to verify the behavior of addAsset...
+ expect(value.value).toEqual({ USDM: BigInt(100), ADA: BigInt(10) });
+ });
});
- 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));
+ describe("addAssets", () => {
+ it("should add multiple assets correctly", () => {
+ const value = new Value();
+ const assets: Asset[] = [
+ { unit: "USDM", quantity: "100" },
+ { unit: "ADA", quantity: "10" },
+ { unit: "USDM", quantity: "100" },
+ { unit: "ADA", quantity: "10" },
+ ];
+ value.addAssets(assets);
+ // Assertions to verify the behavior of addAssets...
+ expect(value.value).toEqual({ USDM: BigInt(200), ADA: BigInt(20) });
+ });
+ it("should add multiple assets correctly with different units", () => {
+ const value = new Value();
+ const assets: Asset[] = [
+ { unit: "USDM", quantity: "100" },
+ { unit: "ADA", quantity: "10" },
+ { unit: "USDC", quantity: "100" },
+ { unit: "ADA", quantity: "10" },
+ ];
+ value.addAssets(assets);
+ // Assertions to verify the behavior of addAssets...
+ expect(value.value).toEqual({
+ USDM: BigInt(100),
+ ADA: BigInt(20),
+ USDC: BigInt(100),
+ });
+ });
});
- 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("negateAsset", () => {
+ describe("negateAsset", () => {
+ it("should subtract quantity from an existing asset", () => {
+ const value = new Value();
+ value.value = { ADA: 10n };
+ value.negateAsset({ unit: "ADA", quantity: "5" });
+ expect(value.value).toEqual({ ADA: BigInt(5) });
+ });
+
+ it("should remove the asset if the resulting quantity is zero", () => {
+ const value = new Value();
+ value.value = { ADA: 10n };
+ value.negateAsset({ unit: "ADA", quantity: "10" });
+ expect(value.value.ADA).toBeUndefined();
+ });
+
+ it("should allow negative quantity if the subtraction results in negative value", () => {
+ const value = new Value();
+ value.value = { ADA: 10n };
+ value.negateAsset({ unit: "ADA", quantity: "15" });
+ expect(value.value).toEqual({ ADA: BigInt(-5) });
+ });
+
+ it("should add a new asset with negative quantity if the asset does not exist", () => {
+ const value = new Value();
+ value.negateAsset({ unit: "ADA", quantity: "5" });
+ expect(value.value).toEqual({ ADA: BigInt(-5) });
+ });
+ });
});
-});
+ describe("negateAssets", () => {
+ it("should subtract quantities from existing assets", () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ value.negateAssets([
+ { unit: "ADA", quantity: "5" },
+ { unit: "BTC", quantity: "3" },
+ ]);
+ expect(value.value).toEqual({ ADA: BigInt(15), BTC: BigInt(7) });
+ });
+
+ it("should remove the asset if the resulting quantity is zero", () => {
+ const value = new Value();
+ value.value = { ADA: 10n, BTC: 5n };
+ value.negateAssets([
+ { unit: "ADA", quantity: "10" },
+ { unit: "BTC", quantity: "5" },
+ ]);
+ expect(value.value.ADA).toBeUndefined();
+ expect(value.value.BTC).toBeUndefined();
+ });
+
+ it("should allow negative quantity if the subtraction results in negative value", () => {
+ const value = new Value();
+ value.value = { ADA: 10n, BTC: 5n };
+ value.negateAssets([
+ { unit: "ADA", quantity: "15" },
+ { unit: "BTC", quantity: "10" },
+ ]);
+ expect(value.value).toEqual({ ADA: BigInt(-5), BTC: BigInt(-5) });
+ });
+
+ it("should add new assets with negative quantities if the assets do not exist", () => {
+ const value = new Value();
+ value.negateAssets([
+ { unit: "ADA", quantity: "5" },
+ { unit: "BTC", quantity: "3" },
+ ]);
+ expect(value.value).toEqual({ ADA: BigInt(-5), BTC: BigInt(-3) });
+ });
+
+ it("should handle a mix of existing and non-existing assets", () => {
+ const value = new Value();
+ value.value = { ADA: 10n };
+ value.negateAssets([
+ { unit: "ADA", quantity: "5" },
+ { unit: "BTC", quantity: "3" },
+ ]);
+ expect(value.value).toEqual({ ADA: BigInt(5), BTC: BigInt(-3) });
+ });
+ });
+ describe("get", () => {
+ it("should return the quantity of an existing asset", () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ expect(value.get("ADA")).toEqual(BigInt(20));
+ expect(value.get("BTC")).toEqual(BigInt(10));
+ });
+
+ it("should return 0 for a non-existing asset", () => {
+ const value = new Value();
+ value.value = { ADA: 20n };
+ expect(value.get("BTC")).toEqual(BigInt(0));
+ });
+
+ it("should handle an empty value object", () => {
+ const value = new Value();
+ expect(value.get("ADA")).toEqual(BigInt(0));
+ });
+
+ it("should return the correct quantity after adding assets", () => {
+ const value = new Value();
+ value.value = { ADA: 20n };
+ value.addAsset({ unit: "BTC", quantity: "10" });
+ expect(value.get("BTC")).toEqual(BigInt(10));
+ });
+
+ it("should return the correct quantity after subtracting assets", () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ value.negateAssets([{ unit: "BTC", quantity: "5" }]);
+ expect(value.get("BTC")).toEqual(BigInt(5));
+ });
+ });
+ describe("units", () => {
+ it("should return an empty object when value is empty", () => {
+ const value = new Value();
+ value.value = {};
+ expect(value.units()).toEqual({});
+ });
-describe("Value", () => {
- test("Simple ADA Value", () => {
- const val: Asset[] = [{ unit: "lovelace", quantity: "1000000" }];
- const plutusValue: Value = value(val);
- const assets: Asset[] = parsePlutusValueToAssets(plutusValue);
+ it("should return the correct structure for a single asset", () => {
+ const value = new Value();
+ value.value = { ADA: 20n };
+ expect(value.units()).toEqual({
+ ADA: [{ unit: "ADA", quantity: BigInt(20) }],
+ });
+ });
+
+ it("should return the correct structure for multiple assets", () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ expect(value.units()).toEqual({
+ ADA: [{ unit: "ADA", quantity: BigInt(20) }],
+ BTC: [{ unit: "BTC", quantity: BigInt(10) }],
+ });
+ });
+
+ it("should handle both positive and negative quantities correctly", () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: -10n };
+ expect(value.units()).toEqual({
+ ADA: [{ unit: "ADA", quantity: BigInt(20) }],
+ BTC: [{ unit: "BTC", quantity: BigInt(-10) }],
+ });
+ });
+ });
+ 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 Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ADA: 10n, BTC: 5n };
+ expect(value.geq("ADA", target)).toBe(true);
+ expect(value.geq("BTC", target)).toBe(true);
+ });
+
+ it("should return false if the value is less than the target value for a specific unit", () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ADA: 30n, BTC: 15n };
+ expect(value.geq("ADA", target)).toBe(false);
+ expect(value.geq("BTC", target)).toBe(false);
+ });
+
+ it("should return true if the value is equal to the target value for a specific unit", () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ADA: 20n, BTC: 10n };
+ expect(value.geq("ADA", target)).toBe(true);
+ expect(value.geq("BTC", target)).toBe(true);
+ });
+
+ it("should return false if the unit does not exist in value.value", () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ETH: 5n };
+ expect(value.geq("ETH", 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 Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ADA: 30n, BTC: 15n };
+ expect(value.leq("ADA", target)).toBe(true);
+ expect(value.leq("BTC", target)).toBe(true);
+ });
- expect(JSON.stringify(val)).toBe(JSON.stringify(assets));
+ it("should return false if the value is greater than the target value for a specific unit", () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ADA: 10n, BTC: 5n };
+ expect(value.leq("ADA", target)).toBe(false);
+ expect(value.leq("BTC", target)).toBe(false);
+ });
+
+ it("should return true if the value is equal to the target value for a specific unit", () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ADA: 20n, BTC: 10n };
+ expect(value.leq("ADA", target)).toBe(true);
+ expect(value.leq("BTC", target)).toBe(true);
+ });
+
+ it("should return false if the unit does not exist in value.value", () => {
+ const value = new Value();
+ value.value = { ADA: 20n, BTC: 10n };
+ const target = new Value();
+ target.value = { ETH: 5n };
+ expect(value.leq("ETH", target)).toBe(false);
+ });
});
- 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));
+ describe("isEmpty", () => {
+ it("should return true if the value is empty", () => {
+ const value = new Value();
+ value.value = {};
+ expect(value.isEmpty()).toBe(true);
+ });
+
+ it("should return false if the value is not empty", () => {
+ const value = new Value();
+ value.value = { ADA: 20n };
+ expect(value.isEmpty()).toBe(false);
+ });
});
- 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));
+ describe("merge", () => {
+ it("should merge two values correctly", () => {
+ const value1 = new Value();
+ value1.value = { ADA: 20n, BTC: 10n };
+ const value2 = new Value();
+ value2.value = { ADA: 10n, BTC: 5n };
+ expect(value1.merge(value2).value).toEqual({ ADA: 30n, BTC: 15n });
+ });
+
+ it("should merge two values correctly with different units", () => {
+ const value1 = new Value();
+ value1.value = { ADA: 20n, BTC: 10n };
+ const value2 = new Value();
+ value2.value = { ETH: 10n, BTC: 5n };
+ expect(value1.merge(value2).value).toEqual({
+ ADA: 20n,
+ BTC: 15n,
+ ETH: 10n,
+ });
+ });
+
+ it("should merge two values correctly with negative quantities", () => {
+ const value1 = new Value();
+ value1.value = { ADA: 20n, BTC: -10n };
+ const value2 = new Value();
+ value2.value = { ADA: 10n, BTC: 5n };
+ expect(value1.merge(value2).value).toEqual({ ADA: 30n, BTC: -5n });
+ });
});
});
-
-// tests/value.test.ts
-import { Asset } from '@meshsdk/core';
-import { Value } from '../src/types';
-
-describe('Value class', () => {
- describe('addAsset', () => {
- it('should add a new asset correctly', () => {
- const value = new Value();
- const singleAsset: Asset = { unit: 'USDM', quantity: '100' };
- value.addAsset(singleAsset);
- // Assertions to verify the behavior of addAsset...
- expect(value.value).toEqual({ USDM: BigInt(100) });
- });
- it('should add to an existing asset correctly', () => {
- const value = new Value();
- const singleAsset: Asset = { unit: 'USDM', quantity: '100' };
- value.addAsset(singleAsset);
- value.addAsset(singleAsset);
- // Assertions to verify the behavior of addAsset...
- expect(value.value).toEqual({ USDM: BigInt(200) });
- });
- it('should add multiple assets correctly', () => {
- const value = new Value();
- const assets: Asset[] = [
- { unit: 'USDM', quantity: '100' },
- { unit: 'ADA', quantity: '10' },
- ];
- value.addAsset(assets[0]).addAsset(assets[1]);
- // Assertions to verify the behavior of addAsset...
- expect(value.value).toEqual({ USDM: BigInt(100), ADA: BigInt(10) });
- });
- });
- describe('addAssets', () => {
- it('should add multiple assets correctly', () => {
- const value = new Value();
- const assets: Asset[] = [
- { unit: 'USDM', quantity: '100' },
- { unit: 'ADA', quantity: '10' },
- { unit: 'USDM', quantity: '100' },
- { unit: 'ADA', quantity: '10' },
- ];
- value.addAssets(assets);
- // Assertions to verify the behavior of addAssets...
- expect(value.value).toEqual({ USDM: BigInt(200), ADA: BigInt(20) });
- });
- it('should add multiple assets correctly with different units', () => {
- const value = new Value();
- const assets: Asset[] = [
- { unit: 'USDM', quantity: '100' },
- { unit: 'ADA', quantity: '10' },
- { unit: 'USDC', quantity: '100' },
- { unit: 'ADA', quantity: '10' },
- ];
- value.addAssets(assets);
- // Assertions to verify the behavior of addAssets...
- expect(value.value).toEqual({ USDM: BigInt(100), ADA: BigInt(20), USDC: BigInt(100) });
- });
- });
- describe('negateAsset', () => {
- describe('negateAsset', () => {
- it('should subtract quantity from an existing asset', () => {
- const value = new Value();
- value.value = { ADA: 10n };
- value.negateAsset({ unit: 'ADA', quantity: '5' });
- expect(value.value).toEqual({ ADA: BigInt(5) });
- });
-
- it('should remove the asset if the resulting quantity is zero', () => {
- const value = new Value();
- value.value = { ADA: 10n };
- value.negateAsset({ unit: 'ADA', quantity: '10' });
- expect(value.value.ADA).toBeUndefined();
- });
-
- it('should allow negative quantity if the subtraction results in negative value', () => {
- const value = new Value();
- value.value = { ADA: 10n };
- value.negateAsset({ unit: 'ADA', quantity: '15' });
- expect(value.value).toEqual({ ADA: BigInt(-5) });
- });
-
- it('should add a new asset with negative quantity if the asset does not exist', () => {
- const value = new Value();
- value.negateAsset({ unit: 'ADA', quantity: '5' });
- expect(value.value).toEqual({ ADA: BigInt(-5) });
- });
- });
- });
- describe('negateAssets', () => {
- it('should subtract quantities from existing assets', () => {
- const value = new Value();
- value.value = { ADA: 20n, BTC: 10n };
- value.negateAssets([
- { unit: 'ADA', quantity: '5' },
- { unit: 'BTC', quantity: '3' },
- ]);
- expect(value.value).toEqual({ ADA: BigInt(15), BTC: BigInt(7) });
- });
-
- it('should remove the asset if the resulting quantity is zero', () => {
- const value = new Value();
- value.value = { ADA: 10n, BTC: 5n };
- value.negateAssets([
- { unit: 'ADA', quantity: '10' },
- { unit: 'BTC', quantity: '5' },
- ]);
- expect(value.value.ADA).toBeUndefined();
- expect(value.value.BTC).toBeUndefined();
- });
-
- it('should allow negative quantity if the subtraction results in negative value', () => {
- const value = new Value();
- value.value = { ADA: 10n, BTC: 5n };
- value.negateAssets([
- { unit: 'ADA', quantity: '15' },
- { unit: 'BTC', quantity: '10' },
- ]);
- expect(value.value).toEqual({ ADA: BigInt(-5), BTC: BigInt(-5) });
- });
-
- it('should add new assets with negative quantities if the assets do not exist', () => {
- const value = new Value();
- value.negateAssets([
- { unit: 'ADA', quantity: '5' },
- { unit: 'BTC', quantity: '3' },
- ]);
- expect(value.value).toEqual({ ADA: BigInt(-5), BTC: BigInt(-3) });
- });
-
- it('should handle a mix of existing and non-existing assets', () => {
- const value = new Value();
- value.value = { ADA: 10n };
- value.negateAssets([
- { unit: 'ADA', quantity: '5' },
- { unit: 'BTC', quantity: '3' },
- ]);
- expect(value.value).toEqual({ ADA: BigInt(5), BTC: BigInt(-3) });
- });
- });
- describe('get', () => {
- it('should return the quantity of an existing asset', () => {
- const value = new Value();
- value.value = { ADA: 20n, BTC: 10n };
- expect(value.get('ADA')).toEqual(BigInt(20));
- expect(value.get('BTC')).toEqual(BigInt(10));
- });
-
- it('should return 0 for a non-existing asset', () => {
- const value = new Value();
- value.value = { ADA: 20n };
- expect(value.get('BTC')).toEqual(BigInt(0));
- });
-
- it('should handle an empty value object', () => {
- const value = new Value();
- expect(value.get('ADA')).toEqual(BigInt(0));
- });
-
- it('should return the correct quantity after adding assets', () => {
- const value = new Value();
- value.value = { ADA: 20n };
- value.addAsset({ unit: 'BTC', quantity: '10' });
- expect(value.get('BTC')).toEqual(BigInt(10));
- });
-
- it('should return the correct quantity after subtracting assets', () => {
- const value = new Value();
- value.value = { ADA: 20n, BTC: 10n };
- value.negateAssets([{ unit: 'BTC', quantity: '5' }]);
- expect(value.get('BTC')).toEqual(BigInt(5));
- });
- });
- describe('units', () => {
- it('should return an empty object when value is empty', () => {
- const value = new Value();
- value.value = {};
- expect(value.units()).toEqual({});
- });
-
- it('should return the correct structure for a single asset', () => {
- const value = new Value();
- value.value = { ADA: 20n };
- expect(value.units()).toEqual({
- ADA: [{ unit: 'ADA', quantity: BigInt(20) }],
- });
- });
-
- it('should return the correct structure for multiple assets', () => {
- const value = new Value();
- value.value = { ADA: 20n, BTC: 10n };
- expect(value.units()).toEqual({
- ADA: [{ unit: 'ADA', quantity: BigInt(20) }],
- BTC: [{ unit: 'BTC', quantity: BigInt(10) }],
- });
- });
-
- it('should handle both positive and negative quantities correctly', () => {
- const value = new Value();
- value.value = { ADA: 20n, BTC: -10n };
- expect(value.units()).toEqual({
- ADA: [{ unit: 'ADA', quantity: BigInt(20) }],
- BTC: [{ unit: 'BTC', quantity: BigInt(-10) }],
- });
- });
- });
- 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 Value();
- value.value = { ADA: 20n, BTC: 10n };
- const target = new Value();
- target.value = { ADA: 10n, BTC: 5n };
- expect(value.geq('ADA', target)).toBe(true);
- expect(value.geq('BTC', target)).toBe(true);
- });
-
- it('should return false if the value is less than the target value for a specific unit', () => {
- const value = new Value();
- value.value = { ADA: 20n, BTC: 10n };
- const target = new Value();
- target.value = { ADA: 30n, BTC: 15n };
- expect(value.geq('ADA', target)).toBe(false);
- expect(value.geq('BTC', target)).toBe(false);
- });
-
- it('should return true if the value is equal to the target value for a specific unit', () => {
- const value = new Value();
- value.value = { ADA: 20n, BTC: 10n };
- const target = new Value();
- target.value = { ADA: 20n, BTC: 10n };
- expect(value.geq('ADA', target)).toBe(true);
- expect(value.geq('BTC', target)).toBe(true);
- });
-
- it('should return false if the unit does not exist in value.value', () => {
- const value = new Value();
- value.value = { ADA: 20n, BTC: 10n };
- const target = new Value();
- target.value = { ETH: 5n };
- expect(value.geq('ETH', 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 Value();
- value.value = { ADA: 20n, BTC: 10n };
- const target = new Value();
- target.value = { ADA: 30n, BTC: 15n };
- expect(value.leq('ADA', target)).toBe(true);
- expect(value.leq('BTC', target)).toBe(true);
- });
-
- it('should return false if the value is greater than the target value for a specific unit', () => {
- const value = new Value();
- value.value = { ADA: 20n, BTC: 10n };
- const target = new Value();
- target.value = { ADA: 10n, BTC: 5n };
- expect(value.leq('ADA', target)).toBe(false);
- expect(value.leq('BTC', target)).toBe(false);
- });
-
- it('should return true if the value is equal to the target value for a specific unit', () => {
- const value = new Value();
- value.value = { ADA: 20n, BTC: 10n };
- const target = new Value();
- target.value = { ADA: 20n, BTC: 10n };
- expect(value.leq('ADA', target)).toBe(true);
- expect(value.leq('BTC', target)).toBe(true);
- });
-
- it('should return false if the unit does not exist in value.value', () => {
- const value = new Value();
- value.value = { ADA: 20n, BTC: 10n };
- const target = new Value();
- target.value = { ETH: 5n };
- expect(value.leq('ETH', target)).toBe(false);
- });
- });
- describe('isEmpty', () => {
- it('should return true if the value is empty', () => {
- const value = new Value();
- value.value = {};
- expect(value.isEmpty()).toBe(true);
- });
-
- it('should return false if the value is not empty', () => {
- const value = new Value();
- value.value = { ADA: 20n };
- expect(value.isEmpty()).toBe(false);
- });
- });
- describe('merge', () => {
- it('should merge two values correctly', () => {
- const value1 = new Value();
- value1.value = { ADA: 20n, BTC: 10n };
- const value2 = new Value();
- value2.value = { ADA: 10n, BTC: 5n };
- expect(value1.merge(value2).value).toEqual({ ADA: 30n, BTC: 15n });
- });
-
- it('should merge two values correctly with different units', () => {
- const value1 = new Value();
- value1.value = { ADA: 20n, BTC: 10n };
- const value2 = new Value();
- value2.value = { ETH: 10n, BTC: 5n };
- expect(value1.merge(value2).value).toEqual({ ADA: 20n, BTC: 15n, ETH: 10n });
- });
-
- it('should merge two values correctly with negative quantities', () => {
- const value1 = new Value();
- value1.value = { ADA: 20n, BTC: -10n };
- const value2 = new Value();
- value2.value = { ADA: 10n, BTC: 5n };
- expect(value1.merge(value2).value).toEqual({ ADA: 30n, BTC: -5n });
- });
- });
-});
\ No newline at end of file
From 664b0ed96a449703f42a22754ce9289cd5679fae Mon Sep 17 00:00:00 2001
From: "Hong Jing (Jingles)"
Date: Sat, 3 Aug 2024 12:15:33 +0800
Subject: [PATCH 06/17] add metamask support, fixed giftcard, upgrade wallets
---
.../components/cardano/mint-mesh-token.tsx | 67 +++++++++++++++++
.../components/sections/live-code-demo.tsx | 17 +++--
.../sections/title-icon-description-body.tsx | 4 +-
.../wallets/browserwallet/connect-wallet.tsx | 2 +-
.../browserwallet/get-available-wallets.tsx | 75 +++++++++++++++++++
.../apis/wallets/browserwallet/index.tsx | 6 +-
.../pages/smart-contracts/escrow/index.tsx | 5 +-
.../pages/smart-contracts/giftcard/index.tsx | 2 +-
.../smart-contracts/marketplace/index.tsx | 5 +-
.../marketplace/list-asset.tsx | 1 +
.../payment-splitter/index.tsx | 2 +-
.../src/pages/smart-contracts/swap/index.tsx | 5 +-
.../pages/smart-contracts/vesting/index.tsx | 2 +-
package-lock.json | 65 ++++++++++++----
packages/mesh-contract/src/common.ts | 22 +++---
packages/mesh-contract/src/escrow/offchain.ts | 2 +-
.../mesh-contract/src/giftcard/offchain.ts | 16 +++-
.../mesh-contract/src/hello-world/offchain.ts | 2 +-
.../mesh-contract/src/marketplace/offchain.ts | 2 +-
packages/mesh-contract/src/swap/offchain.ts | 2 +-
.../mesh-contract/src/vesting/offchain.ts | 2 +-
.../mesh-react/src/cardano-wallet/index.tsx | 19 ++---
packages/mesh-react/src/common/button.tsx | 6 ++
.../mesh-react/src/hooks/useWalletList.ts | 5 +-
packages/mesh-wallet/package.json | 10 ++-
packages/mesh-wallet/src/browser/index.ts | 21 +++++-
packages/mesh-wallet/src/browser/metamask.ts | 42 +++++++++++
27 files changed, 340 insertions(+), 69 deletions(-)
create mode 100644 apps/playground/src/components/cardano/mint-mesh-token.tsx
create mode 100644 apps/playground/src/pages/apis/wallets/browserwallet/get-available-wallets.tsx
create mode 100644 packages/mesh-wallet/src/browser/metamask.ts
diff --git a/apps/playground/src/components/cardano/mint-mesh-token.tsx b/apps/playground/src/components/cardano/mint-mesh-token.tsx
new file mode 100644
index 00000000..85d7c601
--- /dev/null
+++ b/apps/playground/src/components/cardano/mint-mesh-token.tsx
@@ -0,0 +1,67 @@
+import {
+ AppWallet,
+ AssetMetadata,
+ ForgeScript,
+ Mint,
+ Transaction,
+} from "@meshsdk/core";
+import { useWallet } from "@meshsdk/react";
+
+import { demoAssetMetadata, demoMnemonic } from "~/data/cardano";
+import LiveCodeDemo from "../sections/live-code-demo";
+import { getProvider } from "./mesh-wallet";
+
+export default function MintMeshToken() {
+ const { wallet, connected } = useWallet();
+
+ async function runDemo() {
+ const blockchainProvider = getProvider();
+ const mintingWallet = new AppWallet({
+ networkId: 0,
+ fetcher: blockchainProvider,
+ submitter: blockchainProvider,
+ key: {
+ type: "mnemonic",
+ words: demoMnemonic,
+ },
+ });
+
+ const usedAddress = await wallet.getUsedAddresses();
+ const address = usedAddress[0];
+ const forgingScript = ForgeScript.withOneSignature(
+ mintingWallet.getPaymentAddress(),
+ );
+
+ const tx = new Transaction({ initiator: wallet });
+
+ const asset: Mint = {
+ assetName: "MeshToken",
+ assetQuantity: "1",
+ metadata: demoAssetMetadata,
+ label: "721",
+ recipient: address,
+ };
+ tx.mintAsset(forgingScript, asset);
+
+ const unsignedTx = await tx.build();
+ const signedTx = await wallet.signTx(unsignedTx, true);
+ const signedTx2 = await mintingWallet.signTx(signedTx, true);
+ const txHash = await wallet.submitTx(signedTx2);
+ return txHash;
+ }
+
+ return (
+
+ );
+}
diff --git a/apps/playground/src/components/sections/live-code-demo.tsx b/apps/playground/src/components/sections/live-code-demo.tsx
index 882f809c..9b8ecc52 100644
--- a/apps/playground/src/components/sections/live-code-demo.tsx
+++ b/apps/playground/src/components/sections/live-code-demo.tsx
@@ -23,6 +23,8 @@ export default function LiveCodeDemo({
runDemoShowBrowseWalletConnect = false,
runDemoShowProviderInit = false,
runDemoProvider = undefined,
+ hideDemoButtonIfnotConnected = false,
+ hideConnectButtonIfConnected = false,
}: {
children?: React.ReactNode;
title: string;
@@ -36,6 +38,8 @@ export default function LiveCodeDemo({
runDemoShowBrowseWalletConnect?: boolean;
runDemoShowProviderInit?: boolean;
runDemoProvider?: string | undefined;
+ hideDemoButtonIfnotConnected?: boolean;
+ hideConnectButtonIfConnected?: boolean;
}) {
const { connected } = useWallet();
const [loading, setLoading] = useState(false);
@@ -77,7 +81,7 @@ export default function LiveCodeDemo({
)}
- {runCodeFunction && (
+ {runCodeFunction && (connected || !hideDemoButtonIfnotConnected) && (
);
}
diff --git a/apps/playground/src/pages/apis/wallets/browserwallet/connect-wallet.tsx b/apps/playground/src/pages/apis/wallets/browserwallet/connect-wallet.tsx
index 6e2adf7b..40b35646 100644
--- a/apps/playground/src/pages/apis/wallets/browserwallet/connect-wallet.tsx
+++ b/apps/playground/src/pages/apis/wallets/browserwallet/connect-wallet.tsx
@@ -26,7 +26,7 @@ function Left() {
dApp to use.
- Query BrowserWallet.getInstalledWallets() to get a list of
+ Query BrowserWallet.getAvailableWallets() to get a list of
available wallets, then provide the wallet name for which
wallet the user would like to connect with.
diff --git a/apps/playground/src/pages/apis/wallets/browserwallet/get-available-wallets.tsx b/apps/playground/src/pages/apis/wallets/browserwallet/get-available-wallets.tsx
new file mode 100644
index 00000000..c0e9dbb2
--- /dev/null
+++ b/apps/playground/src/pages/apis/wallets/browserwallet/get-available-wallets.tsx
@@ -0,0 +1,75 @@
+import { BrowserWallet } from "@meshsdk/core";
+
+import LiveCodeDemo from "~/components/sections/live-code-demo";
+import TwoColumnsScroll from "~/components/sections/two-columns-scroll";
+import Codeblock from "~/components/text/codeblock";
+
+export default function BrowserWalletGetAvailableWallets() {
+ return (
+
+ );
+}
+
+function Left() {
+ let example = ``;
+ example += `[\n`;
+ example += ` {\n`;
+ example += ` "id": "nufiSnap",\n`;
+ example += ` "name": "MetaMask",\n`;
+ example += ` "icon": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI4LjMuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAzMTguNiAzMTguNiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMzE4LjYgMzE4LjY7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbDojRTI3NjFCO3N0cm9rZTojRTI3NjFCO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDt9Cgkuc3Qxe2ZpbGw6I0U0NzYxQjtzdHJva2U6I0U0NzYxQjtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7fQoJLnN0MntmaWxsOiNEN0MxQjM7c3Ryb2tlOiNEN0MxQjM7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO30KCS5zdDN7ZmlsbDojMjMzNDQ3O3N0cm9rZTojMjMzNDQ3O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDt9Cgkuc3Q0e2ZpbGw6I0NENjExNjtzdHJva2U6I0NENjExNjtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7fQoJLnN0NXtmaWxsOiNFNDc1MUY7c3Ryb2tlOiNFNDc1MUY7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO30KCS5zdDZ7ZmlsbDojRjY4NTFCO3N0cm9rZTojRjY4NTFCO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDt9Cgkuc3Q3e2ZpbGw6I0MwQUQ5RTtzdHJva2U6I0MwQUQ5RTtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7fQoJLnN0OHtmaWxsOiMxNjE2MTY7c3Ryb2tlOiMxNjE2MTY7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO30KCS5zdDl7ZmlsbDojNzYzRDE2O3N0cm9rZTojNzYzRDE2O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDt9Cgkuc3QxMHtmaWxsOiMyMTIxMjE7fQoJLnN0MTF7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojQzZGRjAwO30KCS5zdDEye2ZpbGw6IzBEMUUzMDt9Cgkuc3QxM3tmaWxsOiNGRkZGRkY7fQo8L3N0eWxlPgo8ZyBpZD0iTGF5ZXJfMV8wMDAwMDA5MjQ0OTYwMTMwNjUyMjkxNzI0MDAwMDAwNzE3NTg0ODQ4MTM1NTIzODUzNV8iPgoJPHBhdGggY2xhc3M9InN0MCIgZD0iTTI4My4zLDMxLjZsLTEwNy41LDc5LjhsMTkuOS00Ny4xTDI4My4zLDMxLjZ6Ii8+Cgk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNMzUuMiwzMS42bDEwNi42LDgwLjZsLTE4LjktNDcuOUwzNS4yLDMxLjZ6IE0yNDQuNiwyMTYuN0wyMTYsMjYwLjVsNjEuMywxNi45bDE3LjYtNTkuN0wyNDQuNiwyMTYuN3oKCQkgTTIzLjgsMjE3LjZsMTcuNSw1OS43bDYxLjMtMTYuOUw3NCwyMTYuN0wyMy44LDIxNy42eiIvPgoJPHBhdGggY2xhc3M9InN0MSIgZD0iTTk5LjEsMTQyLjZMODIsMTY4LjRsNjAuOCwyLjdsLTIuMi02NS40TDk5LjEsMTQyLjZ6IE0yMTkuNCwxNDIuNkwxNzcuMiwxMDVsLTEuNCw2Ni4xbDYwLjctMi43TDIxOS40LDE0Mi42egoJCSBNMTAyLjYsMjYwLjVsMzYuNS0xNy44bC0zMS41LTI0LjZMMTAyLjYsMjYwLjV6IE0xNzkuNCwyNDIuN2wzNi42LDE3LjhsLTUuMS00Mi41TDE3OS40LDI0Mi43eiIvPgoJPHBhdGggY2xhc3M9InN0MiIgZD0iTTIxNiwyNjAuNWwtMzYuNi0xNy44bDIuOSwyMy45bC0wLjMsMTBMMjE2LDI2MC41eiBNMTAyLjYsMjYwLjVsMzQsMTYuMWwtMC4yLTEwbDIuNy0yMy45TDEwMi42LDI2MC41eiIvPgoJPHBhdGggY2xhc3M9InN0MyIgZD0iTTEzNy4yLDIwMi4zbC0zMC41LTlsMjEuNS05LjhMMTM3LjIsMjAyLjN6IE0xODEuMywyMDIuM2w5LTE4LjhsMjEuNiw5LjhMMTgxLjMsMjAyLjN6Ii8+Cgk8cGF0aCBjbGFzcz0ic3Q0IiBkPSJNMTAyLjYsMjYwLjVsNS4yLTQzLjlsLTMzLjgsMUwxMDIuNiwyNjAuNXogTTIxMC44LDIxNi43bDUuMiw0My45bDI4LjYtNDIuOUwyMTAuOCwyMTYuN3ogTTIzNi41LDE2OC40CgkJbC02MC43LDIuN2w1LjYsMzEuMmw5LTE4LjhsMjEuNiw5LjhMMjM2LjUsMTY4LjR6IE0xMDYuNywxOTMuM2wyMS42LTkuOGw4LjksMTguOGw1LjctMzEuMmwtNjAuOC0yLjdMMTA2LjcsMTkzLjN6Ii8+Cgk8cGF0aCBjbGFzcz0ic3Q1IiBkPSJNODIuMSwxNjguNGwyNS41LDQ5LjdsLTAuOS0yNC43TDgyLjEsMTY4LjR6IE0yMTIsMTkzLjNsLTEuMSwyNC43bDI1LjYtNDkuN0wyMTIsMTkzLjN6IE0xNDIuOSwxNzEuMQoJCWwtNS43LDMxLjJsNy4xLDM2LjhsMS42LTQ4LjVMMTQyLjksMTcxLjF6IE0xNzUuOCwxNzEuMWwtMi45LDE5LjRsMS4zLDQ4LjZsNy4yLTM2LjhMMTc1LjgsMTcxLjF6Ii8+Cgk8cGF0aCBjbGFzcz0ic3Q2IiBkPSJNMTgxLjQsMjAyLjNsLTcuMiwzNi44bDUuMiwzLjZsMzEuNS0yNC42bDEuMS0yNC43TDE4MS40LDIwMi4zeiBNMTA2LjcsMTkzLjNsMC45LDI0LjdsMzEuNSwyNC42bDUuMi0zLjYKCQlsLTcuMS0zNi44TDEwNi43LDE5My4zeiIvPgoJPHBhdGggY2xhc3M9InN0NyIgZD0iTTE4MiwyNzYuNmwwLjMtMTBsLTIuNy0yLjRoLTQwLjdsLTIuNSwyLjRsMC4yLDEwbC0zNC0xNi4xbDExLjksOS43bDI0LjEsMTYuN0gxODBsMjQuMi0xNi43bDExLjktOS43CgkJTDE4MiwyNzYuNnoiLz4KCTxwYXRoIGNsYXNzPSJzdDgiIGQ9Ik0xNzkuNCwyNDIuN2wtNS4yLTMuNmgtMjkuOWwtNS4yLDMuNmwtMi43LDIzLjlsMi41LTIuNGg0MC43bDIuNywyLjRMMTc5LjQsMjQyLjd6Ii8+Cgk8cGF0aCBjbGFzcz0ic3Q5IiBkPSJNMjg3LjksMTE2LjZsOS4yLTQ0LjFsLTEzLjctNDAuOWwtMTAzLjksNzcuMWw0MCwzMy44TDI3NiwxNTlsMTIuNS0xNC42bC01LjQtMy45bDguNi03LjlsLTYuNy01LjJsOC42LTYuNgoJCUwyODcuOSwxMTYuNnogTTIxLjYsNzIuNWw5LjIsNDQuMWwtNS44LDQuM2w4LjYsNi42bC02LjYsNS4ybDguNiw3LjlsLTUuNCwzLjlsMTIuNCwxNC42bDU2LjUtMTYuNWw0MC0zMy44TDM1LjIsMzEuNkwyMS42LDcyLjV6IgoJCS8+Cgk8cGF0aCBjbGFzcz0ic3Q2IiBkPSJNMjc1LjksMTU5LjFsLTU2LjUtMTYuNWwxNy4yLDI1LjhMMjExLDIxOC4xbDMzLjctMC40aDUwLjJMMjc1LjksMTU5LjF6IE05OS4xLDE0Mi42bC01Ni41LDE2LjVsLTE4LjgsNTguNgoJCUg3NGwzMy42LDAuNGwtMjUuNS00OS43TDk5LjEsMTQyLjZ6IE0xNzUuOCwxNzEuMWwzLjYtNjIuM2wxNi40LTQ0LjRoLTcyLjlsMTYuMiw0NC40bDMuOCw2Mi4zbDEuMywxOS43bDAuMSw0OC40aDI5LjlsMC4yLTQ4LjQKCQlMMTc1LjgsMTcxLjF6Ii8+CjwvZz4KPGcgaWQ9IkxheWVyXzJfMDAwMDAwMTg5NDI2NDc1ODI1NTk2Mjk3OTAwMDAwMDQ3MDk1NDU4NDI3Nzk1ODU5MzVfIj4KCTxwYXRoIGNsYXNzPSJzdDEwIiBkPSJNMTgzLjIsMjUwLjNjMC0zNS41LDI4LjgtNjQuMiw2NC4yLTY0LjJjMzUuNSwwLDY0LjMsMjguOCw2NC4zLDY0LjJjMCwzNS41LTI4LjgsNjQuMi02NC4zLDY0LjIKCQlTMTgzLjIsMjg1LjcsMTgzLjIsMjUwLjN6Ii8+Cgk8cGF0aCBjbGFzcz0ic3QxMSIgZD0iTTI0Ny40LDMwOC41YzI3LjIsMCw1MC0xOC44LDU2LjItNDQuM2gtMTkuNGMtNS42LDE1LTIwLDI1LjYtMzYuOCwyNS42cy0zMS4yLTEwLjYtMzYuOC0yNS42aC0xOS40CgkJQzE5Ny40LDI4OS42LDIyMC4yLDMwOC41LDI0Ny40LDMwOC41eiBNMjQ3LjQsMTkyYzI3LjIsMCw1MCwxOC44LDU2LjIsNDQuM2gtMTkuNGMtNS42LTE1LTIwLTI1LjYtMzYuOC0yNS42cy0zMS4yLDEwLjYtMzYuOCwyNS42CgkJaC0xOS40QzE5Ny40LDIxMC45LDIyMC4yLDE5MiwyNDcuNCwxOTJ6IE0yMzcuMiwyMzYuM2MtMiwwLTMuNywxLjctMy43LDMuN3YyMC41YzAsMi4xLDEuNywzLjcsMy43LDMuN2gyMC40YzIsMCwzLjctMS43LDMuNy0zLjcKCQlWMjQwYzAtMi4xLTEuNy0zLjctMy43LTMuN0gyMzcuMnoiLz4KPC9nPgo8cGF0aCBjbGFzcz0ic3QxMiIgZD0iTTI0Ny41LDMxNC41YzM1LjUsMCw2NC4zLTI4LjgsNjQuMy02NC4zYzAtMzUuNS0yOC44LTY0LjMtNjQuMy02NC4zYy0zNS41LDAtNjQuMywyOC44LTY0LjMsNjQuMwoJQzE4My4yLDI4NS43LDIxMiwzMTQuNSwyNDcuNSwzMTQuNXoiLz4KPGc+Cgk8cGF0aCBkPSJNMjQ2LjMsMjEwLjNjMS45LTEsNC4zLDEuMywzLjMsMy4yYy0wLjYsMS41LTIuOSwyLTQsMC44QzI0NC40LDIxMy4yLDI0NC44LDIxMC45LDI0Ni4zLDIxMC4zTDI0Ni4zLDIxMC4zeiBNMjI1LjYsMjEyLjUKCQljMS4yLTAuNSwyLjcsMC42LDIuNSwxLjhjMC4xLDEuNC0xLjYsMi40LTIuOCwxLjdDMjIzLjgsMjE1LjUsMjI0LDIxMi45LDIyNS42LDIxMi41eiBNMjY4LjEsMjE2LjFjLTEuOC0wLjItMi4xLTMtMC40LTMuNgoJCWMxLjQtMC43LDIuNiwwLjYsMi44LDEuOEMyNzAuMiwyMTUuNCwyNjkuMywyMTYuNCwyNjguMSwyMTYuMXogTTIzMC4zLDIyMS4yYzItMS4yLDQuNywwLjYsNC40LDIuOGMtMC4xLDIuMy0zLjEsMy42LTQuOSwyCgkJQzIyOC4zLDIyNC45LDIyOC41LDIyMi4xLDIzMC4zLDIyMS4yeiBNMjYwLjIsMjIyLjVjMC45LTIuMiw0LjQtMi4zLDUuNC0wLjFjMSwxLjctMC4yLDMuOC0yLDQuMwoJCUMyNjEuMywyMjcuMSwyNTkuMSwyMjQuNiwyNjAuMiwyMjIuNXogTTI0My45LDIyNi41YzAtMS45LDEuNy0zLjMsMy42LTMuNWMxLjIsMC4yLDIuNSwwLjgsMy4xLDJjMSwxLjcsMC4xLDQtMS42LDQuNwoJCWMtMC44LDAuNC0xLjgsMC4zLTIuNiwwLjJDMjQ0LjksMjI5LjQsMjQzLjcsMjI4LjEsMjQzLjksMjI2LjV6IE0yMTMuMSwyMjkuM2MxLjgtMS4xLDQuMiwwLjksMy41LDIuOGMtMC40LDEuNy0yLjYsMi4zLTMuOSwxLjMKCQlDMjExLjMsMjMyLjQsMjExLjUsMjMwLDIxMy4xLDIyOS4zTDIxMy4xLDIyOS4zeiBNMjc5LjIsMjI5LjNjMS41LTEuMiw0LDAuMiwzLjgsMi4xYzAuMSwxLjctMi4xLDMtMy42LDIuMQoJCUMyNzcuOCwyMzIuOCwyNzcuNiwyMzAuMiwyNzkuMiwyMjkuM0wyNzkuMiwyMjkuM3ogTTI1Mi41LDIzMi43YzIuNS0wLjksNS41LDAuMiw2LjksMi40YzEuOSwyLjcsMC45LDYuOC0yLDguMwoJCWMtMywxLjgtNy40LDAuMy04LjYtM0MyNDcuNSwyMzcuNCwyNDkuNCwyMzMuNywyNTIuNSwyMzIuN0wyNTIuNSwyMzIuN3ogTTIzNy44LDIzM2MyLjgtMS4zLDYuNS0wLjIsNy44LDIuNgoJCWMxLjYsMi43LDAuNCw2LjUtMi41LDcuOWMtMi44LDEuNi02LjgsMC40LTguMi0yLjVDMjMzLjUsMjM4LjEsMjM0LjksMjM0LjMsMjM3LjgsMjMzeiBNMjIzLjEsMjM4YzAuMi0xLjgsMS45LTIuOSwzLjYtMwoJCWMwLjksMC4xLDEuNywwLjUsMi4zLDEuMWMwLjYsMC42LDEsMS40LDEuMSwyLjNjLTAuMSwxLjgtMS41LDMuNi0zLjUsMy42QzIyNC42LDI0Mi4xLDIyMi43LDI0MCwyMjMuMSwyMzh6IE0yNjYuNSwyMzUuMwoJCWMyLjItMS4zLDUuMiwwLjYsNS4yLDMuMWMwLjEsMi42LTMuMiw0LjUtNS40LDIuOUMyNjQsMjQwLDI2NC4yLDIzNi40LDI2Ni41LDIzNS4zeiBNMjMxLjksMjQ0LjZjMi42LTAuNyw1LjUsMC41LDYuOCwyLjgKCQljMS40LDIuMywwLjgsNS42LTEuMyw3LjNjLTIuOCwyLjUtNy44LDEuNS05LjMtMS45QzIyNi4zLDI0OS42LDIyOC40LDI0NS40LDIzMS45LDI0NC42TDIzMS45LDI0NC42eiBNMjU5LjcsMjQ0LjYKCQljMi41LTAuNyw1LjQsMC4yLDYuOCwyLjVjMS44LDIuNiwwLjksNi40LTEuNyw4Yy0yLjgsMS45LTcuMSwwLjktOC42LTIuMUMyNTQuMywyNDkuOSwyNTYuMiwyNDUuNSwyNTkuNywyNDQuNnogTTIxNS4zLDI0Ny41CgkJYzIuMi0wLjgsNC43LDEuNiwzLjgsMy43Yy0wLjUsMi0zLjQsMi43LTQuOCwxLjJDMjEyLjYsMjUxLjEsMjEzLjIsMjQ4LjEsMjE1LjMsMjQ3LjV6IE0yNzUuNSwyNTAuNmMwLTAuOSwwLjMtMS43LDAuOS0yLjQKCQljMC42LTAuNywxLjQtMS4xLDIuMy0xLjFjMS41LDAuMiwzLDEuNCwyLjksMy4xYzAuMSwyLjEtMi41LDMuNi00LjQsMi42QzI3Ni4zLDI1Mi40LDI3NS45LDI1MS41LDI3NS41LDI1MC42eiBNMjA0LjQsMjQ4LjYKCQljMS4zLTAuNiwzLDAuNiwyLjcsMmMtMC4xLDEuNy0yLjYsMi4zLTMuNSwwLjlDMjAyLjksMjUwLjUsMjAzLjMsMjQ5LjEsMjA0LjQsMjQ4LjZMMjA0LjQsMjQ4LjZ6IE0yODguNiwyNDguNQoJCWMwLjktMC43LDIuNS0wLjIsMi44LDAuOWMwLjYsMS4yLTAuNSwyLjgtMS45LDIuNkMyODcuNiwyNTIuMiwyODcsMjQ5LjQsMjg4LjYsMjQ4LjV6IE0yMzkuMSwyNTYuNWMzLjUtMC45LDcuMywyLDcuMyw1LjUKCQljMC4yLDMuNi0zLjUsNi44LTcuMSw2Yy0yLjgtMC40LTUtMy4xLTQuOS01LjhDMjM0LjUsMjU5LjUsMjM2LjUsMjU3LDIzOS4xLDI1Ni41eiBNMjUzLDI1Ni40YzMuNi0xLDcuNSwyLDcuNCw1LjYKCQljMC4yLDMuNS0zLjQsNi42LTYuOSw1LjljLTMuMy0wLjQtNS44LTQtNC44LTcuMkMyNDkuMSwyNTguNywyNTAuOSwyNTcsMjUzLDI1Ni40TDI1MywyNTYuNHogTTIyNi4yLDI1OC42CgkJYzIuNS0wLjQsNC44LDIuMywzLjgsNC42Yy0wLjcsMi41LTQuNCwzLjEtNiwxLjFDMjIyLjEsMjYyLjQsMjIzLjUsMjU4LjksMjI2LjIsMjU4LjZ6IE0yNjcsMjU4LjdjMi4yLTAuOSw0LjksMSw0LjcsMy4zCgkJYzAuMSwyLjYtMy4yLDQuNC01LjQsMi45QzI2My45LDI2My42LDI2NC4zLDI1OS42LDI2NywyNTguN3ogTTI3OC40LDI3MGMtMC45LTEuNiwwLjctMy43LDIuNS0zLjRjMC45LDAsMS41LDAuNywyLjEsMS4yCgkJYzAuMSwwLjksMC4zLDIuMS0wLjUsMi44QzI4MS40LDI3MiwyNzksMjcxLjYsMjc4LjQsMjcweiBNMjEzLDI2Ny4xYzEuNy0xLjEsNC4xLDAuNSwzLjcsMi41Yy0wLjIsMS43LTIuNCwyLjctMy44LDEuNwoJCUMyMTEuNCwyNzAuMywyMTEuNSwyNjcuOCwyMTMsMjY3LjF6IE0yNDYsMjcwLjZjMi4yLTAuOSw1LDAuOSw0LjgsMy4zYzAuMiwyLjYtMy4zLDQuNC01LjQsMi45QzI0Mi45LDI3NS40LDI0My4zLDI3MS40LDI0NiwyNzAuNgoJCXogTTIzMC43LDI3NC4xYzEuOS0xLDQuMywwLjcsNC4yLDIuN2MwLjEsMS43LTEuNiwzLjEtMy4zLDIuOWMtMS40LDAtMi4zLTEuMy0yLjgtMi40QzIyOC45LDI3NiwyMjkuNCwyNzQuNiwyMzAuNywyNzQuMQoJCUwyMzAuNywyNzQuMXogTTI2MS42LDI3NC4xYzEuOS0xLjIsNC42LDAuNSw0LjQsMi43YzAsMi4zLTMsMy44LTQuOCwyLjJDMjU5LjUsMjc3LjksMjU5LjcsMjc1LjEsMjYxLjYsMjc0LjF6IE0yNjcsMjg3LjIKCQljLTAuOS0xLjMsMC4xLTIuOCwxLjUtMy4xYzEuMSwwLjIsMi4zLDEsMi4xLDIuM0MyNzAuNCwyODguMSwyNjcuOCwyODguNywyNjcsMjg3LjJMMjY3LDI4Ny4yeiBNMjI0LjMsMjg2LjFjMC4zLTEsMS4yLTIsMi40LTEuNwoJCWMxLjcsMC4xLDIuMywyLjcsMC43LDMuNUMyMjYuMSwyODguOCwyMjQuNSwyODcuNSwyMjQuMywyODYuMXogTTI0NC45LDI4Ny4yYzAuMy0xLjUsMi4zLTIuMiwzLjYtMS40YzAuOSwwLjQsMS4xLDEuMywxLjMsMi4xCgkJYy0wLjEsMC40LTAuMiwwLjgtMC4zLDEuMmMtMC41LDAuNi0xLjIsMS4yLTIuMSwxLjJDMjQ1LjgsMjkwLjYsMjQ0LjMsMjg4LjcsMjQ0LjksMjg3LjJMMjQ0LjksMjg3LjJ6Ii8+CjwvZz4KPHBhdGggY2xhc3M9InN0MTMiIGQ9Ik0yNDYuMywyMTAuM2MxLjktMSw0LjMsMS4zLDMuMywzLjJjLTAuNiwxLjUtMi45LDItNCwwLjhDMjQ0LjQsMjEzLjIsMjQ0LjgsMjEwLjksMjQ2LjMsMjEwLjNMMjQ2LjMsMjEwLjN6CgkgTTIyNS42LDIxMi41YzEuMi0wLjUsMi43LDAuNiwyLjUsMS44YzAuMSwxLjQtMS42LDIuNC0yLjgsMS43QzIyMy44LDIxNS41LDIyNCwyMTIuOSwyMjUuNiwyMTIuNXogTTI2OC4xLDIxNi4xCgljLTEuOC0wLjItMi4xLTMtMC40LTMuNmMxLjQtMC43LDIuNiwwLjYsMi44LDEuOEMyNzAuMiwyMTUuNCwyNjkuMywyMTYuNCwyNjguMSwyMTYuMXogTTIzMC4zLDIyMS4yYzItMS4yLDQuNywwLjYsNC40LDIuOAoJYy0wLjEsMi4zLTMuMSwzLjYtNC45LDJDMjI4LjMsMjI0LjksMjI4LjUsMjIyLjEsMjMwLjMsMjIxLjJ6IE0yNjAuMiwyMjIuNWMwLjktMi4yLDQuNC0yLjMsNS40LTAuMWMxLDEuNy0wLjIsMy44LTIsNC4zCglDMjYxLjMsMjI3LjEsMjU5LjEsMjI0LjYsMjYwLjIsMjIyLjV6IE0yNDMuOSwyMjYuNWMwLTEuOSwxLjctMy4zLDMuNi0zLjVjMS4yLDAuMiwyLjUsMC44LDMuMSwyYzEsMS43LDAuMSw0LTEuNiw0LjcKCWMtMC44LDAuNC0xLjgsMC4zLTIuNiwwLjJDMjQ0LjksMjI5LjQsMjQzLjcsMjI4LjEsMjQzLjksMjI2LjV6IE0yMTMuMSwyMjkuM2MxLjgtMS4xLDQuMiwwLjksMy41LDIuOGMtMC40LDEuNy0yLjYsMi4zLTMuOSwxLjMKCUMyMTEuMywyMzIuNCwyMTEuNSwyMzAsMjEzLjEsMjI5LjNMMjEzLjEsMjI5LjN6IE0yNzkuMiwyMjkuM2MxLjUtMS4yLDQsMC4yLDMuOCwyLjFjMC4xLDEuNy0yLjEsMy0zLjYsMi4xCglDMjc3LjgsMjMyLjgsMjc3LjYsMjMwLjIsMjc5LjIsMjI5LjNMMjc5LjIsMjI5LjN6IE0yNTIuNSwyMzIuN2MyLjUtMC45LDUuNSwwLjIsNi45LDIuNGMxLjksMi43LDAuOSw2LjgtMiw4LjMKCWMtMywxLjgtNy40LDAuMy04LjYtM0MyNDcuNSwyMzcuNCwyNDkuNCwyMzMuNywyNTIuNSwyMzIuN0wyNTIuNSwyMzIuN3ogTTIzNy44LDIzM2MyLjgtMS4zLDYuNS0wLjIsNy44LDIuNgoJYzEuNiwyLjcsMC40LDYuNS0yLjUsNy45Yy0yLjgsMS42LTYuOCwwLjQtOC4yLTIuNUMyMzMuNSwyMzguMSwyMzQuOSwyMzQuMywyMzcuOCwyMzN6IE0yMjMuMSwyMzhjMC4yLTEuOCwxLjktMi45LDMuNi0zCgljMC45LDAuMSwxLjcsMC41LDIuMywxLjFjMC42LDAuNiwxLDEuNCwxLjEsMi4zYy0wLjEsMS44LTEuNSwzLjYtMy41LDMuNkMyMjQuNiwyNDIuMSwyMjIuNywyNDAsMjIzLjEsMjM4eiBNMjY2LjUsMjM1LjMKCWMyLjItMS4zLDUuMiwwLjYsNS4yLDMuMWMwLjEsMi42LTMuMiw0LjUtNS40LDIuOUMyNjQsMjQwLDI2NC4yLDIzNi40LDI2Ni41LDIzNS4zeiBNMjMxLjksMjQ0LjZjMi42LTAuNyw1LjUsMC41LDYuOCwyLjgKCWMxLjQsMi4zLDAuOCw1LjYtMS4zLDcuM2MtMi44LDIuNS03LjgsMS41LTkuMy0xLjlDMjI2LjMsMjQ5LjYsMjI4LjQsMjQ1LjQsMjMxLjksMjQ0LjZMMjMxLjksMjQ0LjZ6IE0yNTkuNywyNDQuNgoJYzIuNS0wLjcsNS40LDAuMiw2LjgsMi41YzEuOCwyLjYsMC45LDYuNC0xLjcsOGMtMi44LDEuOS03LjEsMC45LTguNi0yLjFDMjU0LjMsMjQ5LjksMjU2LjIsMjQ1LjUsMjU5LjcsMjQ0LjZ6IE0yMTUuMywyNDcuNQoJYzIuMi0wLjgsNC43LDEuNiwzLjgsMy43Yy0wLjUsMi0zLjQsMi43LTQuOCwxLjJDMjEyLjYsMjUxLjEsMjEzLjIsMjQ4LjEsMjE1LjMsMjQ3LjV6IE0yNzUuNSwyNTAuNmMwLTAuOSwwLjMtMS43LDAuOS0yLjQKCWMwLjYtMC43LDEuNC0xLjEsMi4zLTEuMWMxLjUsMC4yLDMsMS40LDIuOSwzLjFjMC4xLDIuMS0yLjUsMy42LTQuNCwyLjZDMjc2LjMsMjUyLjQsMjc1LjksMjUxLjUsMjc1LjUsMjUwLjZ6IE0yMDQuNCwyNDguNgoJYzEuMy0wLjYsMywwLjYsMi43LDJjLTAuMSwxLjctMi42LDIuMy0zLjUsMC45QzIwMi45LDI1MC41LDIwMy4zLDI0OS4xLDIwNC40LDI0OC42TDIwNC40LDI0OC42eiBNMjg4LjYsMjQ4LjUKCWMwLjktMC43LDIuNS0wLjIsMi44LDAuOWMwLjYsMS4yLTAuNSwyLjgtMS45LDIuNkMyODcuNiwyNTIuMiwyODcsMjQ5LjQsMjg4LjYsMjQ4LjV6IE0yMzkuMSwyNTYuNWMzLjUtMC45LDcuMywyLDcuMyw1LjUKCWMwLjIsMy42LTMuNSw2LjgtNy4xLDZjLTIuOC0wLjQtNS0zLjEtNC45LTUuOEMyMzQuNSwyNTkuNSwyMzYuNSwyNTcsMjM5LjEsMjU2LjV6IE0yNTMsMjU2LjRjMy42LTEsNy41LDIsNy40LDUuNgoJYzAuMiwzLjUtMy40LDYuNi02LjksNS45Yy0zLjMtMC40LTUuOC00LTQuOC03LjJDMjQ5LjEsMjU4LjcsMjUwLjksMjU3LDI1MywyNTYuNEwyNTMsMjU2LjR6IE0yMjYuMiwyNTguNmMyLjUtMC40LDQuOCwyLjMsMy44LDQuNgoJYy0wLjcsMi41LTQuNCwzLjEtNiwxLjFDMjIyLjEsMjYyLjQsMjIzLjUsMjU4LjksMjI2LjIsMjU4LjZ6IE0yNjcsMjU4LjdjMi4yLTAuOSw0LjksMSw0LjcsMy4zYzAuMSwyLjYtMy4yLDQuNC01LjQsMi45CglDMjYzLjksMjYzLjYsMjY0LjMsMjU5LjYsMjY3LDI1OC43eiBNMjc4LjQsMjcwYy0wLjktMS42LDAuNy0zLjcsMi41LTMuNGMwLjksMCwxLjUsMC43LDIuMSwxLjJjMC4xLDAuOSwwLjMsMi4xLTAuNSwyLjgKCUMyODEuNCwyNzIsMjc5LDI3MS42LDI3OC40LDI3MHogTTIxMywyNjcuMWMxLjctMS4xLDQuMSwwLjUsMy43LDIuNWMtMC4yLDEuNy0yLjQsMi43LTMuOCwxLjdDMjExLjQsMjcwLjMsMjExLjUsMjY3LjgsMjEzLDI2Ny4xegoJIE0yNDYsMjcwLjZjMi4yLTAuOSw1LDAuOSw0LjgsMy4zYzAuMiwyLjYtMy4zLDQuNC01LjQsMi45QzI0Mi45LDI3NS40LDI0My4zLDI3MS40LDI0NiwyNzAuNnogTTIzMC43LDI3NC4xYzEuOS0xLDQuMywwLjcsNC4yLDIuNwoJYzAuMSwxLjctMS42LDMuMS0zLjMsMi45Yy0xLjQsMC0yLjMtMS4zLTIuOC0yLjRDMjI4LjksMjc2LDIyOS40LDI3NC42LDIzMC43LDI3NC4xTDIzMC43LDI3NC4xeiBNMjYxLjYsMjc0LjEKCWMxLjktMS4yLDQuNiwwLjUsNC40LDIuN2MwLDIuMy0zLDMuOC00LjgsMi4yQzI1OS41LDI3Ny45LDI1OS43LDI3NS4xLDI2MS42LDI3NC4xeiBNMjY3LDI4Ny4yYy0wLjktMS4zLDAuMS0yLjgsMS41LTMuMQoJYzEuMSwwLjIsMi4zLDEsMi4xLDIuM0MyNzAuNCwyODguMSwyNjcuOCwyODguNywyNjcsMjg3LjJMMjY3LDI4Ny4yeiBNMjI0LjMsMjg2LjFjMC4zLTEsMS4yLTIsMi40LTEuN2MxLjcsMC4xLDIuMywyLjcsMC43LDMuNQoJQzIyNi4xLDI4OC44LDIyNC41LDI4Ny41LDIyNC4zLDI4Ni4xeiBNMjQ0LjksMjg3LjJjMC4zLTEuNSwyLjMtMi4yLDMuNi0xLjRjMC45LDAuNCwxLjEsMS4zLDEuMywyLjFjLTAuMSwwLjQtMC4yLDAuOC0wLjMsMS4yCgljLTAuNSwwLjYtMS4yLDEuMi0yLjEsMS4yQzI0NS44LDI5MC42LDI0NC4zLDI4OC43LDI0NC45LDI4Ny4yTDI0NC45LDI4Ny4yeiIvPgo8L3N2Zz4K",\n`;
+ example += ` "version": "1.1.0"\n`;
+ example += ` },\n`;
+ example += ` {\n`;
+ example += ` "name": "eternl",\n`;
+ example += ` "icon": "data:image/png;base64,ICONBASE64HERE=",\n`;
+ example += ` "version": "0.1.0"\n`;
+ example += ` }\n`;
+ example += `]\n`;
+
+ return (
+ <>
+
+ Returns a list of wallets available on user's device. Each wallet is an
+ object with the following properties:
+
+
+
+ A name is provided to display wallet's name on the user interface.
+
+
+ A version is provided to display wallet's version on the user
+ interface.
+
+
+ An icon is provided to display wallet's icon on the user interface.
+
+
+
Example:
+
+ >
+ );
+}
+
+function Right() {
+ async function runDemo() {
+ return await BrowserWallet.getAvailableWallets();
+ }
+
+ let codeSnippet = "";
+ codeSnippet += `import { BrowserWallet } from '@meshsdk/core';\n\n`;
+ codeSnippet += `const wallets = await BrowserWallet.getAvailableWallets()`;
+
+ return (
+
+ );
+}
diff --git a/apps/playground/src/pages/apis/wallets/browserwallet/index.tsx b/apps/playground/src/pages/apis/wallets/browserwallet/index.tsx
index 935ef35d..4ab9b7bf 100644
--- a/apps/playground/src/pages/apis/wallets/browserwallet/index.tsx
+++ b/apps/playground/src/pages/apis/wallets/browserwallet/index.tsx
@@ -7,10 +7,10 @@ import Metatags from "~/components/site/metatags";
import { metaBrowserwallet } from "~/data/links-wallets";
import BrowserWalletConnectWallet from "./connect-wallet";
import BrowserWalletGetAssets from "./get-assets";
+import BrowserWalletGetAvailableWallets from "./get-available-wallets";
import BrowserWalletGetBalance from "./get-balance";
import BrowserWalletGetChangeAddress from "./get-change-address";
import BrowserWalletGetCollateral from "./get-collateral";
-import BrowserWalletGetInstalledWallets from "./get-installed-wallets";
import BrowserWalletGetLovelace from "./get-lovelace";
import BrowserWalletGetNetworkId from "./get-networkid";
import BrowserWalletGetPolicyIdAssets from "./get-policyid-assets";
@@ -25,7 +25,7 @@ import BrowserWalletSubmitTransaction from "./submit-tx";
const ReactPage: NextPage = () => {
const sidebarItems = [
- { label: "Get installed wallets", to: "getInstallWallets" },
+ { label: "Get available wallets", to: "getAvailableWallets" },
{ label: "Connect wallet", to: "connectWallet" },
{ label: "Get balance", to: "getBalance" },
{ label: "Get change address", to: "getChangeAddress" },
@@ -76,7 +76,7 @@ const ReactPage: NextPage = () => {
-
+
diff --git a/apps/playground/src/pages/smart-contracts/escrow/index.tsx b/apps/playground/src/pages/smart-contracts/escrow/index.tsx
index 79e1444c..a9928c5e 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";
@@ -76,11 +77,13 @@ const ReactPage: NextPage = () => {
Both on-chain and off-chain codes are open-source and available on{" "}
-
+
Mesh Github Repository
.
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..917cb6fa 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";
@@ -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..f1c2f7de 100644
--- a/apps/playground/src/pages/smart-contracts/payment-splitter/index.tsx
+++ b/apps/playground/src/pages/smart-contracts/payment-splitter/index.tsx
@@ -95,7 +95,7 @@ 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/swap/index.tsx b/apps/playground/src/pages/smart-contracts/swap/index.tsx
index 968da425..4e386a3a 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";
@@ -76,11 +77,13 @@ const ReactPage: NextPage = () => {
Both on-chain and off-chain codes are open-source and available on{" "}
-
+
Mesh Github Repository
.