@strkfarm/sdk 1.0.61 → 1.0.63

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
@@ -464,7 +464,8 @@ var Pricer = class extends PricerBase {
464
464
  const url = this.EKUBO_API.replace("{{TOKEN_ADDRESS}}", token.address.toString()).replace("{{AMOUNT}}", amountIn.toWei());
465
465
  const result = await axios2.get(url);
466
466
  const data = result.data;
467
- const outputUSDC = Number(Web3Number.fromWei(data.total_calculated, 6).toFixed(6));
467
+ const multiplier = 1 / amountIn.toNumber();
468
+ const outputUSDC = Number(Web3Number.fromWei(data.total_calculated, 6).toFixed(6)) * multiplier;
468
469
  logger.verbose(`Ekubo: ${token.symbol} -> USDC: ${outputUSDC}, retry: ${retry}`);
469
470
  if (outputUSDC === 0 && retry < 3) {
470
471
  const amountIn2 = new Web3Number(100, token.decimals);
@@ -3889,11 +3890,12 @@ var EkuboHarvests = class extends Harvests {
3889
3890
  return rewards.sort((a, b) => b.endDate.getTime() - a.endDate.getTime());
3890
3891
  }
3891
3892
  };
3893
+ var VESU_REWARDS_CONTRACT = ContractAddr.from("0x0387f3eb1d98632fbe3440a9f1385Aec9d87b6172491d3Dd81f1c35A7c61048F");
3892
3894
  var VesuHarvests = class _VesuHarvests extends Harvests {
3893
3895
  async getHarvests(addr) {
3894
3896
  const result = await fetch(`https://api.vesu.xyz/users/${addr.address}/strk-rewards/calldata`);
3895
3897
  const data = await result.json();
3896
- const rewardsContract = ContractAddr.from("0x0387f3eb1d98632fbe3440a9f1385Aec9d87b6172491d3Dd81f1c35A7c61048F");
3898
+ const rewardsContract = VESU_REWARDS_CONTRACT;
3897
3899
  const cls = await this.config.provider.getClassAt(rewardsContract.address);
3898
3900
  const contract = new Contract4(cls.abi, rewardsContract.address, this.config.provider);
3899
3901
  const _claimed_amount = await contract.call("amount_already_claimed", [addr.address]);
@@ -18485,7 +18487,9 @@ var SenseiStrategies = [
18485
18487
  import { hash, num as num6, shortString } from "starknet";
18486
18488
 
18487
18489
  // src/strategies/universal-adapters/adapter-utils.ts
18488
- var SIMPLE_SANITIZER = ContractAddr.from("0x3798dc4f83fdfad199e5236e3656cf2fb79bc50c00504d0dd41522e0f042072");
18490
+ var SIMPLE_SANITIZER = ContractAddr.from("0x5a2e3ceb3da368b983a8717898427ab7b6daf04014b70f321e777f9aad940b4");
18491
+ var PRICE_ROUTER = ContractAddr.from("0x05e83Fa38D791d2dba8E6f487758A9687FfEe191A6Cf8a6c5761ab0a110DB837");
18492
+ var AVNU_MIDDLEWARE = ContractAddr.from("0x4a7972ed3f5d1e74a6d6c4a8f467666953d081c8f2270390cc169d50d17cb0d");
18489
18493
  function toBigInt(value) {
18490
18494
  if (typeof value === "string") {
18491
18495
  return BigInt(value);
@@ -18518,7 +18522,7 @@ var BaseAdapter = class extends CacheClass {
18518
18522
  };
18519
18523
 
18520
18524
  // src/strategies/universal-adapters/common-adapter.ts
18521
- import { hash as hash2, uint256 as uint2566 } from "starknet";
18525
+ import { hash as hash2, num as num7, uint256 as uint2566 } from "starknet";
18522
18526
  var CommonAdapter = class extends BaseAdapter {
18523
18527
  constructor(config) {
18524
18528
  super();
@@ -18629,10 +18633,70 @@ var CommonAdapter = class extends BaseAdapter {
18629
18633
  };
18630
18634
  };
18631
18635
  }
18636
+ getAvnuAdapter(fromToken, toToken, id) {
18637
+ return () => ({
18638
+ leaf: this.constructSimpleLeafData({
18639
+ id,
18640
+ target: AVNU_MIDDLEWARE,
18641
+ method: "multi_route_swap",
18642
+ packedArguments: [
18643
+ fromToken.toBigInt(),
18644
+ toToken.toBigInt(),
18645
+ this.config.vaultAllocator.toBigInt()
18646
+ ]
18647
+ }),
18648
+ callConstructor: this.getAvnuCall(fromToken, toToken).bind(this)
18649
+ });
18650
+ }
18651
+ getAvnuCall(fromToken, toToken) {
18652
+ return (params) => {
18653
+ return {
18654
+ sanitizer: SIMPLE_SANITIZER,
18655
+ call: {
18656
+ contractAddress: AVNU_MIDDLEWARE,
18657
+ selector: hash2.getSelectorFromName("multi_route_swap"),
18658
+ calldata: [
18659
+ fromToken.toBigInt(),
18660
+ // sell_token_address
18661
+ toBigInt(params.props.token_from_amount.low.toString()),
18662
+ // sell_token_amount low
18663
+ toBigInt(params.props.token_from_amount.high.toString()),
18664
+ // sell_token_amount high
18665
+ toToken.toBigInt(),
18666
+ // buy_token_address
18667
+ toBigInt(params.props.token_to_amount.low.toString()),
18668
+ // buy_token_amount low
18669
+ toBigInt(params.props.token_to_amount.high.toString()),
18670
+ // buy_token_amount high
18671
+ toBigInt(params.props.token_to_min_amount.low.toString()),
18672
+ // buy_token_min_amount low
18673
+ toBigInt(params.props.token_to_min_amount.high.toString()),
18674
+ // buy_token_min_amount high
18675
+ this.config.vaultAllocator.toBigInt(),
18676
+ // beneficiary
18677
+ toBigInt(0),
18678
+ // integrator_fee_amount_bps
18679
+ this.config.vaultAllocator.toBigInt(),
18680
+ // integrator_fee_recipient
18681
+ // unpack routes
18682
+ BigInt(params.props.routes.length),
18683
+ ...params.props.routes.map((r) => [
18684
+ BigInt(num7.hexToDecimalString(r.token_from)),
18685
+ BigInt(num7.hexToDecimalString(r.token_to)),
18686
+ BigInt(num7.hexToDecimalString(r.exchange_address)),
18687
+ BigInt(r.percent),
18688
+ BigInt(r.additional_swap_params.length),
18689
+ ...r.additional_swap_params.map((p) => BigInt(num7.hexToDecimalString(p)))
18690
+ ]).flat()
18691
+ ]
18692
+ }
18693
+ };
18694
+ };
18695
+ }
18632
18696
  };
18633
18697
 
18634
18698
  // src/strategies/universal-adapters/vesu-adapter.ts
18635
- import { CairoCustomEnum as CairoCustomEnum2, Contract as Contract8, hash as hash3, RpcProvider as RpcProvider4, uint256 as uint2567 } from "starknet";
18699
+ import { CairoCustomEnum as CairoCustomEnum2, Contract as Contract8, hash as hash3, num as num8, RpcProvider as RpcProvider4, shortString as shortString3, uint256 as uint2567 } from "starknet";
18636
18700
 
18637
18701
  // src/data/vesu-singleton.abi.json
18638
18702
  var vesu_singleton_abi_default = [
@@ -20965,6 +21029,40 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
20965
21029
  }
20966
21030
  };
20967
21031
  };
21032
+ this.getDefispringRewardsAdapter = (id) => {
21033
+ return () => {
21034
+ const packedArguments = [];
21035
+ const output = {
21036
+ id: BigInt(num8.getDecimalString(shortString3.encodeShortString(id))),
21037
+ readableId: id,
21038
+ data: [
21039
+ SIMPLE_SANITIZER.toBigInt(),
21040
+ // sanitizer address
21041
+ VESU_REWARDS_CONTRACT.toBigInt(),
21042
+ // contract
21043
+ toBigInt(hash3.getSelectorFromName("claim")),
21044
+ // method name
21045
+ BigInt(packedArguments.length),
21046
+ ...packedArguments
21047
+ ]
21048
+ };
21049
+ return { leaf: output, callConstructor: this.getDefiSpringClaimCall().bind(this) };
21050
+ };
21051
+ };
21052
+ this.getDefiSpringClaimCall = () => {
21053
+ return (params) => ({
21054
+ sanitizer: SIMPLE_SANITIZER,
21055
+ call: {
21056
+ contractAddress: VESU_REWARDS_CONTRACT,
21057
+ selector: hash3.getSelectorFromName("claim"),
21058
+ calldata: [
21059
+ BigInt(params.amount.toWei()),
21060
+ BigInt(params.proofs.length),
21061
+ ...params.proofs.map((proof) => BigInt(num8.hexToDecimalString(proof)))
21062
+ ]
21063
+ }
21064
+ });
21065
+ };
20968
21066
  this.config = config;
20969
21067
  }
20970
21068
  static getDefaultModifyPositionCallParams(params) {
@@ -23594,7 +23692,7 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
23594
23692
  const aumToken = vesuAum.plus(balance.amount);
23595
23693
  logger.verbose(`${this.getTag()} Actual AUM: ${aumToken}`);
23596
23694
  const netAPY = await this.netAPY();
23597
- const defispringAPY = netAPY.splits.find((s) => s.id === "defispring")?.apy || 0;
23695
+ const defispringAPY = (netAPY.splits.find((s) => s.id === "defispring")?.apy || 0) * 0.8;
23598
23696
  if (!defispringAPY) throw new Error("DefiSpring APY not found");
23599
23697
  const timeDiff = Math.round(Date.now() / 1e3) - Number(lastReportTime);
23600
23698
  const growthRate = timeDiff * defispringAPY / (365 * 24 * 60 * 60);
@@ -23837,6 +23935,51 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
23837
23935
  const manageCall = this.getManageCall(["approve_bring_liquidity" /* APPROVE_BRING_LIQUIDITY */, "bring_liquidity" /* BRING_LIQUIDITY */], [manageCall1, manageCall2]);
23838
23936
  return manageCall;
23839
23937
  }
23938
+ async getHarvestCall() {
23939
+ const vesuHarvest = new VesuHarvests(this.config);
23940
+ const harvestInfo = await vesuHarvest.getUnHarvestedRewards(this.metadata.additionalInfo.vaultAllocator);
23941
+ if (harvestInfo.length != 1) {
23942
+ throw new Error(`Expected 1 harvest info, got ${harvestInfo.length}`);
23943
+ }
23944
+ const amount = harvestInfo[0].claim.amount;
23945
+ const actualReward = harvestInfo[0].actualReward;
23946
+ const proofs = harvestInfo[0].proof;
23947
+ if (actualReward.isZero()) {
23948
+ throw new Error(`Expected non-zero actual reward, got ${harvestInfo[0].actualReward}`);
23949
+ }
23950
+ const manage1Info = this.getProofs("defispring_rewards" /* DEFISPRING_REWARDS */);
23951
+ const manageCall1 = manage1Info.callConstructor({
23952
+ amount,
23953
+ proofs
23954
+ });
23955
+ const proofIds = ["defispring_rewards" /* DEFISPRING_REWARDS */];
23956
+ const manageCalls = [manageCall1];
23957
+ const STRK2 = Global.getDefaultTokens().find((t) => t.symbol === "STRK");
23958
+ if (this.asset().symbol != "STRK") {
23959
+ const manage2Info = this.getProofs("approve_swap_token1" /* APPROVE_SWAP_TOKEN1 */);
23960
+ const manageCall2 = manage2Info.callConstructor({
23961
+ amount: actualReward
23962
+ });
23963
+ const avnuModule = new AvnuWrapper();
23964
+ const quote = await avnuModule.getQuotes(
23965
+ STRK2.address.address,
23966
+ this.asset().address.address,
23967
+ actualReward.toWei(),
23968
+ this.address.address
23969
+ );
23970
+ const swapInfo = await avnuModule.getSwapInfo(quote, this.address.address, 0, this.address.address);
23971
+ const manage3Info = this.getProofs("avnu_swap_rewards" /* AVNU_SWAP_REWARDS */);
23972
+ const manageCall3 = manage3Info.callConstructor({
23973
+ props: swapInfo
23974
+ });
23975
+ proofIds.push("approve_swap_token1" /* APPROVE_SWAP_TOKEN1 */);
23976
+ proofIds.push("avnu_swap_rewards" /* AVNU_SWAP_REWARDS */);
23977
+ manageCalls.push(manageCall2);
23978
+ manageCalls.push(manageCall3);
23979
+ }
23980
+ const manageCall = this.getManageCall(proofIds, manageCalls);
23981
+ return { call: manageCall, reward: actualReward, tokenInfo: STRK2 };
23982
+ }
23840
23983
  async getRebalanceCall(params) {
23841
23984
  let callSet1 = this.getVesuModifyPositionCalls({
23842
23985
  isLeg1: true,
@@ -23873,6 +24016,9 @@ var UNIVERSAL_MANAGE_IDS = /* @__PURE__ */ ((UNIVERSAL_MANAGE_IDS2) => {
23873
24016
  UNIVERSAL_MANAGE_IDS2["APPROVE_TOKEN2"] = "approve_token2";
23874
24017
  UNIVERSAL_MANAGE_IDS2["APPROVE_BRING_LIQUIDITY"] = "approve_bring_liquidity";
23875
24018
  UNIVERSAL_MANAGE_IDS2["BRING_LIQUIDITY"] = "bring_liquidity";
24019
+ UNIVERSAL_MANAGE_IDS2["DEFISPRING_REWARDS"] = "defispring_rewards";
24020
+ UNIVERSAL_MANAGE_IDS2["APPROVE_SWAP_TOKEN1"] = "approve_swap_token1";
24021
+ UNIVERSAL_MANAGE_IDS2["AVNU_SWAP_REWARDS"] = "avnu_swap_rewards";
23876
24022
  return UNIVERSAL_MANAGE_IDS2;
23877
24023
  })(UNIVERSAL_MANAGE_IDS || {});
23878
24024
  var UNIVERSAL_ADAPTERS = /* @__PURE__ */ ((UNIVERSAL_ADAPTERS2) => {
@@ -23922,6 +24068,10 @@ function getLooperSettings(token1Symbol, token2Symbol, vaultSettings, pool1, poo
23922
24068
  vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(ETHToken.address, vesuAdapterETHUSDC.VESU_SINGLETON, "approve_token2" /* APPROVE_TOKEN2 */).bind(commonAdapter));
23923
24069
  vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(USDCToken.address, vaultSettings.vaultAddress, "approve_bring_liquidity" /* APPROVE_BRING_LIQUIDITY */).bind(commonAdapter));
23924
24070
  vaultSettings.leafAdapters.push(commonAdapter.getBringLiquidityAdapter("bring_liquidity" /* BRING_LIQUIDITY */).bind(commonAdapter));
24071
+ vaultSettings.leafAdapters.push(vesuAdapterUSDCETH.getDefispringRewardsAdapter("defispring_rewards" /* DEFISPRING_REWARDS */).bind(vesuAdapterUSDCETH));
24072
+ const STRKToken = Global.getDefaultTokens().find((token) => token.symbol === "STRK");
24073
+ vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(STRKToken.address, AVNU_MIDDLEWARE, "approve_swap_token1" /* APPROVE_SWAP_TOKEN1 */).bind(commonAdapter));
24074
+ vaultSettings.leafAdapters.push(commonAdapter.getAvnuAdapter(STRKToken.address, USDCToken.address, "avnu_swap_rewards" /* AVNU_SWAP_REWARDS */).bind(commonAdapter));
23925
24075
  return vaultSettings;
23926
24076
  }
23927
24077
  var _riskFactor4 = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strkfarm/sdk",
3
- "version": "1.0.61",
3
+ "version": "1.0.63",
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",
@@ -83,12 +83,14 @@ export class EkuboHarvests extends Harvests {
83
83
  }
84
84
  }
85
85
 
86
+ export const VESU_REWARDS_CONTRACT = ContractAddr.from('0x0387f3eb1d98632fbe3440a9f1385Aec9d87b6172491d3Dd81f1c35A7c61048F');
87
+
86
88
  export class VesuHarvests extends Harvests {
87
89
  async getHarvests(addr: ContractAddr): Promise<HarvestInfo[]> {
88
90
  const result = await fetch(`https://api.vesu.xyz/users/${addr.address}/strk-rewards/calldata`);
89
91
  const data = await result.json();
90
- const rewardsContract = ContractAddr.from('0x0387f3eb1d98632fbe3440a9f1385Aec9d87b6172491d3Dd81f1c35A7c61048F');
91
-
92
+ const rewardsContract = VESU_REWARDS_CONTRACT;
93
+
92
94
  // get already claimed amount
93
95
  const cls = await this.config.provider.getClassAt(rewardsContract.address);
94
96
  const contract = new Contract(cls.abi, rewardsContract.address, this.config.provider);
@@ -187,7 +187,8 @@ export class Pricer extends PricerBase {
187
187
  const url = this.EKUBO_API.replace("{{TOKEN_ADDRESS}}", token.address.toString()).replace("{{AMOUNT}}", amountIn.toWei());
188
188
  const result = await axios.get(url);
189
189
  const data: any = result.data;
190
- const outputUSDC = Number(Web3Number.fromWei(data.total_calculated, 6).toFixed(6));
190
+ const multiplier = 1 / amountIn.toNumber();
191
+ const outputUSDC = Number(Web3Number.fromWei(data.total_calculated, 6).toFixed(6)) * multiplier;
191
192
  logger.verbose(`Ekubo: ${token.symbol} -> USDC: ${outputUSDC}, retry: ${retry}`);
192
193
  if (outputUSDC === 0 && retry < 3) {
193
194
  // try again with a higher amount
@@ -1,6 +1,8 @@
1
1
  import { ContractAddr } from "@/dataTypes";
2
2
 
3
- export const SIMPLE_SANITIZER = ContractAddr.from('0x3798dc4f83fdfad199e5236e3656cf2fb79bc50c00504d0dd41522e0f042072');
3
+ export const SIMPLE_SANITIZER = ContractAddr.from('0x5a2e3ceb3da368b983a8717898427ab7b6daf04014b70f321e777f9aad940b4');
4
+ export const PRICE_ROUTER = ContractAddr.from('0x05e83Fa38D791d2dba8E6f487758A9687FfEe191A6Cf8a6c5761ab0a110DB837');
5
+ export const AVNU_MIDDLEWARE = ContractAddr.from('0x4a7972ed3f5d1e74a6d6c4a8f467666953d081c8f2270390cc169d50d17cb0d');
4
6
 
5
7
  export function toBigInt(value: string | number): bigint {
6
8
  if (typeof value === 'string') {
@@ -1,8 +1,9 @@
1
1
  import { ContractAddr, Web3Number } from "@/dataTypes";
2
2
  import { LeafData } from "@/utils";
3
3
  import { Call, hash, num, shortString, uint256 } from "starknet";
4
- import { SIMPLE_SANITIZER, toBigInt } from "./adapter-utils";
4
+ import { AVNU_MIDDLEWARE, SIMPLE_SANITIZER, toBigInt } from "./adapter-utils";
5
5
  import { AdapterLeafType, BaseAdapter, GenerateCallFn, LeafAdapterFn, ManageCall } from "./baseAdapter";
6
+ import { SwapInfo } from "@/modules";
6
7
 
7
8
  export interface FlashloanCallParams {
8
9
  amount: Web3Number,
@@ -11,6 +12,9 @@ export interface FlashloanCallParams {
11
12
  export interface ApproveCallParams {
12
13
  amount: Web3Number,
13
14
  }
15
+ export interface AvnuSwapCallParams {
16
+ props: SwapInfo
17
+ }
14
18
 
15
19
  export interface CommonAdapterConfig {
16
20
  id: string,
@@ -124,4 +128,56 @@ export class CommonAdapter extends BaseAdapter {
124
128
  }
125
129
  }
126
130
  }
131
+
132
+ getAvnuAdapter(fromToken: ContractAddr, toToken: ContractAddr, id: string): () => AdapterLeafType<AvnuSwapCallParams> {
133
+ return () => ({
134
+ leaf: this.constructSimpleLeafData({
135
+ id: id,
136
+ target: AVNU_MIDDLEWARE,
137
+ method: 'multi_route_swap',
138
+ packedArguments: [
139
+ fromToken.toBigInt(),
140
+ toToken.toBigInt(),
141
+ this.config.vaultAllocator.toBigInt(),
142
+ ]
143
+ }),
144
+ callConstructor: this.getAvnuCall(fromToken, toToken).bind(this)
145
+ });
146
+ }
147
+
148
+ getAvnuCall(fromToken: ContractAddr, toToken: ContractAddr): GenerateCallFn<AvnuSwapCallParams> {
149
+ return (params: AvnuSwapCallParams): ManageCall => {
150
+ return {
151
+ sanitizer: SIMPLE_SANITIZER,
152
+ call: {
153
+ contractAddress: AVNU_MIDDLEWARE,
154
+ selector: hash.getSelectorFromName('multi_route_swap'),
155
+ calldata: [
156
+ fromToken.toBigInt(), // sell_token_address
157
+ toBigInt(params.props.token_from_amount.low.toString()), // sell_token_amount low
158
+ toBigInt(params.props.token_from_amount.high.toString()), // sell_token_amount high
159
+ toToken.toBigInt(), // buy_token_address
160
+ toBigInt(params.props.token_to_amount.low.toString()), // buy_token_amount low
161
+ toBigInt(params.props.token_to_amount.high.toString()), // buy_token_amount high
162
+ toBigInt(params.props.token_to_min_amount.low.toString()), // buy_token_min_amount low
163
+ toBigInt(params.props.token_to_min_amount.high.toString()), // buy_token_min_amount high
164
+ this.config.vaultAllocator.toBigInt(), // beneficiary
165
+ toBigInt(0), // integrator_fee_amount_bps
166
+ this.config.vaultAllocator.toBigInt(), // integrator_fee_recipient
167
+
168
+ // unpack routes
169
+ BigInt(params.props.routes.length),
170
+ ...params.props.routes.map(r => ([
171
+ BigInt(num.hexToDecimalString(r.token_from)),
172
+ BigInt(num.hexToDecimalString(r.token_to)),
173
+ BigInt(num.hexToDecimalString(r.exchange_address)),
174
+ BigInt(r.percent),
175
+ BigInt(r.additional_swap_params.length),
176
+ ...r.additional_swap_params.map(p => BigInt(num.hexToDecimalString(p)))
177
+ ])).flat()
178
+ ]
179
+ }
180
+ }
181
+ }
182
+ }
127
183
  }
@@ -9,6 +9,7 @@ import { PricerBase } from "@/modules/pricerBase";
9
9
  import VesuPoolIDs from "@/data/vesu_pools.json";
10
10
  import { getAPIUsingHeadlessBrowser } from "@/node/headless";
11
11
  import { Global } from "@/global";
12
+ import { VESU_REWARDS_CONTRACT } from "@/modules/harvests";
12
13
 
13
14
  interface VesuPoolsInfo { pools: any[]; isErrorPoolsAPI: boolean };
14
15
 
@@ -38,6 +39,11 @@ export interface VesuModifyPositionCallParams {
38
39
  debtAmount: VesuAmount
39
40
  }
40
41
 
42
+ export interface VesuDefiSpringRewardsCallParams {
43
+ amount: Web3Number,
44
+ proofs: string[],
45
+ }
46
+
41
47
  export interface VesuAdapterConfig {
42
48
  poolId: ContractAddr,
43
49
  collateral: TokenInfo,
@@ -156,6 +162,39 @@ export class VesuAdapter extends BaseAdapter {
156
162
  }
157
163
  }
158
164
  }
165
+
166
+ getDefispringRewardsAdapter = (id: string): () => AdapterLeafType<VesuDefiSpringRewardsCallParams> => {
167
+ return () => {
168
+ const packedArguments: bigint[] = [];
169
+ const output = {
170
+ id: BigInt(num.getDecimalString(shortString.encodeShortString(id))),
171
+ readableId: id,
172
+ data: [
173
+ SIMPLE_SANITIZER.toBigInt(), // sanitizer address
174
+ VESU_REWARDS_CONTRACT.toBigInt(), // contract
175
+ toBigInt(hash.getSelectorFromName("claim")), // method name
176
+ BigInt(packedArguments.length),
177
+ ...packedArguments
178
+ ]
179
+ };
180
+ return { leaf: output, callConstructor: this.getDefiSpringClaimCall().bind(this) };
181
+ }
182
+ }
183
+
184
+ getDefiSpringClaimCall = (): GenerateCallFn<VesuDefiSpringRewardsCallParams> => {
185
+ return (params: VesuDefiSpringRewardsCallParams) => ({
186
+ sanitizer: SIMPLE_SANITIZER,
187
+ call: {
188
+ contractAddress: VESU_REWARDS_CONTRACT,
189
+ selector: hash.getSelectorFromName('claim'),
190
+ calldata: [
191
+ BigInt(params.amount.toWei()),
192
+ BigInt(params.proofs.length),
193
+ ...params.proofs.map(proof => BigInt(num.hexToDecimalString(proof)))
194
+ ]
195
+ }
196
+ })
197
+ }
159
198
 
160
199
  formatAmountTypeEnum(amountType: VesuAmountType) {
161
200
  switch(amountType) {
@@ -7,9 +7,11 @@ import { VesuRebalanceSettings } from "./vesu-rebalance";
7
7
  import { assert, LeafData, logger, StandardMerkleTree } from "@/utils";
8
8
  import UniversalVaultAbi from '../data/universal-vault.abi.json';
9
9
  import ManagerAbi from '../data/vault-manager.abi.json';
10
- import { ApproveCallParams, BaseAdapter, CommonAdapter, FlashloanCallParams, GenerateCallFn, LeafAdapterFn, ManageCall, VesuAdapter, VesuModifyPositionCallParams, VesuPools } from "./universal-adapters";
10
+ import { ApproveCallParams, AvnuSwapCallParams, BaseAdapter, CommonAdapter, FlashloanCallParams, GenerateCallFn, LeafAdapterFn, ManageCall, VesuAdapter, VesuDefiSpringRewardsCallParams, VesuModifyPositionCallParams, VesuPools } from "./universal-adapters";
11
11
  import { Global } from "@/global";
12
- import { ERC20 } from "@/modules";
12
+ import { AvnuWrapper, ERC20 } from "@/modules";
13
+ import { AVNU_MIDDLEWARE } from "./universal-adapters/adapter-utils";
14
+ import { VesuHarvests } from "@/modules/harvests";
13
15
 
14
16
  export interface UniversalStrategySettings {
15
17
  vaultAddress: ContractAddr,
@@ -312,7 +314,8 @@ export class UniversalStrategy<
312
314
 
313
315
  // calculate estimated growth from strk rewards
314
316
  const netAPY = await this.netAPY();
315
- const defispringAPY = netAPY.splits.find(s => s.id === 'defispring')?.apy || 0;
317
+ // account only 80% of value
318
+ const defispringAPY = (netAPY.splits.find(s => s.id === 'defispring')?.apy || 0) * 0.8;
316
319
  if (!defispringAPY) throw new Error('DefiSpring APY not found');
317
320
 
318
321
  const timeDiff = (Math.round(Date.now() / 1000) - Number(lastReportTime));
@@ -605,6 +608,61 @@ export class UniversalStrategy<
605
608
  return manageCall;
606
609
  }
607
610
 
611
+ async getHarvestCall() {
612
+ const vesuHarvest = new VesuHarvests(this.config);
613
+ const harvestInfo = await vesuHarvest.getUnHarvestedRewards(this.metadata.additionalInfo.vaultAllocator);
614
+ if (harvestInfo.length != 1) {
615
+ throw new Error(`Expected 1 harvest info, got ${harvestInfo.length}`);
616
+ }
617
+
618
+ const amount = harvestInfo[0].claim.amount;
619
+ const actualReward = harvestInfo[0].actualReward;
620
+ const proofs = harvestInfo[0].proof;
621
+ if (actualReward.isZero()) {
622
+ throw new Error(`Expected non-zero actual reward, got ${harvestInfo[0].actualReward}`);
623
+ }
624
+
625
+ const manage1Info = this.getProofs<VesuDefiSpringRewardsCallParams>(UNIVERSAL_MANAGE_IDS.DEFISPRING_REWARDS);
626
+ const manageCall1 = manage1Info.callConstructor({
627
+ amount,
628
+ proofs
629
+ });
630
+ const proofIds: string[] = [UNIVERSAL_MANAGE_IDS.DEFISPRING_REWARDS];
631
+ const manageCalls: ManageCall[] = [manageCall1];
632
+
633
+ // swap rewards for underlying
634
+ const STRK = Global.getDefaultTokens().find(t => t.symbol === 'STRK')!;
635
+ if (this.asset().symbol != 'STRK') {
636
+ // approve
637
+ const manage2Info = this.getProofs<ApproveCallParams>(UNIVERSAL_MANAGE_IDS.APPROVE_SWAP_TOKEN1);
638
+ const manageCall2 = manage2Info.callConstructor({
639
+ amount: actualReward
640
+ });
641
+
642
+ // swap
643
+ const avnuModule = new AvnuWrapper();
644
+ const quote = await avnuModule.getQuotes(
645
+ STRK.address.address,
646
+ this.asset().address.address,
647
+ actualReward.toWei(),
648
+ this.address.address
649
+ );
650
+ const swapInfo = await avnuModule.getSwapInfo(quote, this.address.address, 0, this.address.address);
651
+ const manage3Info = this.getProofs<AvnuSwapCallParams>(UNIVERSAL_MANAGE_IDS.AVNU_SWAP_REWARDS);
652
+ const manageCall3 = manage3Info.callConstructor({
653
+ props: swapInfo
654
+ });
655
+ proofIds.push(UNIVERSAL_MANAGE_IDS.APPROVE_SWAP_TOKEN1);
656
+ proofIds.push(UNIVERSAL_MANAGE_IDS.AVNU_SWAP_REWARDS);
657
+
658
+ manageCalls.push(manageCall2);
659
+ manageCalls.push(manageCall3);
660
+ }
661
+
662
+ const manageCall = this.getManageCall(proofIds, manageCalls);
663
+ return { call: manageCall, reward: actualReward, tokenInfo: STRK };
664
+ }
665
+
608
666
  async getRebalanceCall(params: {
609
667
  isLeg1toLeg2: boolean,
610
668
  amount: Web3Number
@@ -646,7 +704,14 @@ export enum UNIVERSAL_MANAGE_IDS {
646
704
  APPROVE_TOKEN1 = 'approve_token1',
647
705
  APPROVE_TOKEN2 = 'approve_token2',
648
706
  APPROVE_BRING_LIQUIDITY = 'approve_bring_liquidity',
649
- BRING_LIQUIDITY = 'bring_liquidity'
707
+ BRING_LIQUIDITY = 'bring_liquidity',
708
+
709
+ // defi spring claim
710
+ DEFISPRING_REWARDS = 'defispring_rewards',
711
+
712
+ // avnu swaps
713
+ APPROVE_SWAP_TOKEN1 = 'approve_swap_token1',
714
+ AVNU_SWAP_REWARDS = 'avnu_swap_rewards'
650
715
  }
651
716
 
652
717
  export enum UNIVERSAL_ADAPTERS {
@@ -707,7 +772,15 @@ function getLooperSettings(
707
772
  // to bridge liquidity back to vault (used by bring_liquidity)
708
773
  vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(USDCToken.address, vaultSettings.vaultAddress, UNIVERSAL_MANAGE_IDS.APPROVE_BRING_LIQUIDITY).bind(commonAdapter));
709
774
  vaultSettings.leafAdapters.push(commonAdapter.getBringLiquidityAdapter(UNIVERSAL_MANAGE_IDS.BRING_LIQUIDITY).bind(commonAdapter));
710
- return vaultSettings;
775
+
776
+ // claim rewards
777
+ vaultSettings.leafAdapters.push(vesuAdapterUSDCETH.getDefispringRewardsAdapter(UNIVERSAL_MANAGE_IDS.DEFISPRING_REWARDS).bind(vesuAdapterUSDCETH));
778
+
779
+ // avnu swap
780
+ const STRKToken = Global.getDefaultTokens().find(token => token.symbol === 'STRK')!;
781
+ vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(STRKToken.address, AVNU_MIDDLEWARE, UNIVERSAL_MANAGE_IDS.APPROVE_SWAP_TOKEN1).bind(commonAdapter));
782
+ vaultSettings.leafAdapters.push(commonAdapter.getAvnuAdapter(STRKToken.address, USDCToken.address, UNIVERSAL_MANAGE_IDS.AVNU_SWAP_REWARDS).bind(commonAdapter));
783
+ return vaultSettings;
711
784
  }
712
785
 
713
786
  const _riskFactor: RiskFactor[] = [