@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.browser.global.js +459 -309
- package/dist/index.browser.mjs +156 -6
- package/dist/index.d.ts +21 -2
- package/dist/index.js +154 -4
- package/dist/index.mjs +156 -6
- package/package.json +1 -1
- package/src/modules/harvests.ts +4 -2
- package/src/modules/pricer.ts +2 -1
- package/src/strategies/universal-adapters/adapter-utils.ts +3 -1
- package/src/strategies/universal-adapters/common-adapter.ts +57 -1
- package/src/strategies/universal-adapters/vesu-adapter.ts +39 -0
- package/src/strategies/universal-strategy.tsx +78 -5
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
|
|
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 =
|
|
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("
|
|
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
package/src/modules/harvests.ts
CHANGED
|
@@ -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 =
|
|
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);
|
package/src/modules/pricer.ts
CHANGED
|
@@ -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
|
|
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('
|
|
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
|
-
|
|
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
|
-
|
|
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[] = [
|