Staking Transactions
Transactions for delegating ADA and managing stakepools
In the code snippet, you will find txBuilder, which is an instance of MeshTxBuilder, with powerful low-level APIs that allow you to build transactions. Here's how to initialize MeshTxBuilder.
const txBuilder = new MeshTxBuilder({
fetcher: provider, // get a provider https://meshjs.dev/providers
verbose: true,
});Register Stake Address
Same as Transaction, with MeshTxBuilder, you have to register a stake address before delegating to stakepools. Here are the 2 APIs you need:
txBuilder
.registerStakeCertificate(rewardAddress)
.delegateStakeCertificate(rewardAddress, poolIdHash)Since we need to provide the deserialize hash of pool ID, we can use the following util to get it:
const poolIdHash = deserializePoolId(
"pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx",
);Register Stake Address
Register a stake address before delegating to a stakepool.
Pool ID
pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx
const utxos = await wallet.getUtxos();
const address = await wallet.getChangeAddress();
const addresses = await wallet.getRewardAddresses();
const rewardAddress = addresses[0]!;
const poolIdHash = deserializePoolId("pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx");
if (rewardAddress === undefined) {
throw "No address found";
}
const txBuilder = new MeshTxBuilder({
fetcher: provider, // get a provider https://meshjs.dev/providers
verbose: true,
});
const unsignedTx = await txBuilder
.registerStakeCertificate(rewardAddress)
.delegateStakeCertificate(rewardAddress, poolIdHash)
.selectUtxosFrom(utxos)
.changeAddress(address)
.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);Delegate Stake
Stake delegation with MeshTxBuilder is the same as the first delegate, but without registering the stake key, so only one API call is needed:
txBuilder
.delegateStakeCertificate(rewardAddress, poolIdHash)Delegate Stake
Delegate stake to a stake pool
Pool ID
pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx
const utxos = await wallet.getUtxos();
const address = await wallet.getChangeAddress();
const addresses = await wallet.getRewardAddresses();
const rewardAddress = addresses[0]!;
const poolIdHash = deserializePoolId("pool107k26e3wrqxwghju2py40ngngx2qcu48ppeg7lk0cm35jl2aenx");
if (rewardAddress === undefined) {
throw "No address found";
}
const txBuilder = new MeshTxBuilder({
fetcher: provider, // get a provider https://meshjs.dev/providers
verbose: true,
});
const unsignedTx = await txBuilder
.delegateStakeCertificate(rewardAddress, poolIdHash)
.selectUtxosFrom(utxos)
.changeAddress(address)
.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);Withdraw Rewards
Use MeshTxBuilder’s withdrawal method to specify the reward address and amount.
- rewardAddress (string) - the reward address to withdraw from
- lovelace (number) - the amount to withdraw in Lovelace
txBuilder
.withdrawal(rewardAddress, lovelace)Withdraw Rewards
Withdraw staking rewards.
Amount in lovelace: 1000000
const utxos = await wallet.getUtxos();
const address = await wallet.getChangeAddress();
const addresses = await wallet.getRewardAddresses();
const rewardAddress = addresses[0]!;
if (rewardAddress === undefined) {
throw "No address found";
}
const txBuilder = new MeshTxBuilder({
fetcher: provider, // get a provider https://meshjs.dev/providers
verbose: true,
});
const unsignedTx = await txBuilder
.withdrawal(rewardAddress, "1000000")
.selectUtxosFrom(utxos)
.changeAddress(address)
.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);Deregister Stake
To deregister a stake address with MeshTxBuilder, use the following method:
- rewardAddress (string) - the bech32 reward address to deregister
txBuilder
.deregisterStakeCertificate(rewardAddress: string)Deregister Stake
Deregister a stake address.
const utxos = await wallet.getUtxos();
const address = await wallet.getChangeAddress();
const addresses = await wallet.getRewardAddresses();
const rewardAddress = addresses[0]!;
if (rewardAddress === undefined) {
throw "No address found";
}
const txBuilder = new MeshTxBuilder({
fetcher: provider, // get a provider https://meshjs.dev/providers
verbose: true,
});
const unsignedTx = await txBuilder
.deregisterStakeCertificate(rewardAddress)
.selectUtxosFrom(utxos)
.changeAddress(address)
.complete();
const signedTx = await wallet.signTx(unsignedTx);
const txHash = await wallet.submitTx(signedTx);Script Withdrawal - Supporting Withdraw Zero
Withdrawal from a script is supported by MeshTxBuilder with this set of APIs:
txBuilder
.withdrawalPlutusScriptV2()
.withdrawal(rewardAddress, withdrawalAmount)
.withdrawalScript(stakeScriptCbor)
.withdrawalRedeemerValue(redeemer)Withdraw Zero
This is a technique commonly used on Cardano to prove control of a stake key without actually withdrawing any rewards from its withdrawal account. To perform a "withdraw zero", you have to follow these steps:
- Register script stake key
txBuilder
.registerStakeCertificate(stakeScriptHash)- Withdraw Zero
txBuilder
.withdrawalPlutusScriptV2()
.withdrawal(rewardAddress, "0")
.withdrawalScript(stakeScriptCbor)
.withdrawalRedeemerValue(redeemer)Register Script Stake Key
One off setup before triggering withdraw zero
const utxos = await wallet.getUtxos();
const address = await wallet.getChangeAddress();
const txBuilder = getTxBuilder();
const stakeScriptCbor = alwaysSucceedMintingStakingScriptCbor(
deserializeAddress(address).pubKeyHash,
);
const txBuilder = new MeshTxBuilder({
fetcher: provider, // get a provider https://meshjs.dev/providers
verbose: true,
});
const unsignedTx = await txBuilder
.registerStakeCertificate(resolveScriptHash(stakeScriptCbor, "V2"))
.selectUtxosFrom(utxos)
.changeAddress(address)
.complete();
const signedTx = await wallet.signTx(unsignedTx, true);
const txHash = await wallet.submitTx(signedTx);Withdraw Zero
Actual withdrawal of zero to trigger script validation
const utxos = await wallet.getUtxos();
const collateral = await wallet.getCollateral();
const address = await wallet.getChangeAddress();
const stakeScriptCbor = alwaysSucceedMintingStakingScriptCbor(
deserializeAddress(address).pubKeyHash,
);
const rewardAddress = serializeRewardAddress(
resolveScriptHash(stakeScriptCbor, "V2"),
true,
0,
);
const txBuilder = new MeshTxBuilder({
fetcher: provider, // get a provider https://meshjs.dev/providers
verbose: true,
});
const unsignedTx = await txBuilder
.withdrawalPlutusScriptV2()
.withdrawal(rewardAddress, "0")
.withdrawalScript(stakeScriptCbor)
.withdrawalRedeemerValue("")
.selectUtxosFrom(utxos)
.changeAddress(address)
.txInCollateral(...utxoToTxIn(collateral[0]!))
.complete();
const signedTx = await wallet.signTx(unsignedTx, true);
const txHash = await wallet.submitTx(signedTx);