Mesh LogoMesh

Governance Transactions

Participate in Cardano's on-chain governance through DRep delegation, registration, voting, and submitting governance action proposals.

Overview

Cardano's on-chain governance system (CIP-1694) enables the community to vote on proposals and protocol updates. Mesh SDK implements the CIP-95 Web-Wallet Bridge extension, allowing dApps to interact with governance features. You can delegate your voting power to Decentralized Representatives (DReps), register as a DRep yourself, vote on governance actions, and submit new governance action proposals.

When to use this:

  • Delegating your voting power to a DRep
  • Registering as a DRep to represent other voters
  • Voting on governance actions and protocol changes
  • Submitting governance action proposals (info actions, parameter changes, treasury withdrawals, etc.)
  • Building governance dashboards and tools
  • Creating DRep management applications

Quick Start

import { MeshTxBuilder, BlockfrostProvider } from "@meshsdk/core";

// Initialize
const provider = new BlockfrostProvider("<YOUR_API_KEY>");
const txBuilder = new MeshTxBuilder({
  fetcher: provider,
  verbose: true,
});

// Get wallet data
const utxos = await wallet.getUtxos();
const changeAddress = await wallet.getChangeAddress();
const rewardAddresses = await wallet.getRewardAddresses();
const rewardAddress = rewardAddresses[0]!;

// Delegate to a DRep
txBuilder
  .voteDelegationCertificate(
    { dRepId: "drep1yv4uesaj92wk8ljlsh4p7jzndnzrflchaz5fzug3zxg4naqkpeas3" },
    rewardAddress
  )
  .changeAddress(changeAddress)
  .selectUtxosFrom(utxos);

const unsignedTx = await txBuilder.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);

API Reference

voteDelegationCertificate()

Delegate voting power to a DRep.

.voteDelegationCertificate(drep: DRepId, rewardAddress: string)
ParameterTypeDescription
drepDRepIdDRep identifier object
rewardAddressstringYour stake/reward address

The DRepId object can specify:

  • { dRepId: "drep1..." } - Delegate to a specific DRep
  • { alwaysAbstain: true } - Always abstain from voting
  • { alwaysNoConfidence: true } - Always vote no confidence

drepRegistrationCertificate()

Register as a DRep.

.drepRegistrationCertificate(dRepId: string, anchor?: Anchor)
ParameterTypeDescription
dRepIdstringYour DRep ID (from wallet)
anchorAnchorOptional metadata anchor

The Anchor object:

{
  anchorUrl: string;      // URL to metadata JSON
  anchorDataHash: string; // Hash of metadata content
}

drepUpdateCertificate()

Update DRep metadata.

.drepUpdateCertificate(dRepId: string, anchor?: Anchor)
ParameterTypeDescription
dRepIdstringYour DRep ID
anchorAnchorNew metadata anchor

drepDeregistrationCertificate()

Retire as a DRep and reclaim deposit.

.drepDeregistrationCertificate(dRepId: string)
ParameterTypeDescription
dRepIdstringYour DRep ID to retire

vote()

Cast a vote on a governance action.

.vote(voter: Voter, govActionId: GovActionId, votingProcedure: VotingProcedure)
ParameterTypeDescription
voterVoterVoter identity
govActionIdGovActionIdGovernance action reference
votingProcedureVotingProcedureVote details

The Voter object:

// DRep voter
{ type: "DRep", drepId: "drep1..." }

// Stake pool operator
{ type: "StakePool", poolId: "pool1..." }

// Constitutional committee member
{ type: "ConstitutionalCommittee", hotCred: "..." }

The VotingProcedure object:

{
  voteKind: "Yes" | "No" | "Abstain";
  anchor?: {
    anchorUrl: string;
    anchorDataHash: string;
  };
}

votePlutusScriptV3()

Indicate voting with a Plutus script.

.votePlutusScriptV3()

voteScript()

Provide the voting script.

.voteScript(scriptCbor: string)

voteRedeemerValue()

Provide the redeemer for script-based voting.

.voteRedeemerValue(redeemer: Data | object | string, type?: "Mesh" | "CBOR" | "JSON", exUnits?: Budget)

proposal()

Submit a governance action proposal. Requires a deposit (returned when the action is resolved).

