@kamino-finance/kliquidity-sdk 8.5.3 → 8.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Kamino.d.ts +6 -0
- package/dist/Kamino.d.ts.map +1 -1
- package/dist/Kamino.js +116 -12
- package/dist/Kamino.js.map +1 -1
- package/package.json +1 -1
- package/src/Kamino.ts +175 -12
package/package.json
CHANGED
package/src/Kamino.ts
CHANGED
|
@@ -1387,10 +1387,11 @@ export class Kamino {
|
|
|
1387
1387
|
};
|
|
1388
1388
|
|
|
1389
1389
|
/**
|
|
1390
|
-
*
|
|
1390
|
+
* Used only for testing
|
|
1391
1391
|
* @param strategyFilters strategy filters or a list of strategy public keys
|
|
1392
|
+
* @deprecated use getStrategiesShareData instead
|
|
1392
1393
|
*/
|
|
1393
|
-
|
|
1394
|
+
legacyGetStrategiesShareData = async (
|
|
1394
1395
|
strategyFilters: StrategiesFilters | Address[],
|
|
1395
1396
|
stratsWithAddresses?: StrategyWithAddress[],
|
|
1396
1397
|
collateralInfos?: CollateralInfo[],
|
|
@@ -1523,6 +1524,169 @@ export class Kamino {
|
|
|
1523
1524
|
return result;
|
|
1524
1525
|
};
|
|
1525
1526
|
|
|
1527
|
+
/**
|
|
1528
|
+
* Batch fetch share data for all or a filtered list of strategies
|
|
1529
|
+
* @param strategyFilters strategy filters or a list of strategy public keys
|
|
1530
|
+
*/
|
|
1531
|
+
getStrategiesShareData = async (
|
|
1532
|
+
strategyFilters: StrategiesFilters | Address[],
|
|
1533
|
+
stratsWithAddresses?: StrategyWithAddress[],
|
|
1534
|
+
collateralInfos?: CollateralInfo[],
|
|
1535
|
+
disabledTokensPrices?: Map<Address, Decimal>
|
|
1536
|
+
): Promise<Array<ShareDataWithAddress>> => {
|
|
1537
|
+
const result: Array<ShareDataWithAddress> = [];
|
|
1538
|
+
const strategiesWithAddresses = stratsWithAddresses
|
|
1539
|
+
? stratsWithAddresses
|
|
1540
|
+
: Array.isArray(strategyFilters)
|
|
1541
|
+
? await this.getStrategiesWithAddresses(strategyFilters)
|
|
1542
|
+
: await this.getAllStrategiesWithFilters(strategyFilters);
|
|
1543
|
+
const fetchBalances: Promise<StrategyBalanceWithAddress>[] = [];
|
|
1544
|
+
const allScopePrices = strategiesWithAddresses.map((x) => x.strategy.scopePrices);
|
|
1545
|
+
const scopePrices = await this._scope.getMultipleOraclePrices(allScopePrices);
|
|
1546
|
+
const scopePricesMap: Record<Address, OraclePrices> = scopePrices.reduce(
|
|
1547
|
+
(map: Record<Address, OraclePrices>, [address, price]) => {
|
|
1548
|
+
map[address] = price;
|
|
1549
|
+
return map;
|
|
1550
|
+
},
|
|
1551
|
+
{}
|
|
1552
|
+
);
|
|
1553
|
+
|
|
1554
|
+
const activeStrategies = strategiesWithAddresses.filter(
|
|
1555
|
+
(x) => x.strategy.position !== DEFAULT_PUBLIC_KEY
|
|
1556
|
+
);
|
|
1557
|
+
|
|
1558
|
+
const poolsAndPositions = await batchFetch([...activeStrategies.map((x) => x.strategy.pool), ...activeStrategies.map((x) => x.strategy.position)], chunk => fetchEncodedAccounts(this._rpc, chunk));
|
|
1559
|
+
const pools = poolsAndPositions.slice(0, activeStrategies.length);
|
|
1560
|
+
const positions = poolsAndPositions.slice(activeStrategies.length);
|
|
1561
|
+
|
|
1562
|
+
const raydiumStrategies: StrategyWithAddress[] = [];
|
|
1563
|
+
const orcaStrategies: StrategyWithAddress[] = [];
|
|
1564
|
+
const meteoraStrategies: StrategyWithAddress[] = [];
|
|
1565
|
+
|
|
1566
|
+
const raydiumPools: Map<Address, PoolState> = new Map();
|
|
1567
|
+
const orcaPools: Map<Address, Whirlpool> = new Map();
|
|
1568
|
+
const meteoraPools: Map<Address, LbPair> = new Map();
|
|
1569
|
+
|
|
1570
|
+
const raydiumPositions: PersonalPositionState[] = [];
|
|
1571
|
+
const orcaPositions: OrcaPosition[] = [];
|
|
1572
|
+
const meteoraPositions: PositionV2[] = [];
|
|
1573
|
+
|
|
1574
|
+
for (let i = 0; i < activeStrategies.length; i++) {
|
|
1575
|
+
const pool = pools[i];
|
|
1576
|
+
const position = positions[i];
|
|
1577
|
+
const strategy = activeStrategies[i];
|
|
1578
|
+
if (!pool.exists || !position.exists) {
|
|
1579
|
+
console.error(`Pool or position does not exist for strategy ${strategy.address.toString()}, skipping`);
|
|
1580
|
+
continue;
|
|
1581
|
+
}
|
|
1582
|
+
const positionBuffer = Buffer.from(position.data);
|
|
1583
|
+
const poolBuffer = Buffer.from(pool.data);
|
|
1584
|
+
|
|
1585
|
+
switch (strategy.strategy.strategyDex.toNumber()) {
|
|
1586
|
+
case dexToNumber('RAYDIUM'):
|
|
1587
|
+
raydiumPools.set(strategy.strategy.pool, PoolState.decode(poolBuffer));
|
|
1588
|
+
raydiumPositions.push(PersonalPositionState.decode(positionBuffer));
|
|
1589
|
+
raydiumStrategies.push(strategy);
|
|
1590
|
+
break;
|
|
1591
|
+
case dexToNumber('ORCA'):
|
|
1592
|
+
orcaPools.set(strategy.strategy.pool, Whirlpool.decode(poolBuffer));
|
|
1593
|
+
orcaPositions.push(OrcaPosition.decode(positionBuffer));
|
|
1594
|
+
orcaStrategies.push(strategy);
|
|
1595
|
+
break;
|
|
1596
|
+
case dexToNumber('METEORA'):
|
|
1597
|
+
meteoraPools.set(strategy.strategy.pool, LbPair.decode(poolBuffer));
|
|
1598
|
+
meteoraPositions.push(PositionV2.decode(positionBuffer));
|
|
1599
|
+
meteoraStrategies.push(strategy);
|
|
1600
|
+
break;
|
|
1601
|
+
default:
|
|
1602
|
+
throw new Error(`Dex ${strategy.strategy.strategyDex.toNumber()} is not supported`);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
const inactiveStrategies = strategiesWithAddresses.filter((x) => x.strategy.position === DEFAULT_PUBLIC_KEY);
|
|
1607
|
+
const collInfos = collateralInfos ? collateralInfos : await this.getCollateralInfos();
|
|
1608
|
+
const disabledPrices = disabledTokensPrices ? disabledTokensPrices : await this.getDisabledTokensPrices(collInfos);
|
|
1609
|
+
for (const { strategy, address } of inactiveStrategies) {
|
|
1610
|
+
const strategyPrices = await this.getStrategyPrices(
|
|
1611
|
+
strategy,
|
|
1612
|
+
collInfos,
|
|
1613
|
+
scopePricesMap[strategy.scopePrices],
|
|
1614
|
+
disabledPrices
|
|
1615
|
+
);
|
|
1616
|
+
result.push({
|
|
1617
|
+
address,
|
|
1618
|
+
strategy,
|
|
1619
|
+
shareData: getEmptyShareData({
|
|
1620
|
+
...strategyPrices,
|
|
1621
|
+
poolPrice: ZERO,
|
|
1622
|
+
upperPrice: ZERO,
|
|
1623
|
+
lowerPrice: ZERO,
|
|
1624
|
+
twapPrice: ZERO,
|
|
1625
|
+
lowerResetPrice: ZERO,
|
|
1626
|
+
upperResetPrice: ZERO,
|
|
1627
|
+
}),
|
|
1628
|
+
});
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
fetchBalances.push(
|
|
1632
|
+
...this.getBalance<PoolState, PersonalPositionState>(
|
|
1633
|
+
raydiumStrategies,
|
|
1634
|
+
raydiumPools,
|
|
1635
|
+
raydiumPositions,
|
|
1636
|
+
this.getRaydiumBalances,
|
|
1637
|
+
collInfos,
|
|
1638
|
+
scopePricesMap,
|
|
1639
|
+
disabledPrices
|
|
1640
|
+
)
|
|
1641
|
+
);
|
|
1642
|
+
|
|
1643
|
+
fetchBalances.push(
|
|
1644
|
+
...this.getBalance<Whirlpool, OrcaPosition>(
|
|
1645
|
+
orcaStrategies,
|
|
1646
|
+
orcaPools,
|
|
1647
|
+
orcaPositions,
|
|
1648
|
+
this.getOrcaBalances,
|
|
1649
|
+
collInfos,
|
|
1650
|
+
scopePricesMap,
|
|
1651
|
+
disabledPrices
|
|
1652
|
+
)
|
|
1653
|
+
);
|
|
1654
|
+
|
|
1655
|
+
fetchBalances.push(
|
|
1656
|
+
...this.getBalance<LbPair, PositionV2>(
|
|
1657
|
+
meteoraStrategies,
|
|
1658
|
+
meteoraPools,
|
|
1659
|
+
meteoraPositions,
|
|
1660
|
+
this.getMeteoraBalances,
|
|
1661
|
+
collInfos,
|
|
1662
|
+
scopePricesMap,
|
|
1663
|
+
disabledPrices
|
|
1664
|
+
)
|
|
1665
|
+
);
|
|
1666
|
+
|
|
1667
|
+
const strategyBalances = await Promise.all(fetchBalances);
|
|
1668
|
+
|
|
1669
|
+
for (const { balance, strategyWithAddress } of strategyBalances) {
|
|
1670
|
+
const sharesFactor = Decimal.pow(10, strategyWithAddress.strategy.sharesMintDecimals.toString());
|
|
1671
|
+
const sharesIssued = new Decimal(strategyWithAddress.strategy.sharesIssued.toString());
|
|
1672
|
+
if (sharesIssued.isZero()) {
|
|
1673
|
+
result.push({
|
|
1674
|
+
address: strategyWithAddress.address,
|
|
1675
|
+
strategy: strategyWithAddress.strategy,
|
|
1676
|
+
shareData: { price: new Decimal(1), balance },
|
|
1677
|
+
});
|
|
1678
|
+
} else {
|
|
1679
|
+
result.push({
|
|
1680
|
+
address: strategyWithAddress.address,
|
|
1681
|
+
strategy: strategyWithAddress.strategy,
|
|
1682
|
+
shareData: { price: balance.computedHoldings.totalSum.div(sharesIssued).mul(sharesFactor), balance },
|
|
1683
|
+
});
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
return result;
|
|
1688
|
+
};
|
|
1689
|
+
|
|
1526
1690
|
private getBalance = <PoolT, PositionT>(
|
|
1527
1691
|
strategies: StrategyWithAddress[],
|
|
1528
1692
|
pools: Map<Address, PoolT | null>,
|
|
@@ -1652,7 +1816,7 @@ export class Kamino {
|
|
|
1652
1816
|
): Promise<StrategyBalances> => {
|
|
1653
1817
|
const strategyPricesPromise = this.getStrategyPrices(strategy, collateralInfos, prices, disabledTokensPrices);
|
|
1654
1818
|
const rebalanceKind = numberToRebalanceType(strategy.rebalanceType);
|
|
1655
|
-
const tokenHoldingsPromise = this.getMeteoraTokensBalances(strategy);
|
|
1819
|
+
const tokenHoldingsPromise = this.getMeteoraTokensBalances(strategy, pool, position);
|
|
1656
1820
|
const [strategyPrices, tokenHoldings] = await Promise.all([strategyPricesPromise, tokenHoldingsPromise]);
|
|
1657
1821
|
|
|
1658
1822
|
const computedHoldings: Holdings = this.getStrategyHoldingsUsd(
|
|
@@ -1749,11 +1913,11 @@ export class Kamino {
|
|
|
1749
1913
|
return holdings;
|
|
1750
1914
|
};
|
|
1751
1915
|
|
|
1752
|
-
private getMeteoraTokensBalances = async (strategy: WhirlpoolStrategy): Promise<TokenHoldings> => {
|
|
1916
|
+
private getMeteoraTokensBalances = async (strategy: WhirlpoolStrategy, pool?: LbPair, position?: PositionV2): Promise<TokenHoldings> => {
|
|
1753
1917
|
let aInvested = ZERO;
|
|
1754
1918
|
let bInvested = ZERO;
|
|
1755
1919
|
try {
|
|
1756
|
-
const userPosition = await this.readMeteoraPosition(strategy.pool, strategy.position);
|
|
1920
|
+
const userPosition = await this.readMeteoraPosition(strategy.pool, strategy.position, pool, position);
|
|
1757
1921
|
|
|
1758
1922
|
if (!userPosition?.amountX.isNaN() && !userPosition?.amountY.isNaN()) {
|
|
1759
1923
|
aInvested = userPosition.amountX;
|
|
@@ -4557,9 +4721,9 @@ export class Kamino {
|
|
|
4557
4721
|
};
|
|
4558
4722
|
};
|
|
4559
4723
|
|
|
4560
|
-
private readMeteoraPosition = async (poolPk: Address, positionPk: Address): Promise<MeteoraPosition> => {
|
|
4561
|
-
|
|
4562
|
-
|
|
4724
|
+
private readMeteoraPosition = async (poolPk: Address, positionPk: Address, pool?: LbPair | null, position?: PositionV2 | null): Promise<MeteoraPosition> => {
|
|
4725
|
+
pool = pool ?? await LbPair.fetch(this._rpc, poolPk, this._meteoraService.getMeteoraProgramId());
|
|
4726
|
+
position = position ?? await PositionV2.fetch(this._rpc, positionPk, this._meteoraService.getMeteoraProgramId());
|
|
4563
4727
|
if (!pool || !position) {
|
|
4564
4728
|
return {
|
|
4565
4729
|
Address: positionPk,
|
|
@@ -4572,16 +4736,15 @@ export class Kamino {
|
|
|
4572
4736
|
poolPk,
|
|
4573
4737
|
position.lowerBinId
|
|
4574
4738
|
);
|
|
4575
|
-
const
|
|
4576
|
-
|
|
4577
|
-
if (!lowerBinArray || !upperBinArray) {
|
|
4739
|
+
const binArray = await BinArray.fetchMultiple(this._rpc, [lowerTickPk, upperTickPk], this._meteoraService.getMeteoraProgramId());
|
|
4740
|
+
if (!binArray || !binArray[0] || !binArray[1]) {
|
|
4578
4741
|
return {
|
|
4579
4742
|
Address: positionPk,
|
|
4580
4743
|
amountX: new Decimal(0),
|
|
4581
4744
|
amountY: new Decimal(0),
|
|
4582
4745
|
};
|
|
4583
4746
|
}
|
|
4584
|
-
const binArrays = [
|
|
4747
|
+
const binArrays = [binArray[0], binArray[1]];
|
|
4585
4748
|
let totalAmountX = new Decimal(0);
|
|
4586
4749
|
let totalAmountY = new Decimal(0);
|
|
4587
4750
|
for (let idx = position.lowerBinId; idx <= position.upperBinId; idx++) {
|