-
- 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 efbea4310..9042e9fd7 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 c9cb4d3a6..fe07568f2 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 b19bbac3e..99f6336dd 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 ab2c18209..46ea13503 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 097e393ad..72db3cd8c 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 aaebd06b1..65e92aa60 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 94d65ab5f..822676850 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 d212607dd..9edef3e6e 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 97f07c597..f5bc705db 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 7c02467a4..ed1836ca9 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 fb02f4c5e..74c8f6dbe 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 a77a39cfb..24e89920f 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 fe26894a4..7204d5235 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 a377425db..f121b41b2 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 3f816be16..a2cf110a3 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 b9910e05e..7d5a7cb7b 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 94ab149b4..115aef108 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 bb57e248f..076e83f47 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 e244c407f..244ee2af4 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 2a9f68931..3322eb8f2 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 d3cba2a17..7a92933ae 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 d2a45f08b..569239dda 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 fed9c007d..02c6730f7 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 ac7d6f9c4..e2db9b52f 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 7c95132e9..9b0e84c2c 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 7b78638cc..0b3bbf20e 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 f88b7089f..5599af872 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 b0975b523..35c0fabdc 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 30339ac0f..a07c4acb6 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 000000000..30a2ac88f
--- /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 2a8e353c7..49861be7c 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 0113311c5..883b56756 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 822676850..1488a5fb9 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 8381022c6..3aa6bcade 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 5599af872..1da217e6c 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 1488a5fb9..7ef3ef2bf 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 000000000..85d7c6018
--- /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 882f809cf..9b8ecc522 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 6e2adf7b2..40b356466 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 000000000..c0e9dbb2d
--- /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 935ef35dc..4ab9b7bfb 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 79e1444ce..a9928c5e6 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 7caf6d364..917cb6fa5 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 aa7c51070..53d50d007 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 8d68e67cd..f1c2f7ded 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 968da425a..4e386a3a2 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
.