Skip to main content

Staking

Pre-requisites

Please make sure that you've followed our getting started guide and set up your development environment.

You'll also need the following:

  1. A project
  2. At least one resource
  3. Characters

In order to stake, your users will need to have created a profile for your project. They'll also need eligible characters that can stake (more on this below).

Overview

Staking is very similar to missions in the way that it allows users to earn rewards.

The difference is that when characters are staked in a staking pool, they're locked until a user unstakes them. During that time, these characters earn rewards based on the staking pool's reward distribution mechanism.

Create staking pool

import { LockTypeEnum } from "@honeycomb-protocol/edge-client";

const {
createCreateStakingPoolTransaction: {
transactions, // The transaction response, you'll need to sign and send this transaction through client.sendBulkTransactions
stakingPoolAddress, // The address of the staking pool when it's created
multipliersAddress, // The address of the multipliers when they're created (if you've added any)
},
} = await client.createCreateStakingPoolTransaction({
project: projectAddress.toString(),
resource: resourceAddress.toString(), // Resource's pubkey address in string format, your users will earn rewards in the form of this resource
authority: adminPublicKey.toString(),
delegateAuthority: delegateAuthority.toString(),
payer: payerPublicKey.toString(),
multiplier: { // Optional, if you want to add multipliers, these multipliers increase the rewards for your users based on the conditions you set
decimals: 2,
multipliers: [
// Provide one of these per multiplier: collection, creator, minNftCount, minStakeDuration
{
value: "10",
type: {

collection: collection.toString(),
}
},
{
value: "5",
type: {
creator: creatorPublicKey.toString(),
}
},
{
value: "2",
type: {
minNftCount: "1",
}
},
{
value: "3",
type: {
minStakeDuration: "1",
}
}
]
},
metadata: { // Staking pool metadata
name: "Staking", // Staking pool name
rewardsPerDuration: "1", // Rewards per duration
rewardsDuration: "3600", // Rewards duration in seconds, 3600 means rewards can be collected every hour
maxRewardsDuration: "7200", // Maximum rewards duration in seconds
minStakeDuration: "7200", // Minimum stake duration in seconds before rewards can be claimed
cooldownDuration: "0", // Rewards cooldown
resetStakeDuration: "0", // Reset stake duration
startTime: Date.now().toString(), // Staking pool start time, UNIX second format send as a string
endTime: null, // Staking pool endtime, UNIX second format send as a string, send null if you don't want to set an end time
lockType: LockTypeEnum.Freeze, // Character lock type for the staking pool, send either Freeze or Custody
}
});

Update staking pool

The create staking pool function will create a new pool, but your users won't be able to stake in it until you update it with a character model. Here's how you can do so.

import { LockTypeEnum } from "@honeycomb-protocol/edge-client";

const {
createUpdateStakingPoolTransaction: txResponse // This is the transaction response, you'll need to sign and send this transaction through client.sendBulkTransactions
} = await client.createUpdateStakingPoolTransaction({
project: projectAddress.toString(),
authority: adminPublicKey.toString(),
resource: resourceAddress.toString(), // Optional, only use if you want to change the resource
delegateAuthority: delegateAuthority.toString(), // Optional, only use if you want to change the delegate authority
stakingPool: stakingPoolAddress.toString(),
characterModel: characterModelAddress.toString(), // Optional, but you'll need to initially provide this if you want to allow characters to stake in this pool
payer: payerPublicKey.toString(), // Optional, tx payer pubkey
metadata: { // Optional, all of the properties in this object are also optional
cooldownDuration: "0", // Duration in seconds, UNIX format, send as a string (example: 1 week = 604800 seconds)
endTime: null, // Staking pool endtime, UNIX second format send as a string, send null if you don't want to set an end time
lockType: LockTypeEnum.Freeze, // Character lock type for the staking pool, send either Freeze or Custody
maxRewardsDuration: "9600", // Maximum rewards duration in seconds, send as a string
minStakeDuration: "3600", // Minimum stake duration in seconds, send as a string
name: "New name", // Staking pool name
resetStakeDuration: "86400", // Reset stake duration in seconds, send as a string
rewardsDuration: "3600", // Rewards duration in seconds, send as a string
rewardsPerDuration: "100", // Rewards per duration, send as a string
startTime: Date.now().toString(), // Staking pool start time, UNIX second format send as a string
}
});

Create multipliers

const {
createInitMultipliersTransaction: {
tx, // The transaction response, you'll need to sign and send this transaction through client.sendBulkTransactions
multipliersAddress, // The address of the multipliers when they're created
},
} = await client.createInitMultipliersTransaction({
project: projectAddress.toString(),
authority: adminPublicKey.toString(),
stakingPool: stakingPoolAddress.toString(),
multipliers: [
{
value: "10",
type: {
collection: collection.toString(),
},
},
{
value: "5",
type: {
creator: creatorPublicKey.toString(),
},
},
{
value: "2",
type: {
minNftCount: "1",
},
},
{
value: "3",
type: {
minStakeDuration: "1", // Minimum stake duration in seconds
},
}
],
decimals: 3,
});

Add multipliers

const {
createAddMultiplierTransaction: txResponse // This is the transaction response, you'll need to sign and send this transaction through client.sendBulkTransactions
} = await client.createAddMultiplierTransaction({
project: projectAddress,
authority: adminPublicKey.toString(),
multiplier: multipliersAddress.toString(), // Existing multipliers address
payer: payerPublicKey.toString(), // Optional, tx payer pubkey
delegateAuthority: delegateAuthority.toString(), // Optional, delegate authority pubkey
metadata: [
// Specify any multipliers you want to add here
{
value: "10",
type: {
collection: collection.toString(),
},
},
{
value: "5",
type: {
creator: creatorPublicKey.toString(),
},
},
{
value: "2",
type: {
minNftCount: "1",
},
},
{
value: "3",
type: {
minStakeDuration: "1",
},
}
],
});

Stake characters

const {
createStakeCharactersTransactions: txResponse // This is the transaction response, you'll need to sign and send this transaction through client.sendBulkTransactions
} = await client.createStakeCharactersTransactions({
project: projectAddress.toString(),
stakingPool: stakingPoolAddress.toString(),
characterModel: characterModelAddress.toString(),
characterAddresses: [
characterAddress.toString(),
],
feePayer: payerPublicKey.toString(),
});

Claim staking rewards

const {
createClaimStakingRewardsTransactions: txResponse // This is the transaction response, you'll need to sign and send this transaction through client.sendBulkTransactions
} = await client.createClaimStakingRewardsTransactions({
characterAddresses: [
characterAddress.toString(),
],
characterModel: characterModelAddress.toString(),
feePayer: payerPublicKey.toString(),
});

Unstake characters

const {
createUnstakeCharactersTransactions: txResponse // This is the transaction response, you'll need to sign and send this transaction through client.sendBulkTransactions
} = await client.createUnstakeCharactersTransactions({
characterAddresses: [
characterAddress.toString(),
],
characterModel: characterModelAddress.toString(),
feePayer: payerPublicKey.toString(),
});