> ## Documentation Index
> Fetch the complete documentation index at: https://docs.starknet.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Staking

> Enable users to stake tokens, earn passive income, and grow their holdings while supporting network security

<img src="https://mintcdn.com/starkware-9575960b/Dy5qvEgMdOdPzC_A/assets/starkzap/staking-delegation.png?fit=max&auto=format&n=Dy5qvEgMdOdPzC_A&q=85&s=5625c72f7a5054d25d0a08239eedd98d" alt="Staking and Delegation hero" width="1024" height="576" data-path="assets/starkzap/staking-delegation.png" />

## Overview

Starkzap supports Starknet's native staking protocol. Validators run pools where delegators can stake tokens and earn rewards.

**What users can do with staking:**

* 💰 **Earn passive income** - Stake tokens (like STRK) and earn rewards over time, similar to a savings account with interest
* 🏦 **Support network security** - Stake tokens to help secure the Starknet network while earning rewards
* 📈 **Grow their holdings** - Rewards compound over time, allowing users to increase their token holdings without additional purchases
* ⏰ **Flexible participation** - Add more tokens anytime, claim rewards when ready, and exit when needed (with a cooldown period)

**Real-world analogy:** Think of staking like putting money in a high-yield savings account or certificate of deposit (CD). You lock up your tokens for a period, and in return, you earn interest (rewards). The longer you stake, the more you can potentially earn.

<Info>
  Staking contract is selected automatically from chain-aware presets. You only need `staking.contract` if you want to override the default.
</Info>

## Configuration

Staking works out of the box when using a supported chain preset:

```typescript theme={null}
import { StarkZap } from "starkzap";

const sdk = new StarkZap({
  network: "mainnet",
});
```

Optional override:

```typescript theme={null}
import { StarkZap, fromAddress } from "starkzap";

const sdk = new StarkZap({
  network: "mainnet",
  staking: {
    contract: fromAddress(
      "0x00ca1702e64c81d9a07b86bd2c540188d92a2c73cf5cc0e508d949015e7e84a7"
    ),
  },
});
```

## Discovering Validators and Pools

### Using Validator Presets

```typescript theme={null}
import { mainnetValidators, sepoliaValidators } from "starkzap";

// Use built-in validator presets
for (const validator of Object.values(mainnetValidators)) {
  console.log(`${validator.name}: ${validator.stakerAddress}`);
}
// Also available: sepoliaValidators
```

### Getting Stakeable Tokens

```typescript theme={null}
const tokens = await sdk.stakingTokens();
console.log(tokens.map((t) => t.symbol)); // ["STRK", ...]
```

### Getting Pools for a Validator

```typescript theme={null}
const pools = await sdk.getStakerPools(validator.stakerAddress);
for (const pool of pools) {
  console.log(`${pool.token.symbol}: ${pool.amount.toFormatted()} delegated`);
  console.log(`Pool contract: ${pool.poolContract}`);
}
```

## Entering a Pool

Stake tokens for the first time in a validator's pool. The SDK handles the token approval automatically.

```typescript theme={null}
const tx = await wallet.enterPool(poolAddress, Amount.parse("100", STRK));
await tx.wait();
```

This will:

1. Approve the staking contract to spend your tokens (if needed)
2. Call `enter_delegation_pool` on the staking contract
3. Return a transaction you can track

## Smart Stake (Recommended)

Use `wallet.stake()` when you don't want to branch on membership manually:

```typescript theme={null}
const tx = await wallet.stake(poolAddress, Amount.parse("100", STRK));
await tx.wait();
```

`wallet.stake()` automatically:

* calls `enter_delegation_pool` for first-time stakers
* calls `add_to_delegation_pool` for existing members

## Adding to an Existing Stake

If you're already a pool member, add more tokens:

```typescript theme={null}
const tx = await wallet.addToPool(poolAddress, Amount.parse("50", STRK));
await tx.wait();
```

