# Stake Tokens and Assets

Staking is the process of locking up tokens or assets (NFTs) to a specific receiver, often to secure a network, participate in governance, or earn rewards. This guide provides a step-by-step walkthrough of the entire staking lifecycle using the OCAP Client, including creating a stake, revoking it, claiming the assets back, and slashing a stake for punitive reasons.

This process involves a few key methods:

* `stake()`: To create a new stake.
* `revokeStake()`: To initiate the process of withdrawing your staked items.
* `claimStake()`: To finalize the withdrawal and return the items to your account.
* `slashStake()`: To allow authorized parties to penalize a staker.


## How to Stake

To begin, you use the `stake` method to lock your tokens or assets. This action creates a new, unique stake address on the chain that holds your staked items and the rules governing them.

### Parameters

<x-field-group>
  <x-field data-name="to" data-type="string" data-required="true" data-desc="The DID address of the account that will receive the stake."></x-field>
  <x-field data-name="assets" data-type="string[]" data-required="false" data-desc="An array of asset addresses (NFTs) to be staked."></x-field>
  <x-field data-name="tokens" data-type="object[]" data-required="false" data-desc="An array of token objects to be staked.">
    <x-field data-name="address" data-type="string" data-required="true" data-desc="The address of the token contract."></x-field>
    <x-field data-name="value" data-type="number" data-required="true" data-desc="The amount of tokens to stake."></x-field>
  </x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The wallet object of the staker."></x-field>
  <x-field data-name="locked" data-type="boolean" data-default="false" data-required="false" data-desc="A boolean indicating if the stake is locked upon creation."></x-field>
  <x-field data-name="slashers" data-type="string[]" data-required="false" data-desc="An array of DID addresses permitted to slash this stake. Defaults to the receiver's address if not provided."></x-field>
  <x-field data-name="message" data-type="string" data-required="false" data-desc="An optional note or message for the stake."></x-field>
  <x-field data-name="nonce" data-type="string" data-required="false" data-desc="An optional nonce to ensure the stake address is unique."></x-field>
</x-field-group>

### Example

```javascript Staking Tokens and an Asset icon=logos:javascript
// Assume 'client' is an initialized GraphQLClient instance
// and 'stakerWallet' is a valid wallet object.
const receiverAddress = 'z29d5852576b8a8b6f3a8b4b74a3f4a3e2e1d'; // The address of the stake receiver

async function createStake() {
  try {
    const [txHash, stakeAddress] = await client.stake({
      to: receiverAddress,
      tokens: [{
        address: 'z35n6aTUTK8h5nAF43h21A1g84g3C3D7B5E', // Address of the token to stake
        value: 100, // Amount of tokens to stake
      }],
      assets: ['zNKtA1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6'], // Address of the asset/NFT to stake
      message: 'Staking for validator rewards',
      wallet: stakerWallet,
    });

    console.log('Stake transaction sent:', txHash);
    console.log('New stake address created:', stakeAddress);
    return stakeAddress;
  } catch (error) {
    console.error('Error creating stake:', error);
  }
}
```

### Return Value

The `stake` method returns a tuple containing the transaction hash and the newly created `stakeAddress`. This address is crucial for all future interactions with this specific stake, such as revoking or slashing.

---


## How to Revoke a Stake

Revoking a stake is the process initiated by the staker to retrieve their locked tokens and assets. This transaction does not immediately return the funds; instead, it marks them as available for claiming, subject to any on-chain lock-up periods.

### Parameters

<x-field-group>
  <x-field data-name="from" data-type="string" data-required="true" data-desc="The address of the stake to be revoked (obtained from the 'stake' call)."></x-field>
  <x-field data-name="assets" data-type="string[]" data-required="false" data-desc="An array of asset addresses to revoke from the stake."></x-field>
  <x-field data-name="tokens" data-type="object[]" data-required="false" data-desc="An array of token objects to revoke.">
    <x-field data-name="address" data-type="string" data-required="true" data-desc="The address of the token contract."></x-field>
    <x-field data-name="value" data-type="number" data-required="true" data-desc="The amount of tokens to revoke."></x-field>
  </x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The staker's wallet object, which must be the original creator of the stake."></x-field>
</x-field-group>

### Example