.proposal(governanceAction: GovernanceAction, anchor: Anchor, rewardAccount: string, deposit?: string)
ParameterTypeDescription
governanceActionGovernanceActionThe governance action to propose
anchorAnchorProposal metadata anchor (URL + hash)
rewardAccountstringReward address for deposit return
depositstringDeposit amount in lovelace (defaults to "100000000000", i.e. 100,000 ADA)

The GovernanceAction is a discriminated union with a kind and action field:

// Info action (no on-chain effect, used for polls/sentiment)
{ kind: "InfoAction", action: {} }

// Protocol parameter change
{
  kind: "ParameterChangeAction",
  action: {
    govActionId?: { transactionId: string; govActionIndex: number },
    protocolParamUpdates: ProtocolParamUpdate,
    policyHash?: { bytes: string },
  }
}

// Treasury withdrawal
{
  kind: "TreasuryWithdrawalsAction",
  action: {
    withdrawals: Record<string, string>,  // reward address -> lovelace amount
    policyHash?: { bytes: string },
  }
}

// No confidence in current committee
{
  kind: "NoConfidenceAction",
  action: {
    govActionId?: { transactionId: string; govActionIndex: number },
  }
}

// Update constitutional committee
{
  kind: "UpdateCommitteeAction",
  action: {
    govActionId?: { transactionId: string; govActionIndex: number },
    committee: {
      members: Array<{ stakeCredential: Credential; termLimit: number }>,
      quorumThreshold: { numerator: string; denominator: string },
    },
    membersToRemove: Credential[],
  }
}

// New constitution
{
  kind: "NewConstitutionAction",
  action: {
    govActionId?: { transactionId: string; govActionIndex: number },
    constitution: {
      anchor: Anchor,
      scriptHash?: { bytes: string },
    },
  }
}

// Hard fork initiation
{
  kind: "HardForkInitiationAction",
  action: {
    govActionId?: { transactionId: string; govActionIndex: number },
    protocolVersion: { major: number; minor: number },
  }
}

The Credential type used in committee actions:

{ type: "KeyHash", keyHash: string }
// or
{ type: "ScriptHash", scriptHash: string }

The govActionId field is optional and refers to the most recently enacted governance action of the same type that this proposal builds upon. It is required for action types that must chain from a previous action (parameter changes, hard forks, committee updates, no confidence, new constitution).

proposalScript()

Attach a Plutus script witness to the proposal.

.proposalScript(scriptCbor: string, version: "V1" | "V2" | "V3")
ParameterTypeDescription
scriptCborstringCBOR hex of the Plutus script
versionLanguageVersionPlutus language version

proposalTxInReference()

Use a reference script for the proposal instead of providing it inline.

.proposalTxInReference(txHash: string, txIndex: number, scriptSize: string, scriptHash: string, version: "V1" | "V2" | "V3")
ParameterTypeDescription
txHashstringTransaction hash of the reference UTxO
txIndexnumberTransaction index of the reference UTxO
scriptSizestringSize of the Plutus script in bytes
scriptHashstringScript hash of the referenced script
versionLanguageVersionPlutus language version

proposalRedeemerValue()

Provide the redeemer for a Plutus script proposal.

.proposalRedeemerValue(redeemer: Data | object | string, type?: "Mesh" | "CBOR" | "JSON", exUnits?: Budget)
ParameterTypeDescription
redeemerData | object | stringRedeemer data
typestringData format type (default "Mesh")
exUnitsBudgetExecution units budget (default { mem: 7_000_000, steps: 3_000_000_000 })

Common Patterns

Delegate to a DRep

Delegate your voting power to a registered DRep:

import { MeshTxBuilder, BlockfrostProvider } from "@meshsdk/core";

const provider = new BlockfrostProvider("<YOUR_API_KEY>");
const txBuilder = new MeshTxBuilder({
  fetcher: provider,
  verbose: true,
});

const utxos = await wallet.getUtxos();
const changeAddress = await wallet.getChangeAddress();
const rewardAddresses = await wallet.getRewardAddresses();
const rewardAddress = rewardAddresses[0]!;

const dRepId = "drep1yv4uesaj92wk8ljlsh4p7jzndnzrflchaz5fzug3zxg4naqkpeas3";

txBuilder
  .voteDelegationCertificate({ dRepId }, rewardAddress)
  .changeAddress(changeAddress)
  .selectUtxosFrom(utxos);

