Typescript SDK
All examples are tested using SDK version 2.3.3. Please use this major version and an equal to or higher minor version to replicate results.t
yarn add @friktion-labs/friktion-sdk
import {
// sdk WITHOUT a user wallet attached
VoltSDK,
// sdk WITH a user wallet attached
toConnectedSDK,
FriktionSDK,
} from "@friktion-labs/friktion-sdk";
// SOL Covered Call Volt pubkey
const voltVaultId = new PublicKey(
"CbPemKEEe7Y7YgBmYtFaZiECrVTP5sGrYzrrrviSewKY"
);
const friktionSDK: FriktionSDK = new FriktionSDK({
provider: provider, // e.g AnchorProvider
network: CLUSTER, // e.g mainnet-beta
});
// loads a volt SDK based on the VoltVault account pubkey
// friktionSDK.loadShortOptionsVoltSDKByKey to load a ShortOptionsVoltSDK
// friktionSDK.loadEntropyVoltSDKByKey to load an EntropyVoltSDK
const voltSdk = await friktionSDK.loadVoltAndExtraDataByKey(voltVaultId), // friktionSdk.loadVolt(...) is a lightweight version of sdk with reduced functionality
// creates a ConnectedSDK instance
// toConnectedEntropySDK for getting a ConnectedEntropyVoltSDK (
const cVoltSdk = toConnectedVoltSDK(
voltSdk,
connection, // solana cluster connection
user, // generally, provider.wallet pubkey
undefined, // only used if depositing from a PDA or other program-owned account
);
3. Use this reference package.json for example dependencies:
In the below examples, SOL is used as a default placeholder for the deposit token of a volt. The deposit token can be easily found by calling
voltSdk.depositMint()
The SDK provides a method for each instruction, returning a
TransactionInstruction
object later to be included in a transaction.//// DEPOSIT EXAMPLE ////
// depositing 0.00001 SOL
const depositAmount: Decimal = new Decimal(0.00001);
await cVoltSdk.doFullDeposit(depositAmount);
See a Full Withdraw Example for implementation details. Keep in mind that it is impossible to 100% accurately know the value of a volt before the epoch ends, and thus any withdrawal done mid-epoch is based on a (fairly accurate) estimate.
//// WITHDRAW EXAMPLE ////
// withdrawing 0.00001 SOL
const withdrawAmount: Decimal = new Decimal(0.00001);
await cVoltSdk.doFullWithdraw(withdrawAmount); // creates and send transactions
// NOTE: in below definitions, 'SOL' would be replaced by the deposit token for that volt.
const {
totalBalance, // total # SOL user has in Friktion (e.g 0.001 SOL)
normalBalance, // SOL value of volt tokens in user's wallet
pendingDeposits, // SOL value of users's unclaimed and pending deposits
pendingWithdrawals, // SOL value of user's unclaimed and pending withdrawals
mintableShares, // # of volt tokens user could mint immediately
claimableUnderlying, // SOL value of user's *mintableShares*
normFactor, // 10^(number of decimals in SOL mint) = 10^9 for SOL, varies depending on deposit token
vaultNormFactor, // generally equivalent to normFactor, but may differ if deposit token was migrated (e.g sollet deprecation)
} = await voltSdk.getBalancesForUser(user // wallet pubkey or PDA);
This retrieves the pnl denominated in the deposit token of the volt. This can be accessed via
voltSdk.voltVault.depositMint
. This feature is only supported after a certain epoch on each volt. For full historicals or user-specific PnL (like this), please ask in the #developers channel in discord// denominated in deposit token.
// e.g if the volt made $1000 in premium, SOL is worth $100,
const epochPnl = await voltSdk.getPnlForEpoch(roundNumber)
// for SOL Call round 25, outputs 325.872 SOL.
This gets the TVL (total value locked) of a volt (all collateral under control of the volt's on-chain authorities).
const tvl = await voltSdk.getTvlInDepositToken()
To convert to USD-demoninated TVL, simply multiply by the deposit token price (scraped from coingecko). Or, call the built-in function.
const usdTvl = await voltSdk.getTvl();
// or:
// const usdTvl = tvl.mul(await voltSdk.depositTokenPrice());VoltSDK vs. ConnectedVoltSDK
For more detailed statistics about TVL, call
getTvlStats()
const {
tvl
usdTvl
strategyDeposits,
pendingDeposits,
pendingWithdrawals, // SOL
} = await voltSdk.getTvlStats();
To see the loaded volt's type, strategy, and name.
const type: VoltType = voltSdk.voltType() //
// export enum VoltType {
// ShortOptions = 0,
// Entropy = 1,
// }
const strategy: VoltStrategy = await voltSdk.voltStrategy()
// export enum VoltStrategy {
// ShortCalls,
// ShortPuts,
// ShortCrab,
// LongBasis,
// }
const voltNumber: number = await voltSdk.voltNumber()
// ShortCalls => 1
// ShortPuts => 2
// ShortCrab => 3
// LongBasis => 4
//
const name: string = voltSdk.voltName()
// e.g Volt #01: Covered Call
It's often useful to print more details of volt in order to visually interpret the current state (e.g stage of rebalancing, total TVL,
await voltSdk.printState();
Truncated output below. To see full output check out the example
-------------------------
ID: CbPemKEEe7Y7YgBmYtFaZiECrVTP5sGrYzrrrviSewKY
-------------------------
Volt #01: Covered Call
volt 1 or 2
returning...
Short (Fri, 01 Jul 2022 02:00:00 GMT $0.019230769230769230769 PUT)
-------------------------
HIGH LEVEL STATS
-------------------------
Total Value (minus pending deposits) (SOL): 159155.947477497 , ($): 6124320.85893408456
deposit pool: 0.947477497
premium pool: 0.535425 permissioned premium pool: 35795.55105
...
...
Each Volt epoch contains valuable information about deposits/withdrawals, fees collected, PnL, and the rebalancing process.
const currentRound = await voltSdk.getRoundByNumber(voltSdk.voltVault.roundNumber) // Round account
const currentRound2 = await voltSdk.getCurrentRound() // equivalent to currentRound
const currentEpochInfo = await voltSdk.getEpochInfoByNumber(voltSdk.voltVault.roundNumber) // FriktionEpochInfo account
const currentEpochInfo2 = await voltSdk.getCurrentEpochInfo() // equivalent to currentEpochInfo
Performance fees can be easily calculated given an expected reward (denominated in deposit token).
const totalReward = 100 * voltSdk.getDepositTokenNormalizationFactor() // 100 SOL in lamports
const performanceFee = voltSdk.performanceFeeAmount(totalReward) // 1000 bps = 10% * 100 SOL = 10 SOL = 10000000000 lamports
while withdrawal fees require an estimation of the underlying received.
const expectedWithdrawnUnderlying = 100 * voltSdk.getDepositTokenNormalizationFactor() // 100 SOL in lamports
const withdrawalFee = voltSdk.withdrawalFeeAmount(expectedWithdrawnUnderlying) // 10 bps = 0.1% * 100 SOL = 0.1 SOL = 100000000 lamports
If there are operational difficulties with public volts, or if a Circuits volt requests to pause the current strategy, all Friktion volts can utilize a simple, low risk lending aggregator.
const {tvlDepositToken, tvlUsd} = await voltSdk.getEntropyLendingTvl()
Entropy describes the set of exchanges + lending platforms that are based off the original Mango Markets codebase. To view the lower-level objects used to calculate volt TVL in this set of lending platforms, see below.
const {
entropyGroup,
entropyAccount,
entropyCache
} = await this.getEntropyLendingObjects(); // may fail if lending has not been initialized
let friktionSdk = new FriktionSDK({
provider: new AnchorProvider(
new Connection("https://api.mainnet-beta.solana.com"),
Wallet.local(),
{}
), // with mainnet RPC
network: 'mainnet-beta',
});
const allMainnetVolts: VoltSDK[] = await friktionSdk.getAllVoltsInSnapshot();
friktionSdk = new FriktionSDK({
provider: new AnchorProvider(
new Connection("https://api.devnet.solana.com"),
Wallet.local(),
{}
), // with devnet RPC
network: 'devnet',
});
const allDevnetVolts: VoltSDK[] = await friktionSdk.getAllVoltsInSnapshot();
VoltSDK is a generic wrapper around a single Friktion volt. Useful for retrieving accounts (e.g VoltVault, ExtraVoltData) and calculating statistics. It is implemented as an abstract class. Each specific volt type extends VoltSDK to form their own SDK. ShortOptionsVoltSDK provides helper methods for interacting with volt 1 & 2, while EntropyVoltSDK does the same for volt 3 & 4.
ConnectedVoltSDK is an extension of VoltSDK tied to a specific user, and provides an API for creating any Friktion volt instruction using the provided wallet as an authority. It's also an abstract class, so requires a specific implementation given by ConnectedShortOptionsVoltSDK or ConnectedEntropyVoltSDK. Examples below:
// VoltSDK
constructor(
readonly sdk: FriktionSDK,
readonly voltVault: VoltVault,
readonly voltKey: PublicKey,
extraVoltData?: ExtraVoltData | undefined
)
// ConnectedVoltSDK extends VoltSDK
constructor(
voltSDK: VoltSDK,
connection: Connection,
user: PublicKey,
daoAuthority?: PublicKey | undefined
)
// load ShortOptionsVoltSDK extends VoltSDK
const solPutLowKey = new PublicKey("2evPXRLaTZj92DM93sdryeszwqoC9C6DoWa1TKHn1AzU");
const solPutLowShortOptionsSdk = await friktionSDK.loadShortOptionsVoltSDKByKey(solPutLowKey);
// convert to ConnectedShortOptionsVoltSDK extends (ConnectedVoltSDK & ShortOptionsVoltSDK)
// this inherits all methods from both parent classes
const solPutLowConnectedSDK: ConnectedSDK = toConnectedSDK(
solPutLowShortOptionsSdk,
provider.connection,
provider.wallet
);
// use short options specific helper to get the specific class type
const solPutLowConnectedSDK: ConnectedShortOptionsVoltSDK = toConnectedShortOptionsSDK(
solPutLowShortOptionsSdk,
provider.connection,
provider.wallet
);
const solBasisKey = new PublicKey("2yPs4YTdMzuKmYeubfNqH2xxgdEkXMxVcFWnAFbsojS2");
const solBasisEntropySdk = await friktionSDK.loadEntropyVoltSDKByKey(solBasisKey);
// mirror methods toConnectedSDK and toConnectedEntropySDK
Last modified 10mo ago