@strkfarm/sdk 1.1.50 → 1.1.52

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.mjs CHANGED
@@ -2165,10 +2165,9 @@ function getTrovesEndpoint() {
2165
2165
  }
2166
2166
 
2167
2167
  // src/modules/avnu.ts
2168
- var AvnuWrapper = class _AvnuWrapper {
2168
+ var AvnuWrapper = class {
2169
2169
  async getQuotes(fromToken, toToken, amountWei, taker, retry = 0, excludeSources = ["Haiko(Solvers)"]) {
2170
2170
  const MAX_RETRY = 5;
2171
- logger.verbose(`${_AvnuWrapper.name}: getQuotes => Getting quotes for ${fromToken} -> ${toToken}, amount: ${amountWei}, taker: ${taker}, retry: ${retry}`);
2172
2171
  const params = {
2173
2172
  sellTokenAddress: fromToken,
2174
2173
  buyTokenAddress: toToken,
@@ -2211,9 +2210,6 @@ var AvnuWrapper = class _AvnuWrapper {
2211
2210
  startIndex += 5 + swap_params_len;
2212
2211
  }
2213
2212
  const _minAmount = minAmount || (quote.buyAmount * 95n / 100n).toString();
2214
- logger.verbose(`${_AvnuWrapper.name}: getSwapInfo => sellToken: ${quote.sellTokenAddress}, sellAmount: ${quote.sellAmount}`);
2215
- logger.verbose(`${_AvnuWrapper.name}: getSwapInfo => buyToken: ${quote.buyTokenAddress}`);
2216
- logger.verbose(`${_AvnuWrapper.name}: getSwapInfo => buyAmount: ${quote.buyAmount}, minAmount: ${_minAmount}`);
2217
2213
  const swapInfo = {
2218
2214
  token_from_address: quote.sellTokenAddress,
2219
2215
  token_from_amount: uint256.bnToUint256(quote.sellAmount),
@@ -4034,20 +4030,26 @@ var Harvests = class _Harvests {
4034
4030
  const rewards = await this.getHarvests(addr);
4035
4031
  if (rewards.length == 0) return [];
4036
4032
  const unClaimed = [];
4037
- const reward = rewards.sort((a, b) => b.endDate.getTime() - a.endDate.getTime())[0];
4038
- const cls = await this.config.provider.getClassAt(reward.rewardsContract.address);
4039
- const contract = new Contract4({ abi: cls.abi, address: reward.rewardsContract.address, providerOrAccount: this.config.provider });
4040
- const isClaimed = await contract.call("is_claimed", [reward.claim.id]);
4041
- logger.verbose(`${_Harvests.name}: isClaimed: ${isClaimed}`);
4042
- if (isClaimed) {
4043
- return unClaimed;
4033
+ const sortedRewards = rewards.sort((a, b) => b.endDate.getTime() - a.endDate.getTime());
4034
+ if (sortedRewards.length == 0) {
4035
+ logger.verbose(`${_Harvests.name}: no rewards found`);
4036
+ return [];
4044
4037
  }
4045
- const bal = await new ERC20(this.config).balanceOf(reward.token, reward.rewardsContract.address, 18);
4046
- if (bal.lessThan(reward.claim.amount)) {
4047
- logger.verbose(`${_Harvests.name}: balance: ${bal.toString()}, amount: ${reward.claim.amount.toString()}`);
4048
- return unClaimed;
4038
+ const cls = await this.config.provider.getClassAt(sortedRewards[0].rewardsContract.address);
4039
+ for (const reward of sortedRewards) {
4040
+ const contract = new Contract4({ abi: cls.abi, address: reward.rewardsContract.address, providerOrAccount: this.config.provider });
4041
+ const isClaimed = await contract.call("is_claimed", [reward.claim.id]);
4042
+ logger.verbose(`${_Harvests.name}: isClaimed: ${isClaimed}, claim id: ${reward.claim.id}, address: ${reward.rewardsContract.address}`);
4043
+ if (isClaimed) {
4044
+ continue;
4045
+ }
4046
+ const bal = await new ERC20(this.config).balanceOf(reward.token, reward.rewardsContract.address, 18);
4047
+ if (bal.lessThan(reward.claim.amount)) {
4048
+ logger.verbose(`${_Harvests.name}: balance: ${bal.toString()}, amount: ${reward.claim.amount.toString()}`);
4049
+ continue;
4050
+ }
4051
+ unClaimed.push(reward);
4049
4052
  }
4050
- unClaimed.unshift(reward);
4051
4053
  return unClaimed;
4052
4054
  }
4053
4055
  };
@@ -16538,11 +16540,15 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
16538
16540
  amount1
16539
16541
  };
16540
16542
  }
16541
- async harvest(acc, maxIterations = 20, priceRatioPrecision = 4) {
16543
+ async harvest(acc, maxIterations = 20, priceRatioPrecision = 4, minRewardAmount = new Web3Number(0, 18)) {
16542
16544
  const ekuboHarvests = new EkuboHarvests(this.config);
16543
- const unClaimedRewards = await ekuboHarvests.getUnHarvestedRewards(
16545
+ const unClaimedRewards = (await ekuboHarvests.getUnHarvestedRewards(
16544
16546
  this.address
16545
- );
16547
+ )).filter((claim) => claim.actualReward.greaterThanOrEqualTo(minRewardAmount));
16548
+ if (unClaimedRewards.length == 0) {
16549
+ logger.verbose(`${_EkuboCLVault.name}: harvest => no unclaimed rewards found`);
16550
+ return [];
16551
+ }
16546
16552
  const poolKey = await this.getPoolKey();
16547
16553
  const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
16548
16554
  const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
@@ -16551,7 +16557,10 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
16551
16557
  `${_EkuboCLVault.name}: harvest => unClaimedRewards: ${unClaimedRewards.length}`
16552
16558
  );
16553
16559
  const calls = [];
16554
- for (let claim of unClaimedRewards) {
16560
+ const chosenClaim = unClaimedRewards[0];
16561
+ logger.info(`${_EkuboCLVault.name}: harvest => doing one at a time`);
16562
+ 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()}`);
16563
+ for (let claim of [chosenClaim]) {
16555
16564
  const fee = claim.claim.amount.multipliedBy(this.metadata.additionalInfo.feeBps).dividedBy(1e4);
16556
16565
  const postFeeAmount = claim.claim.amount.minus(fee);
16557
16566
  const isToken1 = claim.token.eq(poolKey.token1);
@@ -16600,57 +16609,41 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
16600
16609
  const token0Amt = isToken1 ? new Web3Number(0, token0Info.decimals) : postFeeAmount;
16601
16610
  const token1Amt = isToken1 ? postFeeAmount : new Web3Number(0, token0Info.decimals);
16602
16611
  logger.verbose(
16603
- `${_EkuboCLVault.name}: harvest => token0Amt: ${token0Amt.toString()}, token1Amt: ${token1Amt.toString()}`
16604
- );
16605
- const swapInfo = await this.getSwapInfoGivenAmounts(
16606
- poolKey,
16607
- token0Amt,
16608
- token1Amt,
16609
- bounds,
16610
- maxIterations,
16611
- priceRatioPrecision
16612
- );
16613
- swapInfo.token_to_address = token0Info.address.address;
16614
- logger.verbose(
16615
- `${_EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(swapInfo)}`
16612
+ `${_EkuboCLVault.name}: harvest => token0Amt: ${token0Amt.toFixed(18)}, token1Amt: ${token1Amt.toFixed(18)}`
16616
16613
  );
16617
16614
  logger.verbose(
16618
16615
  `${_EkuboCLVault.name}: harvest => claim: ${JSON.stringify(claim)}`
16619
16616
  );
16620
- const harvestEstimateCall = async (swapInfo1) => {
16621
- const swap1Amount = Web3Number.fromWei(
16622
- uint2564.uint256ToBN(swapInfo1.token_from_amount).toString(),
16623
- 18
16624
- // cause its always STRK?
16617
+ const claimTokenInfo = await Global.getTokenInfoFromAddr(claim.token);
16618
+ const harvestEstimateCall = async (baseSwapInfo2) => {
16619
+ let baseSwapAmount = Web3Number.fromWei(
16620
+ uint2564.uint256ToBN(baseSwapInfo2.token_from_amount).toString(),
16621
+ claimTokenInfo.decimals
16625
16622
  ).minimum(
16626
- postFeeAmount.toFixed(18)
16627
- // cause always strk
16628
- );
16629
- swapInfo.token_from_amount = uint2564.bnToUint256(swap1Amount.toWei());
16630
- swapInfo.token_to_min_amount = uint2564.bnToUint256(
16631
- swap1Amount.multipliedBy(0).toWei()
16632
- // placeholder
16623
+ postFeeAmount.toFixed(claimTokenInfo.decimals)
16633
16624
  );
16625
+ if (baseSwapAmount.lt(1e-4)) {
16626
+ baseSwapAmount = new Web3Number(0, claimTokenInfo.decimals);
16627
+ }
16628
+ baseSwapInfo2.token_from_amount = uint2564.bnToUint256(baseSwapAmount.toWei());
16629
+ const isToken0ClaimToken2 = claim.token.eq(poolKey.token0);
16634
16630
  logger.verbose(
16635
- `${_EkuboCLVault.name}: harvest => swap1Amount: ${swap1Amount}`
16631
+ `${_EkuboCLVault.name}: harvest => isToken0ClaimToken: ${isToken0ClaimToken2}, baseSwapAmount: ${baseSwapAmount}`
16636
16632
  );
16637
- const remainingAmount = postFeeAmount.minus(swap1Amount).maximum(0);
16633
+ const remainingAmount = postFeeAmount.minus(baseSwapAmount).maximum(0);
16638
16634
  logger.verbose(
16639
16635
  `${_EkuboCLVault.name}: harvest => remainingAmount: ${remainingAmount}`
16640
16636
  );
16641
- const swapInfo2 = {
16642
- ...swapInfo,
16643
- token_from_amount: uint2564.bnToUint256(remainingAmount.toWei())
16644
- };
16645
- swapInfo2.token_to_address = token1Info.address.address;
16637
+ let dummySwapInfo = AvnuWrapper.buildZeroSwap(claim.token, this.address.address, claim.token);
16638
+ dummySwapInfo.token_from_amount = uint2564.bnToUint256(remainingAmount.toWei());
16646
16639
  logger.verbose(
16647
- `${_EkuboCLVault.name}: harvest => swapInfo: ${JSON.stringify(
16648
- swapInfo
16640
+ `${_EkuboCLVault.name}: harvest => dummySwapInfo: ${JSON.stringify(
16641
+ dummySwapInfo
16649
16642
  )}`
16650
16643
  );
16651
16644
  logger.verbose(
16652
- `${_EkuboCLVault.name}: harvest => swapInfo2: ${JSON.stringify(
16653
- swapInfo2
16645
+ `${_EkuboCLVault.name}: harvest => baseSwapInfo: ${JSON.stringify(
16646
+ baseSwapInfo2
16654
16647
  )}`
16655
16648
  );
16656
16649
  const calldata = [
@@ -16661,18 +16654,36 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
16661
16654
  claimee: claim.claim.claimee.address
16662
16655
  },
16663
16656
  claim.proof.map((p) => num5.getDecimalString(p)),
16664
- swapInfo,
16665
- swapInfo2
16657
+ isToken0ClaimToken2 ? dummySwapInfo : baseSwapInfo2,
16658
+ // is token0 claim token, its just dummy swap
16659
+ isToken0ClaimToken2 ? baseSwapInfo2 : dummySwapInfo
16666
16660
  ];
16667
- logger.verbose(
16668
- `${_EkuboCLVault.name}: harvest => calldata: ${JSON.stringify(
16669
- calldata
16670
- )}`
16671
- );
16672
16661
  return [this.contract.populate("harvest", calldata)];
16673
16662
  };
16663
+ const isToken0ClaimToken = claim.token.eq(poolKey.token0);
16664
+ let baseSwapInfo = AvnuWrapper.buildZeroSwap(claim.token, this.address.address, isToken0ClaimToken ? token1Info.address : token0Info.address);
16665
+ baseSwapInfo.token_from_amount = uint2564.bnToUint256(postFeeAmount.toWei());
16666
+ if (postFeeAmount.greaterThan(0) && !isToken0ClaimToken) {
16667
+ const avnuWrapper = new AvnuWrapper();
16668
+ const quote = await avnuWrapper.getQuotes(
16669
+ claim.token.address,
16670
+ token0Info.address.address,
16671
+ postFeeAmount.toWei(),
16672
+ this.address.address
16673
+ );
16674
+ baseSwapInfo = await avnuWrapper.getSwapInfo(quote, this.address.address, 0, this.address.address);
16675
+ } else if (postFeeAmount.greaterThan(0) && isToken0ClaimToken) {
16676
+ const avnuWrapper = new AvnuWrapper();
16677
+ const quote = await avnuWrapper.getQuotes(
16678
+ claim.token.address,
16679
+ token1Info.address.address,
16680
+ postFeeAmount.toWei(),
16681
+ this.address.address
16682
+ );
16683
+ baseSwapInfo = await avnuWrapper.getSwapInfo(quote, this.address.address, 0, this.address.address);
16684
+ }
16674
16685
  const _callsFinal = await this.rebalanceIter(
16675
- swapInfo,
16686
+ baseSwapInfo,
16676
16687
  acc,
16677
16688
  harvestEstimateCall,
16678
16689
  claim.token.eq(poolKey.token0),
@@ -16716,32 +16727,40 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
16716
16727
  async harvestMismatchEstimateCallFn(params) {
16717
16728
  const { postFeeAmount, claim, token0Info, token1Info, acc } = params;
16718
16729
  let harvestCall = null;
16730
+ logger.verbose(`${_EkuboCLVault.name}: harvestMismatchEstimateCallFn => postFeeAmount: ${postFeeAmount.toString()}`);
16731
+ let attempt = 0;
16732
+ let MAX_ATTEMPTS = 50;
16719
16733
  const binarySearchCallbackFn = async (mid) => {
16734
+ attempt++;
16735
+ logger.verbose(`${_EkuboCLVault.name}: harvestMismatchEstimateCallFn => mid: ${mid}, attempt: ${attempt}/${MAX_ATTEMPTS}`);
16720
16736
  const rewardPart2 = BigInt(postFeeAmount.toWei()) - mid;
16721
16737
  const avnuWrapper = new AvnuWrapper();
16722
16738
  const beneficiary = this.address.address;
16723
- const quote1 = await avnuWrapper.getQuotes(
16739
+ const quote1Prom = avnuWrapper.getQuotes(
16724
16740
  claim.token.address,
16725
16741
  token0Info.address.address,
16726
16742
  mid.toString(),
16727
16743
  beneficiary
16728
16744
  );
16745
+ const quote2Prom = avnuWrapper.getQuotes(
16746
+ claim.token.address,
16747
+ token1Info.address.address,
16748
+ rewardPart2.toString(),
16749
+ beneficiary
16750
+ );
16751
+ const [quote1, quote2] = await Promise.all([quote1Prom, quote2Prom]);
16729
16752
  const swapInfo1 = await avnuWrapper.getSwapInfo(
16730
16753
  quote1,
16731
16754
  beneficiary,
16732
16755
  0,
16733
- beneficiary
16734
- );
16735
- const quote2 = await avnuWrapper.getQuotes(
16736
- claim.token.address,
16737
- token1Info.address.address,
16738
- rewardPart2.toString(),
16756
+ // fee bps
16739
16757
  beneficiary
16740
16758
  );
16741
16759
  const swapInfo2 = await avnuWrapper.getSwapInfo(
16742
16760
  quote2,
16743
16761
  beneficiary,
16744
16762
  0,
16763
+ // fee bps
16745
16764
  beneficiary
16746
16765
  );
16747
16766
  try {
@@ -16758,13 +16777,17 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
16758
16777
  ];
16759
16778
  harvestCall = this.contract.populate("harvest", calldata);
16760
16779
  const gas = await acc.estimateInvokeFee(harvestCall);
16780
+ logger.verbose(`${_EkuboCLVault.name}: harvestMismatchEstimateCallFn => gas: ${gas.overall_fee.toString()}, attempt: ${attempt}/${MAX_ATTEMPTS}`);
16761
16781
  return "found";
16762
16782
  } catch (err) {
16763
16783
  if (err.message.includes("invalid token0 amount")) {
16784
+ logger.verbose(`${_EkuboCLVault.name}: harvestMismatchEstimateCallFn => invalid token0 amount, attempt: ${attempt}/${MAX_ATTEMPTS}`);
16764
16785
  return "go_low";
16765
16786
  } else if (err.message.includes("invalid token1 amount")) {
16787
+ logger.verbose(`${_EkuboCLVault.name}: harvestMismatchEstimateCallFn => invalid token1 amount, attempt: ${attempt}/${MAX_ATTEMPTS}`);
16766
16788
  return "go_high";
16767
16789
  }
16790
+ logger.verbose(`${_EkuboCLVault.name}: harvestMismatchEstimateCallFn => error: ${err.message}, attempt: ${attempt}/${MAX_ATTEMPTS}`);
16768
16791
  return "retry";
16769
16792
  }
16770
16793
  };
@@ -30923,6 +30946,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30923
30946
  * @param params
30924
30947
  */
30925
30948
  async getVesuMultiplyCall(params) {
30949
+ const maxEkuboPriceImpact = params.maxEkuboPriceImpact || 0.01;
30926
30950
  const vesuAdapter1 = this.getVesuSameTokenAdapter();
30927
30951
  const legLTV = await vesuAdapter1.getLTVConfig(this.config);
30928
30952
  logger.verbose(`${this.getTag()}::getVesuMultiplyCall legLTV: ${legLTV}`);
@@ -30958,7 +30982,8 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
30958
30982
  marginAmount,
30959
30983
  debtAmount,
30960
30984
  lstDexPriceInUnderlying: dexPrice,
30961
- isIncrease: debtAmount.greaterThan(0)
30985
+ isIncrease: debtAmount.greaterThan(0),
30986
+ maxEkuboPriceImpact
30962
30987
  });
30963
30988
  }
30964
30989
  getLSTUnderlyingTokenInfo() {
@@ -31135,7 +31160,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
31135
31160
  // negative for exact amount out
31136
31161
  );
31137
31162
  logger.verbose(`${this.getTag()}::getModifyLeverCall leverSwapQuote: ${JSON.stringify(leverSwapQuote)}`);
31138
- assert(leverSwapQuote.price_impact < 0.01, "getIncreaseLeverCall: Price impact is too high [Debt swap]");
31163
+ assert(leverSwapQuote.price_impact <= params.maxEkuboPriceImpact, "getIncreaseLeverCall: Price impact is too high [Debt swap]");
31139
31164
  const leverSwap = ekuboQuoter.getVesuMultiplyQuote(leverSwapQuote, fromToken, toToken);
31140
31165
  logger.verbose(`${this.getTag()}::getModifyLeverCall leverSwap: ${JSON.stringify(leverSwap)}`);
31141
31166
  let minLSTReceived = params.debtAmount.dividedBy(lstDexPriceInUnderlying).multipliedBy(1 - MAX_SLIPPAGE);
@@ -32118,13 +32143,42 @@ async function executeTransactions(calls, acc, provider2, remarks) {
32118
32143
  console.log(`Transaction confirmed: ${tx.transaction_hash}`);
32119
32144
  return tx;
32120
32145
  }
32146
+ async function myWaitForTransaction(transaction_hash, provider2, retry = 0) {
32147
+ const MAX_RETRIES = 60;
32148
+ logger.verbose(`Waiting for transaction: ${transaction_hash}, retry: ${retry}`);
32149
+ try {
32150
+ const status = await provider2.getTransactionStatus(transaction_hash);
32151
+ logger.verbose(`Transaction status: ${JSON.stringify(status.execution_status)}`);
32152
+ if (status.execution_status == TransactionExecutionStatus.SUCCEEDED) {
32153
+ return true;
32154
+ }
32155
+ if (status.execution_status == TransactionExecutionStatus.REVERTED) {
32156
+ throw new Error(`Transaction reverted: ${transaction_hash}`);
32157
+ }
32158
+ if (retry > MAX_RETRIES) {
32159
+ throw new Error(`Transaction not found: ${transaction_hash}`);
32160
+ }
32161
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
32162
+ return myWaitForTransaction(transaction_hash, provider2, retry + 1);
32163
+ } catch (error) {
32164
+ if (error instanceof Error && error.message.includes("Transaction reverted")) {
32165
+ throw new Error(`Transaction reverted: ${transaction_hash}`);
32166
+ }
32167
+ if (retry > MAX_RETRIES) {
32168
+ throw error;
32169
+ }
32170
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
32171
+ return myWaitForTransaction(transaction_hash, provider2, retry + 1);
32172
+ }
32173
+ }
32121
32174
  var Deployer = {
32122
32175
  getAccount,
32123
32176
  myDeclare,
32124
32177
  deployContract,
32125
32178
  prepareMultiDeployContracts,
32126
32179
  executeDeployCalls,
32127
- executeTransactions
32180
+ executeTransactions,
32181
+ myWaitForTransaction
32128
32182
  };
32129
32183
  var deployer_default = Deployer;
32130
32184
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strkfarm/sdk",
3
- "version": "1.1.50",
3
+ "version": "1.1.52",
4
4
  "description": "STRKFarm TS SDK (Meant for our internal use, but feel free to use it)",
5
5
  "typings": "dist/index.d.ts",
6
6
  "types": "dist/index.d.ts",
@@ -37,7 +37,7 @@ export class AvnuWrapper {
37
37
  excludeSources = ['Haiko(Solvers)']
38
38
  ): Promise<Quote> {
39
39
  const MAX_RETRY = 5;
40
- logger.verbose(`${AvnuWrapper.name}: getQuotes => Getting quotes for ${fromToken} -> ${toToken}, amount: ${amountWei}, taker: ${taker}, retry: ${retry}`);
40
+ // logger.verbose(`${AvnuWrapper.name}: getQuotes => Getting quotes for ${fromToken} -> ${toToken}, amount: ${amountWei}, taker: ${taker}, retry: ${retry}`);
41
41
  const params: any = {
42
42
  sellTokenAddress: fromToken,
43
43
  buyTokenAddress: toToken,
@@ -100,9 +100,9 @@ export class AvnuWrapper {
100
100
  // swapInfo as expected by the strategy
101
101
  // fallback, max 1% slippage
102
102
  const _minAmount = minAmount || (quote.buyAmount * 95n / 100n).toString();
103
- logger.verbose(`${AvnuWrapper.name}: getSwapInfo => sellToken: ${quote.sellTokenAddress}, sellAmount: ${quote.sellAmount}`);
104
- logger.verbose(`${AvnuWrapper.name}: getSwapInfo => buyToken: ${quote.buyTokenAddress}`);
105
- logger.verbose(`${AvnuWrapper.name}: getSwapInfo => buyAmount: ${quote.buyAmount}, minAmount: ${_minAmount}`);
103
+ // logger.verbose(`${AvnuWrapper.name}: getSwapInfo => sellToken: ${quote.sellTokenAddress}, sellAmount: ${quote.sellAmount}`);
104
+ // logger.verbose(`${AvnuWrapper.name}: getSwapInfo => buyToken: ${quote.buyTokenAddress}`);
105
+ // logger.verbose(`${AvnuWrapper.name}: getSwapInfo => buyAmount: ${quote.buyAmount}, minAmount: ${_minAmount}`);
106
106
  const swapInfo: SwapInfo = {
107
107
  token_from_address: quote.sellTokenAddress,
108
108
  token_from_amount: uint256.bnToUint256(quote.sellAmount),
@@ -34,23 +34,30 @@ export class Harvests {
34
34
  const unClaimed: HarvestInfo[] = [];
35
35
 
36
36
  // use the latest one
37
- const reward = rewards.sort((a, b) => b.endDate.getTime() - a.endDate.getTime())[0];
38
-
39
- const cls = await this.config.provider.getClassAt(reward.rewardsContract.address);
40
- const contract = new Contract({abi: cls.abi, address: reward.rewardsContract.address, providerOrAccount: this.config.provider});
41
- const isClaimed = await contract.call('is_claimed', [reward.claim.id]);
42
- logger.verbose(`${Harvests.name}: isClaimed: ${isClaimed}`);
43
- if (isClaimed) {
44
- return unClaimed;
45
- }
46
- // rewards contract must have enough balance to claim
47
- const bal = await (new ERC20(this.config)).balanceOf(reward.token, reward.rewardsContract.address, 18);
48
- if (bal.lessThan(reward.claim.amount)) {
49
- logger.verbose(`${Harvests.name}: balance: ${bal.toString()}, amount: ${reward.claim.amount.toString()}`);
50
- return unClaimed;
37
+ const sortedRewards = rewards.sort((a, b) => b.endDate.getTime() - a.endDate.getTime());
38
+ if (sortedRewards.length == 0) {
39
+ logger.verbose(`${Harvests.name}: no rewards found`);
40
+ return [];
51
41
  }
52
42
 
53
- unClaimed.unshift(reward); // to ensure older harvest is first
43
+ const cls = await this.config.provider.getClassAt(sortedRewards[0].rewardsContract.address);
44
+
45
+ for (const reward of sortedRewards) {
46
+ const contract = new Contract({abi: cls.abi, address: reward.rewardsContract.address, providerOrAccount: this.config.provider});
47
+ const isClaimed = await contract.call('is_claimed', [reward.claim.id]);
48
+ logger.verbose(`${Harvests.name}: isClaimed: ${isClaimed}, claim id: ${reward.claim.id}, address: ${reward.rewardsContract.address}`);
49
+ if (isClaimed) {
50
+ continue;
51
+ }
52
+ // rewards contract must have enough balance to claim
53
+ const bal = await (new ERC20(this.config)).balanceOf(reward.token, reward.rewardsContract.address, 18);
54
+ if (bal.lessThan(reward.claim.amount)) {
55
+ logger.verbose(`${Harvests.name}: balance: ${bal.toString()}, amount: ${reward.claim.amount.toString()}`);
56
+ continue;
57
+ }
58
+
59
+ unClaimed.push(reward); // to ensure older harvest is first
60
+ }
54
61
  return unClaimed;
55
62
  }
56
63
  }
@@ -4,6 +4,7 @@ import { readFileSync, existsSync, writeFileSync } from 'fs'
4
4
  import { IConfig } from '../interfaces';
5
5
  import { Store, getDefaultStoreConfig } from '../utils/store';
6
6
  import { add } from 'winston';
7
+ import { logger } from '@/utils';
7
8
 
8
9
  function getContracts() {
9
10
  const PATH = './contracts.json'
@@ -207,13 +208,47 @@ async function executeTransactions(
207
208
  return tx;
208
209
  }
209
210
 
211
+ async function myWaitForTransaction(
212
+ transaction_hash: string,
213
+ provider: RpcProvider,
214
+ retry = 0
215
+ ) {
216
+ const MAX_RETRIES = 60;
217
+ logger.verbose(`Waiting for transaction: ${transaction_hash}, retry: ${retry}`);
218
+ try {
219
+ const status = await provider.getTransactionStatus(transaction_hash);
220
+ logger.verbose(`Transaction status: ${JSON.stringify(status.execution_status)}`);
221
+ if (status.execution_status == TransactionExecutionStatus.SUCCEEDED) {
222
+ return true;
223
+ }
224
+ if (status.execution_status == TransactionExecutionStatus.REVERTED) {
225
+ throw new Error(`Transaction reverted: ${transaction_hash}`);
226
+ }
227
+ if (retry > MAX_RETRIES) {
228
+ throw new Error(`Transaction not found: ${transaction_hash}`);
229
+ }
230
+ await new Promise(resolve => setTimeout(resolve, 1000));
231
+ return myWaitForTransaction(transaction_hash, provider, retry + 1);
232
+ } catch (error) {
233
+ if (error instanceof Error && error.message.includes('Transaction reverted')) {
234
+ throw new Error(`Transaction reverted: ${transaction_hash}`);
235
+ }
236
+ if (retry > MAX_RETRIES) {
237
+ throw error;
238
+ }
239
+ await new Promise(resolve => setTimeout(resolve, 1000));
240
+ return myWaitForTransaction(transaction_hash, provider, retry + 1);
241
+ }
242
+ }
243
+
210
244
  const Deployer = {
211
245
  getAccount,
212
246
  myDeclare,
213
247
  deployContract,
214
248
  prepareMultiDeployContracts,
215
249
  executeDeployCalls,
216
- executeTransactions
250
+ executeTransactions,
251
+ myWaitForTransaction
217
252
  }
218
253
 
219
254
  export default Deployer;