const unsignedTx = await txBuilder.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);

console.log(`Delegated to DRep: ${txHash}`);

Delegate to Always Abstain

Configure your stake to always abstain from voting:

import { MeshTxBuilder, BlockfrostProvider } from "@meshsdk/core";

const provider = new BlockfrostProvider("<YOUR_API_KEY>");
const txBuilder = new MeshTxBuilder({
  fetcher: provider,
  verbose: true,
});

const utxos = await wallet.getUtxos();
const changeAddress = await wallet.getChangeAddress();
const rewardAddresses = await wallet.getRewardAddresses();
const rewardAddress = rewardAddresses[0]!;

txBuilder
  .voteDelegationCertificate({ alwaysAbstain: true }, rewardAddress)
  .changeAddress(changeAddress)
  .selectUtxosFrom(utxos);

const unsignedTx = await txBuilder.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);

Register as a DRep

Register yourself as a DRep with metadata:

import { MeshTxBuilder, BlockfrostProvider, hashDrepAnchor } from "@meshsdk/core";

const provider = new BlockfrostProvider("<YOUR_API_KEY>");
const txBuilder = new MeshTxBuilder({
  fetcher: provider,
  verbose: true,
});

// Get DRep ID from wallet
const dRep = await wallet.getDRep();
const dRepId = dRep.dRepIDCip105;

// Prepare metadata anchor
const anchorUrl = "https://example.com/drep-metadata.jsonld";
const anchorMetadata = {
  "@context": {
    "@language": "en",
    "CIP100": "https://github.com/cardano-foundation/CIPs/blob/master/CIP-0100/README.md",
    "CIP119": "https://github.com/cardano-foundation/CIPs/blob/master/CIP-0119/README.md",
    "hashAlgorithm": "CIP100:hashAlgorithm",
    "body": { "@id": "CIP119:body" },
    "givenName": "CIP119:givenName"
  },
  "hashAlgorithm": "blake2b-256",
  "body": {
    "givenName": "My DRep Name"
  }
};
const anchorHash = hashDrepAnchor(anchorMetadata);

// Get wallet data
const utxos = await wallet.getUtxos();
const changeAddress = await wallet.getChangeAddress();

txBuilder
  .drepRegistrationCertificate(dRepId, {
    anchorUrl,
    anchorDataHash: anchorHash,
  })
  .changeAddress(changeAddress)
  .selectUtxosFrom(utxos);

const unsignedTx = await txBuilder.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);

console.log(`DRep registered: ${txHash}`);

Update DRep Metadata

Update your DRep profile information:

import { MeshTxBuilder, BlockfrostProvider, hashDrepAnchor } from "@meshsdk/core";

const provider = new BlockfrostProvider("<YOUR_API_KEY>");
const txBuilder = new MeshTxBuilder({
  fetcher: provider,
  verbose: true,
});

const dRep = await wallet.getDRep();
const dRepId = dRep.dRepIDCip105;

// New metadata
const anchorUrl = "https://example.com/drep-metadata-v2.jsonld";
const anchorMetadata = { /* updated metadata */ };
const anchorHash = hashDrepAnchor(anchorMetadata);

const utxos = await wallet.getUtxos();
const changeAddress = await wallet.getChangeAddress();

txBuilder
  .drepUpdateCertificate(dRepId, {
    anchorUrl,
    anchorDataHash: anchorHash,
  })
  .changeAddress(changeAddress)
  .selectUtxosFrom(utxos);

const unsignedTx = await txBuilder.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);

console.log(`DRep updated: ${txHash}`);

Retire as DRep

Retire from being a DRep and reclaim your deposit:

import { MeshTxBuilder, BlockfrostProvider } from "@meshsdk/core";

const provider = new BlockfrostProvider("<YOUR_API_KEY>");
const txBuilder = new MeshTxBuilder({
  fetcher: provider,
  verbose: true,
});

const dRep = await wallet.getDRep();
const dRepId = dRep.dRepIDCip105;

const utxos = await wallet.getUtxos();
const changeAddress = await wallet.getChangeAddress();

txBuilder
  .drepDeregistrationCertificate(dRepId)
  .selectUtxosFrom(utxos)
  .changeAddress(changeAddress);

const unsignedTx = await txBuilder.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);

console.log(`DRep retired: ${txHash}`);

