+ First, we get the DRep ID from the wallet, the DRep ID voting for this
+ governance action.
+
+ Then we get the utxos and the change address from the wallet.
+ Finally, we sign the transaction and submit it to the blockchain.
+
+ And another example of a vote transaction with a Plutus script and a
+ redeemer:
+
+
-
-
-
+
Mesh TypeScript SDK
diff --git a/packages/mesh-core/package.json b/packages/mesh-core/package.json
index 94295ae2..5d3d3ef7 100644
--- a/packages/mesh-core/package.json
+++ b/packages/mesh-core/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/core",
- "version": "1.7.7",
+ "version": "1.7.8",
"description": "",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
@@ -33,13 +33,13 @@
"typescript": "^5.3.3"
},
"dependencies": {
- "@meshsdk/common": "1.7.7",
- "@meshsdk/core-csl": "1.7.7",
- "@meshsdk/core-cst": "1.7.7",
- "@meshsdk/provider": "1.7.7",
- "@meshsdk/react": "1.7.7",
- "@meshsdk/transaction": "1.7.7",
- "@meshsdk/wallet": "1.7.7"
+ "@meshsdk/common": "1.7.8",
+ "@meshsdk/core-csl": "1.7.8",
+ "@meshsdk/core-cst": "1.7.8",
+ "@meshsdk/provider": "1.7.8",
+ "@meshsdk/react": "1.7.8",
+ "@meshsdk/transaction": "1.7.8",
+ "@meshsdk/wallet": "1.7.8"
},
"prettier": "@meshsdk/configs/prettier",
"publishConfig": {
diff --git a/packages/mesh-provider/package.json b/packages/mesh-provider/package.json
index 8ef1ddeb..ca122b7a 100644
--- a/packages/mesh-provider/package.json
+++ b/packages/mesh-provider/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/provider",
- "version": "1.7.7",
+ "version": "1.7.8",
"description": "",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
@@ -34,8 +34,8 @@
"typescript": "^5.3.3"
},
"dependencies": {
- "@meshsdk/common": "1.7.7",
- "@meshsdk/core-cst": "1.7.7",
+ "@meshsdk/common": "1.7.8",
+ "@meshsdk/core-cst": "1.7.8",
"axios": "^1.7.2"
},
"prettier": "@meshsdk/configs/prettier",
diff --git a/packages/mesh-react/package.json b/packages/mesh-react/package.json
index 9ad7bb87..0e391ae5 100644
--- a/packages/mesh-react/package.json
+++ b/packages/mesh-react/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/react",
- "version": "1.7.7",
+ "version": "1.7.8",
"description": "",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
@@ -30,9 +30,9 @@
},
"dependencies": {
"react": "^18.2.0",
- "@meshsdk/common": "1.7.7",
- "@meshsdk/transaction": "1.7.7",
- "@meshsdk/wallet": "1.7.7"
+ "@meshsdk/common": "1.7.8",
+ "@meshsdk/transaction": "1.7.8",
+ "@meshsdk/wallet": "1.7.8"
},
"devDependencies": {
"@meshsdk/configs": "*",
diff --git a/packages/mesh-transaction/package.json b/packages/mesh-transaction/package.json
index 209b72f3..e8941969 100644
--- a/packages/mesh-transaction/package.json
+++ b/packages/mesh-transaction/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/transaction",
- "version": "1.7.7",
+ "version": "1.7.8",
"description": "",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
@@ -35,9 +35,9 @@
"typescript": "^5.3.3"
},
"dependencies": {
- "@meshsdk/common": "1.7.7",
- "@meshsdk/core-csl": "1.7.7",
- "@meshsdk/core-cst": "1.7.7",
+ "@meshsdk/common": "1.7.8",
+ "@meshsdk/core-csl": "1.7.8",
+ "@meshsdk/core-cst": "1.7.8",
"json-bigint": "^1.0.0"
},
"prettier": "@meshsdk/configs/prettier",
diff --git a/packages/mesh-transaction/src/mesh-tx-builder/tx-builder-core.ts b/packages/mesh-transaction/src/mesh-tx-builder/tx-builder-core.ts
index 97ec1069..6cf364a2 100644
--- a/packages/mesh-transaction/src/mesh-tx-builder/tx-builder-core.ts
+++ b/packages/mesh-transaction/src/mesh-tx-builder/tx-builder-core.ts
@@ -29,6 +29,9 @@ import {
UTxO,
UtxoSelection,
UtxoSelectionStrategy,
+ Vote,
+ Voter,
+ VotingProcedure,
Withdrawal,
} from "@meshsdk/common";
@@ -41,6 +44,8 @@ export class MeshTxBuilderCore {
private plutusMintingScriptVersion: LanguageVersion | undefined;
private addingPlutusWithdrawal = false;
private plutusWithdrawalScriptVersion: LanguageVersion | undefined;
+ private addingPlutusVote = false;
+ private plutusVoteScriptVersion: LanguageVersion | undefined;
protected _protocolParams: Protocol = DEFAULT_PROTOCOL_PARAMETERS;
@@ -50,6 +55,8 @@ export class MeshTxBuilderCore {
protected withdrawalItem?: Withdrawal;
+ protected voteItem?: Vote;
+
protected collateralQueueItem?: PubKeyTxIn;
protected refScriptTxInQueueItem?: RefTxIn;
@@ -758,7 +765,7 @@ export class MeshTxBuilderCore {
return this;
};
/**
- * Set the instruction that it is currently using V1 Plutus withdrawal scripts
+ * Set the instruction that it is currently using a Plutus withdrawal scripts
* @returns The MeshTxBuilder instance
*/
withdrawalPlutusScriptV1 = () => {
@@ -904,6 +911,181 @@ export class MeshTxBuilderCore {
return this;
};
+ /**
+ * Set the instruction that it is currently using a Plutus voting scripts
+ * @param languageVersion The Plutus script version
+ * @returns The MeshTxBuilder instance
+ */
+ votePlutusScript = (languageVersion: LanguageVersion) => {
+ this.addingPlutusVote = true;
+ this.plutusVoteScriptVersion = languageVersion;
+ return this;
+ };
+ /**
+ * Set the instruction that it is currently using V1 Plutus voting scripts
+ * @returns The MeshTxBuilder instance
+ */
+ votePlutusScriptV1 = () => {
+ this.addingPlutusVote = true;
+ this.plutusVoteScriptVersion = "V1";
+ return this;
+ };
+
+ /**
+ * Set the instruction that it is currently using V2 Plutus voting scripts
+ * @returns The MeshTxBuilder instance
+ */
+ votePlutusScriptV2 = () => {
+ this.addingPlutusVote = true;
+ this.plutusVoteScriptVersion = "V2";
+ return this;
+ };
+
+ /**
+ * Set the instruction that it is currently using V3 Plutus voting scripts
+ * @returns The MeshTxBuilder instance
+ */
+ votePlutusScriptV3 = () => {
+ this.addingPlutusVote = true;
+ this.plutusVoteScriptVersion = "V3";
+ return this;
+ };
+
+ /**
+ * Add a vote in the MeshTxBuilder instance
+ * @param voter The voter, can be a ConstitutionalCommitee, a DRep or a StakePool
+ * @param govActionId - The transaction hash and transaction id of the governance action
+ * @param votingProcedure - The voting kind (Yes, No, Abstain) with an optional anchor
+ * @returns The MeshTxBuilder instance
+ */
+ vote = (
+ voter: Voter,
+ govActionId: RefTxIn,
+ votingProcedure: VotingProcedure,
+ ) => {
+ if (this.voteItem) {
+ this.queueVote();
+ }
+
+ if (this.addingPlutusVote) {
+ const vote: Vote = {
+ type: "ScriptVote",
+ vote: {
+ voter,
+ govActionId,
+ votingProcedure,
+ },
+ };
+ this.voteItem = vote;
+ } else {
+ const vote: Vote = {
+ type: "BasicVote",
+ vote: {
+ voter,
+ govActionId,
+ votingProcedure,
+ },
+ };
+ this.voteItem = vote;
+ }
+ return this;
+ };
+
+ /**
+ * Add a voting script to the MeshTxBuilder instance
+ * @param scriptCbor The script in CBOR format
+ * @returns The MeshTxBuilder instance
+ */
+ voteScript = (scriptCbor: string) => {
+ if (!this.voteItem) throw Error("voteScript: Undefined vote");
+ if (this.voteItem.type === "BasicVote") {
+ this.voteItem = {
+ type: "SimpleScriptVote",
+ vote: this.voteItem.vote,
+ simpleScriptSource: {
+ type: "Provided",
+ scriptCode: scriptCbor,
+ },
+ };
+ } else if (this.voteItem.type === "ScriptVote") {
+ this.voteItem.scriptSource = {
+ type: "Provided",
+ script: {
+ code: scriptCbor,
+ version: this.plutusVoteScriptVersion || "V2",
+ },
+ };
+ } else if (this.voteItem.type === "SimpleScriptVote") {
+ throw Error("voteScript: Script is already defined for current vote");
+ }
+ return this;
+ };
+
+ /**
+ * Add a vote reference to the MeshTxBuilder instance
+ * @param txHash The transaction hash of reference UTxO
+ * @param txIndex The transaction index of reference UTxO
+ * @param scriptSize The script size in bytes of the vote script (can be obtained by script hex length / 2)
+ * @param scriptHash The script hash of the vote script
+ * @returns The MeshTxBuilder instance
+ */
+ voteTxInReference = (
+ txHash: string,
+ txIndex: number,
+ scriptSize?: string,
+ scriptHash?: string,
+ ) => {
+ if (!this.voteItem) throw Error("voteTxInReference: Undefined vote");
+ if (this.voteItem.type === "BasicVote")
+ throw Error(
+ "voteTxInReference: Adding script reference to a basic vote",
+ );
+ if (this.voteItem.type === "ScriptVote") {
+ this.voteItem.scriptSource = {
+ type: "Inline",
+ txHash,
+ txIndex,
+ scriptHash,
+ version: this.plutusWithdrawalScriptVersion || "V2",
+ scriptSize,
+ };
+ } else if (this.voteItem.type === "SimpleScriptVote") {
+ this.voteItem.simpleScriptSource = {
+ type: "Inline",
+ txHash,
+ txIndex,
+ scriptSize,
+ simpleScriptHash: scriptHash,
+ };
+ }
+
+ return this;
+ };
+
+ /**
+ * Set the transaction vote redeemer value in the MeshTxBuilder instance
+ * @param redeemer The redeemer in Mesh Data type, JSON in raw constructor like format, or CBOR hex string
+ * @param type The redeemer data type, either Mesh Data type, JSON in raw constructor like format, or CBOR hex string
+ * @param exUnits The execution units budget for the redeemer
+ * @returns The MeshTxBuilder instance
+ */
+ voteRedeemerValue = (
+ redeemer: BuilderData["content"],
+ type: BuilderData["type"] = "Mesh",
+ exUnits = { ...DEFAULT_REDEEMER_BUDGET },
+ ) => {
+ if (!this.voteItem) throw Error("voteRedeemerValue: Undefined vote");
+ if (!(this.voteItem.type === "ScriptVote"))
+ throw Error("voteRedeemerValue: Adding redeemer to non plutus vote");
+ this.voteItem.redeemer = this.castBuilderDataToRedeemer(
+ redeemer,
+ type,
+ exUnits,
+ );
+
+ return this;
+ };
+
/**
* Creates a pool registration certificate, and adds it to the transaction
* @param poolParams Parameters for pool registration
@@ -1304,6 +1486,9 @@ export class MeshTxBuilderCore {
if (this.withdrawalItem) {
this.queueWithdrawal();
}
+ if (this.voteItem) {
+ this.queueVote();
+ }
};
private queueInput = () => {
@@ -1359,6 +1544,26 @@ export class MeshTxBuilderCore {
this.withdrawalItem = undefined;
};
+ private queueVote = () => {
+ if (!this.voteItem) {
+ throw Error("queueVote: Undefined vote");
+ }
+ if (this.voteItem.type === "ScriptVote") {
+ if (!this.voteItem.scriptSource) {
+ throw Error("queueVote: Missing vote script information");
+ }
+ if (!this.voteItem.redeemer) {
+ throw Error("queueVote: Missing vote redeemer information");
+ }
+ } else if (this.voteItem.type === "SimpleScriptVote") {
+ if (!this.voteItem.simpleScriptSource) {
+ throw Error("queueVote: Missing vote script information");
+ }
+ }
+ this.meshTxBuilderBody.votes.push(this.voteItem);
+ this.voteItem = undefined;
+ };
+
protected castRawDataToJsonString = (rawData: object | string) => {
if (typeof rawData === "object") {
return JSONBig.stringify(rawData);
@@ -1586,11 +1791,13 @@ export class MeshTxBuilderCore {
this.addingPlutusMint = false;
this.plutusMintingScriptVersion = undefined;
this.addingPlutusWithdrawal = false;
+ this.addingPlutusVote = false;
this.plutusWithdrawalScriptVersion = undefined;
this._protocolParams = DEFAULT_PROTOCOL_PARAMETERS;
this.mintItem = undefined;
this.txInQueueItem = undefined;
this.withdrawalItem = undefined;
+ this.voteItem = undefined;
this.collateralQueueItem = undefined;
this.refScriptTxInQueueItem = undefined;
};
diff --git a/packages/mesh-transaction/test/mesh-tx-builder/tx.test.ts b/packages/mesh-transaction/test/mesh-tx-builder/tx.test.ts
index b5765fb6..88ce7d72 100644
--- a/packages/mesh-transaction/test/mesh-tx-builder/tx.test.ts
+++ b/packages/mesh-transaction/test/mesh-tx-builder/tx.test.ts
@@ -4,8 +4,10 @@ import {
NativeScript,
resolveNativeScriptHash,
resolveNativeScriptHex,
+ resolveScriptHash,
resolveScriptHashDRepId,
} from "@meshsdk/core";
+import { applyCborEncoding } from "@meshsdk/core-csl";
import { MeshTxBuilder } from "@meshsdk/transaction";
describe("MeshTxBuilder transactions", () => {
@@ -352,4 +354,161 @@ describe("MeshTxBuilder transactions", () => {
console.log(txHex);
expect(txHex !== "").toBeTruthy();
});
+
+ it("Drep vote", () => {
+ let mesh = new MeshTxBuilder();
+
+ let txHex = mesh
+ .changeAddress(
+ "addr_test1qpsmz8q2xj43wg597pnpp0ffnlvr8fpfydff0wcsyzqyrxguk5v6wzdvfjyy8q5ysrh8wdxg9h0u4ncse4cxhd7qhqjqk8pse6",
+ )
+ .txIn(
+ "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85",
+ 3,
+ [
+ {
+ unit: "lovelace",
+ quantity: "9891607895",
+ },
+ ],
+ "addr_test1vru4e2un2tq50q4rv6qzk7t8w34gjdtw3y2uzuqxzj0ldrqqactxh",
+ )
+ .vote(
+ {
+ type: "DRep",
+ drepId: "drep1j6257gz2swty9ut46lspyvujkt02pd82am2zq97p7p9pv2euzs7",
+ },
+ {
+ txHash:
+ "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85",
+ txIndex: 3,
+ },
+ {
+ voteKind: "Yes",
+ anchor: {
+ anchorUrl: "https://path-to.jsonld",
+ anchorDataHash:
+ "2aef51273a566e529a2d5958d981d7f0b3c7224fc2853b6c4922e019657b5060",
+ },
+ },
+ )
+ .completeSync();
+
+ console.log(txHex);
+ expect(txHex !== "").toBeTruthy();
+ });
+
+ it("Script drep vote", () => {
+ let mesh = new MeshTxBuilder();
+
+ let txHex = mesh
+ .changeAddress(
+ "addr_test1qpsmz8q2xj43wg597pnpp0ffnlvr8fpfydff0wcsyzqyrxguk5v6wzdvfjyy8q5ysrh8wdxg9h0u4ncse4cxhd7qhqjqk8pse6",
+ )
+ .txIn(
+ "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85",
+ 3,
+ [
+ {
+ unit: "lovelace",
+ quantity: "9891607895",
+ },
+ ],
+ "addr_test1vru4e2un2tq50q4rv6qzk7t8w34gjdtw3y2uzuqxzj0ldrqqactxh",
+ )
+ .txInCollateral(
+ "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85",
+ 3,
+ [
+ {
+ unit: "lovelace",
+ quantity: "9891607895",
+ },
+ ],
+ "addr_test1vru4e2un2tq50q4rv6qzk7t8w34gjdtw3y2uzuqxzj0ldrqqactxh",
+ )
+ .votePlutusScriptV3()
+ .vote(
+ {
+ type: "DRep",
+ drepId: resolveScriptHashDRepId(
+ resolveScriptHash(
+ applyCborEncoding(
+ "5834010100323232322533300232323232324a260106012004600e002600e004600a00260066ea8004526136565734aae795d0aba201",
+ ),
+ "V3",
+ ),
+ ),
+ },
+ {
+ txHash:
+ "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85",
+ txIndex: 3,
+ },
+ {
+ voteKind: "Yes",
+ anchor: {
+ anchorUrl: "https://path-to.jsonld",
+ anchorDataHash:
+ "2aef51273a566e529a2d5958d981d7f0b3c7224fc2853b6c4922e019657b5060",
+ },
+ },
+ )
+ .voteScript(
+ applyCborEncoding(
+ "5834010100323232322533300232323232324a260106012004600e002600e004600a00260066ea8004526136565734aae795d0aba201",
+ ),
+ )
+ .voteRedeemerValue("")
+ .completeSync();
+
+ console.log(txHex);
+ expect(txHex !== "").toBeTruthy();
+ });
+
+ it("CC vote", () => {
+ let mesh = new MeshTxBuilder();
+
+ let txHex = mesh
+ .changeAddress(
+ "addr_test1qpsmz8q2xj43wg597pnpp0ffnlvr8fpfydff0wcsyzqyrxguk5v6wzdvfjyy8q5ysrh8wdxg9h0u4ncse4cxhd7qhqjqk8pse6",
+ )
+ .txIn(
+ "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85",
+ 3,
+ [
+ {
+ unit: "lovelace",
+ quantity: "9891607895",
+ },
+ ],
+ "addr_test1vru4e2un2tq50q4rv6qzk7t8w34gjdtw3y2uzuqxzj0ldrqqactxh",
+ )
+ .vote(
+ {
+ type: "ConstitutionalCommittee",
+ hotCred: {
+ type: "KeyHash",
+ keyHash: "e3a4c41d67592a1b8d87c62e5c5d73f7e8db836171945412d13f40f8",
+ },
+ },
+ {
+ txHash:
+ "2cb57168ee66b68bd04a0d595060b546edf30c04ae1031b883c9ac797967dd85",
+ txIndex: 3,
+ },
+ {
+ voteKind: "Yes",
+ anchor: {
+ anchorUrl: "https://path-to.jsonld",
+ anchorDataHash:
+ "2aef51273a566e529a2d5958d981d7f0b3c7224fc2853b6c4922e019657b5060",
+ },
+ },
+ )
+ .completeSync();
+
+ console.log(txHex);
+ expect(txHex !== "").toBeTruthy();
+ });
});
diff --git a/packages/mesh-wallet/package.json b/packages/mesh-wallet/package.json
index 5d5b4c43..e8e68ef0 100644
--- a/packages/mesh-wallet/package.json
+++ b/packages/mesh-wallet/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/wallet",
- "version": "1.7.7",
+ "version": "1.7.8",
"description": "",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
@@ -35,10 +35,10 @@
"typescript": "^5.3.3"
},
"dependencies": {
- "@meshsdk/common": "1.7.7",
- "@meshsdk/core-csl": "1.7.7",
- "@meshsdk/core-cst": "1.7.7",
- "@meshsdk/transaction": "1.7.7",
+ "@meshsdk/common": "1.7.8",
+ "@meshsdk/core-csl": "1.7.8",
+ "@meshsdk/core-cst": "1.7.8",
+ "@meshsdk/transaction": "1.7.8",
"@nufi/dapp-client-cardano": "^0.3.1",
"@nufi/dapp-client-core": "^0.3.1"
},
diff --git a/scripts/mesh-cli/package.json b/scripts/mesh-cli/package.json
index e2fec016..992365f4 100644
--- a/scripts/mesh-cli/package.json
+++ b/scripts/mesh-cli/package.json
@@ -3,7 +3,7 @@
"description": "A quick and easy way to bootstrap your dApps on Cardano using Mesh.",
"homepage": "https://meshjs.dev",
"author": "MeshJS",
- "version": "1.7.7",
+ "version": "1.7.8",
"license": "Apache-2.0",
"type": "module",
"main": "./dist/index.cjs",