Skip to content

Latest commit

 

History

History
1208 lines (933 loc) · 30.5 KB

README.md

File metadata and controls

1208 lines (933 loc) · 30.5 KB

StakeWise Logo

StakeWise Labs V3 SDK

The official SDK designed for effortless data retrieval from the StakeWise platform. This SDK provides a streamlined interface over GraphQL requests and contract interactions.

Version Size Unit Tests GitHub issues GitHub pull requests GitHub forks Ethers version

Table of Contents

Prerequisites

For successful utilization of this library, ensure you have ethers version 6.7.1 or higher installed. The ethers package isn't bundled within the SDK. Instead, we leverage peerDependencies to maintain a lean package size.

Note: If your project uses version 5 of ethers, consider installing version 6 alongside it. Adjust import paths via a bundler. Additionally, you might consider loading our SDK asynchronously using dynamic imports to optimize your application's initial load performance. Here's a sample configuration with webpack:

npm i ethers-6@npm:[email protected]

webpackConfig.plugins.push(
  new webpack.NormalModuleReplacementPlugin(
    /ethers$/m, (resource) => {
      const isStakeWise = /@stakewise\/v3-sdk/.test(resource.context)

      if (isStakeWise) {
        resource.request = resource.request.replace(/ethers/, 'ethers-6')
      }
    }
  )
)

You can do something similar for other builders as well

Installation and Setup

npm i @stakewise/v3-sdk

If your builder doesn't support .graphql files, then you need to add a plugin. For example, for webpack this would be graphql-tag. If you are using another builder, you can easily find GQL support plugins

webpackConfig.module.rules.push(
  {
    test: /\.(graphql|gql)$/,
    loader: 'graphql-tag/loader',
    exclude: /node_modules/,
  }
)

Create SDK instance

import { StakeWiseSDK, Network } from '@stakewise/v3-sdk'

const sdk = new StakeWiseSDK({ network: Network.Mainnet })

SDK Constructor Arguments:

Name Type Type Description
network Network Require Chain id
provider BrowserProvider or JsonRpcProvider Optional You can provide your implementation of the provender for ethers
endpoints.web3 string OR string[] Optional Your urls for connect to blockchain
endpoints.subgraph string Optional stakewise sbugraph url
endpoints.api string Optional stakewise backend url

Quick Links

Request table:
Vault osToken Utils
sdk.vault.getStakerActions sdk.osToken.getBurnAmount sdk.utils.getSwiseUsdPrice
sdk.vault.getSnapshots sdk.osToken.getHealthFactor sdk.utils.getTransactions
sdk.vault.getExitQueuePositions sdk.osToken.getAPY
sdk.vault.getValidators sdk.osToken.getPosition
sdk.vault.getVault sdk.osToken.getMaxMint
sdk.vault.getMaxWithdraw sdk.osToken.getBaseData
sdk.vault.getHarvestParams sdk.osToken.getSharesFromAssets
sdk.vault.getStakeBalance sdk.osToken.getAssetsFromShares
sdk.vault.getUserRewards sdk.vault.getScorePercentiles
sdk.vault.getWhitelist
sdk.vault.getBlocklist
Table of transactions:
Vault osToken
sdk.vault.deposit sdk.osToken.mint
sdk.vault.withdraw sdk.osToken.burn
sdk.vault.claimExitQueue

API-Vault

sdk.vault.getStakerActions

Description:

Get a list of interactions with the vault.

Arguments:

Name Type Type Description
vaultAddress string Require -
userAddress string Optional If a user address is specified, the query will look for events for that address and the vault address only
types AllocatorActionType Require Event types can be found in enum AllocatorActionType which you can import from the library
limit number Require To implement pagination
skip number Require To implement pagination

Returns:

type Output = Array<{
  actionType: AllocatorActionType
  createdAt: number
  assets: string
  shares: string
  link: string
  id: string
}>