Vote on Governance Action

Cast a vote as a DRep:

import { MeshTxBuilder, BlockfrostProvider } from "@meshsdk/core";

const provider = new BlockfrostProvider("<YOUR_API_KEY>");
const txBuilder = new MeshTxBuilder({
  fetcher: provider,
  verbose: true,
});

const dRep = await wallet.getDRep();
const dRepId = dRep.dRepIDCip105;

const utxos = await wallet.getUtxos();
const changeAddress = await wallet.getChangeAddress();

// Governance action to vote on
const govActionTxHash = "aff2909f8175ee02a8c1bf96ff516685d25bf0c6b95aac91f4dfd53a5c0867cc";
const govActionIndex = 0;

txBuilder
  .vote(
    {
      type: "DRep",
      drepId: dRepId,
    },
    {
      txHash: govActionTxHash,
      txIndex: govActionIndex,
    },
    {
      voteKind: "Yes",
    }
  )
  .selectUtxosFrom(utxos)
  .changeAddress(changeAddress);

const unsignedTx = await txBuilder.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);

console.log(`Vote cast: ${txHash}`);

Vote with Rationale

Include reasoning for your vote:

import { MeshTxBuilder, BlockfrostProvider, hashDrepAnchor } from "@meshsdk/core";

const provider = new BlockfrostProvider("<YOUR_API_KEY>");
const txBuilder = new MeshTxBuilder({
  fetcher: provider,
  verbose: true,
});

const dRep = await wallet.getDRep();
const dRepId = dRep.dRepIDCip105;

const utxos = await wallet.getUtxos();
const changeAddress = await wallet.getChangeAddress();

// Prepare vote rationale
const rationaleUrl = "https://example.com/vote-rationale.jsonld";
const rationaleContent = {
  rationale: "I support this proposal because...",
  references: ["https://example.com/supporting-doc"],
};
const rationaleHash = hashDrepAnchor(rationaleContent);

txBuilder
  .vote(
    {
      type: "DRep",
      drepId: dRepId,
    },
    {
      txHash: "abc123...",
      txIndex: 0,
    },
    {
      voteKind: "Yes",
      anchor: {
        anchorUrl: rationaleUrl,
        anchorDataHash: rationaleHash,
      },
    }
  )
  .selectUtxosFrom(utxos)
  .changeAddress(changeAddress);

const unsignedTx = await txBuilder.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);

Vote with Plutus Script

Vote using a Plutus script DRep:

import {
  MeshTxBuilder,
  BlockfrostProvider,
  resolveScriptHash,
  resolveScriptHashDRepId,
  applyCborEncoding
} from "@meshsdk/core";

const provider = new BlockfrostProvider("<YOUR_API_KEY>");
const txBuilder = new MeshTxBuilder({
  fetcher: provider,
  verbose: true,
});

const utxos = await wallet.getUtxos();
const collateral = await wallet.getCollateral();
const changeAddress = await wallet.getChangeAddress();

// Your voting script
const votingScriptCbor = applyCborEncoding("your-voting-script-cbor");
const scriptHash = resolveScriptHash(votingScriptCbor, "V3");
const scriptDRepId = resolveScriptHashDRepId(scriptHash);

txBuilder
  .txIn(
    utxos[0]!.input.txHash,
    utxos[0]!.input.outputIndex,
    utxos[0]!.output.amount,
    utxos[0]!.output.address
  )
  .txInCollateral(
    collateral[0]!.input.txHash,
    collateral[0]!.input.outputIndex,
    collateral[0]!.output.amount,
    collateral[0]!.output.address
  )
  .votePlutusScriptV3()
  .vote(
    {
      type: "DRep",
      drepId: scriptDRepId,
    },
    {
      txHash: "abc123...",
      txIndex: 0,
    },
    {
      voteKind: "Yes",
    }
  )
  .voteScript(votingScriptCbor)
  .voteRedeemerValue("")
  .changeAddress(changeAddress);

const unsignedTx = await txBuilder.complete();
const signedTx = await wallet.signTx(unsignedTx, true);
const txHash = await wallet.submitTx(signedTx);

Submit an Info Action

Submit an info action (used for polls and sentiment checks — has no on-chain effect):

import { MeshTxBuilder, BlockfrostProvider } from "@meshsdk/core";

