Skip to main content

Delegate and Withdraw

This page is the first half of the staking lifecycle in code: register the stake credential, delegate it to a pool, and withdraw the rewards it earns. Each operation is a single transaction, shown in Evolution, Mesh, and cardano-cli.

Before you start

The snippets below set up a provider and a wallet once and reuse them; each transaction uses a fresh builder.

import { preprod, Client } from "@evolution-sdk/evolution"

const client = Client.make(preprod)
.withBlockfrost({
baseUrl: "https://cardano-preprod.blockfrost.io/api/v0",
projectId: process.env.BLOCKFROST_API_KEY!
})
.withSeed({ mnemonic: process.env.WALLET_MNEMONIC!, accountIndex: 0 })

const address = await client.address()
const stakeCredential = address.stakingCredential! // staking certificates act on this

Register and delegate

Delegating for the first time means two things: registering the stake credential (a small refundable deposit) and delegating it to a pool. The Conway era added a combined certificate that does both in one step and saves a certificate fee, so either way it's a single transaction.

import { Credential } from "@evolution-sdk/evolution"

declare const stakeCredential: Credential.Credential
declare const poolKeyHash: any

const tx = await client
.newTx()
.registerAndDelegateTo({ stakeCredential, poolKeyHash })
.build()

const signed = await tx.sign()
await signed.submit()

You can also chain the two certificates explicitly, which is what you'd do with legacy (pre-Conway, no-deposit) registration:

// Conway certificates
const tx = await client
.newTx()
.registerStake({ stakeCredential })
.delegateToPool({ stakeCredential, poolKeyHash })
.build()

// Legacy certificates (no deposit), use registerStakeLegacy() instead
const legacyTx = await client
.newTx()
.registerStakeLegacy({ stakeCredential })
.delegateToPool({ stakeCredential, poolKeyHash })
.build()

The deposit (currently 2 ADA) is fetched from protocol parameters automatically. Already registered? Drop the registration call and just delegateToPool({ stakeCredential, poolKeyHash }).

Withdraw rewards

Rewards accumulate to the reward address each epoch and must be explicitly withdrawn. You always withdraw the entire balance. Partial withdrawals aren't allowed.

const delegation = await client.getWalletDelegation()
console.log("Available rewards:", delegation.rewards, "lovelace")

const tx = await client
.newTx()
.withdraw({ stakeCredential, amount: delegation.rewards })
.build()

const signed = await tx.sign()
await signed.submit()

Next steps

  • Manage stake: query delegation status, deregister cleanly, and delegate stake and vote together