In events related to osToken you can use shares, in all other assets

Name Description
id Event identifier
assets Transaction amount
shares Transaction amount
createdAt Transaction date
actionType Type of action
link Transaction link (etherscan/blockscout)

Example:

import { AllocatorActionType } from '@stakewise/v3-sdk'

await sdk.vault.getStakerActions({
  skip: 0,
  limit: 20,
  userAddress: '0x...',
  vaultAddress: '0x...',
  types: [
    AllocatorActionType.Redeemed,
    AllocatorActionType.Deposited,
    AllocatorActionType.VaultCreated,
    AllocatorActionType.ExitedAssetsClaimed,
  ],
})

sdk.vault.getSnapshots

Description:

TVL and APY snapshots for the vault. With the help of this data it is possible to build a chart.

Arguments:

Name Type Type Description
vaultAddress string Require -
dateFrom number Require Time to start

Returns:

type Snapshot = {
  APY: number
  TVL: string
}

type Output = {
  days: Record<number, Snapshot>
  first: Snapshot
}
Name Description
days The result of the query on your parameters, is returned as an object where the keys are timestamps
first We always send the very first saved snapshot regardless of the request parameters, this helps for rendering the chart

Example:

await sdk.vault.getSnapshots({
  vaultAddress: '0x...',
  dateFrom: 1695730032793,
})

sdk.vault.getScorePercentiles

Description:

This method is used to fetch information indicating the effectiveness or performance level of the vault. The retrieved data includes percentiles corresponding to various statuses.

Returns:

type Output = {
  percentile25: number
  percentile50: number
  percentile75: number
}
Name Description
percentile25 Represents the value corresponding to the lowest status. It is associated with the color (red)
percentile50 Represents the value corresponding to the moderate status. It is associated with the color (orange)
percentile75 Represents the value corresponding to the good status. It is associated with the color (light green)

For values greater than percentile75 the status corresponds to excellent with color (green)

Example:

await sdk.vault.getScorePercentiles()

sdk.vault.getUserRewards

Description:

Daily rewards for the user who has made a deposit in the vault. With the help of this data it is possible to build a chart.

Arguments:

Name Type Type Description
vaultAddress string Require -
userAddress string Require -
dateFrom number Require Time to start
dateTo number Optional Time to end
fillGaps boolean Optional Fill in the empty days with zeros

Returns:

type UserReward = {
  date: number
  sumRewards: string
  dailyRewards: string
  dailyRewardsEur: string
  dailyRewardsGbp: string
  dailyRewardsUsd: string
}

type Output = {
  days: Record<number, UserReward>
}
Name Description
days The result of the query on your parameters, is returned as an object where the keys are timestamps

Example:

await sdk.vault.getUserRewards({
  userAddress: '0x...',
  vaultAddress: '0x...',
  dateFrom: 1695730032793,
})

sdk.vault.getWhitelist

Description:

Fetch the whitelist for private vaults. Only addresses included in this list are eligible to stake in the private vault. The number of addresses in this list is indicated by the vault whitelistCount field.

Arguments:

Name Type Type Description
vaultAddress string Require -
orderDirection 'asc' | 'desc' Optional Sort, by default desc (descending order)
search string Optional Filters results by the address field
limit number Optional Limit the number of addresses, default is 100
skip number Optional Skip the number of addresses, default is 0

Returns:

type List = {
  createdAt: number
  address: string
}

type Output = {
  whitelist: List[]
}
Name Description
whitelist An array of objects representing the result of the query based on your parameters

Example:

await sdk.vault.getWhitelist({
  vaultAddress: '0x...',
})

sdk.vault.getBlocklist

Description:

Fetch the blocklist for blocklisted vaults. Addresses included in this list are not eligible to stake in the blocklisted vault. The number of addresses in this list is indicated by the vault blocklistCount field.

Arguments:

Name Type Type Description
vaultAddress string Require -
orderDirection 'asc' | 'desc' Optional Sort, by default desc (descending order)
search string Optional Filters results by the address field
limit number Optional Limit the number of addresses, default is 100
skip number Optional Skip the number of addresses, default is 0

Returns:

type List = {
  createdAt: number
  address: string
}

type Output = {
  blocklist: List[]
}
Name Description
blocklist An array of objects representing the result of the query based on your parameters

Example:

await sdk.vault.getBlocklist({
  vaultAddress: '0x...',
})

sdk.vault.getExitQueuePositions

Description:

Returns the withdrawal queue for a specific user.

Arguments:

Name Type Type
userAddress string Require
vaultAddress string Require

Returns:

type Position = {
  exitQueueIndex: bigint
  positionTicket: string
  timestamp: string
}

type Output = {
  total: bigint
  withdrawable: bigint
  positions: Position[]
}
Name Description
positions Queue positions
total Total withdrawal amount (in ETH)
withdrawable Amount available for withdrawal (in ETH)

Example:

await sdk.vault.getExitQueuePositions({
  vaultAddress: '0x...',
  userAddress: '0x...',
})

sdk.vault.getValidators

Description:

Returns the running vault validators.

Arguments:

Name Type Type
vaultAddress string Require
limit number Require
skip number Require

Returns:

type Output = {
  createdAt: number
  publicKey: string
  earned: string
  link: string
  apy: string
}
Name Description
createdAt Date of Creation
publicKey Validator public key
earned Validator balance (in ETH)
link Link to beaconchain
apy Current validator apy

Example:

await sdk.vault.getValidators({
  skip: 0,
  limit: 5,
  vaultAddress: '0x...'
})

sdk.vault.getVault

Description:

Returns the master data of the vault

Arguments:

Name Type Type
vaultAddress string Require

Returns:

type Output = {
  apy: number
  isErc20: boolean
  capacity: string
  createdAt: number
  feePercent: number
  isPrivate: boolean
  vaultAdmin: string
  totalAssets: string
  feeRecipient: string
  whitelister: string
  vaultAddress: string
  mevRecipient: string
  whitelistCount: number
  blocklistCount: number
  imageUrl: string | null
  blocklistManager: string
  vaultKeysManager: string
  isSmoothingPool: boolean
  tokenName: string | null
  tokenSymbol: string | null
  displayName: string | null
  description: string | null
  performance: number
}
Name Description
apy Current vault apy
isErc20 Does the vault have its own ERC20 token
capacity Maximum TVL of Vault
createdAt Date of Creation
feePercent Commission rate
isPrivate Whether the storage is private
isBlocklist Whether the storage has blocklist
vaultAdmin Vault administrator address
totalAssets TVL of Vault
feeRecipient Vault fee address
whitelister Whitelist manager
vaultAddress Address of vault
mevRecipient Validator fee recipient
whitelistCount Number of addresses in the whitelist
blocklistCount Number of addresses in the blocklist
imageUrl Link for vault logo
blocklistManager Blocklist manager
vaultKeysManager Keys manager address
isSmoothingPool Smoothing poll or Vault escrow
tokenName ERC20 token name
tokenSymbol ERC20 token symbol
displayName Name of vault
description Description of vault
whitelist List of authorized users for deposits
blocklist List of blocked users for deposits
performance Vault performance indicator (percent)

Example:

await sdk.vault.getVault({ vaultAddress: '0x...' })

sdk.vault.getMaxWithdraw

Description:

How much a user can withdraw

Arguments:

Name Type Type Info
ltvPercent bigint Require sdk.osToken.getBaseData
mintedAssets bigint Require sdk.osToken.getPosition
stakedAssets bigint Require sdk.vault.getStakeBalance

Returns:

type Output = bigint

Example:

await sdk.vault.getMaxWithdraw({
  ltvPercent: 0n,
  mintedAssets: 0n,
  stakedAssets: 0n,
})

