@hubbleprotocol/hubble-sdk
Version:
Hubble Protocol client SDK
617 lines • 32 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Hubble = void 0;
const hubble_config_1 = require("@hubbleprotocol/hubble-config");
const web3_js_1 = require("@solana/web3.js");
const anchor_1 = require("@coral-xyz/anchor");
const borrowing_json_1 = __importDefault(require("./borrowing.json"));
const utils_1 = require("./utils");
const constants_1 = require("./constants");
const decimal_js_1 = __importDefault(require("decimal.js"));
const stream_1 = require("@streamflow/stream");
const TermsSignature_1 = require("./models/TermsSignature");
const scope_sdk_1 = require("@kamino-finance/scope-sdk");
class Hubble {
_cluster;
_connection;
_scope;
_config;
_provider;
_borrowingProgram;
/**
* Create a new instance of the Hubble SDK class.
* @param cluster Name of the Solana cluster
* @param connection Connection to the Solana cluster
*/
constructor(cluster, connection, borrowingProgramId) {
this._cluster = cluster;
this._connection = connection;
this._scope = new scope_sdk_1.Scope(cluster, connection);
this._config = (0, hubble_config_1.getConfigByCluster)(cluster);
// for localnet integration tests
if (borrowingProgramId) {
this._config.borrowing.programId = new web3_js_1.PublicKey(borrowingProgramId);
}
this._provider = new anchor_1.AnchorProvider(connection, (0, utils_1.getReadOnlyWallet)(), {
commitment: connection.commitment,
});
this._borrowingProgram = new anchor_1.Program(borrowing_json_1.default, this._config.borrowing.programId, this._provider);
}
/**
* Get Hubble's staking pool state.
* @return on-chain {@link StakingPoolState} from the borrowing program with numbers as lamports
*/
async getStakingPoolState() {
const stakingPoolState = (await this._borrowingProgram.account.stakingPoolState.fetch(this._config.borrowing.accounts.stakingPoolState));
return (0, utils_1.replaceBigNumberWithDecimal)(stakingPoolState);
}
/**
* Get Hubble's stability pool state.
* @return on-chain {@link StabilityPoolState} from the borrowing program with numbers as lamports
*/
async getStabilityPoolState() {
let stability = (await this._borrowingProgram.account.stabilityPoolState.fetch(this._config.borrowing.accounts.stabilityPoolState));
stability = (0, utils_1.replaceBigNumberWithDecimal)(stability);
stability.cumulativeGainsTotal = (0, utils_1.replaceBigNumberWithDecimal)(stability.cumulativeGainsTotal);
stability.lastCollLossErrorOffset = (0, utils_1.replaceBigNumberWithDecimal)(stability.lastCollLossErrorOffset);
stability.pendingCollateralGains = (0, utils_1.replaceBigNumberWithDecimal)(stability.pendingCollateralGains);
return stability;
}
borrowingMarketStateToDecimals(state, pubkey) {
state = (0, utils_1.replaceBigNumberWithDecimal)(state);
state.depositedCollateral.amounts = (0, utils_1.replaceBigNumberWithDecimal)(state.depositedCollateral.amounts);
state.inactiveCollateral.amounts = (0, utils_1.replaceBigNumberWithDecimal)(state.inactiveCollateral.amounts);
state.collateralRewardPerToken = (0, utils_1.replaceBigNumberWithDecimal)(state.collateralRewardPerToken);
state.withdrawalCap = (0, utils_1.decimalToNumWithdrawalCap)((0, utils_1.replaceBigNumberWithDecimal)(state.withdrawalCap));
state.withdrawalCapsCollateral = state.withdrawalCapsCollateral.map((collCap) => {
collCap.tokenCap = (0, utils_1.decimalToNumWithdrawalCap)((0, utils_1.replaceBigNumberWithDecimal)(collCap.tokenCap));
return (0, utils_1.decimalToNumCollateralWithdrawalCap)((0, utils_1.replaceBigNumberWithDecimal)(collCap));
});
state.supportedCollaterals = state.supportedCollaterals.map((collateral) => (0, utils_1.decimalToNumSupportedCollateral)((0, utils_1.replaceBigNumberWithDecimal)(collateral)));
state.pubkey = pubkey;
return state;
}
/**
* @deprecated Deprecated since version 1.0.114.
* Please use getBorrowingMarketStateByPubkey or getBorrowingMarketStates and use the correct borrowing market state specified by the UserMetadata.
* Get Hubble's borrowing market state.
* @return on-chain {@link BorrowingMarketState} from the borrowing program with numbers as lamports
*/
async getBorrowingMarketState() {
console.warn('getBorrowingMarketState has been deprecated since version 1.0.114. Please use getBorrowingMarketStates and use the correct borrowing market state specified by the UserMetadata.');
const state = (await this._borrowingProgram.account.borrowingMarketState.fetch(this._config.borrowing.accounts.borrowingMarketState));
return this.borrowingMarketStateToDecimals(state, this._config.borrowing.accounts.borrowingMarketState);
}
/**
* Get Hubble's borrowing market state by public key.
* @return on-chain {@link BorrowingMarketState} from the borrowing program with numbers as lamports
*/
async getBorrowingMarketStateByPubkey(pubkey) {
const state = (await this._borrowingProgram.account.borrowingMarketState.fetch(pubkey));
return this.borrowingMarketStateToDecimals(state, pubkey);
}
/**
* Get Hubble's borrowing market states.
* @return list of on-chain {@link BorrowingMarketState} from the borrowing program with numbers as lamports
*/
async getBorrowingMarketStates() {
const states = [];
for (const pubkey of this._config.borrowing.accounts.borrowingMarketStates) {
const state = (await this._borrowingProgram.account.borrowingMarketState.fetch(pubkey));
states.push(this.borrowingMarketStateToDecimals(state, pubkey));
}
return states;
}
/**
* Get user's staking state (staking stats).
* @param user Base58 encoded Public Key of the user
* @return on-chain {@link UserStakingState} from the borrowing program for the specific user with numbers as lamports
* or undefined if user has never used Hubble before or authorized HBB staking
*/
async getUserStakingState(user) {
const userStakingStates = (await this._borrowingProgram.account.userStakingState.all([
{
memcmp: {
bytes: user instanceof web3_js_1.PublicKey ? user.toBase58() : user,
offset: 49, // 8 (account discriminator for user staking state) + 1 (version u8) + 8 (user_id u64) + 32 (staking_pool_state pubkey [u8, 32])
},
},
{
memcmp: {
bytes: this._config.borrowing.accounts.stakingPoolState.toBase58(),
offset: 17, // 8 (account discriminator for user staking state) + 1 (version u8) + 8 (user_id u64)
},
},
])).map((x) => (0, utils_1.replaceBigNumberWithDecimal)(x.account));
return userStakingStates.find((x) => !x.userStake.isZero());
}
/**
* Convert anchor's stability provider state with BN to stability provider state with decimals
* @param stabilityProviderState
*/
static stabilityProviderStateToDecimals(stabilityProviderState) {
const converted = (0, utils_1.replaceBigNumberWithDecimal)(stabilityProviderState);
converted.userDepositSnapshot = (0, utils_1.replaceBigNumberWithDecimal)(converted.userDepositSnapshot);
converted.userDepositSnapshot.sum = (0, utils_1.replaceBigNumberWithDecimal)(converted.userDepositSnapshot.sum);
converted.pendingGainsPerUser = (0, utils_1.replaceBigNumberWithDecimal)(converted.pendingGainsPerUser);
converted.cumulativeGainsPerUser = (0, utils_1.replaceBigNumberWithDecimal)(converted.cumulativeGainsPerUser);
return converted;
}
/**
* Get user's stability provider state (stability pool stats).
* @param user Base58 encoded Public Key of the user
* @return on-chain {@link StabilityProviderState} from the borrowing program for the specific user with numbers as lamports.
* Returns undefined if this user has never used Hubble Stability pool before and does not exist in Hubble on-chain data
*/
async getUserStabilityProviderState(user) {
const stabilityProviderStates = (await this._borrowingProgram.account.stabilityProviderState.all([
{
memcmp: {
bytes: user instanceof web3_js_1.PublicKey ? user.toBase58() : user,
offset: 41, // 8 (account discriminator for stability provider state) + 1 (version u8) + 32 (stability pool state pubkey [u8, 32])
},
},
{
memcmp: {
bytes: this._config.borrowing.accounts.stabilityPoolState.toBase58(),
offset: 9, // 8 (account discriminator for stability provider state) + 1 (version u8)
},
},
])).map((x) => Hubble.stabilityProviderStateToDecimals(x.account));
return stabilityProviderStates.find((x) => !x.depositedStablecoin.isZero());
}
/**
* Get all Hubble stability providers (stability pool stats).
* @return list of on-chain {@link StabilityProviderState} from the borrowing program
*/
async getStabilityProviders() {
return (await this._borrowingProgram.account.stabilityProviderState.all([
{
memcmp: {
bytes: this._config.borrowing.accounts.stabilityPoolState.toBase58(),
offset: 9, // 8 (account discriminator for stability provider state) + 1 (version u8)
},
},
])).map((x) => Hubble.stabilityProviderStateToDecimals(x.account));
}
/**
* Get all non-zero Hubble user staking states.
* @return list of on-chain {@link UserStakingState} from the borrowing program
*/
async getUserStakingStates() {
const userStakingStates = (await this._borrowingProgram.account.userStakingState.all([
{
memcmp: {
bytes: this._config.borrowing.accounts.stakingPoolState.toBase58(),
offset: 17, // 8 (account discriminator for user staking state) + 1 (version u8) + 8 (user_id u64)
},
},
])).map((x) => (0, utils_1.replaceBigNumberWithDecimal)(x.account));
return userStakingStates.filter((x) => !x.userStake.isZero());
}
/**
* Get all Hubble stability providers (stability pool stats) and include raw JSON RPC responses in the return value.
* @return list of on-chain {@link StabilityProviderStateWithJson} from the borrowing program
*/
async getStabilityProvidersIncludeJsonResponse() {
return (await this._borrowingProgram.account.stabilityProviderState.all([
{
memcmp: {
bytes: this._config.borrowing.accounts.stabilityPoolState.toBase58(),
offset: 9, // 8 (account discriminator for stability provider state) + 1 (version u8)
},
},
])).map((x) => {
const stabilityProvider = Hubble.stabilityProviderStateToDecimals(x.account);
stabilityProvider.jsonResponse = JSON.stringify(x.account);
return stabilityProvider;
});
}
/**
* Convert user metadata BN fields to Decimal
* @param user
* @private
*/
static userMetadataToDecimals(user) {
const converted = (0, utils_1.replaceBigNumberWithDecimal)(user);
converted.userCollateralRewardPerToken = (0, utils_1.replaceBigNumberWithDecimal)(converted.userCollateralRewardPerToken);
converted.depositedCollateral = (0, utils_1.replaceBigNumberWithDecimal)(converted.depositedCollateral);
converted.inactiveCollateral = (0, utils_1.replaceBigNumberWithDecimal)(converted.inactiveCollateral);
converted.depositedCollateral.extraCollaterals = converted.depositedCollateral.extraCollaterals.map((x) => (0, utils_1.replaceBigNumberWithDecimal)(x));
converted.inactiveCollateral.extraCollaterals = converted.inactiveCollateral.extraCollaterals.map((x) => (0, utils_1.replaceBigNumberWithDecimal)(x));
return (0, utils_1.replaceBigNumberWithDecimal)(converted);
}
/**
* Get all of user's metadatas (borrowing state, debt, collateral stats...), user can have multiple borrowing accounts.
* @param user Base58 encoded Public Key of the user
* @return on-chain {@link UserMetadata} from the borrowing program for the specific user with numbers as lamports
*/
async getUserMetadatas(user) {
const result = [];
for (const bms of this._config.borrowing.accounts.borrowingMarketStates) {
const userMetadatas = (await this._borrowingProgram.account.userMetadata.all([
{
memcmp: {
bytes: user instanceof web3_js_1.PublicKey ? user.toBase58() : user,
offset: 50, // 8 (account discriminator for usermetadata) + 1 (version u8) + 1 (status u8) + 8 (user_id u64) + 32 (metadata_pk pubkey [u8, 32])
},
},
{
memcmp: {
bytes: bms.toBase58(),
offset: 82, // 8 (account discriminator for usermetadata) + 1 (version u8) + 1 (status u8) + 8 (user_id u64) + 32 (metadata_pk pubkey [u8, 32]) + 32 (owner pubkey)
},
},
])).map((x) => Hubble.userMetadataToDecimals(x.account));
result.push(...userMetadatas);
}
return result;
}
/**
* Get specific user metadata (borrowing state, debt, collateral stats...).
* @param metadata Base58 encoded Public Key of the user metadata
* @return on-chain {@link UserMetadata} from the borrowing program for the specific user with numbers as lamports
*/
async getUserMetadata(metadata) {
return Hubble.userMetadataToDecimals((await this._borrowingProgram.account.userMetadata.fetch(metadata)));
}
/**
* Get all Hubble user metadatas (borrowing state, debt, collateral stats...), one user can have multiple borrowing accounts.
* @return list of on-chain {@link UserMetadata} from the borrowing program for the specific user with numbers as lamports
*/
async getAllUserMetadatas() {
const result = [];
for (const bms of this._config.borrowing.accounts.borrowingMarketStates) {
const userMetadatas = (await this._borrowingProgram.account.userMetadata.all([
{
memcmp: {
bytes: bms.toBase58(),
offset: 82, // 8 (account discriminator for usermetadata) + 1 (version u8) + 1 (status u8) + 8 (user_id u64) + 32 (metadata_pk pubkey [u8, 32]) + 32 (owner pubkey)
},
},
])).map((x) => Hubble.userMetadataToDecimals(x.account));
result.push(...userMetadatas);
}
return result;
}
/**
* Get all Hubble user metadatas (borrowing state, debt, collateral stats...) and include raw JSON RPC responses in the return value.
* @return list of on-chain {@link UserMetadata} from the borrowing program for the specific user with numbers as lamports
*/
async getAllUserMetadatasIncludeJsonResponse() {
const result = [];
for (const bms of this._config.borrowing.accounts.borrowingMarketStates) {
const userMetadatas = (await this._borrowingProgram.account.userMetadata.all([
{
memcmp: {
bytes: bms.toBase58(),
offset: 82, // 8 (account discriminator for usermetadata) + 1 (version u8) + 1 (status u8) + 8 (user_id u64) + 32 (metadata_pk pubkey [u8, 32]) + 32 (owner pubkey)
},
},
])).map((x) => {
const userMetadata = Hubble.userMetadataToDecimals(x.account);
userMetadata.jsonResponse = JSON.stringify(x.account);
return userMetadata;
});
result.push(...userMetadatas);
}
return result;
}
/**
* Get user's loans. Fetches all {@link UserMetadata} of the specified user and converts it to a human-friendly list of {@link Loan}.
* @param user Base58 encoded Public Key of the user
* @return User's loans with already converted on-chain data (from lamports to decimal values)
*/
async getUserLoans(user) {
const loans = [];
const userVaults = await this.getUserMetadatas(user);
if (userVaults.length === 0) {
return [];
}
const borrowingMarketStates = await this.getBorrowingMarketStates();
for (const userVault of userVaults) {
let borrowingMarketState = borrowingMarketStates.find((x) => x.pubkey.toBase58() === userVault.borrowingMarketState.toBase58());
if (!borrowingMarketState) {
borrowingMarketState = await this.getBorrowingMarketStateByPubkey(userVault.borrowingMarketState);
borrowingMarketStates.push(borrowingMarketState);
}
const loan = {
usdhDebt: (0, utils_1.calculateTotalDebt)(userVault, borrowingMarketState),
collateral: (0, utils_1.calculateTotalCollateral)(userVault, borrowingMarketState),
};
if (loan.usdhDebt.greaterThan(0) || !(0, utils_1.isZero)(loan.collateral)) {
loans.push(loan);
}
}
return loans;
}
/**
* Get user's deposited stablecoin (USDH) in the stability pool.
* @param user Base58 encoded Public Key of the user
* @return Deposited stablecoin (USDH) in decimal format or
* undefined if user has never used Hubble before or authorized stability pool deposits
*/
async getUserUsdhInStabilityPool(user) {
const provider = await this.getUserStabilityProviderState(user);
if (provider) {
const pool = await this.getStabilityPoolState();
return (0, utils_1.calculateStabilityProvided)(pool, provider).dividedBy(constants_1.STABLECOIN_DECIMALS);
}
return undefined;
}
/**
* Get user's USDH vault (usdh staked + liquidation rewards + hbb rewards)
* @param user Base58 encoded Public Key of the user
* @return USDH vault with amount of USDH staked, liquidation rewards and HBB rewards or
* undefined if user has never used Hubble before or authorized stability pool deposits
*/
async getUserUsdhVault(user) {
const provider = await this.getUserStabilityProviderState(user);
if (provider) {
const pool = await this.getStabilityPoolState();
const epoch = await this.getEpochToScaleToSum();
const usdhStaked = (0, utils_1.calculateStabilityProvided)(pool, provider).dividedBy(constants_1.STABLECOIN_DECIMALS);
const gains = (0, utils_1.calculatePendingGains)(pool, provider, epoch);
return {
usdhStaked,
hbbRewards: gains.hbb,
liquidationRewards: {
sol: gains.sol,
eth: gains.eth,
ftt: gains.ftt,
btc: gains.btc,
ray: gains.ray,
srm: gains.srm,
msol: gains.msol,
extraCollaterals: [], // user does not gain any liquidation rewards from extra collateral
},
};
}
return undefined;
}
/**
* Get a list of epoch to scale to sum values for Hubble
* @return Array of epoch to scale to sum in decimal format
*/
async getEpochToScaleToSum() {
const epoch = await this._borrowingProgram.account.epochToScaleToSumAccount.fetch(this._config.borrowing.accounts.epochToScaleToSum);
if (epoch) {
return (0, utils_1.replaceBigNumberWithDecimal)(epoch.data);
}
throw Error(`Could not get epoch to scale to sum values from ${this._config.borrowing.accounts.epochToScaleToSum}`);
}
/**
* Get the amount of staked HBB of a specific user.
* @param user Base58 encoded Public Key of the user
* @return HBB staked in decimal format or
* undefined if user has never used Hubble before or authorized HBB staking
*/
async getUserStakedHbb(user) {
const stakingState = await this.getUserStakingState(user);
if (stakingState) {
return stakingState.userStake.dividedBy(constants_1.HBB_DECIMALS);
}
return undefined;
}
/**
* Get the user's HBB vault (HBB staked + USDH rewards)
* @param user Base58 encoded Public Key of the user
* @return HBB vault with number of HBB staked and USDH rewards or
* undefined if user has never used Hubble before or authorized HBB staking
*/
async getUserHbbVault(user) {
const stakingState = await this.getUserStakingState(user);
if (stakingState) {
const stakingPoolState = await this.getStakingPoolState();
const usdhRewards = new decimal_js_1.default(stakingState.userStake.mul(stakingPoolState.rewardPerToken).minus(stakingState.rewardsTally))
.div(constants_1.DECIMAL_FACTOR)
.div(constants_1.STABLECOIN_DECIMALS);
return {
hbbStaked: stakingState.userStake.dividedBy(constants_1.HBB_DECIMALS),
usdhRewards,
};
}
return undefined;
}
/**
* Get Hubble's treasury vault value
* @return Value of Hubble's treasury vault in decimal representation
*/
async getTreasuryVault() {
const acccountBalance = await this._provider.connection.getTokenAccountBalance(this._config.borrowing.accounts.treasuryVault);
if (!acccountBalance.value.uiAmountString) {
throw Error(`Could not get account balance of Hubble treasury vault: ${this._config.borrowing.accounts.treasuryVault}`);
}
return new decimal_js_1.default(acccountBalance.value.uiAmountString);
}
/**
* Get circulating supply number of the Hubble (HBB) token.
* This also takes into account the locked HBB inside Streamflow vesting contracts and subtracts the locked HBB amount.
* @return Number of HBB in circulation in decimal representation
*/
async getHbbCirculatingSupply() {
const tokenSupply = await this._provider.connection.getTokenSupply(this._config.borrowing.accounts.mint.HBB);
if (!tokenSupply.value.uiAmountString) {
throw Error(`Could not get HBB circulating supply from the HBB mint account: ${this._config.borrowing.accounts.mint.HBB}`);
}
let totalTokenSupply = new decimal_js_1.default(tokenSupply.value.uiAmountString);
if (this._cluster === 'mainnet-beta') {
try {
const client = new stream_1.StreamflowSolana.SolanaStreamClient(this._connection.rpcEndpoint, stream_1.ICluster.Mainnet);
const streams = await client.get({
address: constants_1.STREAMFLOW_HBB_CONTRACT,
type: stream_1.StreamType.All,
direction: stream_1.StreamDirection.All,
});
let notWithdrawnTokens = new decimal_js_1.default(0);
for (let [pubkey, stream] of streams) {
const totalWithdrawn = new decimal_js_1.default(stream.withdrawnAmount.toString()).add(stream.streamflowFeeWithdrawn.toString());
const deposited = new decimal_js_1.default(stream.depositedAmount.toString());
notWithdrawnTokens = notWithdrawnTokens.add(deposited.minus(totalWithdrawn).dividedBy(constants_1.HBB_DECIMALS));
}
totalTokenSupply = totalTokenSupply.minus(notWithdrawnTokens);
}
catch (exception) {
throw Error(`Could not get HBB Streamflow contract data: ${exception}`);
}
}
return totalTokenSupply;
}
async getUsdhCirculatingSupply() {
const tokenSupply = await this._provider.connection.getTokenSupply(this._config.borrowing.accounts.stablecoinMint);
if (!tokenSupply.value.uiAmountString) {
throw Error(`Could not get USDH circulating supply from the USDH mint account: ${this._config.borrowing.accounts.stablecoinMint}`);
}
return new decimal_js_1.default(tokenSupply.value.uiAmountString);
}
/**
* Get all token accounts that are holding HBB
*/
getHbbTokenAccounts() {
//how to get all token accounts for specific mint: https://spl.solana.com/token#finding-all-token-accounts-for-a-specific-mint
//get it from the hardcoded token program and create a filter with the actual mint address
//datasize:165 filter selects all token accounts, memcmp filter selects based on the mint address withing each token account
const tokenProgram = new web3_js_1.PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');
return this._provider.connection.getParsedProgramAccounts(tokenProgram, {
filters: [
{ dataSize: 165 },
{ memcmp: { offset: 0, bytes: this._config.borrowing.accounts.mint.HBB.toBase58() } },
],
});
}
/**
* Get Hubble's global config values
*/
async getGlobalConfig() {
let globalConfig = (await this._borrowingProgram.account.globalConfig.fetch(this._config.borrowing.accounts.globalConfig));
globalConfig = (0, utils_1.replaceBigNumberWithDecimal)(globalConfig);
return globalConfig;
}
/**
* Get PSM reserve state
*/
async getPsmReserve() {
const psmPubkey = await this.getPsmPublicKey();
let reserve = (await this._borrowingProgram.account.psmReserve.fetch(psmPubkey));
reserve.withdrawalCapStable = (0, utils_1.decimalToNumWithdrawalCap)((0, utils_1.replaceBigNumberWithDecimal)(reserve.withdrawalCapStable));
reserve.withdrawalCapUsdh = (0, utils_1.decimalToNumWithdrawalCap)((0, utils_1.replaceBigNumberWithDecimal)(reserve.withdrawalCapUsdh));
reserve = (0, utils_1.replaceBigNumberWithDecimal)(reserve);
reserve.mintFeeBps = reserve.mintFeeBps.toNumber();
reserve.burnFeeBps = reserve.burnFeeBps.toNumber();
return reserve;
}
/**
* Get PSM public key
*/
async getPsmPublicKey() {
const res = await web3_js_1.PublicKey.findProgramAddress([Buffer.from('PSM'), this._config.borrowing.accounts.USDC.toBuffer()], this._config.borrowing.programId);
return res[0];
}
/**
* Get the USDC -> USDH swap information
* @param usdcInAmount number of USDC tokens
* @param slippage
*/
async getUsdcToUsdhSwap(usdcInAmount, slippage = new decimal_js_1.default(0)) {
const psmReserve = await this.getPsmReserve();
// we would be minting USDH with this operation
// remaining USDC = max capacity - deposited,
// this is the amount of USDC that can be stored inside the PSM reserve
// we can only mint max this much USDH
const availableUsdc = psmReserve.maxCapacity
.dividedBy(10 ** psmReserve.stablecoinMintDecimals)
.minus(psmReserve.depositedStablecoin.dividedBy(10 ** psmReserve.stablecoinMintDecimals));
let outAmount = usdcInAmount;
if (usdcInAmount.greaterThan(availableUsdc)) {
outAmount = new decimal_js_1.default(0);
}
return {
fees: new decimal_js_1.default(0), // TODO after fees are implemented
slippage: new decimal_js_1.default(0), // TODO: there is no slippage (currently) with PSM
inAmount: usdcInAmount,
outAmount,
};
}
/**
* Get the USDH -> USDC swap information
* @param usdhInAmount number of USDH tokens
* @param slippage
*/
async getUsdhToUsdcSwap(usdhInAmount, slippage = new decimal_js_1.default(0)) {
const psmReserve = await this.getPsmReserve();
let outAmount = new decimal_js_1.default(0);
// we are burning USDH with this operation and we can only burn as much as there is deposited_stablecoin inside psm reserve
const usdcAvailable = psmReserve.depositedStablecoin.dividedBy(10 ** psmReserve.stablecoinMintDecimals);
if (usdhInAmount.lessThanOrEqualTo(usdcAvailable)) {
outAmount = usdhInAmount;
}
return {
fees: new decimal_js_1.default(0), // TODO: after fees are implemented
slippage: new decimal_js_1.default(0), // TODO: there is no slippage (currently) with PSM
inAmount: usdhInAmount,
outAmount,
};
}
/**
* Get the instruction to store the on chain owner signature of terms&conditions
* @param owner
* @param signature
*/
async getUserTermsSignatureIx(owner, signature) {
const pdaSeed = [Buffer.from('signature'), owner.toBuffer()];
const [signatureStateKey, _signatureStateBump] = web3_js_1.PublicKey.findProgramAddressSync(pdaSeed, this._config.borrowing.programId);
const args = {
signature: Array.from(signature),
};
const accounts = {
owner: owner,
ownerSignatureState: signatureStateKey,
systemProgram: web3_js_1.SystemProgram.programId,
rent: web3_js_1.SYSVAR_RENT_PUBKEY,
};
return (0, TermsSignature_1.signTerms)(args, accounts, this._config.borrowing.programId);
}
/**
* Get the on-chain state of the terms&conditions signature for the owner
* @param owner
*/
async getUserTermsSignatureState(owner) {
const pdaSeed = [Buffer.from('signature'), owner.toBuffer()];
const [signatureStateKey, _signatureStateBump] = web3_js_1.PublicKey.findProgramAddressSync(pdaSeed, this._config.borrowing.programId);
return await TermsSignature_1.TermsSignature.fetch(this._connection, signatureStateKey, this._config.borrowing.programId);
}
/**
* Get all Scope prices used by Hubble
*/
async getAllPrices(oraclePrices) {
if (!oraclePrices) {
oraclePrices = await this._scope.getOraclePrices();
}
const spotPrices = {};
const twaps = {};
for (const collateral of constants_1.ExtraCollateralMap.filter((x) => x.mint !== undefined)) {
if (collateral.scopePriceChain && scope_sdk_1.Scope.isScopeChainValid(collateral.scopePriceChain)) {
const spotPrice = await this._scope.getPriceFromChain(collateral.scopePriceChain, oraclePrices);
spotPrices[collateral.mint.toString()] = {
price: spotPrice.price,
name: collateral.name,
};
const filteredTwapChain = collateral?.scopeTwapChain?.filter((x) => x > 0);
if (filteredTwapChain && scope_sdk_1.Scope.isScopeChainValid(filteredTwapChain)) {
const twap = await this._scope.getPriceFromChain(filteredTwapChain, oraclePrices);
twaps[collateral.mint.toString()] = {
price: twap.price,
name: collateral.name,
};
}
}
}
return { spot: spotPrices, twap: twaps };
}
}
exports.Hubble = Hubble;
exports.default = Hubble;
//# sourceMappingURL=Hubble.js.map