```javascript Revoking a Stake icon=logos:javascript
// Assume 'stakeAddress' is the address returned from the previous step
// and 'stakerWallet' is the same wallet used to create the stake.

async function revokeExistingStake(stakeAddress) {
  try {
    const revokeTxHash = await client.revokeStake({
      from: stakeAddress,
      tokens: [{
        address: 'z35n6aTUTK8h5nAF43h21A1g84g3C3D7B5E',
        value: 100,
      }],
      assets: ['zNKtA1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6'],
      wallet: stakerWallet,
    });

    console.log('Revoke stake transaction sent:', revokeTxHash);
    console.log('IMPORTANT: Save this hash to claim your stake later.');
    return revokeTxHash;
  } catch (error) {
    console.error('Error revoking stake:', error);
  }
}
```

### Return Value

This function returns the transaction hash of the revoke operation. This hash serves as evidence and is **required** for the final step of claiming the stake.

---


## How to Claim a Revoked Stake

After a stake has been successfully revoked, the staker must send a `claimStake` transaction to move the tokens and assets back into their account. This finalizes the withdrawal process.

### Parameters

<x-field-group>
  <x-field data-name="from" data-type="string" data-required="true" data-desc="The address of the stake."></x-field>
  <x-field data-name="evidence" data-type="string" data-required="true" data-desc="The transaction hash from the 'revokeStake' call, which serves as proof of revocation."></x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The staker's wallet object."></x-field>
</x-field-group>

### Example

```javascript Claiming Staked Items icon=logos:javascript
// Assume 'stakeAddress' and 'revokeTxHash' are from the previous steps,
// and 'stakerWallet' is the staker's wallet.

async function claimRevokedStake(stakeAddress, revokeTxHash) {
  try {
    const claimTxHash = await client.claimStake({
      from: stakeAddress,
      evidence: revokeTxHash,
      wallet: stakerWallet,
    });

    console.log('Claim stake transaction sent:', claimTxHash);
    console.log('Your tokens and assets have been returned to your account.');
  } catch (error) {
    console.error('Error claiming stake:', error);
  }
}
```

### Return Value

The method returns the final transaction hash. Once this transaction is confirmed on the chain, the staked items are returned to the `wallet`'s address.

---


## How to Slash a Stake

Slashing is a punitive action that can be taken by a designated `slasher` (usually the stake receiver) against a staker. This typically happens if the staker violates certain rules. The slashed tokens or assets are removed from the stake and sent to a designated vault.

### Parameters

<x-field-group>
  <x-field data-name="from" data-type="string" data-required="true" data-desc="The address of the stake to be slashed."></x-field>
  <x-field data-name="reason" data-type="string" data-required="true" data-desc="A mandatory message explaining why the slash is occurring."></x-field>
  <x-field data-name="assets" data-type="string[]" data-required="false" data-desc="An array of asset addresses to be slashed from the stake."></x-field>
  <x-field data-name="tokens" data-type="object[]" data-required="false" data-desc="An array of token objects to be slashed.">
    <x-field data-name="address" data-type="string" data-required="true" data-desc="The address of the token contract."></x-field>
    <x-field data-name="value" data-type="number" data-required="true" data-desc="The amount of tokens to slash."></x-field>
  </x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The wallet object of an authorized slasher."></x-field>
</x-field-group>

### Example

```javascript Slashing a Stake icon=logos:javascript
// Assume 'stakeAddress' is the address of the stake to be slashed,
// and 'slasherWallet' is the wallet of an authorized slasher.

async function slashExistingStake(stakeAddress) {
  try {
    const slashTxHash = await client.slashStake({
      from: stakeAddress,
      reason: 'Validator missed signing 10 consecutive blocks.',
      tokens: [{
        address: 'z35n6aTUTK8h5nAF43h21A1g84g3C3D7B5E',
        value: 10, // Slashing 10 tokens as a penalty
      }],
      wallet: slasherWallet,
    });

    console.log('Slash stake transaction sent:', slashTxHash);
  } catch (error) {
    console.error('Error slashing stake:', error);
  }
}
```

### Return Value

This method returns the transaction hash for the slashing operation.


## Summary

You've now learned the complete lifecycle of staking on the OCAP blockchain: creating a stake with `stake`, retrieving funds with `revokeStake` and `claimStake`, and penalizing bad actors with `slashStake`. This powerful mechanism is fundamental to many decentralized applications.

To learn more about the items you can stake, see the [Manage Tokens](./how-to-guides-manage-tokens.md) and [Manage Assets (NFTs)](./how-to-guides-manage-assets.md) guides.