sdk.vault.getHarvestParams

Description:

Necessary to update the vault state

Returns:

type Output = {
  reward: string
  proof: Array<string>
  rewardsRoot: string
  unlockedMevReward: string 
}

Example:

await sdk.vault.getHarvestParams({ vaultAddress: '0x...' })

sdk.vault.getStakeBalance

Description:

Getting user's balance in the vault

Arguments:

Name Type Type
userAddress string Require
vaultAddress string Require

Returns:

type Output = {
  shares: bigint
  assets: bigint
}
Name Description
shares Balance in vault tokens
assets Balance in ETH

Example:

await sdk.vault.getStakeBalance({
  userAddress: '0x...',
  vaultAddress: '0x...',
})

API-osToken

sdk.osToken.getBurnAmount

Description:

How many osToken burn do you need to make to withdraw all deposit.

Arguments:

Name Type Type Description
ltvPercent bigint Require sdk.osToken.getBaseData
mintedAssets bigint Require sdk.osToken.getPosition
stakedAssets bigint Require sdk.vault.getStakeBalance
newStakedAssets bigint Require The future amount of stake after the deposit

Returns:

type Output = bigint

Example:

sdk.osToken.getBurnAmount({
  ltvPercent: 0n,
  mintedAssets: 0n,
  stakedAssets: 0n,
  newStakedAssets: 0n,
})

sdk.osToken.getHealthFactor

Description:

Get the health of the position

Arguments:

Name Type Type Description
thresholdPercent bigint Require sdk.osToken.getBaseData
mintedAssets bigint Require sdk.osToken.getPosition
stakedAssets bigint Require sdk.vault.getStakeBalance

Returns:

type Output = {
  value: number
  health: OsTokenPositionHealth
}
Name Description
value Numerical value
health Position Health (enum)

Example:

sdk.osToken.getHealthFactor({
  thresholdPercent: 0n,
  mintedAssets: 0n,
  stakedAssets: 0n,
})

sdk.osToken.getAPY

Description:

Current os token APY

Returns:

type Output = string

Example:

const apy = await sdk.osToken.getAPY()

sdk.osToken.getAvgRewardsPerSecond

Description:

Os token average rewards per second

Returns:

type Output = bigint

Example:

const averageRewardsPerSecond = await sdk.osToken.getAvgRewardsPerSecond()

sdk.osToken.getPosition

Description:

User position data

Arguments:

Name Type Type Description
thresholdPercent bigint Require sdk.osToken.getBaseData
stakedAssets bigint Require sdk.vault.getStakeBalance
userAddress string Require -
vaultAddress string Require -

Returns:

type Output = {
  minted: {
    fee: bigint
    assets: bigint
    shares: bigint
  }
  healthFactor: {
    value: number
    health: OsTokenPositionHealth
  }
  protocolFeePercent: bigint
}
Name Description
minted.fee Usage fee amount
minted.shares Balance
minted.assets Balance in ETH
healthFactor sdk.osToken.getHealthFactor
protocolFeePercent Usage fee percent

Example:

await sdk.osToken.getPosition({
  stakedAssets: 0n,
  userAddress: '0x...',
  vaultAddress: '0x...',
  thresholdPercent:  0n,
})

sdk.osToken.getMaxMint

Description:

Maximum number of shares for minting

Arguments:

Name Type Type Description
ltvPercent bigint Require sdk.osToken.getBaseData
stakedAssets bigint Require sdk.vault.getStakeBalance
mintedAssets bigint Require sdk.osToken.getPosition

Returns:

type Output = bigint

Example:

await sdk.osToken.getMaxMint({
  ltvPercent: 0n,
  mintedAssets: 0n,
  stakedAssets: 0n,
})

sdk.osToken.getBaseData

Description:

Basic information on the token

Returns:

type Output = {
  rate: string
  ltvPercent: bigint
  thresholdPercent: bigint
}
Name Description
rate ETH - osToken rate
ltvPercent The percent used to calculate how much user can mint OsToken shares
thresholdPercent The liquidation threshold percent used to calculate health factor for OsToken position

Example:

await sdk.osToken.getBaseData()

sdk.osToken.getAssetsFromShares

Description:

Convert osToken to ETH

Arguments:

Name Type Type
amount bigint Require

Returns:

type Output = bigint

Example:

await sdk.utils.getAssetsFromShares({ amount: 0n })

sdk.osToken.getSharesFromAssets

Description:

Convert ETH to osToken

Arguments:

Name Type Type
amount bigint Require

Returns:

type Output = bigint

Example:

await sdk.utils.getSharesFromAssets({ amount: 0n })

API-utils

sdk.utils.getSwiseUsdPrice

Description:

Current price of SWISE token to USD.

Returns:

type Output = string

Example:

await sdk.utils.getSwiseUsdPrice()

sdk.utils.getTransactions

Description:

Retrieving a transaction to verify that the data went into the subgraph after the transaction

Arguments:

Name Type Type Description
hash string Require Transaction hash

Returns:

type Output = Array<{
  id: string
}>

Example:

await sdk.utils.getTransactions({ hash: '0x...' })

Transactions

Transactions work through the provider you sent when creating an instance of our SDK class. Or, if you are a custodian, you can get the transaction data and sign it yourself. Each transaction also gives you the opportunity to get an approximate gas for sending it. For custodians, it is more reliable to calculate the gas yourself. Each transaction has encode and estimateGas methods for your convenience

sdk.vault.deposit

Description:

Deposit (stake) in a vault

Arguments:

Name Type Type Description
assets bigint Require Deposit amount
userAddress string Require -
vaultAddress string Require -

Example:

const params = {
  assets: 0n,
  userAddress: '0x...',
  vaultAddress: '0x...',
}

// Send transaction
const hash = await sdk.vault.deposit(params)
// When you sign transactions on the backend (for custodians)
const { data, to, value } = await sdk.vault.deposit.encode(params)
// Get an approximate gas per transaction
const gas = await sdk.vault.deposit.estimateGas(params)

sdk.vault.withdraw

Description:

Withdrawal of funds from a vault

Arguments:

Name Type Type Description
assets bigint Require Withdraw amount
userAddress string Require -
vaultAddress string Require -

Example:

const amountAssets = 200n // from input mb

const [
  { ltvPercent, thresholdPercent },
  stake,
] = await Promise.all([
  sdk.osToken.getBaseData(),
  sdk.vault.getStakeBalance({
    vaultAddress: '0x...',
    userAddress: '0x...',
  }),
])

const osToken = await sdk.osToken.getPosition({
  stakedAssets: stake.assets,
  vaultAddress: '0x...',
  userAddress: '0x...',
  thresholdPercent,
})

const maxWithdrawAssets = await sdk.vault.getMaxWithdraw({
  mintedAssets: osToken.minted.assets,
  stakedAssets: stake.assets,
  ltvPercent,
})

if (amountAssets > maxWithdrawAssets) {
  // There is a withdrawal restriction if you have an osToken.

  return
}

const params = {
  vaultAddress: '0x...',
  userAddress: '0x...',
  assets: amountAssets,
}

// Send transaction
const hash = await sdk.vault.withdraw(params)
// When you sign transactions on the backend (for custodians)
const { data, to } = await sdk.vault.withdraw.encode(params)
// Get an approximate gas per transaction
const gas = await sdk.vault.withdraw.estimateGas(params)

sdk.vault.claimExitQueue

Description:

Take the freed tokens from the queue

Arguments:

Name Type Type Description
positions string Require postions from sdk.vault.getExitQueuePositions
userAddress string Require -
vaultAddress string Require -

Example:

