@strkfarm/sdk 1.0.62 → 1.1.0
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/cli.js +8 -2
- package/dist/cli.mjs +9 -3
- package/dist/index.browser.global.js +37782 -36017
- package/dist/index.browser.mjs +241 -92
- package/dist/index.d.ts +23 -4
- package/dist/index.js +247 -92
- package/dist/index.mjs +252 -97
- package/package.json +2 -2
- package/src/interfaces/common.tsx +2 -2
- package/src/modules/erc20.ts +1 -1
- package/src/modules/harvests.ts +6 -4
- package/src/modules/pragma.ts +1 -1
- package/src/modules/pricer.ts +1 -1
- package/src/node/deployer.ts +2 -2
- package/src/strategies/autoCompounderStrk.ts +1 -1
- package/src/strategies/ekubo-cl-vault.tsx +41 -41
- package/src/strategies/sensei.ts +6 -6
- 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 +41 -2
- package/src/strategies/universal-strategy.tsx +93 -20
- package/src/strategies/vesu-rebalance.tsx +15 -15
- package/src/utils/store.ts +9 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ContractAddr, Web3Number } from "@/dataTypes";
|
|
2
|
-
import { BlockIdentifier, constants, RpcProvider } from "starknet";
|
|
2
|
+
import { BlockIdentifier, BlockTag, constants, RpcProvider } from "starknet";
|
|
3
3
|
import React, { ReactNode } from "react";
|
|
4
4
|
|
|
5
5
|
export enum RiskType {
|
|
@@ -107,7 +107,7 @@ export interface IInvestmentFlow {
|
|
|
107
107
|
|
|
108
108
|
export function getMainnetConfig(
|
|
109
109
|
rpcUrl: string = 'https://starknet-mainnet.public.blastapi.io',
|
|
110
|
-
blockIdentifier: BlockIdentifier =
|
|
110
|
+
blockIdentifier: BlockIdentifier = BlockTag.LATEST
|
|
111
111
|
// specVersion = constants.SupportedRpcVersion.v0_8_1
|
|
112
112
|
): IConfig {
|
|
113
113
|
return {
|
package/src/modules/erc20.ts
CHANGED
|
@@ -12,7 +12,7 @@ export class ERC20 {
|
|
|
12
12
|
|
|
13
13
|
contract(addr: string | ContractAddr) {
|
|
14
14
|
const _addr = typeof addr === 'string' ? addr : addr.address;
|
|
15
|
-
return new Contract(ERC20Abi, _addr, this.config.provider);
|
|
15
|
+
return new Contract({abi: ERC20Abi, address: _addr, providerOrAccount: this.config.provider});
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
async balanceOf(token: string | ContractAddr, address: string | ContractAddr, tokenDecimals: number) {
|
package/src/modules/harvests.ts
CHANGED
|
@@ -34,7 +34,7 @@ export class Harvests {
|
|
|
34
34
|
|
|
35
35
|
const cls = await this.config.provider.getClassAt(rewards[0].rewardsContract.address);
|
|
36
36
|
for (let reward of rewards) {
|
|
37
|
-
const contract = new Contract(cls.abi, reward.rewardsContract.address, this.config.provider);
|
|
37
|
+
const contract = new Contract({abi: cls.abi, address: reward.rewardsContract.address, providerOrAccount: this.config.provider});
|
|
38
38
|
const isClaimed = await contract.call('is_claimed', [reward.claim.id]);
|
|
39
39
|
logger.verbose(`${Harvests.name}: isClaimed: ${isClaimed}`);
|
|
40
40
|
if (isClaimed) {
|
|
@@ -83,15 +83,17 @@ 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
|
-
const contract = new Contract(cls.abi, rewardsContract.address, this.config.provider);
|
|
96
|
+
const contract = new Contract({abi: cls.abi, address: rewardsContract.address, providerOrAccount: this.config.provider});
|
|
95
97
|
const _claimed_amount: any = await contract.call('amount_already_claimed', [addr.address]);
|
|
96
98
|
const claimed_amount = Web3Number.fromWei(_claimed_amount.toString(), 18);
|
|
97
99
|
logger.verbose(`${VesuHarvests.name}: claimed_amount: ${claimed_amount.toString()}`);
|
package/src/modules/pragma.ts
CHANGED
|
@@ -7,7 +7,7 @@ export class Pragma {
|
|
|
7
7
|
readonly contract: Contract;
|
|
8
8
|
|
|
9
9
|
constructor(provider: RpcProvider) {
|
|
10
|
-
this.contract = new Contract(PragmaAbi, this.contractAddr, provider);
|
|
10
|
+
this.contract = new Contract({abi: PragmaAbi, address: this.contractAddr, providerOrAccount: provider});
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
async getPrice(tokenAddr: string) {
|
package/src/modules/pricer.ts
CHANGED
|
@@ -127,7 +127,7 @@ export class Pricer extends PricerBase {
|
|
|
127
127
|
|
|
128
128
|
async _getPrice(token: TokenInfo, defaultMethod = 'all'): Promise<number> {
|
|
129
129
|
const methodToUse: string = this.methodToUse[token.symbol] || defaultMethod; // default start with coinbase
|
|
130
|
-
logger.
|
|
130
|
+
logger.verbose(`Fetching price of ${token.symbol} using ${methodToUse}`);
|
|
131
131
|
switch (methodToUse) {
|
|
132
132
|
case 'Coinbase':
|
|
133
133
|
try {
|
package/src/node/deployer.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import assert from 'assert'
|
|
2
|
-
import {Account, Call, RawArgs, RpcProvider, TransactionExecutionStatus, constants, extractContractHashes, hash, json, num, provider, transaction} from 'starknet'
|
|
2
|
+
import {Account, Call, RawArgs, Deployer as SnDeployer, RpcProvider, TransactionExecutionStatus, constants, extractContractHashes, hash, json, num, provider, transaction} from 'starknet'
|
|
3
3
|
import { readFileSync, existsSync, writeFileSync } from 'fs'
|
|
4
4
|
import { IConfig } from '../interfaces';
|
|
5
5
|
import { Store, getDefaultStoreConfig } from '../utils/store';
|
|
@@ -136,7 +136,7 @@ async function prepareMultiDeployContracts(
|
|
|
136
136
|
const declaredInfo = await myDeclare(contract_name, package_name, config, acc);
|
|
137
137
|
const classHash = declaredInfo.class_hash;
|
|
138
138
|
|
|
139
|
-
const {calls, addresses} =
|
|
139
|
+
const {calls, addresses} = (new SnDeployer()).buildDeployerCall({
|
|
140
140
|
classHash,
|
|
141
141
|
constructorCalldata: constructorData,
|
|
142
142
|
}, acc.address);
|
|
@@ -31,7 +31,7 @@ export class AutoCompounderSTRK {
|
|
|
31
31
|
async init() {
|
|
32
32
|
const provider: RpcProvider = this.config.provider;
|
|
33
33
|
const cls = await provider.getClassAt(this.addr.address);
|
|
34
|
-
this.contract = new Contract(cls.abi, this.addr.address, provider);
|
|
34
|
+
this.contract = new Contract({abi: cls.abi, address: this.addr.address, providerOrAccount: provider});
|
|
35
35
|
this.initialized = true;
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -113,17 +113,17 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
113
113
|
this.metadata = metadata;
|
|
114
114
|
this.address = metadata.address;
|
|
115
115
|
|
|
116
|
-
this.contract = new Contract(
|
|
117
|
-
CLVaultAbi,
|
|
118
|
-
this.address.address,
|
|
119
|
-
this.config.provider
|
|
120
|
-
);
|
|
116
|
+
this.contract = new Contract({
|
|
117
|
+
abi: CLVaultAbi,
|
|
118
|
+
address: this.address.address,
|
|
119
|
+
providerOrAccount: this.config.provider
|
|
120
|
+
});
|
|
121
121
|
if (this.metadata.additionalInfo.lstContract) {
|
|
122
|
-
this.lstContract = new Contract(
|
|
123
|
-
ERC4626Abi,
|
|
124
|
-
this.metadata.additionalInfo.lstContract.address,
|
|
125
|
-
this.config.provider
|
|
126
|
-
);
|
|
122
|
+
this.lstContract = new Contract({
|
|
123
|
+
abi: ERC4626Abi,
|
|
124
|
+
address: this.metadata.additionalInfo.lstContract.address,
|
|
125
|
+
providerOrAccount: this.config.provider
|
|
126
|
+
});
|
|
127
127
|
} else {
|
|
128
128
|
this.lstContract = null;
|
|
129
129
|
}
|
|
@@ -131,18 +131,18 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
131
131
|
// ekubo positions contract
|
|
132
132
|
const EKUBO_POSITION =
|
|
133
133
|
"0x02e0af29598b407c8716b17f6d2795eca1b471413fa03fb145a5e33722184067";
|
|
134
|
-
this.ekuboPositionsContract = new Contract(
|
|
135
|
-
EkuboPositionsAbi,
|
|
136
|
-
EKUBO_POSITION,
|
|
137
|
-
this.config.provider
|
|
138
|
-
);
|
|
134
|
+
this.ekuboPositionsContract = new Contract({
|
|
135
|
+
abi: EkuboPositionsAbi,
|
|
136
|
+
address: EKUBO_POSITION,
|
|
137
|
+
providerOrAccount: this.config.provider
|
|
138
|
+
});
|
|
139
139
|
const EKUBO_MATH =
|
|
140
140
|
"0x04a72e9e166f6c0e9d800af4dc40f6b6fb4404b735d3f528d9250808b2481995";
|
|
141
|
-
this.ekuboMathContract = new Contract(
|
|
142
|
-
EkuboMathAbi,
|
|
143
|
-
EKUBO_MATH,
|
|
144
|
-
this.config.provider
|
|
145
|
-
);
|
|
141
|
+
this.ekuboMathContract = new Contract({
|
|
142
|
+
abi: EkuboMathAbi,
|
|
143
|
+
address: EKUBO_MATH,
|
|
144
|
+
providerOrAccount: this.config.provider
|
|
145
|
+
});
|
|
146
146
|
|
|
147
147
|
this.avnu = new AvnuWrapper();
|
|
148
148
|
}
|
|
@@ -207,16 +207,16 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
207
207
|
const updateAmountInfo = await this.getMinDepositAmounts(amountInfo);
|
|
208
208
|
// Technically its not erc4626 abi, but we just need approve call
|
|
209
209
|
// so, its ok to use it
|
|
210
|
-
const token0Contract = new Contract(
|
|
211
|
-
ERC4626Abi,
|
|
212
|
-
amountInfo.token0.tokenInfo.address.address,
|
|
213
|
-
this.config.provider
|
|
214
|
-
);
|
|
215
|
-
const token1Contract = new Contract(
|
|
216
|
-
ERC4626Abi,
|
|
217
|
-
amountInfo.token1.tokenInfo.address.address,
|
|
218
|
-
this.config.provider
|
|
219
|
-
);
|
|
210
|
+
const token0Contract = new Contract({
|
|
211
|
+
abi: ERC4626Abi,
|
|
212
|
+
address: amountInfo.token0.tokenInfo.address.address,
|
|
213
|
+
providerOrAccount: this.config.provider
|
|
214
|
+
});
|
|
215
|
+
const token1Contract = new Contract({
|
|
216
|
+
abi: ERC4626Abi,
|
|
217
|
+
address: amountInfo.token1.tokenInfo.address.address,
|
|
218
|
+
providerOrAccount: this.config.provider
|
|
219
|
+
});
|
|
220
220
|
const call1 = token0Contract.populate("approve", [
|
|
221
221
|
this.address.address,
|
|
222
222
|
uint256.bnToUint256(updateAmountInfo.token0.amount.toWei()),
|
|
@@ -286,7 +286,7 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
286
286
|
* @returns {Promise<number>} The weighted average APY across all pools
|
|
287
287
|
*/
|
|
288
288
|
async netAPY(
|
|
289
|
-
blockIdentifier: BlockIdentifier = "
|
|
289
|
+
blockIdentifier: BlockIdentifier = "pre_confirmed",
|
|
290
290
|
sinceBlocks = 20000
|
|
291
291
|
): Promise<number> {
|
|
292
292
|
// no special provisions required to account for defi spring rewards
|
|
@@ -376,7 +376,7 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
376
376
|
|
|
377
377
|
async balanceOf(
|
|
378
378
|
user: ContractAddr,
|
|
379
|
-
blockIdentifier: BlockIdentifier = "
|
|
379
|
+
blockIdentifier: BlockIdentifier = "pre_confirmed"
|
|
380
380
|
): Promise<Web3Number> {
|
|
381
381
|
let bal = await this.contract.call("balance_of", [user.address], {
|
|
382
382
|
blockIdentifier,
|
|
@@ -386,7 +386,7 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
386
386
|
|
|
387
387
|
async getUserTVL(
|
|
388
388
|
user: ContractAddr,
|
|
389
|
-
blockIdentifier: BlockIdentifier = "
|
|
389
|
+
blockIdentifier: BlockIdentifier = "pre_confirmed"
|
|
390
390
|
): Promise<DualTokenInfo> {
|
|
391
391
|
let bal = await this.balanceOf(user, blockIdentifier);
|
|
392
392
|
const assets: any = await this.contract.call(
|
|
@@ -428,7 +428,7 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
428
428
|
};
|
|
429
429
|
}
|
|
430
430
|
|
|
431
|
-
async _getTVL(blockIdentifier: BlockIdentifier = "
|
|
431
|
+
async _getTVL(blockIdentifier: BlockIdentifier = "pre_confirmed") {
|
|
432
432
|
const result = await this.contract.call("total_liquidity", [], {
|
|
433
433
|
blockIdentifier,
|
|
434
434
|
});
|
|
@@ -443,7 +443,7 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
443
443
|
}
|
|
444
444
|
|
|
445
445
|
async totalSupply(
|
|
446
|
-
blockIdentifier: BlockIdentifier = "
|
|
446
|
+
blockIdentifier: BlockIdentifier = "pre_confirmed"
|
|
447
447
|
): Promise<Web3Number> {
|
|
448
448
|
const res = await this.contract.call("total_supply", [], {
|
|
449
449
|
blockIdentifier,
|
|
@@ -464,7 +464,7 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
464
464
|
}
|
|
465
465
|
|
|
466
466
|
async getTVL(
|
|
467
|
-
blockIdentifier: BlockIdentifier = "
|
|
467
|
+
blockIdentifier: BlockIdentifier = "pre_confirmed"
|
|
468
468
|
): Promise<DualTokenInfo> {
|
|
469
469
|
const { amount0, amount1 } = await this._getTVL(blockIdentifier);
|
|
470
470
|
const poolKey = await this.getPoolKey(blockIdentifier);
|
|
@@ -561,14 +561,14 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
561
561
|
throw new Error("No true price available");
|
|
562
562
|
}
|
|
563
563
|
|
|
564
|
-
async getCurrentPrice(blockIdentifier: BlockIdentifier = "
|
|
564
|
+
async getCurrentPrice(blockIdentifier: BlockIdentifier = "pre_confirmed") {
|
|
565
565
|
const poolKey = await this.getPoolKey(blockIdentifier);
|
|
566
566
|
return this._getCurrentPrice(poolKey, blockIdentifier);
|
|
567
567
|
}
|
|
568
568
|
|
|
569
569
|
async _getCurrentPrice(
|
|
570
570
|
poolKey: EkuboPoolKey,
|
|
571
|
-
blockIdentifier: BlockIdentifier = "
|
|
571
|
+
blockIdentifier: BlockIdentifier = "pre_confirmed"
|
|
572
572
|
) {
|
|
573
573
|
const priceInfo: any = await this.ekuboPositionsContract.call(
|
|
574
574
|
"get_pool_price",
|
|
@@ -606,7 +606,7 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
606
606
|
}
|
|
607
607
|
|
|
608
608
|
async getCurrentBounds(
|
|
609
|
-
blockIdentifier: BlockIdentifier = "
|
|
609
|
+
blockIdentifier: BlockIdentifier = "pre_confirmed"
|
|
610
610
|
): Promise<EkuboBounds> {
|
|
611
611
|
const result: any = await this.contract.call("get_position_key", [], {
|
|
612
612
|
blockIdentifier,
|
|
@@ -632,7 +632,7 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
632
632
|
}
|
|
633
633
|
|
|
634
634
|
async getPoolKey(
|
|
635
|
-
blockIdentifier: BlockIdentifier = "
|
|
635
|
+
blockIdentifier: BlockIdentifier = "pre_confirmed"
|
|
636
636
|
): Promise<EkuboPoolKey> {
|
|
637
637
|
if (this.poolKey) {
|
|
638
638
|
return this.poolKey;
|
|
@@ -1345,7 +1345,7 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
1345
1345
|
async getLiquidityToAmounts(
|
|
1346
1346
|
liquidity: Web3Number,
|
|
1347
1347
|
bounds: EkuboBounds,
|
|
1348
|
-
blockIdentifier: BlockIdentifier = "
|
|
1348
|
+
blockIdentifier: BlockIdentifier = "pre_confirmed",
|
|
1349
1349
|
_poolKey: EkuboPoolKey | null = null,
|
|
1350
1350
|
_currentPrice: {
|
|
1351
1351
|
price: number;
|
package/src/strategies/sensei.ts
CHANGED
|
@@ -30,7 +30,7 @@ export class SenseiVault extends BaseStrategy<
|
|
|
30
30
|
this.address = metadata.address;
|
|
31
31
|
this.pricer = pricer;
|
|
32
32
|
this.metadata = metadata;
|
|
33
|
-
this.contract = new Contract(SenseiABI, this.address.address, this.config.provider);
|
|
33
|
+
this.contract = new Contract({abi: SenseiABI, address: this.address.address, providerOrAccount: this.config.provider});
|
|
34
34
|
|
|
35
35
|
if (metadata.depositTokens.length === 0) {
|
|
36
36
|
throw new Error("Deposit tokens are not defined in metadata");
|
|
@@ -90,11 +90,11 @@ export class SenseiVault extends BaseStrategy<
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
async depositCall(amountInfo: SingleActionAmount, receiver: ContractAddr): Promise<Call[]> {
|
|
93
|
-
const mainTokenContract = new Contract(
|
|
94
|
-
ERC20ABI,
|
|
95
|
-
this.metadata.depositTokens[0].address.address,
|
|
96
|
-
this.config.provider,
|
|
97
|
-
);
|
|
93
|
+
const mainTokenContract = new Contract({
|
|
94
|
+
abi: ERC20ABI,
|
|
95
|
+
address: this.metadata.depositTokens[0].address.address,
|
|
96
|
+
providerOrAccount: this.config.provider,
|
|
97
|
+
});
|
|
98
98
|
const call1 = mainTokenContract.populate('approve', [
|
|
99
99
|
this.address.address,
|
|
100
100
|
uint256.bnToUint256(amountInfo.amount.toWei()),
|
|
@@ -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,
|
|
@@ -133,7 +139,7 @@ export class VesuAdapter extends BaseAdapter {
|
|
|
133
139
|
}
|
|
134
140
|
};
|
|
135
141
|
logger.verbose(`VesuAdapter::ConstructingModify::Debt::${JSON.stringify(_debt)}`)
|
|
136
|
-
const singletonContract = new Contract(VesuSingletonAbi, this.VESU_SINGLETON.toString(), new RpcProvider({nodeUrl: ''}));
|
|
142
|
+
const singletonContract = new Contract({abi: VesuSingletonAbi, address: this.VESU_SINGLETON.toString(), providerOrAccount: new RpcProvider({nodeUrl: ''})});
|
|
137
143
|
const call = singletonContract.populate('modify_position', {
|
|
138
144
|
params: {
|
|
139
145
|
pool_id: this.config.poolId.toBigInt(),
|
|
@@ -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) {
|
|
@@ -178,7 +217,7 @@ export class VesuAdapter extends BaseAdapter {
|
|
|
178
217
|
}
|
|
179
218
|
|
|
180
219
|
getVesuSingletonContract(config: IConfig) {
|
|
181
|
-
return new Contract(VesuSingletonAbi, this.VESU_SINGLETON.address, config.provider);
|
|
220
|
+
return new Contract({abi: VesuSingletonAbi, address: this.VESU_SINGLETON.address, providerOrAccount: config.provider});
|
|
182
221
|
}
|
|
183
222
|
|
|
184
223
|
async getLTVConfig(config: IConfig) {
|
|
@@ -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,
|
|
@@ -61,16 +63,16 @@ export class UniversalStrategy<
|
|
|
61
63
|
this.metadata = metadata;
|
|
62
64
|
this.address = metadata.address;
|
|
63
65
|
|
|
64
|
-
this.contract = new Contract(
|
|
65
|
-
UniversalVaultAbi,
|
|
66
|
-
this.address.address,
|
|
67
|
-
this.config.provider
|
|
68
|
-
);
|
|
69
|
-
this.managerContract = new Contract(
|
|
70
|
-
ManagerAbi,
|
|
71
|
-
this.metadata.additionalInfo.manager.address,
|
|
72
|
-
this.config.provider
|
|
73
|
-
);
|
|
66
|
+
this.contract = new Contract({
|
|
67
|
+
abi: UniversalVaultAbi,
|
|
68
|
+
address: this.address.address,
|
|
69
|
+
providerOrAccount: this.config.provider
|
|
70
|
+
});
|
|
71
|
+
this.managerContract = new Contract({
|
|
72
|
+
abi: ManagerAbi,
|
|
73
|
+
address: this.metadata.additionalInfo.manager.address,
|
|
74
|
+
providerOrAccount: this.config.provider
|
|
75
|
+
});
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
getMerkleTree() {
|
|
@@ -130,11 +132,11 @@ export class UniversalStrategy<
|
|
|
130
132
|
amountInfo.tokenInfo.address.eq(this.asset().address),
|
|
131
133
|
"Deposit token mismatch"
|
|
132
134
|
);
|
|
133
|
-
const assetContract = new Contract(
|
|
134
|
-
UniversalVaultAbi,
|
|
135
|
-
this.asset().address.address,
|
|
136
|
-
this.config.provider
|
|
137
|
-
);
|
|
135
|
+
const assetContract = new Contract({
|
|
136
|
+
abi: UniversalVaultAbi,
|
|
137
|
+
address: this.asset().address.address,
|
|
138
|
+
providerOrAccount: this.config.provider
|
|
139
|
+
});
|
|
138
140
|
const call1 = assetContract.populate("approve", [
|
|
139
141
|
this.address.address,
|
|
140
142
|
uint256.bnToUint256(amountInfo.amount.toWei())
|
|
@@ -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[] = [
|