## Claiming Rewards

Users earn rewards continuously while their tokens are staked. Rewards accumulate over time and can be claimed at any time:

```typescript theme={null}
const position = await wallet.getPoolPosition(poolAddress);

if (position && !position.rewards.isZero()) {
  const tx = await wallet.claimPoolRewards(poolAddress);
  await tx.wait();
  console.log(`Claimed ${position.rewards.toFormatted()}`);
}
```

**What users get:** Rewards are paid in the same token they staked (e.g., if you stake STRK, you earn STRK rewards). Users can claim rewards and either:

* Withdraw them to their wallet
* Re-stake them to compound earnings (add them back to the pool)

## Exiting a Pool (Two-Step Process)

Exiting a pool is a two-step process with an exit window:

### Step 1: Declare Exit Intent

Tokens stop earning rewards immediately:

```typescript theme={null}
const tx = await wallet.exitPoolIntent(
  poolAddress,
  Amount.parse("50", STRK)
);
await tx.wait();
```

### Step 2: Complete Withdrawal

Wait for the exit window, then complete the withdrawal:

```typescript theme={null}
const position = await wallet.getPoolPosition(poolAddress);
if (position?.unpoolTime && new Date() >= position.unpoolTime) {
  const tx = await wallet.exitPool(poolAddress);
  await tx.wait();
  console.log("Tokens returned to wallet");
}
```

## Querying Position

Get detailed information about your staking position to show users their earnings:

```typescript theme={null}
const position = await wallet.getPoolPosition(poolAddress);

if (position) {
  console.log(`Staked:     ${position.staked.toFormatted()}`); // Original amount staked
  console.log(`Rewards:    ${position.rewards.toFormatted()}`); // Earned rewards (can claim)
  console.log(`Total:      ${position.total.toFormatted()}`); // Staked + rewards combined
  console.log(`Commission: ${position.commissionPercent}%`); // Validator's fee
  console.log(`Unpooling:  ${position.unpooling.toFormatted()}`); // Amount being withdrawn
  console.log(`Unpool at:  ${position.unpoolTime}`); // When withdrawal completes
}
```

**What this shows users:**

* How much they've staked (their original investment)
* How much they've earned in rewards (their passive income)
* Their total position value (staked + rewards)
* When they can withdraw if they've initiated an exit

### Position Interface

```typescript theme={null}
interface PoolMember {
  staked: Amount;
  rewards: Amount;
  total: Amount;
  unpooling: Amount;
  unpoolTime: Date | null;
  commissionPercent: number;
  rewardAddress: Address;
}
```

### Checking Membership

```typescript theme={null}
const isMember = await wallet.isPoolMember(poolAddress);
```

### Getting Commission Rate

```typescript theme={null}
const commission = await wallet.getPoolCommission(poolAddress);
console.log(`Commission: ${commission}%`);
```

## Using Transaction Builder

The transaction builder makes it easy to combine staking operations with other actions:

```typescript theme={null}
const tx = await wallet
  .tx()
  // Transfer some tokens
  .transfer(STRK, [{ to: recipient, amount: Amount.parse("10", STRK) }])
  // Stake in a pool (auto-detects enter vs. add)
  .stake(poolAddress, Amount.parse("100", STRK))
  // Claim rewards from another pool
  .claimPoolRewards(anotherPoolAddress)
  .send();

await tx.wait();
```

The `.stake()` method automatically:

* Calls `enter_delegation_pool` for new members
* Calls `add_to_delegation_pool` for existing members

## Staking Flow Examples

### Complete Staking Flow

Here's a complete example showing how users can stake, earn, and manage their position:

```typescript theme={null}
// 1. Discover pools
const pools = await sdk.getStakerPools(validator.stakerAddress);
const strkPool = pools.find((p) => p.token.symbol === "STRK");

// 2. Enter pool - User stakes 100 STRK and starts earning immediately
await wallet.enterPool(strkPool.poolContract, Amount.parse("100", STRK));
// User's tokens are now earning rewards in the background

// 3. Check position - Show user their earnings
const position = await wallet.getPoolPosition(strkPool.poolContract);
console.log(`Staked: ${position.staked.toFormatted()}`); // "STRK 100"
console.log(`Rewards earned: ${position.rewards.toFormatted()}`); // "STRK 2.5" (example)

// 4. Add more later - User can increase their stake anytime
await wallet.addToPool(strkPool.poolContract, Amount.parse("50", STRK));
// Now staking 150 STRK total, earning more rewards

// 5. Claim rewards - User withdraws their earned rewards
await wallet.claimPoolRewards(strkPool.poolContract);
// Rewards are sent to user's wallet, can be spent or re-staked

// 6. Exit (two-step) - User wants to withdraw some tokens
await wallet.exitPoolIntent(strkPool.poolContract, Amount.parse("25", STRK));
// ... wait for exit window (cooldown period) ...
await wallet.exitPool(strkPool.poolContract);
// 25 STRK returned to user's wallet
```

### Monitoring Rewards

Show users their earnings and help them claim rewards:

```typescript theme={null}
async function checkRewards(wallet, poolAddress) {
  const position = await wallet.getPoolPosition(poolAddress);
  
  if (!position) {
    console.log("Not a member of this pool");
    return;
  }
  
  if (position.rewards.isZero()) {
    console.log("No rewards available yet");
    return;
  }
  
  // Show user their earnings
  console.log(`Available rewards: ${position.rewards.toFormatted()}`);
  console.log(`Total position: ${position.total.toFormatted()}`); // Staked + rewards
  
  // Auto-claim if above threshold (optional)
  if (position.rewards.gt(Amount.parse("1", STRK))) {
    await wallet.claimPoolRewards(poolAddress);
    console.log("Rewards claimed! Tokens sent to your wallet.");
  }
}
```

**User experience:** Users can see their earnings growing in real-time, claim rewards whenever they want, and watch their total position value increase over time.

## User Benefits Summary

**What users can do with staking in your app:**

* 💰 **Earn passive income** - Stake tokens and earn rewards automatically, like interest on a savings account
* 📈 **Grow their holdings** - Rewards accumulate over time, increasing their total token balance
* 🔄 **Flexible management** - Add more tokens anytime, claim rewards when ready, exit when needed
* 🏦 **Support the network** - Help secure Starknet while earning rewards
* ⏱️ **Set and forget** - Once staked, tokens earn rewards in the background without daily management

**Real-world use cases:**

* **Savings feature** - Let users "save" their tokens and earn interest
* **Investment tool** - Enable users to grow their crypto holdings over time
* **Rewards program** - Users can stake tokens to earn additional rewards
* **Long-term holding** - Encourage users to hold tokens by offering staking rewards

## Best Practices

1. **Always check pool membership** before calling `addToPool`
2. **Monitor rewards regularly** and show users their earnings
3. **Help users understand exit windows** before initiating exit
4. **Use transaction builder** to batch staking with other operations
5. **Override staking contract only if needed** (custom deployments, forks, or private environments)
6. **Display earnings clearly** - Show users their staked amount, earned rewards, and total position value

## Troubleshooting

### "No staking contract configured for chain ..."

The SDK has no staking contract for the current chain, or you set a custom `staking.contract` that doesn't match. Remove the override to use the built-in preset, or set the correct contract for your network.

### Pool Not Found

Ensure you're using the correct pool contract address. Use `getStakerPools()` to discover available pools.

## Next Steps

* Learn about [Transaction Builder](/build/starkzap/transactions#transaction-builder) for batching operations
* Explore [ERC20 Token Operations](/build/starkzap/erc20)
* Check the [API Reference](/build/starkzap/api-reference) for detailed method signatures