const exitQueue = await sdk.vault.getExitQueuePositions({
  vaultAddress: '0x...',
  userAddress: '0x...',
})

if (!exitQueue.withdrawable) {
  // The exit queue has not yet accumulated funds for withdrawal
  return
}

if (!exitQueue.data.length) {
  // No withdrawal positions
  return
}

const params = {
  positions: exitQueue.data,
  vaultAddress: '0x...',
  userAddress: '0x...',
}

// Send transaction
const hash = await sdk.vault.claimExitQueue(params)
// When you sign transactions on the backend (for custodians)
const { data, to } = await sdk.vault.claimExitQueue.encode(params)
// Get an approximate gas per transaction
const gas = await sdk.vault.claimExitQueue.estimateGas(params)

sdk.osToken.mint

Description:

Getting osToken. The amount of token you can get depends on the user's current deposit in the storage. Use data from methods sdk.osToken.getMaxMint and sdk.osToken.getHealthFactor to block a call to mint() if the number of shares is greater than what getMaxMint returns or if the number of osToken after the transaction would make the position unhealthy

Arguments:

Name Type Type Description
shares bigint Require mint amount
userAddress string Require -
vaultAddress string Require -

Example:

import { OsTokenPositionHealth } from '@stakewise/v3-sdk'

const amountShares = 200n // from input mb

const [
  { ltvPercent, thresholdPercent },
  stake,
] = await Promise.all([
  sdk.osToken.getBaseData(),
  sdk.vault.getStakeBalance({
    vaultAddress: '0x...',
    userAddress: '0x...',
  }),
])

const osToken = await sdk.osToken.getPosition({
  stakedAssets: stake.assets,
  vaultAddress: '0x...',
  userAddress: '0x...',
  thresholdPercent,
})

const maxMint = await sdk.osToken.getMaxMint({
  mintedAssets: osToken.minted.assets,
  stakedAssets: stake.assets,
  ltvPercent,
})

if (amountShares > maxMint) {
  // The value of amountShares is more than we can mint
  return
}

const newMintShares = osToken.minted.shares + amountShares
const newMintAssets = await sdk.osToken.getAssetsFromShares({
  amount: newMintShares
})

const { health } = sdk.osToken.getHealthFactor({
  thresholdPercent,
  stakedAssets: stake.assets,
  mintedAssets: newMintAssets,
})

if (health !== OsTokenPositionHealth.Healthy) {
  // If you do a minting with so many amountShares, your position is no longer healthy
  return
}

const params = {
  vaultAddress: '0x...',
  userAddress: '0x...',
  shares: amountShares,
}

// Send transaction
const hash = await sdk.osToken.mint(params)
// When you sign transactions on the backend (for custodians)
const { data, to } = await sdk.osToken.mint.encode(params)
// Get an approximate gas per transaction
const gas = await sdk.osToken.mint.estimateGas(params)

sdk.osToken.burn

Description:

Burns your osToken

Arguments:

Name Type Type Description
shares bigint Require Burn amount
userAddress string Require -
vaultAddress string Require -

Example:

const params = {
  shares: 0n,
  userAddress: '0x...',
  vaultAddress: '0x...',
}

// Send transaction
const hash = await sdk.osToken.burn(params)
// When you sign transactions on the backend (for custodians)
const { data, to, value } = await sdk.osToken.burn.encode(params)
// Get an approximate gas per transaction
const gas = await sdk.osToken.burn.estimateGas(params)

Description of other parts of the api

To retrieve the storage data, you just need the method above. Other parts of the api are needed for specific tasks.

StakeWise class

Name Description
contracts Instances of our contracts
vaultMulticall A method to implement a transaction with vault update
config Object with contract addresses and other data
provider Current provider for blockchain communication
network Selected network

SDK

Name Description
BigDecimal Wrapper over bignumber.js
configs Data for each network
createContract A wrapper over the Contract class from the ethers package