const provider = new BlockfrostProvider("<YOUR_API_KEY>");
const txBuilder = new MeshTxBuilder({
  fetcher: provider,
  verbose: true,
});

const utxos = await wallet.getUtxos();
const changeAddress = await wallet.getChangeAddress();
const rewardAddresses = await wallet.getRewardAddresses();
const rewardAddress = rewardAddresses[0]!;

txBuilder
  .proposal(
    {
      kind: "InfoAction",
      action: {},
    },
    {
      anchorUrl: "https://example.com/proposal.jsonld",
      anchorDataHash: "a1b1c2d3e4f5...",
    },
    rewardAddress
  )
  .changeAddress(changeAddress)
  .selectUtxosFrom(utxos);

const unsignedTx = await txBuilder.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);

console.log(`Info action submitted: ${txHash}`);

Submit a Treasury Withdrawal

Propose a treasury withdrawal to one or more reward addresses:

import { MeshTxBuilder, BlockfrostProvider } from "@meshsdk/core";

const provider = new BlockfrostProvider("<YOUR_API_KEY>");
const txBuilder = new MeshTxBuilder({
  fetcher: provider,
  verbose: true,
});

const utxos = await wallet.getUtxos();
const changeAddress = await wallet.getChangeAddress();
const rewardAddresses = await wallet.getRewardAddresses();
const rewardAddress = rewardAddresses[0]!;

txBuilder
  .proposal(
    {
      kind: "TreasuryWithdrawalsAction",
      action: {
        withdrawals: {
          [rewardAddress]: "50000000000", // 50,000 ADA in lovelace
        },
      },
    },
    {
      anchorUrl: "https://example.com/treasury-proposal.jsonld",
      anchorDataHash: "a1b1c2d3e4f5...",
    },
    rewardAddress
  )
  .changeAddress(changeAddress)
  .selectUtxosFrom(utxos);

const unsignedTx = await txBuilder.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);

console.log(`Treasury withdrawal proposed: ${txHash}`);

Submit a No Confidence Action

Propose a motion of no confidence in the current constitutional committee:

import { MeshTxBuilder, BlockfrostProvider } from "@meshsdk/core";

const provider = new BlockfrostProvider("<YOUR_API_KEY>");
const txBuilder = new MeshTxBuilder({
  fetcher: provider,
  verbose: true,
});

const utxos = await wallet.getUtxos();
const changeAddress = await wallet.getChangeAddress();
const rewardAddresses = await wallet.getRewardAddresses();
const rewardAddress = rewardAddresses[0]!;

txBuilder
  .proposal(
    {
      kind: "NoConfidenceAction",
      action: {
        govActionId: {
          transactionId: "previousNoConfidenceTxHash...",
          govActionIndex: 0,
        },
      },
    },
    {
      anchorUrl: "https://example.com/no-confidence.jsonld",
      anchorDataHash: "a1b1c2d3e4f5...",
    },
    rewardAddress
  )
  .changeAddress(changeAddress)
  .selectUtxosFrom(utxos);

const unsignedTx = await txBuilder.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);

console.log(`No confidence action submitted: ${txHash}`);

Complete Example

This example demonstrates a complete DRep lifecycle:

import {
  MeshTxBuilder,
  BlockfrostProvider,
  hashDrepAnchor
} from "@meshsdk/core";

const provider = new BlockfrostProvider("<YOUR_API_KEY>");

function getTxBuilder() {
  return new MeshTxBuilder({
    fetcher: provider,
    verbose: true,
  });
}

// Register as a DRep
async function registerDRep(
  wallet: any,
  name: string,
  metadataUrl: string
) {
  const txBuilder = getTxBuilder();

  const dRep = await wallet.getDRep();
  const dRepId = dRep.dRepIDCip105;

  const metadata = {
    "@context": { /* CIP-119 context */ },
    "body": { "givenName": name }
  };
  const anchorHash = hashDrepAnchor(metadata);

  const utxos = await wallet.getUtxos();
  const changeAddress = await wallet.getChangeAddress();

  txBuilder
    .drepRegistrationCertificate(dRepId, {
      anchorUrl: metadataUrl,
      anchorDataHash: anchorHash,
    })
    .changeAddress(changeAddress)
    .selectUtxosFrom(utxos);

  const unsignedTx = await txBuilder.complete();
  const signedTx = await wallet.signTx(unsignedTx);
  return await wallet.submitTx(signedTx);
}

