@strkfarm/sdk 1.1.49 → 1.1.51
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/index.browser.global.js +117 -80
- package/dist/index.browser.mjs +115 -78
- package/dist/index.d.ts +3 -1
- package/dist/index.js +145 -79
- package/dist/index.mjs +145 -79
- package/package.json +1 -1
- package/src/modules/avnu.ts +4 -4
- package/src/modules/harvests.ts +22 -15
- package/src/node/deployer.ts +36 -1
- package/src/strategies/ekubo-cl-vault.tsx +127 -68
|
@@ -416,22 +416,41 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
416
416
|
const tvlBefore = await this._getTVL(blockBefore);
|
|
417
417
|
const supplyBefore = await this.totalSupply(blockBefore);
|
|
418
418
|
const priceBefore = await this.getCurrentPrice(blockBefore);
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
419
|
+
const poolKey = await this.getPoolKey(blockBefore);
|
|
420
|
+
logger.verbose(`priceBefore: ${priceBefore.price.toString()}`);
|
|
421
|
+
logger.verbose(`priceNow: ${priceNow.price.toString()}`);
|
|
422
|
+
logger.verbose(`tvlBefore: ${JSON.stringify(tvlBefore)}`);
|
|
423
|
+
logger.verbose(`tvlNow: ${JSON.stringify(tvlNow)}`);
|
|
424
|
+
|
|
425
|
+
const isQuoteTokenToken0 = this.metadata.additionalInfo.quoteAsset.address.eq(poolKey.token0);
|
|
426
|
+
logger.verbose(`isQuoteTokenToken0: ${isQuoteTokenToken0}`);
|
|
427
|
+
let tvlBeforeInBaseAsset = Web3Number.fromWei(0, this.metadata.additionalInfo.quoteAsset.decimals);
|
|
428
|
+
let tvlNowInBaseAsset = Web3Number.fromWei(0, this.metadata.additionalInfo.quoteAsset.decimals);
|
|
429
|
+
if (!isQuoteTokenToken0) {
|
|
430
|
+
tvlNowInBaseAsset = (tvlNow.amount0
|
|
431
|
+
.multipliedBy(priceNow.price))
|
|
432
|
+
.plus(tvlNow.amount1);
|
|
433
|
+
tvlBeforeInBaseAsset = (tvlBefore.amount0
|
|
434
|
+
.multipliedBy(priceBefore.price))
|
|
435
|
+
.plus(tvlBefore.amount1);
|
|
436
|
+
} else {
|
|
437
|
+
tvlNowInBaseAsset = (tvlNow.amount1
|
|
438
|
+
.multipliedBy(1 / priceNow.price))
|
|
439
|
+
.plus(tvlNow.amount0);
|
|
440
|
+
tvlBeforeInBaseAsset = (tvlBefore.amount1
|
|
441
|
+
.multipliedBy(1 / priceBefore.price))
|
|
442
|
+
.plus(tvlBefore.amount0);
|
|
443
|
+
}
|
|
444
|
+
const tvlPerShareNow = tvlNowInBaseAsset
|
|
424
445
|
.multipliedBy(1e18)
|
|
425
446
|
.dividedBy(adjustedSupplyNow.toString());
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
.plus(tvlBefore.amount1);
|
|
429
|
-
const tvlPerShareBf = tvlInToken0Bf
|
|
447
|
+
|
|
448
|
+
const tvlPerShareBf = tvlBeforeInBaseAsset
|
|
430
449
|
.multipliedBy(1e18)
|
|
431
450
|
.dividedBy(supplyBefore.toString());
|
|
432
451
|
const timeDiffSeconds = blockNowTime - blockBeforeInfo.timestamp;
|
|
433
|
-
logger.verbose(`
|
|
434
|
-
logger.verbose(`
|
|
452
|
+
logger.verbose(`tvlNowInBaseAsset: ${tvlNowInBaseAsset.toString()}`);
|
|
453
|
+
logger.verbose(`tvlBeforeInBaseAsset: ${tvlBeforeInBaseAsset.toString()}`);
|
|
435
454
|
logger.verbose(`tvlPerShareNow: ${tvlPerShareNow.toString()}`);
|
|
436
455
|
logger.verbose(`tvlPerShareBf: ${tvlPerShareBf.toString()}`);
|
|
437
456
|
logger.verbose(`Price before: ${priceBefore.price.toString()}`);
|
|
@@ -1578,11 +1597,20 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
1578
1597
|
};
|
|
1579
1598
|
}
|
|
1580
1599
|
|
|
1581
|
-
async harvest(acc: Account, maxIterations = 20, priceRatioPrecision = 4): Promise<Call[]> {
|
|
1600
|
+
async harvest(acc: Account, maxIterations = 20, priceRatioPrecision = 4, minRewardAmount: Web3Number = new Web3Number(0, 18)): Promise<Call[]> {
|
|
1582
1601
|
const ekuboHarvests = new EkuboHarvests(this.config);
|
|
1583
|
-
|
|
1602
|
+
|
|
1603
|
+
// get unclaimed rewards and filter out those less than the minimum reward amount
|
|
1604
|
+
const unClaimedRewards = (await ekuboHarvests.getUnHarvestedRewards(
|
|
1584
1605
|
this.address
|
|
1585
|
-
);
|
|
1606
|
+
)).filter(claim => claim.actualReward.greaterThanOrEqualTo(minRewardAmount));
|
|
1607
|
+
|
|
1608
|
+
if (unClaimedRewards.length == 0) {
|
|
1609
|
+
logger.verbose(`${EkuboCLVault.name}: harvest => no unclaimed rewards found`);
|
|
1610
|
+
return [];
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
// get necessary info for the harvest
|
|
1586
1614
|
const poolKey = await this.getPoolKey();
|
|
1587
1615
|
const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
|
|
1588
1616
|
const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
|
|
@@ -1590,8 +1618,14 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
1590
1618
|
logger.verbose(
|
|
1591
1619
|
`${EkuboCLVault.name}: harvest => unClaimedRewards: ${unClaimedRewards.length}`
|
|
1592
1620
|
);
|
|
1621
|
+
|
|
1622
|
+
// execute the harvest
|
|
1593
1623
|
const calls: Call[] = [];
|
|
1594
|
-
|
|
1624
|
+
// do one at a time.
|
|
1625
|
+
const chosenClaim = unClaimedRewards[0];
|
|
1626
|
+
logger.info(`${EkuboCLVault.name}: harvest => doing one at a time`);
|
|
1627
|
+
logger.info(`${EkuboCLVault.name}: harvest => chosenClaim -> Claim ID: ${chosenClaim.claim.id}, Amount: ${chosenClaim.claim.amount.toString()}, actualAmount: ${chosenClaim.actualReward.toString()}, addr: ${chosenClaim.claim.claimee.toString()}`);
|
|
1628
|
+
for (let claim of [chosenClaim]) {
|
|
1595
1629
|
const fee = claim.claim.amount
|
|
1596
1630
|
.multipliedBy(this.metadata.additionalInfo.feeBps)
|
|
1597
1631
|
.dividedBy(10000);
|
|
@@ -1664,60 +1698,50 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
1664
1698
|
logger.verbose(
|
|
1665
1699
|
`${
|
|
1666
1700
|
EkuboCLVault.name
|
|
1667
|
-
}: harvest => token0Amt: ${token0Amt.
|
|
1668
|
-
);
|
|
1669
|
-
|
|
1670
|
-
// THis function cannot handle swapping of non-STRK pool,
|
|
1671
|
-
// bcz atleast one of token0Amt or token1Amt are in STRK terms.
|
|
1672
|
-
const swapInfo = await this.getSwapInfoGivenAmounts(
|
|
1673
|
-
poolKey,
|
|
1674
|
-
token0Amt,
|
|
1675
|
-
token1Amt,
|
|
1676
|
-
bounds,
|
|
1677
|
-
maxIterations,
|
|
1678
|
-
priceRatioPrecision
|
|
1679
|
-
);
|
|
1680
|
-
swapInfo.token_to_address = token0Info.address.address;
|
|
1681
|
-
logger.verbose(
|
|
1682
|
-
`${EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(swapInfo)}`
|
|
1701
|
+
}: harvest => token0Amt: ${token0Amt.toFixed(18)}, token1Amt: ${token1Amt.toFixed(18)}`
|
|
1683
1702
|
);
|
|
1684
1703
|
|
|
1685
1704
|
logger.verbose(
|
|
1686
1705
|
`${EkuboCLVault.name}: harvest => claim: ${JSON.stringify(claim)}`
|
|
1687
1706
|
);
|
|
1688
|
-
const
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1707
|
+
const claimTokenInfo = await Global.getTokenInfoFromAddr(claim.token);
|
|
1708
|
+
const harvestEstimateCall = async (baseSwapInfo: SwapInfo) => {
|
|
1709
|
+
// - the base swap if actual swap from claim token to non-claim token
|
|
1710
|
+
// - the other swap is just claim token to claim token (e.g. STRK to STRK)
|
|
1711
|
+
// which is just dummy
|
|
1712
|
+
let baseSwapAmount = Web3Number.fromWei(
|
|
1713
|
+
uint256.uint256ToBN(baseSwapInfo.token_from_amount).toString(),
|
|
1714
|
+
claimTokenInfo.decimals
|
|
1692
1715
|
).minimum(
|
|
1693
|
-
postFeeAmount.toFixed(
|
|
1716
|
+
postFeeAmount.toFixed(claimTokenInfo.decimals)
|
|
1694
1717
|
); // ensure we don't swap more than we have
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1718
|
+
if (baseSwapAmount.lt(0.0001)) {
|
|
1719
|
+
baseSwapAmount = new Web3Number(0, claimTokenInfo.decimals);
|
|
1720
|
+
}
|
|
1721
|
+
baseSwapInfo.token_from_amount = uint256.bnToUint256(baseSwapAmount.toWei());
|
|
1699
1722
|
|
|
1723
|
+
const isToken0ClaimToken = claim.token.eq(poolKey.token0);
|
|
1700
1724
|
logger.verbose(
|
|
1701
|
-
`${EkuboCLVault.name}: harvest =>
|
|
1725
|
+
`${EkuboCLVault.name}: harvest => isToken0ClaimToken: ${isToken0ClaimToken}, baseSwapAmount: ${baseSwapAmount}`
|
|
1702
1726
|
);
|
|
1703
1727
|
|
|
1704
|
-
const remainingAmount = postFeeAmount.minus(
|
|
1728
|
+
const remainingAmount = postFeeAmount.minus(baseSwapAmount).maximum(0);
|
|
1705
1729
|
logger.verbose(
|
|
1706
1730
|
`${EkuboCLVault.name}: harvest => remainingAmount: ${remainingAmount}`
|
|
1707
1731
|
);
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1732
|
+
|
|
1733
|
+
// obv, same to same
|
|
1734
|
+
let dummySwapInfo = AvnuWrapper.buildZeroSwap(claim.token, this.address.address, claim.token);
|
|
1735
|
+
dummySwapInfo.token_from_amount = uint256.bnToUint256(remainingAmount.toWei());
|
|
1736
|
+
|
|
1713
1737
|
logger.verbose(
|
|
1714
|
-
`${EkuboCLVault.name}: harvest =>
|
|
1715
|
-
|
|
1738
|
+
`${EkuboCLVault.name}: harvest => dummySwapInfo: ${JSON.stringify(
|
|
1739
|
+
dummySwapInfo
|
|
1716
1740
|
)}`
|
|
1717
1741
|
);
|
|
1718
1742
|
logger.verbose(
|
|
1719
|
-
`${EkuboCLVault.name}: harvest =>
|
|
1720
|
-
|
|
1743
|
+
`${EkuboCLVault.name}: harvest => baseSwapInfo: ${JSON.stringify(
|
|
1744
|
+
baseSwapInfo
|
|
1721
1745
|
)}`
|
|
1722
1746
|
);
|
|
1723
1747
|
const calldata = [
|
|
@@ -1728,18 +1752,41 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
1728
1752
|
claimee: claim.claim.claimee.address,
|
|
1729
1753
|
},
|
|
1730
1754
|
claim.proof.map((p) => num.getDecimalString(p)),
|
|
1731
|
-
|
|
1732
|
-
|
|
1755
|
+
isToken0ClaimToken ? dummySwapInfo : baseSwapInfo, // is token0 claim token, its just dummy swap
|
|
1756
|
+
isToken0ClaimToken ? baseSwapInfo : dummySwapInfo,
|
|
1733
1757
|
];
|
|
1734
|
-
logger.verbose(
|
|
1735
|
-
`${EkuboCLVault.name}: harvest => calldata: ${JSON.stringify(
|
|
1736
|
-
calldata
|
|
1737
|
-
)}`
|
|
1738
|
-
);
|
|
1739
1758
|
return [this.contract.populate("harvest", calldata)];
|
|
1740
1759
|
};
|
|
1760
|
+
|
|
1761
|
+
// if token0 == claim token, then the base swapInfo is from claim token to token1
|
|
1762
|
+
// if token1 == claim token, then the base swapInfo is from claim token to token0
|
|
1763
|
+
const isToken0ClaimToken = claim.token.eq(poolKey.token0);
|
|
1764
|
+
let baseSwapInfo = AvnuWrapper.buildZeroSwap(claim.token, this.address.address, isToken0ClaimToken ? token1Info.address : token0Info.address);
|
|
1765
|
+
baseSwapInfo.token_from_amount = uint256.bnToUint256(postFeeAmount.toWei()); // we try to swap all to start with
|
|
1766
|
+
|
|
1767
|
+
// if token0 != claim token, then we swap from claim token to token0
|
|
1768
|
+
if (postFeeAmount.greaterThan(0) && !isToken0ClaimToken) {
|
|
1769
|
+
const avnuWrapper = new AvnuWrapper();
|
|
1770
|
+
const quote = await avnuWrapper.getQuotes(
|
|
1771
|
+
claim.token.address,
|
|
1772
|
+
token0Info.address.address,
|
|
1773
|
+
postFeeAmount.toWei(),
|
|
1774
|
+
this.address.address
|
|
1775
|
+
);
|
|
1776
|
+
baseSwapInfo = await avnuWrapper.getSwapInfo(quote, this.address.address, 0, this.address.address);
|
|
1777
|
+
} else if (postFeeAmount.greaterThan(0) && isToken0ClaimToken) {
|
|
1778
|
+
// if token0 == claim token, then we swap from claim token to token1
|
|
1779
|
+
const avnuWrapper = new AvnuWrapper();
|
|
1780
|
+
const quote = await avnuWrapper.getQuotes(
|
|
1781
|
+
claim.token.address,
|
|
1782
|
+
token1Info.address.address,
|
|
1783
|
+
postFeeAmount.toWei(),
|
|
1784
|
+
this.address.address
|
|
1785
|
+
);
|
|
1786
|
+
baseSwapInfo = await avnuWrapper.getSwapInfo(quote, this.address.address, 0, this.address.address);
|
|
1787
|
+
}
|
|
1741
1788
|
const _callsFinal = await this.rebalanceIter(
|
|
1742
|
-
|
|
1789
|
+
baseSwapInfo,
|
|
1743
1790
|
acc,
|
|
1744
1791
|
harvestEstimateCall,
|
|
1745
1792
|
claim.token.eq(poolKey.token0),
|
|
@@ -1809,39 +1856,47 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
1809
1856
|
}) {
|
|
1810
1857
|
const { postFeeAmount, claim, token0Info, token1Info, acc } = params;
|
|
1811
1858
|
let harvestCall: Call | null = null;
|
|
1859
|
+
logger.verbose(`${EkuboCLVault.name}: harvestMismatchEstimateCallFn => postFeeAmount: ${postFeeAmount.toString()}`);
|
|
1812
1860
|
|
|
1861
|
+
let attempt = 0;
|
|
1862
|
+
let MAX_ATTEMPTS = 50;
|
|
1813
1863
|
const binarySearchCallbackFn = async (mid: bigint) => {
|
|
1864
|
+
attempt++;
|
|
1865
|
+
logger.verbose(`${EkuboCLVault.name}: harvestMismatchEstimateCallFn => mid: ${mid}, attempt: ${attempt}/${MAX_ATTEMPTS}`);
|
|
1814
1866
|
const rewardPart2 = BigInt(postFeeAmount.toWei()) - mid;
|
|
1815
1867
|
const avnuWrapper = new AvnuWrapper();
|
|
1816
1868
|
const beneficiary = this.address.address;
|
|
1817
1869
|
|
|
1818
1870
|
// get quote for 1st part
|
|
1819
|
-
const
|
|
1871
|
+
const quote1Prom = avnuWrapper.getQuotes(
|
|
1820
1872
|
claim.token.address,
|
|
1821
1873
|
token0Info.address.address,
|
|
1822
1874
|
mid.toString(),
|
|
1823
1875
|
beneficiary
|
|
1824
1876
|
);
|
|
1877
|
+
const quote2Prom = avnuWrapper.getQuotes(
|
|
1878
|
+
claim.token.address,
|
|
1879
|
+
token1Info.address.address,
|
|
1880
|
+
rewardPart2.toString(),
|
|
1881
|
+
beneficiary
|
|
1882
|
+
);
|
|
1883
|
+
const [quote1, quote2] = await Promise.all([quote1Prom, quote2Prom]);
|
|
1884
|
+
|
|
1825
1885
|
// default min amount is ok
|
|
1826
1886
|
const swapInfo1 = await avnuWrapper.getSwapInfo(
|
|
1827
1887
|
quote1,
|
|
1828
1888
|
beneficiary,
|
|
1829
|
-
0,
|
|
1889
|
+
0, // fee bps
|
|
1830
1890
|
beneficiary
|
|
1831
1891
|
);
|
|
1832
1892
|
|
|
1833
1893
|
// get quote for 2nd part
|
|
1834
|
-
|
|
1835
|
-
claim.token.address,
|
|
1836
|
-
token1Info.address.address,
|
|
1837
|
-
rewardPart2.toString(),
|
|
1838
|
-
beneficiary
|
|
1839
|
-
);
|
|
1894
|
+
|
|
1840
1895
|
// default min amount is ok
|
|
1841
1896
|
const swapInfo2 = await avnuWrapper.getSwapInfo(
|
|
1842
1897
|
quote2,
|
|
1843
1898
|
beneficiary,
|
|
1844
|
-
0,
|
|
1899
|
+
0, // fee bps
|
|
1845
1900
|
beneficiary
|
|
1846
1901
|
);
|
|
1847
1902
|
|
|
@@ -1860,15 +1915,19 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
1860
1915
|
];
|
|
1861
1916
|
harvestCall = this.contract.populate("harvest", calldata)
|
|
1862
1917
|
const gas = await acc.estimateInvokeFee(harvestCall);
|
|
1918
|
+
logger.verbose(`${EkuboCLVault.name}: harvestMismatchEstimateCallFn => gas: ${gas.overall_fee.toString()}, attempt: ${attempt}/${MAX_ATTEMPTS}`);
|
|
1863
1919
|
return 'found';
|
|
1864
1920
|
} catch (err: any) {
|
|
1865
1921
|
if (err.message.includes('invalid token0 amount')) {
|
|
1922
|
+
logger.verbose(`${EkuboCLVault.name}: harvestMismatchEstimateCallFn => invalid token0 amount, attempt: ${attempt}/${MAX_ATTEMPTS}`);
|
|
1866
1923
|
// too much token0 amount left, may be swap less to token0
|
|
1867
1924
|
return 'go_low';
|
|
1868
1925
|
} else if (err.message.includes('invalid token1 amount')) {
|
|
1926
|
+
logger.verbose(`${EkuboCLVault.name}: harvestMismatchEstimateCallFn => invalid token1 amount, attempt: ${attempt}/${MAX_ATTEMPTS}`);
|
|
1869
1927
|
// too much token1 balance left, may be swap more to token0
|
|
1870
1928
|
return 'go_high';
|
|
1871
1929
|
}
|
|
1930
|
+
logger.verbose(`${EkuboCLVault.name}: harvestMismatchEstimateCallFn => error: ${err.message}, attempt: ${attempt}/${MAX_ATTEMPTS}`);
|
|
1872
1931
|
return 'retry';
|
|
1873
1932
|
}
|
|
1874
1933
|
}
|