// Vote on a governance action
async function castVote(
  wallet: any,
  govActionTxHash: string,
  govActionIndex: number,
  voteKind: "Yes" | "No" | "Abstain"
) {
  const txBuilder = getTxBuilder();

  const dRep = await wallet.getDRep();
  const dRepId = dRep.dRepIDCip105;

  const utxos = await wallet.getUtxos();
  const changeAddress = await wallet.getChangeAddress();

  txBuilder
    .vote(
      { type: "DRep", drepId: dRepId },
      { txHash: govActionTxHash, txIndex: govActionIndex },
      { voteKind }
    )
    .selectUtxosFrom(utxos)
    .changeAddress(changeAddress);

  const unsignedTx = await txBuilder.complete();
  const signedTx = await wallet.signTx(unsignedTx);
  return await wallet.submitTx(signedTx);
}

// Delegate to a DRep
async function delegateToDRep(wallet: any, dRepId: string) {
  const txBuilder = getTxBuilder();

  const utxos = await wallet.getUtxos();
  const changeAddress = await wallet.getChangeAddress();
  const rewardAddresses = await wallet.getRewardAddresses();
  const rewardAddress = rewardAddresses[0]!;

  txBuilder
    .voteDelegationCertificate({ dRepId }, rewardAddress)
    .changeAddress(changeAddress)
    .selectUtxosFrom(utxos);

  const unsignedTx = await txBuilder.complete();
  const signedTx = await wallet.signTx(unsignedTx);
  return await wallet.submitTx(signedTx);
}

// Retire as DRep
async function retireDRep(wallet: any) {
  const txBuilder = getTxBuilder();

  const dRep = await wallet.getDRep();
  const dRepId = dRep.dRepIDCip105;

  const utxos = await wallet.getUtxos();
  const changeAddress = await wallet.getChangeAddress();

  txBuilder
    .drepDeregistrationCertificate(dRepId)
    .selectUtxosFrom(utxos)
    .changeAddress(changeAddress);

  const unsignedTx = await txBuilder.complete();
  const signedTx = await wallet.signTx(unsignedTx);
  return await wallet.submitTx(signedTx);
}

// Usage
async function main() {
  // 1. Register as DRep
  const regTx = await registerDRep(
    wallet,
    "Community DRep",
    "https://example.com/metadata.jsonld"
  );
  console.log(`Registered as DRep: ${regTx}`);

  // 2. Vote on proposals
  const voteTx = await castVote(
    wallet,
    "proposal-tx-hash...",
    0,
    "Yes"
  );
  console.log(`Vote cast: ${voteTx}`);

  // 3. Others delegate to you
  const delegateTx = await delegateToDRep(
    otherWallet,
    "drep1..." // Your DRep ID
  );
  console.log(`Delegation received: ${delegateTx}`);

  // 4. Eventually retire
  const retireTx = await retireDRep(wallet);
  console.log(`Retired as DRep: ${retireTx}`);
}

Troubleshooting

"DRep not registered" error

  • You must register as a DRep before voting
  • Use drepRegistrationCertificate() first

"Invalid anchor hash" error

  • The hash must match the content at the URL exactly
  • Use hashDrepAnchor() to compute the correct hash
  • Ensure the metadata file is publicly accessible

"Insufficient deposit" error

  • DRep registration requires a deposit (check current protocol parameters)
  • Ensure wallet has enough ADA for deposit + fees

"DRep inactive" error

  • DReps must vote regularly to stay active
  • Vote on governance actions or submit an update certificate

"Governance action not found" error

  • Verify the transaction hash and index are correct
  • The governance action may have already been resolved

"Invalid voter type" error

  • Ensure the voter type matches your role (DRep, SPO, or CC)
  • Use the correct identifier format for each type

"Insufficient deposit" for proposal

  • Governance action proposals require a large deposit (check govActionDeposit in protocol parameters)
  • The deposit is returned when the governance action is resolved (enacted, expired, or dropped)
  • Ensure wallet has enough ADA for deposit + fees

"Missing proposal script information" error

  • When using proposalScript() or proposalTxInReference(), ensure the script source is provided before calling .complete()
  • For Plutus script proposals, a redeemer must also be provided via proposalRedeemerValue()

References

On this page